summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Android.bp1
-rw-r--r--apct-tests/perftests/core/src/android/graphics/perftests/TypefaceSerializationPerfTest.java83
-rw-r--r--apex/appsearch/framework/api/current.txt142
-rw-r--r--apex/appsearch/framework/java/android/app/appsearch/AppSearchEmail.java130
-rw-r--r--apex/appsearch/framework/java/android/app/appsearch/AppSearchSchema.java102
-rw-r--r--apex/appsearch/framework/java/android/app/appsearch/GenericDocument.java219
-rw-r--r--apex/appsearch/framework/java/android/app/appsearch/GetByUriRequest.java3
-rw-r--r--apex/appsearch/framework/java/android/app/appsearch/PutDocumentsRequest.java12
-rw-r--r--apex/appsearch/framework/java/android/app/appsearch/RemoveByUriRequest.java3
-rw-r--r--apex/appsearch/framework/java/android/app/appsearch/SearchResult.java167
-rw-r--r--apex/appsearch/framework/java/android/app/appsearch/SearchResultPage.java11
-rw-r--r--apex/appsearch/framework/java/android/app/appsearch/SearchSpec.java150
-rw-r--r--apex/appsearch/framework/java/android/app/appsearch/SetSchemaRequest.java14
-rw-r--r--apex/appsearch/framework/java/android/app/appsearch/exceptions/AppSearchException.java13
-rw-r--r--apex/appsearch/framework/java/android/app/appsearch/exceptions/IllegalSchemaException.java2
-rw-r--r--apex/appsearch/framework/java/android/app/appsearch/exceptions/IllegalSearchSpecException.java6
-rw-r--r--apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/AppSearchImpl.java632
-rw-r--r--apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/VisibilityStore.java257
-rw-r--r--apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/converter/GenericDocumentToProtoConverter.java7
-rw-r--r--apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/converter/SchemaToProtoConverter.java28
-rw-r--r--apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/converter/SearchResultToProtoConverter.java11
-rw-r--r--apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/converter/SearchSpecToProtoConverter.java17
-rw-r--r--apex/appsearch/synced_jetpack_changeid.txt1
-rw-r--r--apex/jobscheduler/framework/java/android/app/job/JobInfo.java103
-rw-r--r--apex/jobscheduler/framework/java/android/app/job/JobServiceEngine.java6
-rw-r--r--apex/jobscheduler/service/java/com/android/server/DeviceIdleController.java107
-rw-r--r--apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java7
-rw-r--r--apex/jobscheduler/service/java/com/android/server/job/controllers/BackgroundJobsController.java3
-rw-r--r--apex/jobscheduler/service/java/com/android/server/job/controllers/ConnectivityController.java2
-rw-r--r--apex/jobscheduler/service/java/com/android/server/job/controllers/JobStatus.java28
-rw-r--r--apex/jobscheduler/service/java/com/android/server/job/controllers/QuotaController.java69
-rw-r--r--cmds/statsd/src/atoms.proto85
-rw-r--r--config/preloaded-classes1
-rw-r--r--core/api/current.txt192
-rw-r--r--core/api/system-current.txt150
-rw-r--r--core/api/test-current.txt2
-rw-r--r--core/java/android/accessibilityservice/AccessibilityServiceInfo.java1
-rw-r--r--core/java/android/app/AppOpsManager.java34
-rw-r--r--core/java/android/app/ApplicationPackageManager.java110
-rw-r--r--core/java/android/app/IUiAutomationConnection.aidl4
-rw-r--r--core/java/android/app/Instrumentation.java3
-rw-r--r--core/java/android/app/Notification.java73
-rw-r--r--core/java/android/app/PendingIntent.java11
-rw-r--r--core/java/android/app/TEST_MAPPING4
-rw-r--r--core/java/android/app/TaskInfo.java16
-rw-r--r--core/java/android/app/UiAutomation.java50
-rw-r--r--core/java/android/app/UiAutomationConnection.java10
-rw-r--r--core/java/android/app/people/PeopleSpaceTile.java273
-rw-r--r--core/java/android/bluetooth/BluetoothCodecStatus.java9
-rw-r--r--core/java/android/content/pm/IPackageManager.aidl4
-rw-r--r--core/java/android/content/pm/PackageManager.aidl20
-rw-r--r--core/java/android/content/pm/PackageManager.java358
-rw-r--r--core/java/android/content/pm/PermissionInfo.java14
-rw-r--r--core/java/android/content/pm/parsing/ParsingPackage.java4
-rw-r--r--core/java/android/content/pm/parsing/ParsingPackageImpl.java22
-rw-r--r--core/java/android/content/pm/parsing/ParsingPackageRead.java9
-rw-r--r--core/java/android/content/pm/parsing/ParsingPackageUtils.java76
-rw-r--r--core/java/android/content/pm/parsing/component/ParsedActivityUtils.java2
-rw-r--r--core/java/android/content/pm/parsing/component/ParsedComponent.java18
-rw-r--r--core/java/android/content/pm/parsing/component/ParsedComponentUtils.java27
-rw-r--r--core/java/android/content/pm/parsing/component/ParsedProviderUtils.java3
-rw-r--r--core/java/android/content/pm/parsing/component/ParsedServiceUtils.java4
-rw-r--r--core/java/android/hardware/CameraSessionStats.java202
-rw-r--r--core/java/android/hardware/CameraStreamStats.java169
-rw-r--r--core/java/android/hardware/camera2/impl/CameraCaptureSessionImpl.java3
-rw-r--r--core/java/android/hardware/camera2/impl/CameraDeviceImpl.java17
-rw-r--r--core/java/android/hardware/camera2/impl/ICameraDeviceUserWrapper.java6
-rw-r--r--core/java/android/hardware/display/DisplayManagerInternal.java6
-rw-r--r--core/java/android/hardware/hdmi/HdmiControlManager.java16
-rw-r--r--core/java/android/hardware/hdmi/HdmiControlServiceWrapper.java8
-rw-r--r--core/java/android/hardware/hdmi/IHdmiControlService.aidl1
-rw-r--r--core/java/android/net/LinkProperties.java6
-rw-r--r--core/java/android/net/NetworkCapabilities.java26
-rw-r--r--core/java/android/net/vcn/VcnGatewayConnectionConfig.java86
-rw-r--r--core/java/android/os/strictmode/UntaggedSocketViolation.java2
-rw-r--r--core/java/android/service/attestation/IImpressionAttestationService.aidl16
-rw-r--r--core/java/android/service/attestation/ImpressionAttestationService.java52
-rw-r--r--core/java/android/service/quicksettings/TileService.java3
-rw-r--r--core/java/android/telephony/PhoneStateListener.java1438
-rw-r--r--core/java/android/telephony/TelephonyRegistryManager.java358
-rw-r--r--core/java/android/view/IWindowManager.aidl14
-rw-r--r--core/java/android/view/InputEventReceiver.java14
-rw-r--r--core/java/android/view/NotificationHeaderView.java14
-rw-r--r--core/java/android/view/NotificationTopLineView.java52
-rw-r--r--core/java/android/view/inputmethod/BaseInputConnection.java9
-rw-r--r--core/java/com/android/internal/app/IBatteryStats.aidl2
-rw-r--r--core/java/com/android/internal/os/BatteryStatsHelper.java19
-rw-r--r--core/java/com/android/internal/telephony/IPhoneStateListener.aidl4
-rw-r--r--core/java/com/android/internal/telephony/ITelephonyRegistry.aidl16
-rw-r--r--core/jni/android_view_InputEventReceiver.cpp17
-rw-r--r--core/proto/android/stats/camera/Android.bp33
-rw-r--r--core/proto/android/stats/camera/camera.proto44
-rw-r--r--core/proto/android/stats/camera/jarjar-rules.txt1
-rw-r--r--core/proto/android/stats/mediametrics/mediametrics.proto13
-rw-r--r--core/res/res/layout/notification_material_action_list.xml45
-rw-r--r--core/res/res/layout/notification_template_header.xml18
-rw-r--r--core/res/res/layout/notification_template_material_base.xml14
-rw-r--r--core/res/res/layout/notification_template_material_big_media.xml46
-rw-r--r--core/res/res/layout/notification_template_material_conversation.xml4
-rw-r--r--core/res/res/layout/notification_template_material_media.xml48
-rw-r--r--core/res/res/layout/notification_top_line_views.xml14
-rw-r--r--core/res/res/values-af/strings.xml10
-rw-r--r--core/res/res/values-am/strings.xml10
-rw-r--r--core/res/res/values-ar/strings.xml10
-rw-r--r--core/res/res/values-as/strings.xml10
-rw-r--r--core/res/res/values-az/strings.xml10
-rw-r--r--core/res/res/values-b+sr+Latn/strings.xml26
-rw-r--r--core/res/res/values-be/strings.xml10
-rw-r--r--core/res/res/values-bg/strings.xml10
-rw-r--r--core/res/res/values-bn/strings.xml12
-rw-r--r--core/res/res/values-bs/strings.xml10
-rw-r--r--core/res/res/values-ca/strings.xml10
-rw-r--r--core/res/res/values-cs/strings.xml10
-rw-r--r--core/res/res/values-da/strings.xml10
-rw-r--r--core/res/res/values-de/strings.xml10
-rw-r--r--core/res/res/values-el/strings.xml10
-rw-r--r--core/res/res/values-en-rAU/strings.xml5
-rw-r--r--core/res/res/values-en-rCA/strings.xml5
-rw-r--r--core/res/res/values-en-rGB/strings.xml5
-rw-r--r--core/res/res/values-en-rIN/strings.xml5
-rw-r--r--core/res/res/values-en-rXC/strings.xml5
-rw-r--r--core/res/res/values-es-rUS/strings.xml10
-rw-r--r--core/res/res/values-es/strings.xml10
-rw-r--r--core/res/res/values-et/strings.xml10
-rw-r--r--core/res/res/values-eu/strings.xml10
-rw-r--r--core/res/res/values-fa/strings.xml10
-rw-r--r--core/res/res/values-fi/strings.xml10
-rw-r--r--core/res/res/values-fr-rCA/strings.xml10
-rw-r--r--core/res/res/values-fr/strings.xml10
-rw-r--r--core/res/res/values-gl/strings.xml10
-rw-r--r--core/res/res/values-gu/strings.xml10
-rw-r--r--core/res/res/values-hi/strings.xml10
-rw-r--r--core/res/res/values-hr/strings.xml10
-rw-r--r--core/res/res/values-hu/strings.xml10
-rw-r--r--core/res/res/values-hy/strings.xml10
-rw-r--r--core/res/res/values-in/strings.xml10
-rw-r--r--core/res/res/values-is/strings.xml10
-rw-r--r--core/res/res/values-it/strings.xml5
-rw-r--r--core/res/res/values-iw/strings.xml10
-rw-r--r--core/res/res/values-ja/strings.xml10
-rw-r--r--core/res/res/values-ka/strings.xml5
-rw-r--r--core/res/res/values-kk/strings.xml20
-rw-r--r--core/res/res/values-km/strings.xml10
-rw-r--r--core/res/res/values-kn/strings.xml10
-rw-r--r--core/res/res/values-ko/strings.xml10
-rw-r--r--core/res/res/values-ky/strings.xml10
-rw-r--r--core/res/res/values-lo/strings.xml10
-rw-r--r--core/res/res/values-lt/strings.xml10
-rw-r--r--core/res/res/values-lv/strings.xml10
-rw-r--r--core/res/res/values-mk/strings.xml38
-rw-r--r--core/res/res/values-ml/strings.xml10
-rw-r--r--core/res/res/values-mn/strings.xml10
-rw-r--r--core/res/res/values-mr/strings.xml10
-rw-r--r--core/res/res/values-ms/strings.xml10
-rw-r--r--core/res/res/values-my/strings.xml10
-rw-r--r--core/res/res/values-nb/strings.xml10
-rw-r--r--core/res/res/values-ne/strings.xml44
-rw-r--r--core/res/res/values-nl/strings.xml10
-rw-r--r--core/res/res/values-or/strings.xml10
-rw-r--r--core/res/res/values-pa/strings.xml10
-rw-r--r--core/res/res/values-pl/strings.xml40
-rw-r--r--core/res/res/values-pt-rBR/strings.xml5
-rw-r--r--core/res/res/values-pt-rPT/strings.xml5
-rw-r--r--core/res/res/values-pt/strings.xml5
-rw-r--r--core/res/res/values-ro/strings.xml10
-rw-r--r--core/res/res/values-ru/strings.xml10
-rw-r--r--core/res/res/values-si/strings.xml10
-rw-r--r--core/res/res/values-sk/strings.xml10
-rw-r--r--core/res/res/values-sl/strings.xml10
-rw-r--r--core/res/res/values-sq/strings.xml10
-rw-r--r--core/res/res/values-sr/strings.xml26
-rw-r--r--core/res/res/values-sv/strings.xml10
-rw-r--r--core/res/res/values-sw/strings.xml10
-rw-r--r--core/res/res/values-ta/strings.xml10
-rw-r--r--core/res/res/values-te/strings.xml10
-rw-r--r--core/res/res/values-th/strings.xml10
-rw-r--r--core/res/res/values-tl/strings.xml10
-rw-r--r--core/res/res/values-tr/strings.xml10
-rw-r--r--core/res/res/values-uk/strings.xml10
-rw-r--r--core/res/res/values-ur/strings.xml10
-rw-r--r--core/res/res/values-uz/strings.xml10
-rw-r--r--core/res/res/values-vi/strings.xml10
-rw-r--r--core/res/res/values-zh-rCN/strings.xml10
-rw-r--r--core/res/res/values-zh-rHK/strings.xml10
-rw-r--r--core/res/res/values-zh-rTW/strings.xml10
-rw-r--r--core/res/res/values-zu/strings.xml10
-rw-r--r--core/res/res/values/attrs_manifest.xml35
-rw-r--r--core/res/res/values/dimens.xml13
-rw-r--r--core/res/res/values/symbols.xml4
-rw-r--r--core/tests/coretests/src/android/app/appsearch/external/app/AppSearchEmailTest.java27
-rw-r--r--core/tests/coretests/src/android/app/appsearch/external/app/GenericDocumentTest.java252
-rw-r--r--core/tests/coretests/src/android/app/appsearch/external/app/SearchSpecTest.java68
-rw-r--r--core/tests/coretests/src/android/app/appsearch/external/app/cts/AppSearchResultCtsTest.java79
-rw-r--r--core/tests/coretests/src/android/app/appsearch/external/app/cts/AppSearchSchemaCtsTest.java (renamed from core/tests/coretests/src/android/app/appsearch/external/app/AppSearchSchemaTest.java)43
-rw-r--r--core/tests/coretests/src/android/app/appsearch/external/app/cts/GenericDocumentCtsTest.java286
-rw-r--r--core/tests/coretests/src/android/app/appsearch/external/app/cts/SearchSpecCtsTest.java67
-rw-r--r--core/tests/coretests/src/android/app/appsearch/external/app/cts/customer/CustomerDocumentTest.java (renamed from core/tests/coretests/src/android/app/appsearch/external/app/customer/CustomerDocumentTest.java)72
-rw-r--r--core/tests/coretests/src/android/app/people/PeopleSpaceTileTest.java191
-rw-r--r--core/tests/coretests/src/android/content/pm/PackageManagerPropertyTests.java199
-rw-r--r--core/tests/coretests/src/com/android/internal/jank/FrameTrackerTest.java3
-rw-r--r--core/tests/coretests/src/com/android/internal/jank/InteractionJankMonitorTest.java6
-rw-r--r--core/tests/hdmitests/src/android/hardware/hdmi/HdmiAudioSystemClientTest.java4
-rw-r--r--data/etc/car/Android.bp9
-rw-r--r--data/etc/car/com.android.car.shell.xml22
-rw-r--r--graphics/java/android/graphics/Typeface.java61
-rw-r--r--graphics/java/android/graphics/fonts/SystemFonts.java13
-rw-r--r--libs/WindowManager/Shell/res/values-ar/strings.xml4
-rw-r--r--libs/WindowManager/Shell/res/values-be/strings_tv.xml2
-rw-r--r--libs/WindowManager/Shell/res/values-de/strings.xml18
-rw-r--r--libs/WindowManager/Shell/res/values-de/strings_tv.xml3
-rw-r--r--libs/WindowManager/Shell/res/values-ml/strings.xml18
-rw-r--r--libs/WindowManager/Shell/res/values-ml/strings_tv.xml3
-rw-r--r--libs/WindowManager/Shell/res/values-ur/strings.xml18
-rw-r--r--libs/WindowManager/Shell/res/values-ur/strings_tv.xml3
-rw-r--r--libs/WindowManager/Shell/res/values/config.xml6
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedController.java8
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedDisplayAreaOrganizer.java6
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedTutorialHandler.java7
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipBoundsState.java142
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipMotionHelper.java40
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipTouchHandler.java14
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/apppairs/AppPairsTest.kt4
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/helpers/BaseAppHelper.kt8
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipKeyboardTest.kt6
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/tv/TvPipTestBase.kt2
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/EnterSplitScreenTest.kt4
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/ExitSplitScreenTest.kt4
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/PipBoundsStateTest.java34
-rw-r--r--libs/androidfw/AssetManager2.cpp4
-rw-r--r--libs/hwui/jni/Typeface.cpp33
-rw-r--r--location/java/android/location/util/identity/CallerIdentity.java4
-rw-r--r--media/java/android/media/MediaPlayer.java4
-rw-r--r--media/java/android/media/Rating.java11
-rw-r--r--media/java/android/media/tv/tuner/Descrambler.java23
-rw-r--r--media/java/android/media/tv/tuner/filter/RecordSettings.java2
-rw-r--r--packages/CompanionDeviceManager/res/layout/buttons.xml5
-rw-r--r--packages/CompanionDeviceManager/res/layout/device_chooser.xml4
-rw-r--r--packages/CompanionDeviceManager/res/layout/device_confirmation.xml2
-rw-r--r--packages/CompanionDeviceManager/res/layout/profile_summary.xml30
-rw-r--r--packages/CompanionDeviceManager/res/layout/title.xml1
-rw-r--r--packages/CompanionDeviceManager/res/values/strings.xml18
-rw-r--r--packages/CompanionDeviceManager/src/com/android/companiondevicemanager/DeviceChooserActivity.java38
-rw-r--r--packages/CompanionDeviceManager/src/com/android/companiondevicemanager/DeviceDiscoveryService.java23
-rw-r--r--packages/InputDevices/res/values-mn/strings.xml4
-rw-r--r--packages/PackageInstaller/res/values-ne/strings.xml2
-rw-r--r--packages/PackageInstaller/res/values-pl/strings.xml2
-rw-r--r--packages/SettingsLib/Android.bp1
-rw-r--r--packages/SettingsLib/EmergencyNumber/Android.bp10
-rw-r--r--packages/SettingsLib/EmergencyNumber/AndroidManifest.xml23
-rw-r--r--packages/SettingsLib/EmergencyNumber/src/com/android/settingslib/emergencynumber/EmergencyNumberUtils.java133
-rw-r--r--packages/SettingsLib/res/values-af/strings.xml8
-rw-r--r--packages/SettingsLib/res/values-am/strings.xml8
-rw-r--r--packages/SettingsLib/res/values-ar/strings.xml8
-rw-r--r--packages/SettingsLib/res/values-as/strings.xml8
-rw-r--r--packages/SettingsLib/res/values-az/strings.xml8
-rw-r--r--packages/SettingsLib/res/values-b+sr+Latn/strings.xml8
-rw-r--r--packages/SettingsLib/res/values-be/strings.xml8
-rw-r--r--packages/SettingsLib/res/values-bg/strings.xml8
-rw-r--r--packages/SettingsLib/res/values-bn/strings.xml8
-rw-r--r--packages/SettingsLib/res/values-bs/strings.xml8
-rw-r--r--packages/SettingsLib/res/values-ca/strings.xml8
-rw-r--r--packages/SettingsLib/res/values-cs/strings.xml8
-rw-r--r--packages/SettingsLib/res/values-da/strings.xml8
-rw-r--r--packages/SettingsLib/res/values-de/strings.xml8
-rw-r--r--packages/SettingsLib/res/values-el/strings.xml8
-rw-r--r--packages/SettingsLib/res/values-en-rAU/strings.xml7
-rw-r--r--packages/SettingsLib/res/values-en-rCA/strings.xml7
-rw-r--r--packages/SettingsLib/res/values-en-rGB/strings.xml7
-rw-r--r--packages/SettingsLib/res/values-en-rIN/strings.xml7
-rw-r--r--packages/SettingsLib/res/values-en-rXC/strings.xml7
-rw-r--r--packages/SettingsLib/res/values-es-rUS/strings.xml8
-rw-r--r--packages/SettingsLib/res/values-es/strings.xml8
-rw-r--r--packages/SettingsLib/res/values-et/strings.xml8
-rw-r--r--packages/SettingsLib/res/values-eu/strings.xml8
-rw-r--r--packages/SettingsLib/res/values-fa/strings.xml8
-rw-r--r--packages/SettingsLib/res/values-fi/strings.xml8
-rw-r--r--packages/SettingsLib/res/values-fr-rCA/strings.xml12
-rw-r--r--packages/SettingsLib/res/values-fr/strings.xml8
-rw-r--r--packages/SettingsLib/res/values-gl/strings.xml8
-rw-r--r--packages/SettingsLib/res/values-gu/strings.xml11
-rw-r--r--packages/SettingsLib/res/values-hi/strings.xml8
-rw-r--r--packages/SettingsLib/res/values-hr/strings.xml8
-rw-r--r--packages/SettingsLib/res/values-hu/strings.xml8
-rw-r--r--packages/SettingsLib/res/values-hy/strings.xml8
-rw-r--r--packages/SettingsLib/res/values-in/strings.xml8
-rw-r--r--packages/SettingsLib/res/values-is/strings.xml8
-rw-r--r--packages/SettingsLib/res/values-it/strings.xml7
-rw-r--r--packages/SettingsLib/res/values-iw/strings.xml11
-rw-r--r--packages/SettingsLib/res/values-ja/strings.xml8
-rw-r--r--packages/SettingsLib/res/values-ka/strings.xml7
-rw-r--r--packages/SettingsLib/res/values-kk/strings.xml8
-rw-r--r--packages/SettingsLib/res/values-km/strings.xml8
-rw-r--r--packages/SettingsLib/res/values-kn/strings.xml8
-rw-r--r--packages/SettingsLib/res/values-ko/strings.xml8
-rw-r--r--packages/SettingsLib/res/values-ky/strings.xml8
-rw-r--r--packages/SettingsLib/res/values-lo/strings.xml8
-rw-r--r--packages/SettingsLib/res/values-lt/strings.xml8
-rw-r--r--packages/SettingsLib/res/values-lv/strings.xml8
-rw-r--r--packages/SettingsLib/res/values-mk/strings.xml16
-rw-r--r--packages/SettingsLib/res/values-ml/strings.xml8
-rw-r--r--packages/SettingsLib/res/values-mn/strings.xml8
-rw-r--r--packages/SettingsLib/res/values-mr/strings.xml8
-rw-r--r--packages/SettingsLib/res/values-ms/strings.xml8
-rw-r--r--packages/SettingsLib/res/values-my/strings.xml8
-rw-r--r--packages/SettingsLib/res/values-nb/strings.xml8
-rw-r--r--packages/SettingsLib/res/values-ne/strings.xml13
-rw-r--r--packages/SettingsLib/res/values-nl/strings.xml8
-rw-r--r--packages/SettingsLib/res/values-or/strings.xml11
-rw-r--r--packages/SettingsLib/res/values-pa/strings.xml11
-rw-r--r--packages/SettingsLib/res/values-pl/strings.xml10
-rw-r--r--packages/SettingsLib/res/values-pt-rBR/strings.xml7
-rw-r--r--packages/SettingsLib/res/values-pt-rPT/strings.xml7
-rw-r--r--packages/SettingsLib/res/values-pt/strings.xml7
-rw-r--r--packages/SettingsLib/res/values-ro/strings.xml8
-rw-r--r--packages/SettingsLib/res/values-ru/strings.xml8
-rw-r--r--packages/SettingsLib/res/values-si/strings.xml8
-rw-r--r--packages/SettingsLib/res/values-sk/strings.xml8
-rw-r--r--packages/SettingsLib/res/values-sl/strings.xml8
-rw-r--r--packages/SettingsLib/res/values-sq/strings.xml8
-rw-r--r--packages/SettingsLib/res/values-sr/strings.xml8
-rw-r--r--packages/SettingsLib/res/values-sv/strings.xml8
-rw-r--r--packages/SettingsLib/res/values-sw/strings.xml8
-rw-r--r--packages/SettingsLib/res/values-ta/strings.xml8
-rw-r--r--packages/SettingsLib/res/values-te/strings.xml8
-rw-r--r--packages/SettingsLib/res/values-th/strings.xml8
-rw-r--r--packages/SettingsLib/res/values-tl/strings.xml8
-rw-r--r--packages/SettingsLib/res/values-tr/strings.xml8
-rw-r--r--packages/SettingsLib/res/values-uk/strings.xml8
-rw-r--r--packages/SettingsLib/res/values-ur/strings.xml8
-rw-r--r--packages/SettingsLib/res/values-uz/strings.xml8
-rw-r--r--packages/SettingsLib/res/values-vi/strings.xml8
-rw-r--r--packages/SettingsLib/res/values-zh-rCN/strings.xml8
-rw-r--r--packages/SettingsLib/res/values-zh-rHK/strings.xml8
-rw-r--r--packages/SettingsLib/res/values-zh-rTW/strings.xml8
-rw-r--r--packages/SettingsLib/res/values-zu/strings.xml8
-rw-r--r--packages/SettingsLib/tests/robotests/src/com/android/settingslib/emergencynumber/EmergencyNumberUtilsTest.java124
-rw-r--r--packages/SystemUI/AndroidManifest.xml3
-rw-r--r--packages/SystemUI/plugin/src/com/android/systemui/plugins/FalsingManager.java42
-rw-r--r--packages/SystemUI/res-keyguard/layout/keyguard_clock_switch.xml22
-rw-r--r--packages/SystemUI/res-keyguard/values-af/strings.xml2
-rw-r--r--packages/SystemUI/res-keyguard/values-am/strings.xml2
-rw-r--r--packages/SystemUI/res-keyguard/values-ar/strings.xml2
-rw-r--r--packages/SystemUI/res-keyguard/values-as/strings.xml2
-rw-r--r--packages/SystemUI/res-keyguard/values-az/strings.xml2
-rw-r--r--packages/SystemUI/res-keyguard/values-b+sr+Latn/strings.xml2
-rw-r--r--packages/SystemUI/res-keyguard/values-be/strings.xml2
-rw-r--r--packages/SystemUI/res-keyguard/values-bg/strings.xml2
-rw-r--r--packages/SystemUI/res-keyguard/values-bn/strings.xml2
-rw-r--r--packages/SystemUI/res-keyguard/values-bs/strings.xml2
-rw-r--r--packages/SystemUI/res-keyguard/values-ca/strings.xml2
-rw-r--r--packages/SystemUI/res-keyguard/values-cs/strings.xml2
-rw-r--r--packages/SystemUI/res-keyguard/values-da/strings.xml2
-rw-r--r--packages/SystemUI/res-keyguard/values-de/strings.xml2
-rw-r--r--packages/SystemUI/res-keyguard/values-el/strings.xml2
-rw-r--r--packages/SystemUI/res-keyguard/values-en-rAU/strings.xml1
-rw-r--r--packages/SystemUI/res-keyguard/values-en-rCA/strings.xml1
-rw-r--r--packages/SystemUI/res-keyguard/values-en-rGB/strings.xml1
-rw-r--r--packages/SystemUI/res-keyguard/values-en-rIN/strings.xml1
-rw-r--r--packages/SystemUI/res-keyguard/values-en-rXC/strings.xml1
-rw-r--r--packages/SystemUI/res-keyguard/values-es-rUS/strings.xml2
-rw-r--r--packages/SystemUI/res-keyguard/values-es/strings.xml2
-rw-r--r--packages/SystemUI/res-keyguard/values-et/strings.xml2
-rw-r--r--packages/SystemUI/res-keyguard/values-eu/strings.xml2
-rw-r--r--packages/SystemUI/res-keyguard/values-fa/strings.xml2
-rw-r--r--packages/SystemUI/res-keyguard/values-fi/strings.xml2
-rw-r--r--packages/SystemUI/res-keyguard/values-fr-rCA/strings.xml2
-rw-r--r--packages/SystemUI/res-keyguard/values-fr/strings.xml2
-rw-r--r--packages/SystemUI/res-keyguard/values-gl/strings.xml2
-rw-r--r--packages/SystemUI/res-keyguard/values-gu/strings.xml2
-rw-r--r--packages/SystemUI/res-keyguard/values-hi/strings.xml2
-rw-r--r--packages/SystemUI/res-keyguard/values-hr/strings.xml2
-rw-r--r--packages/SystemUI/res-keyguard/values-hu/strings.xml2
-rw-r--r--packages/SystemUI/res-keyguard/values-hy/strings.xml2
-rw-r--r--packages/SystemUI/res-keyguard/values-in/strings.xml2
-rw-r--r--packages/SystemUI/res-keyguard/values-is/strings.xml2
-rw-r--r--packages/SystemUI/res-keyguard/values-it/strings.xml1
-rw-r--r--packages/SystemUI/res-keyguard/values-iw/strings.xml2
-rw-r--r--packages/SystemUI/res-keyguard/values-ja/strings.xml2
-rw-r--r--packages/SystemUI/res-keyguard/values-ka/strings.xml1
-rw-r--r--packages/SystemUI/res-keyguard/values-kk/strings.xml2
-rw-r--r--packages/SystemUI/res-keyguard/values-km/strings.xml2
-rw-r--r--packages/SystemUI/res-keyguard/values-kn/strings.xml2
-rw-r--r--packages/SystemUI/res-keyguard/values-ko/strings.xml2
-rw-r--r--packages/SystemUI/res-keyguard/values-ky/strings.xml2
-rw-r--r--packages/SystemUI/res-keyguard/values-lo/strings.xml2
-rw-r--r--packages/SystemUI/res-keyguard/values-lt/strings.xml2
-rw-r--r--packages/SystemUI/res-keyguard/values-lv/strings.xml2
-rw-r--r--packages/SystemUI/res-keyguard/values-mk/strings.xml2
-rw-r--r--packages/SystemUI/res-keyguard/values-ml/strings.xml2
-rw-r--r--packages/SystemUI/res-keyguard/values-mn/strings.xml2
-rw-r--r--packages/SystemUI/res-keyguard/values-mr/strings.xml2
-rw-r--r--packages/SystemUI/res-keyguard/values-ms/strings.xml2
-rw-r--r--packages/SystemUI/res-keyguard/values-my/strings.xml2
-rw-r--r--packages/SystemUI/res-keyguard/values-nb/strings.xml2
-rw-r--r--packages/SystemUI/res-keyguard/values-ne/strings.xml2
-rw-r--r--packages/SystemUI/res-keyguard/values-nl/strings.xml2
-rw-r--r--packages/SystemUI/res-keyguard/values-or/strings.xml2
-rw-r--r--packages/SystemUI/res-keyguard/values-pa/strings.xml2
-rw-r--r--packages/SystemUI/res-keyguard/values-pl/strings.xml2
-rw-r--r--packages/SystemUI/res-keyguard/values-pt-rBR/strings.xml1
-rw-r--r--packages/SystemUI/res-keyguard/values-pt-rPT/strings.xml1
-rw-r--r--packages/SystemUI/res-keyguard/values-pt/strings.xml1
-rw-r--r--packages/SystemUI/res-keyguard/values-ro/strings.xml2
-rw-r--r--packages/SystemUI/res-keyguard/values-ru/strings.xml2
-rw-r--r--packages/SystemUI/res-keyguard/values-si/strings.xml2
-rw-r--r--packages/SystemUI/res-keyguard/values-sk/strings.xml2
-rw-r--r--packages/SystemUI/res-keyguard/values-sl/strings.xml2
-rw-r--r--packages/SystemUI/res-keyguard/values-sq/strings.xml2
-rw-r--r--packages/SystemUI/res-keyguard/values-sr/strings.xml2
-rw-r--r--packages/SystemUI/res-keyguard/values-sv/strings.xml2
-rw-r--r--packages/SystemUI/res-keyguard/values-sw/strings.xml2
-rw-r--r--packages/SystemUI/res-keyguard/values-ta/strings.xml2
-rw-r--r--packages/SystemUI/res-keyguard/values-te/strings.xml2
-rw-r--r--packages/SystemUI/res-keyguard/values-th/strings.xml2
-rw-r--r--packages/SystemUI/res-keyguard/values-tl/strings.xml2
-rw-r--r--packages/SystemUI/res-keyguard/values-tr/strings.xml2
-rw-r--r--packages/SystemUI/res-keyguard/values-uk/strings.xml2
-rw-r--r--packages/SystemUI/res-keyguard/values-ur/strings.xml2
-rw-r--r--packages/SystemUI/res-keyguard/values-uz/strings.xml2
-rw-r--r--packages/SystemUI/res-keyguard/values-vi/strings.xml2
-rw-r--r--packages/SystemUI/res-keyguard/values-zh-rCN/strings.xml2
-rw-r--r--packages/SystemUI/res-keyguard/values-zh-rHK/strings.xml2
-rw-r--r--packages/SystemUI/res-keyguard/values-zh-rTW/strings.xml2
-rw-r--r--packages/SystemUI/res-keyguard/values-zu/strings.xml2
-rw-r--r--packages/SystemUI/res-product/values-de/strings.xml2
-rw-r--r--packages/SystemUI/res-product/values-pl/strings.xml8
-rw-r--r--packages/SystemUI/res/layout/super_notification_shade.xml3
-rw-r--r--packages/SystemUI/res/values-fr-rCA/strings.xml2
-rw-r--r--packages/SystemUI/res/values-kk/strings.xml10
-rw-r--r--packages/SystemUI/res/values-mn/strings.xml6
-rw-r--r--packages/SystemUI/res/values-ne/strings.xml4
-rw-r--r--packages/SystemUI/res/values-pl/strings.xml12
-rw-r--r--packages/SystemUI/res/values-television/config.xml3
-rw-r--r--packages/SystemUI/res/values/config.xml3
-rw-r--r--packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java33
-rw-r--r--packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitchController.java8
-rw-r--r--packages/SystemUI/src/com/android/keyguard/KeyguardStatusView.java7
-rw-r--r--packages/SystemUI/src/com/android/keyguard/KeyguardStatusViewController.java7
-rw-r--r--packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java12
-rw-r--r--packages/SystemUI/src/com/android/systemui/SwipeHelper.java111
-rw-r--r--packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java1
-rw-r--r--packages/SystemUI/src/com/android/systemui/classifier/AccelerationClassifier.java99
-rw-r--r--packages/SystemUI/src/com/android/systemui/classifier/AnglesClassifier.java207
-rw-r--r--packages/SystemUI/src/com/android/systemui/classifier/AnglesPercentageEvaluator.java28
-rw-r--r--packages/SystemUI/src/com/android/systemui/classifier/AnglesVarianceEvaluator.java28
-rw-r--r--packages/SystemUI/src/com/android/systemui/classifier/Classifier.java5
-rw-r--r--packages/SystemUI/src/com/android/systemui/classifier/ClassifierData.java101
-rw-r--r--packages/SystemUI/src/com/android/systemui/classifier/DirectionClassifier.java39
-rw-r--r--packages/SystemUI/src/com/android/systemui/classifier/DirectionEvaluator.java56
-rw-r--r--packages/SystemUI/src/com/android/systemui/classifier/DurationCountClassifier.java36
-rw-r--r--packages/SystemUI/src/com/android/systemui/classifier/DurationCountEvaluator.java30
-rw-r--r--packages/SystemUI/src/com/android/systemui/classifier/EndPointLengthClassifier.java35
-rw-r--r--packages/SystemUI/src/com/android/systemui/classifier/EndPointLengthEvaluator.java30
-rw-r--r--packages/SystemUI/src/com/android/systemui/classifier/EndPointRatioClassifier.java43
-rw-r--r--packages/SystemUI/src/com/android/systemui/classifier/EndPointRatioEvaluator.java30
-rw-r--r--packages/SystemUI/src/com/android/systemui/classifier/FalsingLog.java169
-rw-r--r--packages/SystemUI/src/com/android/systemui/classifier/FalsingManagerFake.java29
-rw-r--r--packages/SystemUI/src/com/android/systemui/classifier/FalsingManagerImpl.java579
-rw-r--r--packages/SystemUI/src/com/android/systemui/classifier/FalsingManagerProxy.java105
-rw-r--r--packages/SystemUI/src/com/android/systemui/classifier/GestureClassifier.java32
-rw-r--r--packages/SystemUI/src/com/android/systemui/classifier/HistoryEvaluator.java117
-rw-r--r--packages/SystemUI/src/com/android/systemui/classifier/HumanInteractionClassifier.java241
-rw-r--r--packages/SystemUI/src/com/android/systemui/classifier/LengthCountClassifier.java40
-rw-r--r--packages/SystemUI/src/com/android/systemui/classifier/LengthCountEvaluator.java34
-rw-r--r--packages/SystemUI/src/com/android/systemui/classifier/Point.java83
-rw-r--r--packages/SystemUI/src/com/android/systemui/classifier/PointerCountClassifier.java53
-rw-r--r--packages/SystemUI/src/com/android/systemui/classifier/ProximityClassifier.java98
-rw-r--r--packages/SystemUI/src/com/android/systemui/classifier/ProximityEvaluator.java29
-rw-r--r--packages/SystemUI/src/com/android/systemui/classifier/SpeedAnglesClassifier.java164
-rw-r--r--packages/SystemUI/src/com/android/systemui/classifier/SpeedAnglesPercentageEvaluator.java27
-rw-r--r--packages/SystemUI/src/com/android/systemui/classifier/SpeedClassifier.java42
-rw-r--r--packages/SystemUI/src/com/android/systemui/classifier/SpeedEvaluator.java28
-rw-r--r--packages/SystemUI/src/com/android/systemui/classifier/SpeedRatioEvaluator.java29
-rw-r--r--packages/SystemUI/src/com/android/systemui/classifier/SpeedVarianceEvaluator.java28
-rw-r--r--packages/SystemUI/src/com/android/systemui/classifier/Stroke.java79
-rw-r--r--packages/SystemUI/src/com/android/systemui/classifier/StrokeClassifier.java31
-rw-r--r--packages/SystemUI/src/com/android/systemui/classifier/brightline/BrightLineFalsingManager.java59
-rw-r--r--packages/SystemUI/src/com/android/systemui/classifier/brightline/DoubleTapClassifier.java106
-rw-r--r--packages/SystemUI/src/com/android/systemui/classifier/brightline/FalsingClassifier.java7
-rw-r--r--packages/SystemUI/src/com/android/systemui/classifier/brightline/FalsingDataProvider.java30
-rw-r--r--packages/SystemUI/src/com/android/systemui/classifier/brightline/SingleTapClassifier.java68
-rw-r--r--packages/SystemUI/src/com/android/systemui/classifier/brightline/TimeLimitedMotionEventBuffer.java18
-rw-r--r--packages/SystemUI/src/com/android/systemui/controls/controller/ControlsControllerImpl.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java14
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/QSContainerImpl.java24
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/QSFragment.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/QSPanel.java17
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/QSPanelControllerBase.java10
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/QuickQSPanel.java16
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/QuickQSPanelController.java10
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java5
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/NotificationHeaderUtil.java16
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ActivatableNotificationViewController.java56
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java8
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentView.java8
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationMenuRow.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationHeaderViewWrapper.java5
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/AmbientState.java14
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java107
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java28
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/DoubleTapHelper.java176
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationTapHelper.java163
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java8
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java47
-rw-r--r--packages/SystemUI/src/com/android/systemui/util/InjectionInflationController.java12
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/classifier/FalsingManagerProxyTest.java128
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/classifier/brightline/BrightLineFalsingManagerTest.java18
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/classifier/brightline/ClassifierTest.java4
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/classifier/brightline/DoubleTapClassifierTest.java182
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/classifier/brightline/FalsingDataProviderTest.java4
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/classifier/brightline/SingleTapClassifierTest.java159
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/classifier/brightline/TimeLimitedMotionEventBufferTest.java108
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelControllerBaseTest.java4
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelTest.java26
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/qs/QuickQSPanelControllerTest.kt111
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationMenuRowTest.java17
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationTapHelperTest.java (renamed from packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/DoubleTapHelperTest.java)150
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java2
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/util/time/FakeSystemClock.java42
-rw-r--r--services/core/Android.bp1
-rw-r--r--services/core/java/android/content/pm/PackageManagerInternal.java6
-rw-r--r--services/core/java/com/android/server/BatteryService.java26
-rw-r--r--services/core/java/com/android/server/ConnectivityService.java53
-rw-r--r--services/core/java/com/android/server/GestureLauncherService.java40
-rw-r--r--services/core/java/com/android/server/SystemServiceManager.java7
-rw-r--r--services/core/java/com/android/server/TelephonyRegistry.java840
-rw-r--r--services/core/java/com/android/server/VcnManagementService.java10
-rw-r--r--services/core/java/com/android/server/am/ActiveUids.java5
-rw-r--r--services/core/java/com/android/server/am/BatteryStatsService.java18
-rw-r--r--services/core/java/com/android/server/appop/AppOpsService.java35
-rw-r--r--services/core/java/com/android/server/appop/TEST_MAPPING4
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/face/aidl/AidlNativeHandleUtils.java77
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceEnrollClient.java23
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceProvider.java2
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/face/hidl/Face10.java19
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintEnrollClient.java4
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintEnrollClient.java2
-rw-r--r--services/core/java/com/android/server/camera/CameraServiceProxy.java255
-rw-r--r--services/core/java/com/android/server/connectivity/Vpn.java3
-rw-r--r--services/core/java/com/android/server/devicestate/DeviceStateManagerService.java2
-rw-r--r--services/core/java/com/android/server/display/DisplayGroup.java14
-rw-r--r--services/core/java/com/android/server/display/DisplayManagerService.java7
-rw-r--r--services/core/java/com/android/server/display/LogicalDisplayMapper.java20
-rw-r--r--services/core/java/com/android/server/hdmi/Constants.java9
-rwxr-xr-xservices/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java3
-rw-r--r--services/core/java/com/android/server/hdmi/HdmiCecLocalDevicePlayback.java19
-rw-r--r--services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceSource.java69
-rw-r--r--services/core/java/com/android/server/hdmi/HdmiCecMessageBuilder.java8
-rw-r--r--services/core/java/com/android/server/hdmi/HdmiCecMessageValidator.java2
-rw-r--r--services/core/java/com/android/server/hdmi/HdmiCecPowerStatusController.java84
-rw-r--r--services/core/java/com/android/server/hdmi/HdmiControlService.java86
-rw-r--r--services/core/java/com/android/server/hdmi/cec_key_handling.md14
-rw-r--r--services/core/java/com/android/server/inputmethod/InputMethodManagerService.java44
-rw-r--r--services/core/java/com/android/server/location/geofence/GeofenceManager.java28
-rw-r--r--services/core/java/com/android/server/location/gnss/GnssListenerMultiplexer.java29
-rw-r--r--services/core/java/com/android/server/location/gnss/GnssLocationProvider.java6
-rw-r--r--services/core/java/com/android/server/location/injector/SystemUserInfoHelper.java24
-rw-r--r--services/core/java/com/android/server/location/injector/UserInfoHelper.java6
-rw-r--r--services/core/java/com/android/server/location/provider/LocationProviderManager.java53
-rwxr-xr-xservices/core/java/com/android/server/notification/NotificationManagerService.java10
-rw-r--r--services/core/java/com/android/server/pm/PackageManagerService.java247
-rw-r--r--services/core/java/com/android/server/pm/PackageProperty.java287
-rw-r--r--services/core/java/com/android/server/pm/permission/Permission.java11
-rw-r--r--services/core/java/com/android/server/pm/permission/PermissionManagerService.java287
-rw-r--r--services/core/java/com/android/server/pm/permission/PermissionManagerServiceInternal.java94
-rw-r--r--services/core/java/com/android/server/policy/DeviceStatePolicyImpl.java7
-rw-r--r--services/core/java/com/android/server/policy/DeviceStateProviderImpl.java456
-rw-r--r--services/core/java/com/android/server/power/DisplayPowerRequestMapper.java122
-rw-r--r--services/core/java/com/android/server/power/PowerManagerService.java76
-rw-r--r--services/core/java/com/android/server/vcn/UnderlyingNetworkTracker.java100
-rw-r--r--services/core/java/com/android/server/vcn/Vcn.java96
-rw-r--r--services/core/java/com/android/server/vcn/VcnContext.java60
-rw-r--r--services/core/java/com/android/server/vcn/VcnGatewayConnection.java84
-rw-r--r--services/core/java/com/android/server/wm/ActivityRecord.java40
-rw-r--r--services/core/java/com/android/server/wm/ActivityStarter.java18
-rw-r--r--services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java1
-rw-r--r--services/core/java/com/android/server/wm/ActivityTaskManagerService.java29
-rw-r--r--services/core/java/com/android/server/wm/ActivityTaskSupervisor.java37
-rw-r--r--services/core/java/com/android/server/wm/DisplayContent.java14
-rw-r--r--services/core/java/com/android/server/wm/ImpressionAttestationController.java13
-rw-r--r--services/core/java/com/android/server/wm/MirrorActiveUids.java61
-rw-r--r--services/core/java/com/android/server/wm/RecentsAnimation.java9
-rw-r--r--services/core/java/com/android/server/wm/RootWindowContainer.java32
-rw-r--r--services/core/java/com/android/server/wm/Task.java27
-rw-r--r--services/core/java/com/android/server/wm/VisibleActivityProcessTracker.java26
-rw-r--r--services/core/java/com/android/server/wm/WindowAnimator.java3
-rw-r--r--services/core/java/com/android/server/wm/WindowContainer.java2
-rw-r--r--services/core/java/com/android/server/wm/WindowManagerService.java15
-rw-r--r--services/core/java/com/android/server/wm/WindowProcessController.java13
-rw-r--r--services/core/java/com/android/server/wm/WindowState.java22
-rw-r--r--services/core/xsd/Android.bp7
-rw-r--r--services/core/xsd/device-state-config/device-state-config.xsd78
-rw-r--r--services/core/xsd/device-state-config/schema/current.txt61
-rw-r--r--services/core/xsd/device-state-config/schema/last_current.txt0
-rw-r--r--services/core/xsd/device-state-config/schema/last_removed.txt0
-rw-r--r--services/core/xsd/device-state-config/schema/removed.txt1
-rw-r--r--services/incremental/IncrementalService.cpp3
-rw-r--r--services/tests/mockingservicestests/src/com/android/server/job/controllers/QuotaControllerTest.java3
-rw-r--r--services/tests/mockingservicestests/src/com/android/server/location/injector/FakeUserInfoHelper.java5
-rw-r--r--services/tests/servicestests/Android.bp1
-rw-r--r--services/tests/servicestests/src/com/android/server/GestureLauncherServiceTest.java33
-rw-r--r--services/tests/servicestests/src/com/android/server/appsearch/external/localstorage/AppSearchImplTest.java736
-rw-r--r--services/tests/servicestests/src/com/android/server/appsearch/external/localstorage/VisibilityStoreTest.java74
-rw-r--r--services/tests/servicestests/src/com/android/server/appsearch/external/localstorage/converter/GenericDocumentToProtoConverterTest.java65
-rw-r--r--services/tests/servicestests/src/com/android/server/appsearch/external/localstorage/converter/SchemaToProtoConverterTest.java184
-rw-r--r--services/tests/servicestests/src/com/android/server/appsearch/external/localstorage/converter/SnippetTest.java228
-rw-r--r--services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDevicePlaybackTest.java87
-rw-r--r--services/tests/servicestests/src/com/android/server/hdmi/HdmiCecMessageBuilderTest.java17
-rw-r--r--services/tests/servicestests/src/com/android/server/hdmi/HdmiCecMessageValidatorTest.java2
-rw-r--r--services/tests/servicestests/src/com/android/server/hdmi/HdmiCecPowerStatusControllerTest.java264
-rw-r--r--services/tests/servicestests/src/com/android/server/hdmi/HdmiControlServiceTest.java46
-rw-r--r--services/tests/servicestests/src/com/android/server/pm/PackageParserTest.java249
-rw-r--r--services/tests/servicestests/src/com/android/server/policy/DeviceStateProviderImplTest.java289
-rw-r--r--services/tests/servicestests/test-apps/PackageParserApp/Android.bp14
-rw-r--r--services/tests/servicestests/test-apps/PackageParserApp/AndroidManifestApp4.xml65
-rw-r--r--services/tests/servicestests/test-apps/PackageParserApp/res/values/values.xml8
-rw-r--r--services/tests/servicestests/test-apps/PackageParserApp/res/xml/xml_property.xml20
-rw-r--r--services/tests/servicestests/test-apps/PackageParserApp/src/com/android/servicestests/apps/packageparserapp/MyProvider.java57
-rw-r--r--services/tests/uiservicestests/src/com/android/server/notification/BuzzBeepBlinkTest.java75
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java26
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/RootWindowContainerTests.java57
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java34
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java5
-rw-r--r--telephony/java/android/telephony/Annotation.java11
-rw-r--r--telephony/java/android/telephony/DataThrottlingRequest.aidl19
-rw-r--r--telephony/java/android/telephony/DataThrottlingRequest.java244
-rw-r--r--telephony/java/android/telephony/PhoneCapability.java1
-rw-r--r--telephony/java/android/telephony/PhysicalChannelConfig.java12
-rw-r--r--telephony/java/android/telephony/RadioInterfaceCapabilities.java53
-rw-r--r--telephony/java/android/telephony/TelephonyManager.java240
-rw-r--r--telephony/java/android/telephony/ThermalMitigationRequest.aidl (renamed from packages/SystemUI/src/com/android/systemui/classifier/PointerCountEvaluator.java)12
-rw-r--r--telephony/java/android/telephony/ThermalMitigationRequest.java248
-rw-r--r--telephony/java/android/telephony/data/DataCallResponse.java10
-rw-r--r--telephony/java/android/telephony/ims/DelegateRequest.java5
-rw-r--r--telephony/java/android/telephony/ims/SipDelegateManager.java21
-rw-r--r--telephony/java/android/telephony/ims/aidl/IImsRcsController.aidl2
-rw-r--r--telephony/java/android/telephony/ims/aidl/ISipTransport.aidl2
-rw-r--r--telephony/java/android/telephony/ims/stub/SipTransportImplBase.java17
-rw-r--r--telephony/java/com/android/internal/telephony/ITelephony.aidl21
-rw-r--r--telephony/java/com/android/internal/telephony/RILConstants.java3
-rw-r--r--tests/BatteryStatsPerfTest/Android.bp25
-rw-r--r--tests/BatteryStatsPerfTest/AndroidManifest.xml27
-rw-r--r--tests/BatteryStatsPerfTest/AndroidTest.xml28
-rw-r--r--tests/BatteryStatsPerfTest/src/com/android/internal/os/BatteryStatsHelperPerfTest.java135
-rw-r--r--tests/FlickerTests/AndroidManifest.xml2
-rw-r--r--tests/SurfaceViewBufferTests/Android.bp3
-rw-r--r--tests/SurfaceViewBufferTests/AndroidManifest.xml11
-rw-r--r--tests/SurfaceViewBufferTests/cpp/SurfaceProxy.cpp127
-rw-r--r--tests/SurfaceViewBufferTests/src/com/android/test/BufferPresentationTests.kt93
-rw-r--r--tests/SurfaceViewBufferTests/src/com/android/test/BufferRejectionTests.kt151
-rw-r--r--tests/SurfaceViewBufferTests/src/com/android/test/GeometryTests.kt122
-rw-r--r--tests/SurfaceViewBufferTests/src/com/android/test/InverseDisplayTransformTests.kt76
-rw-r--r--tests/SurfaceViewBufferTests/src/com/android/test/MainActivity.kt49
-rw-r--r--tests/SurfaceViewBufferTests/src/com/android/test/ScreenRecordTestBase.kt83
-rw-r--r--tests/SurfaceViewBufferTests/src/com/android/test/SharedBufferModeScreenRecordTests.kt67
-rw-r--r--tests/SurfaceViewBufferTests/src/com/android/test/SharedBufferModeTests.kt89
-rw-r--r--tests/SurfaceViewBufferTests/src/com/android/test/SurfaceProxy.kt31
-rw-r--r--tests/SurfaceViewBufferTests/src/com/android/test/SurfaceTracingTestBase.kt112
-rw-r--r--tests/SurfaceViewBufferTests/src/com/android/test/SurfaceViewBufferTest.kt185
-rw-r--r--tests/SurfaceViewBufferTests/src/com/android/test/SurfaceViewBufferTestBase.kt97
-rw-r--r--tests/TaskOrganizerTest/src/com/android/test/taskembed/ResizeTasksSyncTest.kt11
-rw-r--r--tests/net/integration/src/com/android/server/net/integrationtests/ConnectivityServiceIntegrationTest.kt5
-rw-r--r--tests/net/integration/util/com/android/server/NetworkAgentWrapper.java6
-rw-r--r--tests/net/integration/util/com/android/server/TestNetIdManager.kt1
-rw-r--r--tests/net/java/com/android/server/ConnectivityServiceTest.java743
-rw-r--r--tools/aapt2/cmd/Link.cpp107
-rw-r--r--tools/aapt2/link/ManifestFixer.cpp17
-rw-r--r--tools/aapt2/util/Util.cpp17
-rw-r--r--tools/aapt2/util/Util.h10
-rw-r--r--tools/aapt2/util/Util_test.cpp33
-rw-r--r--tools/aapt2/xml/XmlActionExecutor.cpp29
-rw-r--r--tools/aapt2/xml/XmlActionExecutor.h5
-rw-r--r--wifi/java/android/net/wifi/SoftApConfiguration.java2
674 files changed, 16660 insertions, 9795 deletions
diff --git a/Android.bp b/Android.bp
index aa94d2236084..8164d6a477e4 100644
--- a/Android.bp
+++ b/Android.bp
@@ -528,6 +528,7 @@ java_library {
"android.hardware.vibrator-V1.3-java",
"android.system.keystore2-java",
"android.system.suspend.control.internal-java",
+ "cameraprotosnano",
"devicepolicyprotosnano",
"com.android.sysprop.apex",
diff --git a/apct-tests/perftests/core/src/android/graphics/perftests/TypefaceSerializationPerfTest.java b/apct-tests/perftests/core/src/android/graphics/perftests/TypefaceSerializationPerfTest.java
new file mode 100644
index 000000000000..547369055e95
--- /dev/null
+++ b/apct-tests/perftests/core/src/android/graphics/perftests/TypefaceSerializationPerfTest.java
@@ -0,0 +1,83 @@
+/*
+ * 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.graphics.perftests;
+
+import android.graphics.Typeface;
+import android.os.SharedMemory;
+import android.perftests.utils.BenchmarkState;
+import android.perftests.utils.PerfStatusReporter;
+
+import androidx.test.filters.LargeTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.util.Map;
+
+@LargeTest
+@RunWith(AndroidJUnit4.class)
+public class TypefaceSerializationPerfTest {
+
+ @Rule
+ public PerfStatusReporter mPerfStatusReporter = new PerfStatusReporter();
+
+ @Test
+ public void testSerializeFontMap() throws Exception {
+ Map<String, Typeface> systemFontMap = Typeface.getSystemFontMap();
+ BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+
+ while (state.keepRunning()) {
+ Typeface.serializeFontMap(systemFontMap);
+ }
+ }
+
+ @Test
+ public void testDeserializeFontMap() throws Exception {
+ SharedMemory memory = Typeface.serializeFontMap(Typeface.getSystemFontMap());
+ ByteBuffer buffer = memory.mapReadOnly().order(ByteOrder.BIG_ENDIAN);
+ BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+
+ while (state.keepRunning()) {
+ buffer.position(0);
+ Typeface.deserializeFontMap(buffer);
+ }
+ }
+
+ @Test
+ public void testSetSystemFontMap() throws Exception {
+ SharedMemory memory = null;
+ BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+
+ while (state.keepRunning()) {
+ state.pauseTiming();
+ // Explicitly destroy lazy-loaded typefaces, so that we don't hit the mmap limit
+ // (max_map_count).
+ Typeface.destroySystemFontMap();
+ Typeface.loadPreinstalledSystemFontMap();
+ if (memory != null) {
+ memory.close();
+ }
+ memory = Typeface.serializeFontMap(Typeface.getSystemFontMap());
+ state.resumeTiming();
+ Typeface.setSystemFontMap(memory);
+ }
+ }
+}
diff --git a/apex/appsearch/framework/api/current.txt b/apex/appsearch/framework/api/current.txt
index d802177e249b..2be873cc8bca 100644
--- a/apex/appsearch/framework/api/current.txt
+++ b/apex/appsearch/framework/api/current.txt
@@ -1 +1,143 @@
// Signature format: 2.0
+package android.app.appsearch {
+
+ public final class AppSearchSchema {
+ method @NonNull public java.util.List<android.app.appsearch.AppSearchSchema.PropertyConfig> getProperties();
+ method @NonNull public String getSchemaType();
+ }
+
+ public static final class AppSearchSchema.Builder {
+ ctor public AppSearchSchema.Builder(@NonNull String);
+ method @NonNull public android.app.appsearch.AppSearchSchema.Builder addProperty(@NonNull android.app.appsearch.AppSearchSchema.PropertyConfig);
+ method @NonNull public android.app.appsearch.AppSearchSchema build();
+ }
+
+ public static final class AppSearchSchema.PropertyConfig {
+ method public int getCardinality();
+ method public int getDataType();
+ method public int getIndexingType();
+ method @NonNull public String getName();
+ method @Nullable public String getSchemaType();
+ method public int getTokenizerType();
+ field public static final int CARDINALITY_OPTIONAL = 2; // 0x2
+ field public static final int CARDINALITY_REPEATED = 1; // 0x1
+ field public static final int CARDINALITY_REQUIRED = 3; // 0x3
+ field public static final int DATA_TYPE_BOOLEAN = 4; // 0x4
+ field public static final int DATA_TYPE_BYTES = 5; // 0x5
+ field public static final int DATA_TYPE_DOCUMENT = 6; // 0x6
+ field public static final int DATA_TYPE_DOUBLE = 3; // 0x3
+ field public static final int DATA_TYPE_INT64 = 2; // 0x2
+ field public static final int DATA_TYPE_STRING = 1; // 0x1
+ field public static final int INDEXING_TYPE_EXACT_TERMS = 1; // 0x1
+ field public static final int INDEXING_TYPE_NONE = 0; // 0x0
+ field public static final int INDEXING_TYPE_PREFIXES = 2; // 0x2
+ field public static final int TOKENIZER_TYPE_NONE = 0; // 0x0
+ field public static final int TOKENIZER_TYPE_PLAIN = 1; // 0x1
+ }
+
+ public static final class AppSearchSchema.PropertyConfig.Builder {
+ ctor public AppSearchSchema.PropertyConfig.Builder(@NonNull String);
+ method @NonNull public android.app.appsearch.AppSearchSchema.PropertyConfig build();
+ method @NonNull public android.app.appsearch.AppSearchSchema.PropertyConfig.Builder setCardinality(int);
+ method @NonNull public android.app.appsearch.AppSearchSchema.PropertyConfig.Builder setDataType(int);
+ method @NonNull public android.app.appsearch.AppSearchSchema.PropertyConfig.Builder setIndexingType(int);
+ method @NonNull public android.app.appsearch.AppSearchSchema.PropertyConfig.Builder setSchemaType(@NonNull String);
+ method @NonNull public android.app.appsearch.AppSearchSchema.PropertyConfig.Builder setTokenizerType(int);
+ }
+
+ public class GenericDocument {
+ ctor protected GenericDocument(@NonNull android.app.appsearch.GenericDocument);
+ method public long getCreationTimestampMillis();
+ method public static int getMaxIndexedProperties();
+ method @NonNull public String getNamespace();
+ method public boolean getPropertyBoolean(@NonNull String);
+ method @Nullable public boolean[] getPropertyBooleanArray(@NonNull String);
+ method @Nullable public byte[] getPropertyBytes(@NonNull String);
+ method @Nullable public byte[][] getPropertyBytesArray(@NonNull String);
+ method @Nullable public android.app.appsearch.GenericDocument getPropertyDocument(@NonNull String);
+ method @Nullable public android.app.appsearch.GenericDocument[] getPropertyDocumentArray(@NonNull String);
+ method public double getPropertyDouble(@NonNull String);
+ method @Nullable public double[] getPropertyDoubleArray(@NonNull String);
+ method public long getPropertyLong(@NonNull String);
+ method @Nullable public long[] getPropertyLongArray(@NonNull String);
+ method @NonNull public java.util.Set<java.lang.String> getPropertyNames();
+ method @Nullable public String getPropertyString(@NonNull String);
+ method @Nullable public String[] getPropertyStringArray(@NonNull String);
+ method @NonNull public String getSchemaType();
+ method public int getScore();
+ method public long getTtlMillis();
+ method @NonNull public String getUri();
+ field public static final String DEFAULT_NAMESPACE = "";
+ }
+
+ public static class GenericDocument.Builder<BuilderType extends android.app.appsearch.GenericDocument.Builder> {
+ ctor public GenericDocument.Builder(@NonNull String, @NonNull String);
+ method @NonNull public android.app.appsearch.GenericDocument build();
+ method @NonNull public BuilderType setCreationTimestampMillis(long);
+ method @NonNull public BuilderType setNamespace(@NonNull String);
+ method @NonNull public BuilderType setPropertyBoolean(@NonNull String, @NonNull boolean...);
+ method @NonNull public BuilderType setPropertyBytes(@NonNull String, @NonNull byte[]...);
+ method @NonNull public BuilderType setPropertyDocument(@NonNull String, @NonNull android.app.appsearch.GenericDocument...);
+ method @NonNull public BuilderType setPropertyDouble(@NonNull String, @NonNull double...);
+ method @NonNull public BuilderType setPropertyLong(@NonNull String, @NonNull long...);
+ method @NonNull public BuilderType setPropertyString(@NonNull String, @NonNull java.lang.String...);
+ method @NonNull public BuilderType setScore(@IntRange(from=0, to=java.lang.Integer.MAX_VALUE) int);
+ method @NonNull public BuilderType setTtlMillis(long);
+ }
+
+ public final class SearchResult {
+ method @NonNull public android.app.appsearch.GenericDocument getDocument();
+ method @NonNull public java.util.List<android.app.appsearch.SearchResult.MatchInfo> getMatches();
+ }
+
+ public static final class SearchResult.MatchInfo {
+ method @NonNull public CharSequence getExactMatch();
+ method @NonNull public android.app.appsearch.SearchResult.MatchRange getExactMatchPosition();
+ method @NonNull public String getFullText();
+ method @NonNull public String getPropertyPath();
+ method @NonNull public CharSequence getSnippet();
+ method @NonNull public android.app.appsearch.SearchResult.MatchRange getSnippetPosition();
+ }
+
+ public static final class SearchResult.MatchRange {
+ method public int getEnd();
+ method public int getStart();
+ }
+
+ public final class SearchSpec {
+ method public int getMaxSnippetSize();
+ method @NonNull public java.util.List<java.lang.String> getNamespaces();
+ method public int getOrder();
+ method public int getRankingStrategy();
+ method public int getResultCountPerPage();
+ method @NonNull public java.util.List<java.lang.String> getSchemaTypes();
+ method public int getSnippetCount();
+ method public int getSnippetCountPerProperty();
+ method public int getTermMatch();
+ field public static final int ORDER_ASCENDING = 1; // 0x1
+ field public static final int ORDER_DESCENDING = 0; // 0x0
+ field public static final int RANKING_STRATEGY_CREATION_TIMESTAMP = 2; // 0x2
+ field public static final int RANKING_STRATEGY_DOCUMENT_SCORE = 1; // 0x1
+ field public static final int RANKING_STRATEGY_NONE = 0; // 0x0
+ field public static final int TERM_MATCH_EXACT_ONLY = 1; // 0x1
+ field public static final int TERM_MATCH_PREFIX = 2; // 0x2
+ }
+
+ public static final class SearchSpec.Builder {
+ ctor public SearchSpec.Builder();
+ method @NonNull public android.app.appsearch.SearchSpec.Builder addNamespace(@NonNull java.lang.String...);
+ method @NonNull public android.app.appsearch.SearchSpec.Builder addNamespace(@NonNull java.util.Collection<java.lang.String>);
+ method @NonNull public android.app.appsearch.SearchSpec.Builder addSchemaType(@NonNull java.lang.String...);
+ method @NonNull public android.app.appsearch.SearchSpec.Builder addSchemaType(@NonNull java.util.Collection<java.lang.String>);
+ method @NonNull public android.app.appsearch.SearchSpec build();
+ method @NonNull public android.app.appsearch.SearchSpec.Builder setMaxSnippetSize(@IntRange(from=0, to=android.app.appsearch.SearchSpec.MAX_SNIPPET_SIZE_LIMIT) int);
+ method @NonNull public android.app.appsearch.SearchSpec.Builder setOrder(int);
+ method @NonNull public android.app.appsearch.SearchSpec.Builder setRankingStrategy(int);
+ method @NonNull public android.app.appsearch.SearchSpec.Builder setResultCountPerPage(@IntRange(from=0, to=android.app.appsearch.SearchSpec.MAX_NUM_PER_PAGE) int);
+ method @NonNull public android.app.appsearch.SearchSpec.Builder setSnippetCount(@IntRange(from=0, to=android.app.appsearch.SearchSpec.MAX_SNIPPET_COUNT) int);
+ method @NonNull public android.app.appsearch.SearchSpec.Builder setSnippetCountPerProperty(@IntRange(from=0, to=android.app.appsearch.SearchSpec.MAX_SNIPPET_PER_PROPERTY_COUNT) int);
+ method @NonNull public android.app.appsearch.SearchSpec.Builder setTermMatch(int);
+ }
+
+}
+
diff --git a/apex/appsearch/framework/java/android/app/appsearch/AppSearchEmail.java b/apex/appsearch/framework/java/android/app/appsearch/AppSearchEmail.java
index beb9ad3d27ea..9ca363ed9008 100644
--- a/apex/appsearch/framework/java/android/app/appsearch/AppSearchEmail.java
+++ b/apex/appsearch/framework/java/android/app/appsearch/AppSearchEmail.java
@@ -16,10 +16,8 @@
package android.app.appsearch;
-
import android.annotation.NonNull;
import android.annotation.Nullable;
-
import android.app.appsearch.AppSearchSchema.PropertyConfig;
/**
@@ -29,9 +27,8 @@ import android.app.appsearch.AppSearchSchema.PropertyConfig;
*
* @hide
*/
-
public class AppSearchEmail extends GenericDocument {
- /** The name of the schema type for {@link AppSearchEmail} documents.*/
+ /** The name of the schema type for {@link AppSearchEmail} documents. */
public static final String SCHEMA_TYPE = "builtin:Email";
private static final String KEY_FROM = "from";
@@ -41,54 +38,55 @@ public class AppSearchEmail extends GenericDocument {
private static final String KEY_SUBJECT = "subject";
private static final String KEY_BODY = "body";
- public static final AppSearchSchema SCHEMA = new AppSearchSchema.Builder(SCHEMA_TYPE)
- .addProperty(new PropertyConfig.Builder(KEY_FROM)
- .setDataType(PropertyConfig.DATA_TYPE_STRING)
- .setCardinality(PropertyConfig.CARDINALITY_OPTIONAL)
- .setTokenizerType(PropertyConfig.TOKENIZER_TYPE_PLAIN)
- .setIndexingType(PropertyConfig.INDEXING_TYPE_PREFIXES)
- .build()
-
- ).addProperty(new PropertyConfig.Builder(KEY_TO)
- .setDataType(PropertyConfig.DATA_TYPE_STRING)
- .setCardinality(PropertyConfig.CARDINALITY_REPEATED)
- .setTokenizerType(PropertyConfig.TOKENIZER_TYPE_PLAIN)
- .setIndexingType(PropertyConfig.INDEXING_TYPE_PREFIXES)
- .build()
-
- ).addProperty(new PropertyConfig.Builder(KEY_CC)
- .setDataType(PropertyConfig.DATA_TYPE_STRING)
- .setCardinality(PropertyConfig.CARDINALITY_REPEATED)
- .setTokenizerType(PropertyConfig.TOKENIZER_TYPE_PLAIN)
- .setIndexingType(PropertyConfig.INDEXING_TYPE_PREFIXES)
- .build()
-
- ).addProperty(new PropertyConfig.Builder(KEY_BCC)
- .setDataType(PropertyConfig.DATA_TYPE_STRING)
- .setCardinality(PropertyConfig.CARDINALITY_REPEATED)
- .setTokenizerType(PropertyConfig.TOKENIZER_TYPE_PLAIN)
- .setIndexingType(PropertyConfig.INDEXING_TYPE_PREFIXES)
- .build()
-
- ).addProperty(new PropertyConfig.Builder(KEY_SUBJECT)
- .setDataType(PropertyConfig.DATA_TYPE_STRING)
- .setCardinality(PropertyConfig.CARDINALITY_OPTIONAL)
- .setTokenizerType(PropertyConfig.TOKENIZER_TYPE_PLAIN)
- .setIndexingType(PropertyConfig.INDEXING_TYPE_PREFIXES)
- .build()
-
- ).addProperty(new PropertyConfig.Builder(KEY_BODY)
- .setDataType(PropertyConfig.DATA_TYPE_STRING)
- .setCardinality(PropertyConfig.CARDINALITY_OPTIONAL)
- .setTokenizerType(PropertyConfig.TOKENIZER_TYPE_PLAIN)
- .setIndexingType(PropertyConfig.INDEXING_TYPE_PREFIXES)
- .build()
-
- ).build();
+ public static final AppSearchSchema SCHEMA =
+ new AppSearchSchema.Builder(SCHEMA_TYPE)
+ .addProperty(
+ new PropertyConfig.Builder(KEY_FROM)
+ .setDataType(PropertyConfig.DATA_TYPE_STRING)
+ .setCardinality(PropertyConfig.CARDINALITY_OPTIONAL)
+ .setTokenizerType(PropertyConfig.TOKENIZER_TYPE_PLAIN)
+ .setIndexingType(PropertyConfig.INDEXING_TYPE_PREFIXES)
+ .build())
+ .addProperty(
+ new PropertyConfig.Builder(KEY_TO)
+ .setDataType(PropertyConfig.DATA_TYPE_STRING)
+ .setCardinality(PropertyConfig.CARDINALITY_REPEATED)
+ .setTokenizerType(PropertyConfig.TOKENIZER_TYPE_PLAIN)
+ .setIndexingType(PropertyConfig.INDEXING_TYPE_PREFIXES)
+ .build())
+ .addProperty(
+ new PropertyConfig.Builder(KEY_CC)
+ .setDataType(PropertyConfig.DATA_TYPE_STRING)
+ .setCardinality(PropertyConfig.CARDINALITY_REPEATED)
+ .setTokenizerType(PropertyConfig.TOKENIZER_TYPE_PLAIN)
+ .setIndexingType(PropertyConfig.INDEXING_TYPE_PREFIXES)
+ .build())
+ .addProperty(
+ new PropertyConfig.Builder(KEY_BCC)
+ .setDataType(PropertyConfig.DATA_TYPE_STRING)
+ .setCardinality(PropertyConfig.CARDINALITY_REPEATED)
+ .setTokenizerType(PropertyConfig.TOKENIZER_TYPE_PLAIN)
+ .setIndexingType(PropertyConfig.INDEXING_TYPE_PREFIXES)
+ .build())
+ .addProperty(
+ new PropertyConfig.Builder(KEY_SUBJECT)
+ .setDataType(PropertyConfig.DATA_TYPE_STRING)
+ .setCardinality(PropertyConfig.CARDINALITY_OPTIONAL)
+ .setTokenizerType(PropertyConfig.TOKENIZER_TYPE_PLAIN)
+ .setIndexingType(PropertyConfig.INDEXING_TYPE_PREFIXES)
+ .build())
+ .addProperty(
+ new PropertyConfig.Builder(KEY_BODY)
+ .setDataType(PropertyConfig.DATA_TYPE_STRING)
+ .setCardinality(PropertyConfig.CARDINALITY_OPTIONAL)
+ .setTokenizerType(PropertyConfig.TOKENIZER_TYPE_PLAIN)
+ .setIndexingType(PropertyConfig.INDEXING_TYPE_PREFIXES)
+ .build())
+ .build();
/**
- * Creates a new {@link AppSearchEmail} from the contents of an existing
- * {@link GenericDocument}.
+ * Creates a new {@link AppSearchEmail} from the contents of an existing {@link
+ * GenericDocument}.
*
* @param document The {@link GenericDocument} containing the email content.
*/
@@ -109,8 +107,8 @@ public class AppSearchEmail extends GenericDocument {
/**
* Gets the destination addresses of {@link AppSearchEmail}.
*
- * @return The destination addresses of {@link AppSearchEmail} or {@code null} if it's not
- * been set yet.
+ * @return The destination addresses of {@link AppSearchEmail} or {@code null} if it's not been
+ * set yet.
*/
@Nullable
public String[] getTo() {
@@ -157,9 +155,7 @@ public class AppSearchEmail extends GenericDocument {
return getPropertyString(KEY_BODY);
}
- /**
- * The builder class for {@link AppSearchEmail}.
- */
+ /** The builder class for {@link AppSearchEmail}. */
public static class Builder extends GenericDocument.Builder<AppSearchEmail.Builder> {
/**
@@ -171,54 +167,42 @@ public class AppSearchEmail extends GenericDocument {
super(uri, SCHEMA_TYPE);
}
- /**
- * Sets the from address of {@link AppSearchEmail}
- */
+ /** Sets the from address of {@link AppSearchEmail} */
@NonNull
public AppSearchEmail.Builder setFrom(@NonNull String from) {
setPropertyString(KEY_FROM, from);
return this;
}
- /**
- * Sets the destination address of {@link AppSearchEmail}
- */
+ /** Sets the destination address of {@link AppSearchEmail} */
@NonNull
public AppSearchEmail.Builder setTo(@NonNull String... to) {
setPropertyString(KEY_TO, to);
return this;
}
- /**
- * Sets the CC list of {@link AppSearchEmail}
- */
+ /** Sets the CC list of {@link AppSearchEmail} */
@NonNull
public AppSearchEmail.Builder setCc(@NonNull String... cc) {
setPropertyString(KEY_CC, cc);
return this;
}
- /**
- * Sets the BCC list of {@link AppSearchEmail}
- */
+ /** Sets the BCC list of {@link AppSearchEmail} */
@NonNull
public AppSearchEmail.Builder setBcc(@NonNull String... bcc) {
setPropertyString(KEY_BCC, bcc);
return this;
}
- /**
- * Sets the subject of {@link AppSearchEmail}
- */
+ /** Sets the subject of {@link AppSearchEmail} */
@NonNull
public AppSearchEmail.Builder setSubject(@NonNull String subject) {
setPropertyString(KEY_SUBJECT, subject);
return this;
}
- /**
- * Sets the body of {@link AppSearchEmail}
- */
+ /** Sets the body of {@link AppSearchEmail} */
@NonNull
public AppSearchEmail.Builder setBody(@NonNull String body) {
setPropertyString(KEY_BODY, body);
diff --git a/apex/appsearch/framework/java/android/app/appsearch/AppSearchSchema.java b/apex/appsearch/framework/java/android/app/appsearch/AppSearchSchema.java
index 3933726d6729..2db74a8fb798 100644
--- a/apex/appsearch/framework/java/android/app/appsearch/AppSearchSchema.java
+++ b/apex/appsearch/framework/java/android/app/appsearch/AppSearchSchema.java
@@ -16,15 +16,14 @@
package android.app.appsearch;
-import android.annotation.SuppressLint;
-import android.os.Bundle;
-
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
-
+import android.annotation.SuppressLint;
import android.app.appsearch.exceptions.IllegalSchemaException;
+import android.os.Bundle;
import android.util.ArraySet;
+
import com.android.internal.util.Preconditions;
import java.lang.annotation.Retention;
@@ -40,7 +39,8 @@ import java.util.Set;
* <p>For example, an e-mail message or a music recording could be a schema type.
*
* <p>The schema consists of type information, properties, and config (like tokenization type).
- * @hide
+ *
+ * @see AppSearchManager#setSchema
*/
public final class AppSearchSchema {
private static final String SCHEMA_TYPE_FIELD = "schemaType";
@@ -49,7 +49,6 @@ public final class AppSearchSchema {
private final Bundle mBundle;
/** @hide */
-
public AppSearchSchema(@NonNull Bundle bundle) {
Preconditions.checkNotNull(bundle);
mBundle = bundle;
@@ -57,9 +56,9 @@ public final class AppSearchSchema {
/**
* Returns the {@link Bundle} populated by this builder.
+ *
* @hide
*/
-
@NonNull
public Bundle getBundle() {
return mBundle;
@@ -72,7 +71,7 @@ public final class AppSearchSchema {
/** Returns the name of this schema type, e.g. Email. */
@NonNull
- public String getSchemaTypeName() {
+ public String getSchemaType() {
return mBundle.getString(SCHEMA_TYPE_FIELD, "");
}
@@ -144,8 +143,8 @@ public final class AppSearchSchema {
/**
* Configuration for a single property (field) of a document type.
*
- * <p>For example, an {@code EmailMessage} would be a type and the {@code subject} would be
- * a property.
+ * <p>For example, an {@code EmailMessage} would be a type and the {@code subject} would be a
+ * property.
*/
public static final class PropertyConfig {
private static final String NAME_FIELD = "name";
@@ -157,18 +156,20 @@ public final class AppSearchSchema {
/**
* Physical data-types of the contents of the property.
+ *
* @hide
*/
// NOTE: The integer values of these constants must match the proto enum constants in
// com.google.android.icing.proto.PropertyConfigProto.DataType.Code.
- @IntDef(value = {
- DATA_TYPE_STRING,
- DATA_TYPE_INT64,
- DATA_TYPE_DOUBLE,
- DATA_TYPE_BOOLEAN,
- DATA_TYPE_BYTES,
- DATA_TYPE_DOCUMENT,
- })
+ @IntDef(
+ value = {
+ DATA_TYPE_STRING,
+ DATA_TYPE_INT64,
+ DATA_TYPE_DOUBLE,
+ DATA_TYPE_BOOLEAN,
+ DATA_TYPE_BYTES,
+ DATA_TYPE_DOCUMENT,
+ })
@Retention(RetentionPolicy.SOURCE)
public @interface DataType {}
@@ -181,23 +182,25 @@ public final class AppSearchSchema {
public static final int DATA_TYPE_BYTES = 5;
/**
- * Indicates that the property itself is an Document, making it part a hierarchical
- * Document schema. Any property using this DataType MUST have a valid
- * {@code schemaType}.
+ * Indicates that the property is itself a {@link GenericDocument}, making it part of a
+ * hierarchical schema. Any property using this DataType MUST have a valid {@link
+ * PropertyConfig#getSchemaType}.
*/
public static final int DATA_TYPE_DOCUMENT = 6;
/**
* The cardinality of the property (whether it is required, optional or repeated).
+ *
* @hide
*/
// NOTE: The integer values of these constants must match the proto enum constants in
// com.google.android.icing.proto.PropertyConfigProto.Cardinality.Code.
- @IntDef(value = {
- CARDINALITY_REPEATED,
- CARDINALITY_OPTIONAL,
- CARDINALITY_REQUIRED,
- })
+ @IntDef(
+ value = {
+ CARDINALITY_REPEATED,
+ CARDINALITY_OPTIONAL,
+ CARDINALITY_REQUIRED,
+ })
@Retention(RetentionPolicy.SOURCE)
public @interface Cardinality {}
@@ -212,23 +215,25 @@ public final class AppSearchSchema {
/**
* Encapsulates the configurations on how AppSearch should query/index these terms.
+ *
* @hide
*/
- @IntDef(value = {
- INDEXING_TYPE_NONE,
- INDEXING_TYPE_EXACT_TERMS,
- INDEXING_TYPE_PREFIXES,
- })
+ @IntDef(
+ value = {
+ INDEXING_TYPE_NONE,
+ INDEXING_TYPE_EXACT_TERMS,
+ INDEXING_TYPE_PREFIXES,
+ })
@Retention(RetentionPolicy.SOURCE)
public @interface IndexingType {}
/**
* Content in this property will not be tokenized or indexed.
*
- * <p>Useful if the data type is not made up of terms (e.g.
- * {@link PropertyConfig#DATA_TYPE_DOCUMENT} or {@link PropertyConfig#DATA_TYPE_BYTES}
- * type). All the properties inside the nested property won't be indexed regardless of the
- * value of {@code indexingType} for the nested properties.
+ * <p>Useful if the data type is not made up of terms (e.g. {@link
+ * PropertyConfig#DATA_TYPE_DOCUMENT} or {@link PropertyConfig#DATA_TYPE_BYTES} type). None
+ * of the properties inside the nested property will be indexed regardless of the value of
+ * {@code indexingType} for the nested properties.
*/
public static final int INDEXING_TYPE_NONE = 0;
@@ -250,20 +255,22 @@ public final class AppSearchSchema {
/**
* Configures how tokens should be extracted from this property.
+ *
* @hide
*/
// NOTE: The integer values of these constants must match the proto enum constants in
// com.google.android.icing.proto.IndexingConfig.TokenizerType.Code.
- @IntDef(value = {
- TOKENIZER_TYPE_NONE,
- TOKENIZER_TYPE_PLAIN,
- })
+ @IntDef(
+ value = {
+ TOKENIZER_TYPE_NONE,
+ TOKENIZER_TYPE_PLAIN,
+ })
@Retention(RetentionPolicy.SOURCE)
public @interface TokenizerType {}
/**
- * It is only valid for tokenizer_type to be 'NONE' if the data type is
- * {@link PropertyConfig#DATA_TYPE_DOCUMENT}.
+ * It is only valid for tokenizer_type to be 'NONE' if the data type is {@link
+ * PropertyConfig#DATA_TYPE_DOCUMENT}.
*/
public static final int TOKENIZER_TYPE_NONE = 0;
@@ -295,8 +302,8 @@ public final class AppSearchSchema {
/**
* Returns the logical schema-type of the contents of this property.
*
- * <p>Only set when {@link #getDataType} is set to {@link #DATA_TYPE_DOCUMENT}.
- * Otherwise, it is {@code null}.
+ * <p>Only set when {@link #getDataType} is set to {@link #DATA_TYPE_DOCUMENT}. Otherwise,
+ * it is {@code null}.
*/
@Nullable
public String getSchemaType() {
@@ -325,9 +332,10 @@ public final class AppSearchSchema {
*
* <p>The following properties must be set, or {@link PropertyConfig} construction will
* fail:
+ *
* <ul>
- * <li>dataType
- * <li>cardinality
+ * <li>dataType
+ * <li>cardinality
* </ul>
*
* <p>In addition, if {@code schemaType} is {@link #DATA_TYPE_DOCUMENT}, {@code schemaType}
@@ -359,8 +367,8 @@ public final class AppSearchSchema {
/**
* The logical schema-type of the contents of this property.
*
- * <p>Only required when {@link #setDataType} is set to
- * {@link #DATA_TYPE_DOCUMENT}. Otherwise, it is ignored.
+ * <p>Only required when {@link #setDataType} is set to {@link #DATA_TYPE_DOCUMENT}.
+ * Otherwise, it is ignored.
*/
@NonNull
public PropertyConfig.Builder setSchemaType(@NonNull String schemaType) {
diff --git a/apex/appsearch/framework/java/android/app/appsearch/GenericDocument.java b/apex/appsearch/framework/java/android/app/appsearch/GenericDocument.java
index 48d3ac09d997..0056377f007a 100644
--- a/apex/appsearch/framework/java/android/app/appsearch/GenericDocument.java
+++ b/apex/appsearch/framework/java/android/app/appsearch/GenericDocument.java
@@ -16,15 +16,14 @@
package android.app.appsearch;
-import android.annotation.SuppressLint;
-import android.os.Bundle;
-import android.util.Log;
-
import android.annotation.IntRange;
import android.annotation.NonNull;
import android.annotation.Nullable;
-
+import android.annotation.SuppressLint;
import android.app.appsearch.exceptions.AppSearchException;
+import android.os.Bundle;
+import android.util.Log;
+
import com.android.internal.util.Preconditions;
import java.lang.reflect.Array;
@@ -37,17 +36,20 @@ import java.util.Set;
* Represents a document unit.
*
* <p>Documents are constructed via {@link GenericDocument.Builder}.
- * @hide
+ *
+ * @see AppSearchManager#putDocuments
+ * @see AppSearchManager#getByUri
+ * @see AppSearchManager#query
*/
public class GenericDocument {
private static final String TAG = "GenericDocument";
- /** The default empty namespace.*/
+ /** The default empty namespace. */
public static final String DEFAULT_NAMESPACE = "";
/**
- * The maximum number of elements in a repeatable field. Will reject the request if exceed
- * this limit.
+ * The maximum number of elements in a repeatable field. Will reject the request if exceed this
+ * limit.
*/
private static final int MAX_REPEATED_PROPERTY_LENGTH = 100;
@@ -78,47 +80,43 @@ public class GenericDocument {
/**
* The maximum number of indexed properties a document can have.
*
- * <p>Indexed properties are properties where the
- * {@link android.app.appsearch.annotation.AppSearchDocument.Property#indexingType} constant is
- * anything other than {@link
- * android.app.appsearch.AppSearchSchema.PropertyConfig.IndexingType#INDEXING_TYPE_NONE}.
+ * <p>Indexed properties are properties where the {@link
+ * AppSearchSchema.PropertyConfig#getIndexingType()} constant is anything other than {@link
+ * AppSearchSchema.PropertyConfig.IndexingType#INDEXING_TYPE_NONE}.
*/
public static int getMaxIndexedProperties() {
return MAX_INDEXED_PROPERTIES;
}
- /** Contains {@link GenericDocument} basic information (uri, schemaType etc).*/
- @NonNull
- final Bundle mBundle;
+ /** Contains {@link GenericDocument} basic information (uri, schemaType etc). */
+ @NonNull final Bundle mBundle;
- /** Contains all properties in {@link GenericDocument} to support getting properties via keys.*/
- @NonNull
- private final Bundle mProperties;
+ /**
+ * Contains all properties in {@link GenericDocument} to support getting properties via keys.
+ */
+ @NonNull private final Bundle mProperties;
- @NonNull
- private final String mUri;
- @NonNull
- private final String mSchemaType;
+ @NonNull private final String mUri;
+ @NonNull private final String mSchemaType;
private final long mCreationTimestampMillis;
- @Nullable
- private Integer mHashCode;
+ @Nullable private Integer mHashCode;
/**
* Rebuilds a {@link GenericDocument} by the a bundle.
- * @param bundle Contains {@link GenericDocument} basic information (uri, schemaType etc) and
- * a properties bundle contains all properties in {@link GenericDocument} to
- * support getting properties via keys.
+ *
+ * @param bundle Contains {@link GenericDocument} basic information (uri, schemaType etc) and a
+ * properties bundle contains all properties in {@link GenericDocument} to support getting
+ * properties via keys.
* @hide
*/
-
public GenericDocument(@NonNull Bundle bundle) {
Preconditions.checkNotNull(bundle);
mBundle = bundle;
mProperties = Preconditions.checkNotNull(bundle.getParcelable(PROPERTIES_FIELD));
mUri = Preconditions.checkNotNull(mBundle.getString(URI_FIELD));
mSchemaType = Preconditions.checkNotNull(mBundle.getString(SCHEMA_TYPE_FIELD));
- mCreationTimestampMillis = mBundle.getLong(CREATION_TIMESTAMP_MILLIS_FIELD,
- System.currentTimeMillis());
+ mCreationTimestampMillis =
+ mBundle.getLong(CREATION_TIMESTAMP_MILLIS_FIELD, System.currentTimeMillis());
}
/**
@@ -132,9 +130,9 @@ public class GenericDocument {
/**
* Returns the {@link Bundle} populated by this builder.
+ *
* @hide
*/
-
@NonNull
public Bundle getBundle() {
return mBundle;
@@ -158,7 +156,11 @@ public class GenericDocument {
return mSchemaType;
}
- /** Returns the creation timestamp of the {@link GenericDocument}, in milliseconds. */
+ /**
+ * Returns the creation timestamp of the {@link GenericDocument}, in milliseconds.
+ *
+ * <p>The value is in the {@link System#currentTimeMillis} time base.
+ */
public long getCreationTimestampMillis() {
return mCreationTimestampMillis;
}
@@ -166,8 +168,12 @@ public class GenericDocument {
/**
* Returns the TTL (Time To Live) of the {@link GenericDocument}, in milliseconds.
*
+ * <p>The TTL is measured against {@link #getCreationTimestampMillis}. At the timestamp of
+ * {@code creationTimestampMillis + ttlMillis}, measured in the {@link System#currentTimeMillis}
+ * time base, the document will be auto-deleted.
+ *
* <p>The default value is 0, which means the document is permanent and won't be auto-deleted
- * until the app is uninstalled.
+ * until the app is uninstalled.
*/
public long getTtlMillis() {
return mBundle.getLong(TTL_MILLIS_FIELD, DEFAULT_TTL_MILLIS);
@@ -179,7 +185,10 @@ public class GenericDocument {
* <p>The score is a query-independent measure of the document's quality, relative to other
* {@link GenericDocument}s of the same type.
*
- * <p>The default value is 0.
+ * <p>Results may be sorted by score using {@link SearchSpec.Builder#setRankingStrategy}.
+ * Documents with higher scores are considered better than documents with lower scores.
+ *
+ * <p>Any nonnegative integer can be used a score.
*/
public int getScore() {
return mBundle.getInt(SCORE_FIELD, DEFAULT_SCORE);
@@ -195,8 +204,8 @@ public class GenericDocument {
* Retrieves a {@link String} value by key.
*
* @param key The key to look for.
- * @return The first {@link String} associated with the given key or {@code null} if there
- * is no such key or the value is of a different type.
+ * @return The first {@link String} associated with the given key or {@code null} if there is no
+ * such key or the value is of a different type.
*/
@Nullable
public String getPropertyString(@NonNull String key) {
@@ -214,7 +223,7 @@ public class GenericDocument {
*
* @param key The key to look for.
* @return The first {@code long} associated with the given key or default value {@code 0} if
- * there is no such key or the value is of a different type.
+ * there is no such key or the value is of a different type.
*/
public long getPropertyLong(@NonNull String key) {
Preconditions.checkNotNull(key);
@@ -231,7 +240,7 @@ public class GenericDocument {
*
* @param key The key to look for.
* @return The first {@code double} associated with the given key or default value {@code 0.0}
- * if there is no such key or the value is of a different type.
+ * if there is no such key or the value is of a different type.
*/
public double getPropertyDouble(@NonNull String key) {
Preconditions.checkNotNull(key);
@@ -247,8 +256,8 @@ public class GenericDocument {
* Retrieves a {@code boolean} value by key.
*
* @param key The key to look for.
- * @return The first {@code boolean} associated with the given key or default value
- * {@code false} if there is no such key or the value is of a different type.
+ * @return The first {@code boolean} associated with the given key or default value {@code
+ * false} if there is no such key or the value is of a different type.
*/
public boolean getPropertyBoolean(@NonNull String key) {
Preconditions.checkNotNull(key);
@@ -264,8 +273,8 @@ public class GenericDocument {
* Retrieves a {@code byte[]} value by key.
*
* @param key The key to look for.
- * @return The first {@code byte[]} associated with the given key or {@code null} if there
- * is no such key or the value is of a different type.
+ * @return The first {@code byte[]} associated with the given key or {@code null} if there is no
+ * such key or the value is of a different type.
*/
@Nullable
public byte[] getPropertyBytes(@NonNull String key) {
@@ -283,7 +292,7 @@ public class GenericDocument {
*
* @param key The key to look for.
* @return The first {@link GenericDocument} associated with the given key or {@code null} if
- * there is no such key or the value is of a different type.
+ * there is no such key or the value is of a different type.
*/
@Nullable
public GenericDocument getPropertyDocument(@NonNull String key) {
@@ -300,10 +309,18 @@ public class GenericDocument {
private static void warnIfSinglePropertyTooLong(
@NonNull String propertyType, @NonNull String key, int propertyLength) {
if (propertyLength > 1) {
- Log.w(TAG, "The value for \"" + key + "\" contains " + propertyLength
- + " elements. Only the first one will be returned from "
- + "getProperty" + propertyType + "(). Try getProperty" + propertyType
- + "Array().");
+ Log.w(
+ TAG,
+ "The value for \""
+ + key
+ + "\" contains "
+ + propertyLength
+ + " elements. Only the first one will be returned from "
+ + "getProperty"
+ + propertyType
+ + "(). Try getProperty"
+ + propertyType
+ + "Array().");
}
}
@@ -311,8 +328,8 @@ public class GenericDocument {
* Retrieves a repeated {@code String} property by key.
*
* @param key The key to look for.
- * @return The {@code String[]} associated with the given key, or {@code null} if no value
- * is set or the value is of a different type.
+ * @return The {@code String[]} associated with the given key, or {@code null} if no value is
+ * set or the value is of a different type.
*/
@Nullable
public String[] getPropertyStringArray(@NonNull String key) {
@@ -324,8 +341,8 @@ public class GenericDocument {
* Retrieves a repeated {@link String} property by key.
*
* @param key The key to look for.
- * @return The {@code long[]} associated with the given key, or {@code null} if no value is
- * set or the value is of a different type.
+ * @return The {@code long[]} associated with the given key, or {@code null} if no value is set
+ * or the value is of a different type.
*/
@Nullable
public long[] getPropertyLongArray(@NonNull String key) {
@@ -337,8 +354,8 @@ public class GenericDocument {
* Retrieves a repeated {@code double} property by key.
*
* @param key The key to look for.
- * @return The {@code double[]} associated with the given key, or {@code null} if no value
- * is set or the value is of a different type.
+ * @return The {@code double[]} associated with the given key, or {@code null} if no value is
+ * set or the value is of a different type.
*/
@Nullable
public double[] getPropertyDoubleArray(@NonNull String key) {
@@ -350,8 +367,8 @@ public class GenericDocument {
* Retrieves a repeated {@code boolean} property by key.
*
* @param key The key to look for.
- * @return The {@code boolean[]} associated with the given key, or {@code null} if no value
- * is set or the value is of a different type.
+ * @return The {@code boolean[]} associated with the given key, or {@code null} if no value is
+ * set or the value is of a different type.
*/
@Nullable
public boolean[] getPropertyBooleanArray(@NonNull String key) {
@@ -363,8 +380,8 @@ public class GenericDocument {
* Retrieves a {@code byte[][]} property by key.
*
* @param key The key to look for.
- * @return The {@code byte[][]} associated with the given key, or {@code null} if no value
- * is set or the value is of a different type.
+ * @return The {@code byte[][]} associated with the given key, or {@code null} if no value is
+ * set or the value is of a different type.
*/
@SuppressLint("ArrayReturn")
@Nullable
@@ -397,7 +414,7 @@ public class GenericDocument {
*
* @param key The key to look for.
* @return The {@link GenericDocument}[] associated with the given key, or {@code null} if no
- * value is set or the value is of a different type.
+ * value is set or the value is of a different type.
*/
@SuppressLint("ArrayReturn")
@Nullable
@@ -419,8 +436,8 @@ public class GenericDocument {
}
/**
- * Gets a repeated property of the given key, and casts it to the given class type, which
- * must be an array class type.
+ * Gets a repeated property of the given key, and casts it to the given class type, which must
+ * be an array class type.
*/
@Nullable
private <T> T getAndCastPropertyArray(@NonNull String key, @NonNull Class<T> tClass) {
@@ -449,8 +466,9 @@ public class GenericDocument {
}
/**
- * Deeply checks two bundles are equally or not.
- * <p> Two bundles will be considered equally if they contain same content.
+ * Deeply checks whether two bundles are equal.
+ *
+ * <p>Two bundles will be considered equal if they contain the same content.
*/
@SuppressWarnings("unchecked")
private static boolean bundleEquals(Bundle one, Bundle two) {
@@ -537,8 +555,9 @@ public class GenericDocument {
/**
* Calculates the hash code for a bundle.
- * <p> The hash code is only effected by the contents in the bundle. Bundles will get
- * consistent hash code if they have same contents.
+ *
+ * <p>The hash code is only effected by the contents in the bundle. Bundles will get consistent
+ * hash code if they have same contents.
*/
@SuppressWarnings("unchecked")
private static int bundleHashCode(Bundle bundle) {
@@ -663,11 +682,11 @@ public class GenericDocument {
* Create a new {@link GenericDocument.Builder}.
*
* @param uri The uri of {@link GenericDocument}.
- * @param schemaType The schema type of the {@link GenericDocument}. The passed-in
- * {@code schemaType} must be defined using {@link AppSearchSession#setSchema} prior
- * to inserting a document of this {@code schemaType} into the AppSearch index using
- * {@link AppSearchSession#putDocuments}. Otherwise, the document will be
- * rejected by {@link AppSearchSession#putDocuments}.
+ * @param schemaType The schema type of the {@link GenericDocument}. The passed-in {@code
+ * schemaType} must be defined using {@link AppSearchManager#setSchema} prior to
+ * inserting a document of this {@code schemaType} into the AppSearch index using {@link
+ * AppSearchManager#putDocuments}. Otherwise, the document will be rejected by {@link
+ * AppSearchManager#putDocuments}.
*/
@SuppressWarnings("unchecked")
public Builder(@NonNull String uri, @NonNull String schemaType) {
@@ -678,16 +697,16 @@ public class GenericDocument {
mBundle.putString(GenericDocument.SCHEMA_TYPE_FIELD, schemaType);
mBundle.putString(GenericDocument.NAMESPACE_FIELD, DEFAULT_NAMESPACE);
// Set current timestamp for creation timestamp by default.
- mBundle.putLong(GenericDocument.CREATION_TIMESTAMP_MILLIS_FIELD,
- System.currentTimeMillis());
+ mBundle.putLong(
+ GenericDocument.CREATION_TIMESTAMP_MILLIS_FIELD, System.currentTimeMillis());
mBundle.putLong(GenericDocument.TTL_MILLIS_FIELD, DEFAULT_TTL_MILLIS);
mBundle.putInt(GenericDocument.SCORE_FIELD, DEFAULT_SCORE);
mBundle.putBundle(PROPERTIES_FIELD, mProperties);
}
/**
- * Sets the app-defined namespace this Document resides in. No special values are
- * reserved or understood by the infrastructure.
+ * Sets the app-defined namespace this Document resides in. No special values are reserved
+ * or understood by the infrastructure.
*
* <p>URIs are unique within a namespace.
*
@@ -702,8 +721,13 @@ public class GenericDocument {
/**
* Sets the score of the {@link GenericDocument}.
*
- * <p>The score is a query-independent measure of the document's quality, relative to
- * other {@link GenericDocument}s of the same type.
+ * <p>The score is a query-independent measure of the document's quality, relative to other
+ * {@link GenericDocument}s of the same type.
+ *
+ * <p>Results may be sorted by score using {@link SearchSpec.Builder#setRankingStrategy}.
+ * Documents with higher scores are considered better than documents with lower scores.
+ *
+ * <p>Any nonnegative integer can be used a score.
*
* @throws IllegalArgumentException If the provided value is negative.
*/
@@ -718,22 +742,28 @@ public class GenericDocument {
}
/**
- * Sets the creation timestamp of the {@link GenericDocument}, in milliseconds. Should be
- * set using a value obtained from the {@link System#currentTimeMillis()} time base.
+ * Sets the creation timestamp of the {@link GenericDocument}, in milliseconds.
+ *
+ * <p>Should be set using a value obtained from the {@link System#currentTimeMillis} time
+ * base.
*/
@NonNull
public BuilderType setCreationTimestampMillis(long creationTimestampMillis) {
Preconditions.checkState(!mBuilt, "Builder has already been used");
- mBundle.putLong(GenericDocument.CREATION_TIMESTAMP_MILLIS_FIELD,
- creationTimestampMillis);
+ mBundle.putLong(
+ GenericDocument.CREATION_TIMESTAMP_MILLIS_FIELD, creationTimestampMillis);
return mBuilderTypeInstance;
}
/**
* Sets the TTL (Time To Live) of the {@link GenericDocument}, in milliseconds.
*
- * <p>After this many milliseconds since the {@link #setCreationTimestampMillis creation
- * timestamp}, the document is deleted.
+ * <p>The TTL is measured against {@link #getCreationTimestampMillis}. At the timestamp of
+ * {@code creationTimestampMillis + ttlMillis}, measured in the {@link
+ * System#currentTimeMillis} time base, the document will be auto-deleted.
+ *
+ * <p>The default value is 0, which means the document is permanent and won't be
+ * auto-deleted until the app is uninstalled.
*
* @param ttlMillis A non-negative duration in milliseconds.
* @throws IllegalArgumentException If the provided value is negative.
@@ -749,8 +779,7 @@ public class GenericDocument {
}
/**
- * Sets one or multiple {@code String} values for a property, replacing its previous
- * values.
+ * Sets one or multiple {@code String} values for a property, replacing its previous values.
*
* @param key The key associated with the {@code values}.
* @param values The {@code String} values of the property.
@@ -781,8 +810,7 @@ public class GenericDocument {
}
/**
- * Sets one or multiple {@code long} values for a property, replacing its previous
- * values.
+ * Sets one or multiple {@code long} values for a property, replacing its previous values.
*
* @param key The key associated with the {@code values}.
* @param values The {@code long} values of the property.
@@ -797,8 +825,7 @@ public class GenericDocument {
}
/**
- * Sets one or multiple {@code double} values for a property, replacing its previous
- * values.
+ * Sets one or multiple {@code double} values for a property, replacing its previous values.
*
* @param key The key associated with the {@code values}.
* @param values The {@code double} values of the property.
@@ -851,9 +878,14 @@ public class GenericDocument {
if (values[i] == null) {
throw new IllegalArgumentException("The String at " + i + " is null.");
} else if (values[i].length() > MAX_STRING_LENGTH) {
- throw new IllegalArgumentException("The String at " + i + " length is: "
- + values[i].length() + ", which exceeds length limit: "
- + MAX_STRING_LENGTH + ".");
+ throw new IllegalArgumentException(
+ "The String at "
+ + i
+ + " length is: "
+ + values[i].length()
+ + ", which exceeds length limit: "
+ + MAX_STRING_LENGTH
+ + ".");
}
}
mProperties.putStringArray(key, values);
@@ -911,7 +943,10 @@ public class GenericDocument {
throw new IllegalArgumentException("The input array is empty.");
} else if (length > MAX_REPEATED_PROPERTY_LENGTH) {
throw new IllegalArgumentException(
- "Repeated property \"" + key + "\" has length " + length
+ "Repeated property \""
+ + key
+ + "\" has length "
+ + length
+ ", which exceeds the limit of "
+ MAX_REPEATED_PROPERTY_LENGTH);
}
diff --git a/apex/appsearch/framework/java/android/app/appsearch/GetByUriRequest.java b/apex/appsearch/framework/java/android/app/appsearch/GetByUriRequest.java
index e1e0eda7558c..053d401d06dc 100644
--- a/apex/appsearch/framework/java/android/app/appsearch/GetByUriRequest.java
+++ b/apex/appsearch/framework/java/android/app/appsearch/GetByUriRequest.java
@@ -18,6 +18,7 @@ package android.app.appsearch;
import android.annotation.NonNull;
import android.util.ArraySet;
+
import com.android.internal.util.Preconditions;
import java.util.Arrays;
@@ -28,7 +29,7 @@ import java.util.Set;
/**
* Encapsulates a request to retrieve documents by namespace and URI.
*
- * @see AppSearchManager#getByUri
+ * @see AppSearchSession#getByUri
* @hide
*/
public final class GetByUriRequest {
diff --git a/apex/appsearch/framework/java/android/app/appsearch/PutDocumentsRequest.java b/apex/appsearch/framework/java/android/app/appsearch/PutDocumentsRequest.java
index 1f90bc184f6f..42f1ff2a716a 100644
--- a/apex/appsearch/framework/java/android/app/appsearch/PutDocumentsRequest.java
+++ b/apex/appsearch/framework/java/android/app/appsearch/PutDocumentsRequest.java
@@ -16,10 +16,10 @@
package android.app.appsearch;
-import android.annotation.SuppressLint;
-
import android.annotation.NonNull;
+import android.annotation.SuppressLint;
import android.app.appsearch.exceptions.AppSearchException;
+
import com.android.internal.util.Preconditions;
import java.util.ArrayList;
@@ -29,9 +29,9 @@ import java.util.Collections;
import java.util.List;
/**
- * Encapsulates a request to index a document into an {@link AppSearchManager} database.
+ * Encapsulates a request to index a document into an {@link AppSearchSession} database.
*
- * @see AppSearchManager#putDocuments
+ * @see AppSearchSession#putDocuments
* @hide
*/
public final class PutDocumentsRequest {
@@ -53,7 +53,7 @@ public final class PutDocumentsRequest {
private boolean mBuilt = false;
/** Adds one or more documents to the request. */
- @SuppressLint("MissingGetterMatchingBuilder") // Merged list available from getDocuments()
+ @SuppressLint("MissingGetterMatchingBuilder") // Merged list available from getDocuments()
@NonNull
public Builder addGenericDocument(@NonNull GenericDocument... documents) {
Preconditions.checkNotNull(documents);
@@ -61,7 +61,7 @@ public final class PutDocumentsRequest {
}
/** Adds one or more documents to the request. */
- @SuppressLint("MissingGetterMatchingBuilder") // Merged list available from getDocuments()
+ @SuppressLint("MissingGetterMatchingBuilder") // Merged list available from getDocuments()
@NonNull
public Builder addGenericDocument(@NonNull Collection<GenericDocument> documents) {
Preconditions.checkState(!mBuilt, "Builder has already been used");
diff --git a/apex/appsearch/framework/java/android/app/appsearch/RemoveByUriRequest.java b/apex/appsearch/framework/java/android/app/appsearch/RemoveByUriRequest.java
index 486857fba1de..3d83c390fbad 100644
--- a/apex/appsearch/framework/java/android/app/appsearch/RemoveByUriRequest.java
+++ b/apex/appsearch/framework/java/android/app/appsearch/RemoveByUriRequest.java
@@ -18,6 +18,7 @@ package android.app.appsearch;
import android.annotation.NonNull;
import android.util.ArraySet;
+
import com.android.internal.util.Preconditions;
import java.util.Arrays;
@@ -28,7 +29,7 @@ import java.util.Set;
/**
* Encapsulates a request to remove documents by namespace and URI.
*
- * @see AppSearchManager#removeByUri
+ * @see AppSearchSession#removeByUri
* @hide
*/
public final class RemoveByUriRequest {
diff --git a/apex/appsearch/framework/java/android/app/appsearch/SearchResult.java b/apex/appsearch/framework/java/android/app/appsearch/SearchResult.java
index 99cb2f16ca4d..5ffa7c94087c 100644
--- a/apex/appsearch/framework/java/android/app/appsearch/SearchResult.java
+++ b/apex/appsearch/framework/java/android/app/appsearch/SearchResult.java
@@ -16,60 +16,60 @@
package android.app.appsearch;
-import android.os.Bundle;
-
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.os.Bundle;
-import java.util.Objects;
import com.android.internal.util.Preconditions;
import java.util.ArrayList;
import java.util.List;
+import java.util.Objects;
/**
- * This class represents one of the results obtained from the query.
+ * This class represents one of the results obtained from an AppSearch query.
+ *
+ * <p>This allows clients to obtain:
*
- * <p>It contains the document which matched, information about which section(s) in the document
- * matched, and snippet information containing textual summaries of the document's match(es).
- * @hide
+ * <ul>
+ * <li>The document which matched, using {@link #getDocument}
+ * <li>Information about which properties in the document matched, and "snippet" information
+ * containing textual summaries of the document's matches, using {@link #getMatches}
+ * </ul>
+ *
+ * <p>"Snippet" refers to a substring of text from the content of document that is returned as a
+ * part of search result.
+ *
+ * @see SearchResults
*/
public final class SearchResult {
/** @hide */
-
public static final String DOCUMENT_FIELD = "document";
/** @hide */
-
public static final String MATCHES_FIELD = "matches";
- @NonNull
- private final Bundle mBundle;
+ @NonNull private final Bundle mBundle;
- @NonNull
- private final Bundle mDocumentBundle;
+ @NonNull private final Bundle mDocumentBundle;
/** Cache of the inflated document. Comes from inflating mDocumentBundle at first use. */
- @Nullable
- private GenericDocument mDocument;
+ @Nullable private GenericDocument mDocument;
/**
* Contains a list of MatchInfo bundles that matched the request.
*
- * Only populated when requested in both {@link SearchSpec.Builder#setSnippetCount} and
+ * <p>Only populated when requested in both {@link SearchSpec.Builder#setSnippetCount} and
* {@link SearchSpec.Builder#setSnippetCountPerProperty}.
*
* @see #getMatches()
*/
- @NonNull
- private final List<Bundle> mMatchBundles;
+ @NonNull private final List<Bundle> mMatchBundles;
/** Cache of the inflated matches. Comes from inflating mMatchBundles at first use. */
- @Nullable
- private List<MatchInfo> mMatches;
+ @Nullable private List<MatchInfo> mMatches;
/** @hide */
-
public SearchResult(@NonNull Bundle bundle) {
mBundle = Preconditions.checkNotNull(bundle);
mDocumentBundle = Preconditions.checkNotNull(bundle.getBundle(DOCUMENT_FIELD));
@@ -77,7 +77,6 @@ public final class SearchResult {
}
/** @hide */
-
@NonNull
public Bundle getBundle() {
return mBundle;
@@ -85,6 +84,7 @@ public final class SearchResult {
/**
* Contains the matching {@link GenericDocument}.
+ *
* @return Document object which matched the query.
*/
@NonNull
@@ -98,10 +98,10 @@ public final class SearchResult {
/**
* Contains a list of Snippets that matched the request.
*
- * @return List of matches based on {@link SearchSpec}. If snippeting is disabled using
- * {@link SearchSpec.Builder#setSnippetCount} or
- * {@link SearchSpec.Builder#setSnippetCountPerProperty}, for all results after that
- * value, this method returns an empty list.
+ * @return List of matches based on {@link SearchSpec}. If snippeting is disabled using {@link
+ * SearchSpec.Builder#setSnippetCount} or {@link
+ * SearchSpec.Builder#setSnippetCountPerProperty}, for all results after that value, this
+ * method returns an empty list.
*/
@NonNull
public List<MatchInfo> getMatches() {
@@ -116,79 +116,94 @@ public final class SearchResult {
}
/**
- * Snippet: It refers to a substring of text from the content of document that is returned as a
- * part of search result.
- * This class represents a match objects for any Snippets that might be present in
- * {@link SearchResults} from query. Using this class
- * user can get the full text, exact matches and Snippets of document content for a given match.
- *
- * <p>Class Example 1:
- * A document contains following text in property subject:
+ * This class represents a match objects for any Snippets that might be present in {@link
+ * SearchResults} from query. Using this class user can get the full text, exact matches and
+ * Snippets of document content for a given match.
+ *
+ * <p>Class Example 1: A document contains following text in property subject:
+ *
* <p>A commonly used fake word is foo. Another nonsense word that’s used a lot is bar.
*
* <p>If the queryExpression is "foo".
*
* <p>{@link MatchInfo#getPropertyPath()} returns "subject"
+ *
* <p>{@link MatchInfo#getFullText()} returns "A commonly used fake word is foo. Another
* nonsense word that’s used a lot is bar."
+ *
* <p>{@link MatchInfo#getExactMatchPosition()} returns [29, 32]
+ *
* <p>{@link MatchInfo#getExactMatch()} returns "foo"
+ *
* <p>{@link MatchInfo#getSnippetPosition()} returns [26, 33]
+ *
* <p>{@link MatchInfo#getSnippet()} returns "is foo."
+ *
* <p>
- * <p>Class Example 2:
- * A document contains a property name sender which contains 2 property names name and email, so
- * we will have 2 property paths: {@code sender.name} and {@code sender.email}.
- * <p>Let {@code sender.name = "Test Name Jr."} and
- * {@code sender.email = "TestNameJr@gmail.com"}
+ *
+ * <p>Class Example 2: A document contains a property name sender which contains 2 property
+ * names name and email, so we will have 2 property paths: {@code sender.name} and {@code
+ * sender.email}.
+ *
+ * <p>Let {@code sender.name = "Test Name Jr."} and {@code sender.email =
+ * "TestNameJr@gmail.com"}
*
* <p>If the queryExpression is "Test". We will have 2 matches.
*
- * <p> Match-1
+ * <p>Match-1
+ *
* <p>{@link MatchInfo#getPropertyPath()} returns "sender.name"
+ *
* <p>{@link MatchInfo#getFullText()} returns "Test Name Jr."
+ *
* <p>{@link MatchInfo#getExactMatchPosition()} returns [0, 4]
+ *
* <p>{@link MatchInfo#getExactMatch()} returns "Test"
+ *
* <p>{@link MatchInfo#getSnippetPosition()} returns [0, 9]
+ *
* <p>{@link MatchInfo#getSnippet()} returns "Test Name"
- * <p> Match-2
+ *
+ * <p>Match-2
+ *
* <p>{@link MatchInfo#getPropertyPath()} returns "sender.email"
+ *
* <p>{@link MatchInfo#getFullText()} returns "TestNameJr@gmail.com"
+ *
* <p>{@link MatchInfo#getExactMatchPosition()} returns [0, 20]
+ *
* <p>{@link MatchInfo#getExactMatch()} returns "TestNameJr@gmail.com"
+ *
* <p>{@link MatchInfo#getSnippetPosition()} returns [0, 20]
+ *
* <p>{@link MatchInfo#getSnippet()} returns "TestNameJr@gmail.com"
*/
public static final class MatchInfo {
/**
* The path of the matching snippet property.
+ *
* @hide
*/
-
public static final String PROPERTY_PATH_FIELD = "propertyPath";
/**
* The index of matching value in its property. A property may have multiple values. This
* index indicates which value is the match.
+ *
* @hide
*/
-
public static final String VALUES_INDEX_FIELD = "valuesIndex";
/** @hide */
-
public static final String EXACT_MATCH_POSITION_LOWER_FIELD = "exactMatchPositionLower";
/** @hide */
-
public static final String EXACT_MATCH_POSITION_UPPER_FIELD = "exactMatchPositionUpper";
/** @hide */
-
public static final String WINDOW_POSITION_LOWER_FIELD = "windowPositionLower";
/** @hide */
-
public static final String WINDOW_POSITION_UPPER_FIELD = "windowPositionUpper";
private final String mFullText;
@@ -201,16 +216,18 @@ public final class SearchResult {
mBundle = Preconditions.checkNotNull(bundle);
Preconditions.checkNotNull(document);
mPropertyPath = Preconditions.checkNotNull(bundle.getString(PROPERTY_PATH_FIELD));
- mFullText = getPropertyValues(
- document, mPropertyPath, mBundle.getInt(VALUES_INDEX_FIELD));
+ mFullText =
+ getPropertyValues(document, mPropertyPath, mBundle.getInt(VALUES_INDEX_FIELD));
}
/**
* Gets the property path corresponding to the given entry.
+ *
* <p>Property Path: '.' - delimited sequence of property names indicating which property in
* the Document these snippets correspond to.
- * <p>Example properties: 'body', 'sender.name', 'sender.emailaddress', etc.
- * For class example 1 this returns "subject"
+ *
+ * <p>Example properties: 'body', 'sender.name', 'sender.emailaddress', etc. For class
+ * example 1 this returns "subject"
*/
@NonNull
public String getPropertyPath() {
@@ -219,6 +236,7 @@ public final class SearchResult {
/**
* Gets the full text corresponding to the given entry.
+ *
* <p>For class example this returns "A commonly used fake word is foo. Another nonsense
* word that's used a lot is bar."
*/
@@ -229,20 +247,23 @@ public final class SearchResult {
/**
* Gets the exact {@link MatchRange} corresponding to the given entry.
+ *
* <p>For class example 1 this returns [29, 32]
*/
@NonNull
public MatchRange getExactMatchPosition() {
if (mExactMatchRange == null) {
- mExactMatchRange = new MatchRange(
- mBundle.getInt(EXACT_MATCH_POSITION_LOWER_FIELD),
- mBundle.getInt(EXACT_MATCH_POSITION_UPPER_FIELD));
+ mExactMatchRange =
+ new MatchRange(
+ mBundle.getInt(EXACT_MATCH_POSITION_LOWER_FIELD),
+ mBundle.getInt(EXACT_MATCH_POSITION_UPPER_FIELD));
}
return mExactMatchRange;
}
/**
- * Gets the {@link MatchRange} corresponding to the given entry.
+ * Gets the {@link MatchRange} corresponding to the given entry.
+ *
* <p>For class example 1 this returns "foo"
*/
@NonNull
@@ -252,26 +273,31 @@ public final class SearchResult {
/**
* Gets the snippet {@link MatchRange} corresponding to the given entry.
- * <p>Only populated when set maxSnippetSize > 0 in
- * {@link SearchSpec.Builder#setMaxSnippetSize}.
+ *
+ * <p>Only populated when set maxSnippetSize > 0 in {@link
+ * SearchSpec.Builder#setMaxSnippetSize}.
+ *
* <p>For class example 1 this returns [29, 41].
*/
@NonNull
public MatchRange getSnippetPosition() {
if (mWindowRange == null) {
- mWindowRange = new MatchRange(
- mBundle.getInt(WINDOW_POSITION_LOWER_FIELD),
- mBundle.getInt(WINDOW_POSITION_UPPER_FIELD));
+ mWindowRange =
+ new MatchRange(
+ mBundle.getInt(WINDOW_POSITION_LOWER_FIELD),
+ mBundle.getInt(WINDOW_POSITION_UPPER_FIELD));
}
return mWindowRange;
}
/**
* Gets the snippet corresponding to the given entry.
+ *
* <p>Snippet - Provides a subset of the content to display. Only populated when requested
- * maxSnippetSize > 0. The size of this content can be changed by
- * {@link SearchSpec.Builder#setMaxSnippetSize}. Windowing is centered around the middle of
- * the matched token with content on either side clipped to token boundaries.
+ * maxSnippetSize > 0. The size of this content can be changed by {@link
+ * SearchSpec.Builder#setMaxSnippetSize}. Windowing is centered around the middle of the
+ * matched token with content on either side clipped to token boundaries.
+ *
* <p>For class example 1 this returns "foo. Another"
*/
@NonNull
@@ -302,11 +328,10 @@ public final class SearchResult {
/**
* Class providing the position range of matching information.
*
- * <p> All ranges are finite, and the left side of the range is always {@code <=} the right
- * side of the range.
- *
- * <p> Example: MatchRange(0, 100) represent a hundred ints from 0 to 99."
+ * <p>All ranges are finite, and the left side of the range is always {@code <=} the right side
+ * of the range.
*
+ * <p>Example: MatchRange(0, 100) represent a hundred ints from 0 to 99."
*/
public static final class MatchRange {
private final int mEnd;
@@ -314,18 +339,18 @@ public final class SearchResult {
/**
* Creates a new immutable range.
- * <p> The endpoints are {@code [start, end)}; that is the range is bounded. {@code start}
+ *
+ * <p>The endpoints are {@code [start, end)}; that is the range is bounded. {@code start}
* must be lesser or equal to {@code end}.
*
* @param start The start point (inclusive)
* @param end The end point (exclusive)
* @hide
*/
-
public MatchRange(int start, int end) {
if (start > end) {
- throw new IllegalArgumentException("Start point must be less than or equal to "
- + "end point");
+ throw new IllegalArgumentException(
+ "Start point must be less than or equal to " + "end point");
}
mStart = start;
mEnd = end;
diff --git a/apex/appsearch/framework/java/android/app/appsearch/SearchResultPage.java b/apex/appsearch/framework/java/android/app/appsearch/SearchResultPage.java
index 756d1b5d673f..dbd09d6bb91b 100644
--- a/apex/appsearch/framework/java/android/app/appsearch/SearchResultPage.java
+++ b/apex/appsearch/framework/java/android/app/appsearch/SearchResultPage.java
@@ -16,10 +16,9 @@
package android.app.appsearch;
-import android.os.Bundle;
-
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.os.Bundle;
import com.android.internal.util.Preconditions;
@@ -29,19 +28,17 @@ import java.util.List;
/**
* This class represents a page of {@link SearchResult}s
+ *
* @hide
*/
-
public class SearchResultPage {
public static final String RESULTS_FIELD = "results";
public static final String NEXT_PAGE_TOKEN_FIELD = "nextPageToken";
private final long mNextPageToken;
- @Nullable
- private List<SearchResult> mResults;
+ @Nullable private List<SearchResult> mResults;
- @NonNull
- private final Bundle mBundle;
+ @NonNull private final Bundle mBundle;
public SearchResultPage(@NonNull Bundle bundle) {
mBundle = Preconditions.checkNotNull(bundle);
diff --git a/apex/appsearch/framework/java/android/app/appsearch/SearchSpec.java b/apex/appsearch/framework/java/android/app/appsearch/SearchSpec.java
index 15acf103f2e6..68e31f03fb4d 100644
--- a/apex/appsearch/framework/java/android/app/appsearch/SearchSpec.java
+++ b/apex/appsearch/framework/java/android/app/appsearch/SearchSpec.java
@@ -16,14 +16,14 @@
package android.app.appsearch;
-import android.annotation.SuppressLint;
-import android.os.Bundle;
-
import android.annotation.IntDef;
+import android.annotation.IntRange;
import android.annotation.NonNull;
-
+import android.annotation.SuppressLint;
import android.app.appsearch.exceptions.AppSearchException;
import android.app.appsearch.exceptions.IllegalSearchSpecException;
+import android.os.Bundle;
+
import com.android.internal.util.Preconditions;
import java.lang.annotation.Retention;
@@ -37,7 +37,6 @@ import java.util.List;
/**
* This class represents the specification logic for AppSearch. It can be used to set the type of
* search, like prefix or exact only or apply filters to search for a specific schema type only etc.
- * @hide
*/
// TODO(sidchhabra) : AddResultSpec fields for Snippets etc.
public final class SearchSpec {
@@ -52,10 +51,10 @@ public final class SearchSpec {
static final String MAX_SNIPPET_FIELD = "maxSnippet";
/** @hide */
-
public static final int DEFAULT_NUM_PER_PAGE = 10;
- // TODO(b/170371356): In framework, we may want these limits might be flag controlled.
+ // TODO(b/170371356): In framework, we may want these limits to be flag controlled.
+ // If that happens, the @IntRange() directives in this class may have to change.
private static final int MAX_NUM_PER_PAGE = 10_000;
private static final int MAX_SNIPPET_COUNT = 10_000;
private static final int MAX_SNIPPET_PER_PROPERTY_COUNT = 10_000;
@@ -63,43 +62,45 @@ public final class SearchSpec {
/**
* Term Match Type for the query.
+ *
* @hide
*/
// NOTE: The integer values of these constants must match the proto enum constants in
// {@link com.google.android.icing.proto.SearchSpecProto.termMatchType}
- @IntDef(value = {
- TERM_MATCH_EXACT_ONLY,
- TERM_MATCH_PREFIX
- })
+ @IntDef(value = {TERM_MATCH_EXACT_ONLY, TERM_MATCH_PREFIX})
@Retention(RetentionPolicy.SOURCE)
public @interface TermMatch {}
/**
* Query terms will only match exact tokens in the index.
+ *
* <p>Ex. A query term "foo" will only match indexed token "foo", and not "foot" or "football".
*/
public static final int TERM_MATCH_EXACT_ONLY = 1;
/**
* Query terms will match indexed tokens when the query term is a prefix of the token.
+ *
* <p>Ex. A query term "foo" will match indexed tokens like "foo", "foot", and "football".
*/
public static final int TERM_MATCH_PREFIX = 2;
/**
* Ranking Strategy for query result.
+ *
* @hide
*/
// NOTE: The integer values of these constants must match the proto enum constants in
// {@link ScoringSpecProto.RankingStrategy.Code}
- @IntDef(value = {
- RANKING_STRATEGY_NONE,
- RANKING_STRATEGY_DOCUMENT_SCORE,
- RANKING_STRATEGY_CREATION_TIMESTAMP
- })
+ @IntDef(
+ value = {
+ RANKING_STRATEGY_NONE,
+ RANKING_STRATEGY_DOCUMENT_SCORE,
+ RANKING_STRATEGY_CREATION_TIMESTAMP
+ })
@Retention(RetentionPolicy.SOURCE)
public @interface RankingStrategy {}
- /** No Ranking, results are returned in arbitrary order.*/
+ /** No Ranking, results are returned in arbitrary order. */
public static final int RANKING_STRATEGY_NONE = 0;
/** Ranked by app-provided document scores. */
public static final int RANKING_STRATEGY_DOCUMENT_SCORE = 1;
@@ -108,14 +109,12 @@ public final class SearchSpec {
/**
* Order for query result.
+ *
* @hide
*/
// NOTE: The integer values of these constants must match the proto enum constants in
// {@link ScoringSpecProto.Order.Code}
- @IntDef(value = {
- ORDER_DESCENDING,
- ORDER_ASCENDING
- })
+ @IntDef(value = {ORDER_DESCENDING, ORDER_ASCENDING})
@Retention(RetentionPolicy.SOURCE)
public @interface Order {}
@@ -127,7 +126,6 @@ public final class SearchSpec {
private final Bundle mBundle;
/** @hide */
-
public SearchSpec(@NonNull Bundle bundle) {
Preconditions.checkNotNull(bundle);
mBundle = bundle;
@@ -135,9 +133,9 @@ public final class SearchSpec {
/**
* Returns the {@link Bundle} populated by this builder.
+ *
* @hide
*/
-
@NonNull
public Bundle getBundle() {
return mBundle;
@@ -154,12 +152,12 @@ public final class SearchSpec {
* <p>If empty, the query will search over all schema types.
*/
@NonNull
- public List<String> getSchemas() {
- List<String> schemas = mBundle.getStringArrayList(SCHEMA_TYPE_FIELD);
- if (schemas == null) {
+ public List<String> getSchemaTypes() {
+ List<String> schemaTypes = mBundle.getStringArrayList(SCHEMA_TYPE_FIELD);
+ if (schemaTypes == null) {
return Collections.emptyList();
}
- return Collections.unmodifiableList(schemas);
+ return Collections.unmodifiableList(schemaTypes);
}
/**
@@ -176,8 +174,8 @@ public final class SearchSpec {
return Collections.unmodifiableList(namespaces);
}
- /** Returns the number of results per page in the returned object. */
- public int getNumPerPage() {
+ /** Returns the number of results per page in the result set. */
+ public int getResultCountPerPage() {
return mBundle.getInt(NUM_PER_PAGE_FIELD, DEFAULT_NUM_PER_PAGE);
}
@@ -222,14 +220,12 @@ public final class SearchSpec {
mBundle.putInt(NUM_PER_PAGE_FIELD, DEFAULT_NUM_PER_PAGE);
}
- /**
- * Indicates how the query terms should match {@code TermMatchCode} in the index.
- */
+ /** Indicates how the query terms should match {@code TermMatchCode} in the index. */
@NonNull
public Builder setTermMatch(@TermMatch int termMatchTypeCode) {
Preconditions.checkState(!mBuilt, "Builder has already been used");
- Preconditions.checkArgumentInRange(termMatchTypeCode, TERM_MATCH_EXACT_ONLY,
- TERM_MATCH_PREFIX, "Term match type");
+ Preconditions.checkArgumentInRange(
+ termMatchTypeCode, TERM_MATCH_EXACT_ONLY, TERM_MATCH_PREFIX, "Term match type");
mBundle.putInt(TERM_MATCH_TYPE_FIELD, termMatchTypeCode);
return this;
}
@@ -241,10 +237,10 @@ public final class SearchSpec {
* <p>If unset, the query will search over all schema types.
*/
@NonNull
- public Builder addSchema(@NonNull String... schemaTypes) {
+ public Builder addSchemaType(@NonNull String... schemaTypes) {
Preconditions.checkNotNull(schemaTypes);
Preconditions.checkState(!mBuilt, "Builder has already been used");
- return addSchema(Arrays.asList(schemaTypes));
+ return addSchemaType(Arrays.asList(schemaTypes));
}
/**
@@ -254,7 +250,7 @@ public final class SearchSpec {
* <p>If unset, the query will search over all schema types.
*/
@NonNull
- public Builder addSchema(@NonNull Collection<String> schemaTypes) {
+ public Builder addSchemaType(@NonNull Collection<String> schemaTypes) {
Preconditions.checkNotNull(schemaTypes);
Preconditions.checkState(!mBuilt, "Builder has already been used");
mSchemaTypes.addAll(schemaTypes);
@@ -262,8 +258,9 @@ public final class SearchSpec {
}
/**
- * Adds a namespace filter to {@link SearchSpec} Entry. Only search for documents that
- * have the specified namespaces.
+ * Adds a namespace filter to {@link SearchSpec} Entry. Only search for documents that have
+ * the specified namespaces.
+ *
* <p>If unset, the query will search over all namespaces.
*/
@NonNull
@@ -274,8 +271,9 @@ public final class SearchSpec {
}
/**
- * Adds a namespace filter to {@link SearchSpec} Entry. Only search for documents that
- * have the specified namespaces.
+ * Adds a namespace filter to {@link SearchSpec} Entry. Only search for documents that have
+ * the specified namespaces.
+ *
* <p>If unset, the query will search over all namespaces.
*/
@NonNull
@@ -288,51 +286,56 @@ public final class SearchSpec {
/**
* Sets the number of results per page in the returned object.
- * <p> The default number of results per page is 10. And should be set in range [0, 10k].
+ *
+ * <p>The default number of results per page is 10.
*/
@NonNull
- public SearchSpec.Builder setNumPerPage(int numPerPage) {
+ public SearchSpec.Builder setResultCountPerPage(
+ @IntRange(from = 0, to = MAX_NUM_PER_PAGE) int numPerPage) {
Preconditions.checkState(!mBuilt, "Builder has already been used");
Preconditions.checkArgumentInRange(numPerPage, 0, MAX_NUM_PER_PAGE, "NumPerPage");
mBundle.putInt(NUM_PER_PAGE_FIELD, numPerPage);
return this;
}
- /** Sets ranking strategy for AppSearch results.*/
+ /** Sets ranking strategy for AppSearch results. */
@NonNull
public Builder setRankingStrategy(@RankingStrategy int rankingStrategy) {
Preconditions.checkState(!mBuilt, "Builder has already been used");
- Preconditions.checkArgumentInRange(rankingStrategy, RANKING_STRATEGY_NONE,
- RANKING_STRATEGY_CREATION_TIMESTAMP, "Result ranking strategy");
+ Preconditions.checkArgumentInRange(
+ rankingStrategy,
+ RANKING_STRATEGY_NONE,
+ RANKING_STRATEGY_CREATION_TIMESTAMP,
+ "Result ranking strategy");
mBundle.putInt(RANKING_STRATEGY_FIELD, rankingStrategy);
return this;
}
/**
- * Indicates the order of returned search results, the default is DESC, meaning that results
- * with higher scores come first.
+ * Indicates the order of returned search results, the default is {@link #ORDER_DESCENDING},
+ * meaning that results with higher scores come first.
+ *
* <p>This order field will be ignored if RankingStrategy = {@code RANKING_STRATEGY_NONE}.
*/
@NonNull
public Builder setOrder(@Order int order) {
Preconditions.checkState(!mBuilt, "Builder has already been used");
- Preconditions.checkArgumentInRange(order, ORDER_DESCENDING, ORDER_ASCENDING,
- "Result ranking order");
+ Preconditions.checkArgumentInRange(
+ order, ORDER_DESCENDING, ORDER_ASCENDING, "Result ranking order");
mBundle.putInt(ORDER_FIELD, order);
return this;
}
/**
- * Only the first {@code snippetCount} documents based on the ranking strategy
- * will have snippet information provided.
+ * Only the first {@code snippetCount} documents based on the ranking strategy will have
+ * snippet information provided.
*
* <p>If set to 0 (default), snippeting is disabled and {@link SearchResult#getMatches} will
* return {@code null} for that result.
- *
- * <p>The value should be set in range[0, 10k].
*/
@NonNull
- public SearchSpec.Builder setSnippetCount(int snippetCount) {
+ public SearchSpec.Builder setSnippetCount(
+ @IntRange(from = 0, to = MAX_SNIPPET_COUNT) int snippetCount) {
Preconditions.checkState(!mBuilt, "Builder has already been used");
Preconditions.checkArgumentInRange(snippetCount, 0, MAX_SNIPPET_COUNT, "snippetCount");
mBundle.putInt(SNIPPET_COUNT_FIELD, snippetCount);
@@ -341,39 +344,40 @@ public final class SearchSpec {
/**
* Sets {@code snippetCountPerProperty}. Only the first {@code snippetCountPerProperty}
- * snippets for a every property of {@link GenericDocument} will contain snippet
- * information.
+ * snippets for each property of {@link GenericDocument} will contain snippet information.
*
- * <p>If set to 0, snippeting is disabled and {@link SearchResult#getMatches}
- * will return {@code null} for that result.
- *
- * <p>The value should be set in range[0, 10k].
+ * <p>If set to 0, snippeting is disabled and {@link SearchResult#getMatches} will return
+ * {@code null} for that result.
*/
@NonNull
- public SearchSpec.Builder setSnippetCountPerProperty(int snippetCountPerProperty) {
+ public SearchSpec.Builder setSnippetCountPerProperty(
+ @IntRange(from = 0, to = MAX_SNIPPET_PER_PROPERTY_COUNT)
+ int snippetCountPerProperty) {
Preconditions.checkState(!mBuilt, "Builder has already been used");
- Preconditions.checkArgumentInRange(snippetCountPerProperty,
- 0, MAX_SNIPPET_PER_PROPERTY_COUNT, "snippetCountPerProperty");
+ Preconditions.checkArgumentInRange(
+ snippetCountPerProperty,
+ 0,
+ MAX_SNIPPET_PER_PROPERTY_COUNT,
+ "snippetCountPerProperty");
mBundle.putInt(SNIPPET_COUNT_PER_PROPERTY_FIELD, snippetCountPerProperty);
return this;
}
/**
- * Sets {@code maxSnippetSize}, the maximum snippet size. Snippet windows start at
- * {@code maxSnippetSize/2} bytes before the middle of the matching token and end at
- * {@code maxSnippetSize/2} bytes after the middle of the matching token. It respects
- * token boundaries, therefore the returned window may be smaller than requested.
+ * Sets {@code maxSnippetSize}, the maximum snippet size. Snippet windows start at {@code
+ * maxSnippetSize/2} bytes before the middle of the matching token and end at {@code
+ * maxSnippetSize/2} bytes after the middle of the matching token. It respects token
+ * boundaries, therefore the returned window may be smaller than requested.
*
- * <p> Setting {@code maxSnippetSize} to 0 will disable windowing and an empty string will
- * be returned. If matches enabled is also set to false, then snippeting is disabled.
+ * <p>Setting {@code maxSnippetSize} to 0 will disable windowing and an empty string will be
+ * returned. If matches enabled is also set to false, then snippeting is disabled.
*
* <p>Ex. {@code maxSnippetSize} = 16. "foo bar baz bat rat" with a query of "baz" will
* return a window of "bar baz bat" which is only 11 bytes long.
- *
- * <p>The value should be in range[0, 10k].
*/
@NonNull
- public SearchSpec.Builder setMaxSnippetSize(int maxSnippetSize) {
+ public SearchSpec.Builder setMaxSnippetSize(
+ @IntRange(from = 0, to = MAX_SNIPPET_SIZE_LIMIT) int maxSnippetSize) {
Preconditions.checkState(!mBuilt, "Builder has already been used");
Preconditions.checkArgumentInRange(
maxSnippetSize, 0, MAX_SNIPPET_SIZE_LIMIT, "maxSnippetSize");
diff --git a/apex/appsearch/framework/java/android/app/appsearch/SetSchemaRequest.java b/apex/appsearch/framework/java/android/app/appsearch/SetSchemaRequest.java
index f2c81564908c..3e472fd01939 100644
--- a/apex/appsearch/framework/java/android/app/appsearch/SetSchemaRequest.java
+++ b/apex/appsearch/framework/java/android/app/appsearch/SetSchemaRequest.java
@@ -16,11 +16,11 @@
package android.app.appsearch;
-import android.annotation.SuppressLint;
-
import android.annotation.NonNull;
+import android.annotation.SuppressLint;
import android.app.appsearch.exceptions.AppSearchException;
import android.util.ArraySet;
+
import com.android.internal.util.Preconditions;
import java.util.ArrayList;
@@ -30,9 +30,9 @@ import java.util.List;
import java.util.Set;
/**
- * Encapsulates a request to update the schema of an {@link AppSearchManager} database.
+ * Encapsulates a request to update the schema of an {@link AppSearchSession} database.
*
- * @see AppSearchManager#setSchema
+ * @see AppSearchSession#setSchema
* @hide
*/
public final class SetSchemaRequest {
@@ -81,10 +81,10 @@ public final class SetSchemaRequest {
* Configures the {@link SetSchemaRequest} to delete any existing documents that don't
* follow the new schema.
*
- * <p>By default, this is {@code false} and schema incompatibility causes the
- * {@link AppSearchManager#setSchema} call to fail.
+ * <p>By default, this is {@code false} and schema incompatibility causes the {@link
+ * AppSearchSession#setSchema} call to fail.
*
- * @see AppSearchManager#setSchema
+ * @see AppSearchSession#setSchema
*/
@NonNull
public Builder setForceOverride(boolean forceOverride) {
diff --git a/apex/appsearch/framework/java/android/app/appsearch/exceptions/AppSearchException.java b/apex/appsearch/framework/java/android/app/appsearch/exceptions/AppSearchException.java
index 15d0992cd081..704f180bffc4 100644
--- a/apex/appsearch/framework/java/android/app/appsearch/exceptions/AppSearchException.java
+++ b/apex/appsearch/framework/java/android/app/appsearch/exceptions/AppSearchException.java
@@ -21,18 +21,19 @@ import android.annotation.Nullable;
import android.app.appsearch.AppSearchResult;
/**
- * An exception thrown by {@code android.app.appsearch.AppSearchManager} or a subcomponent.
+ * An exception thrown by {@link android.app.appsearch.AppSearchSession} or a subcomponent.
+ *
+ * <p>These exceptions can be converted into a failed {@link AppSearchResult} for propagating to the
+ * client.
*
- * <p>These exceptions can be converted into a failed {@link AppSearchResult}
- * for propagating to the client.
* @hide
*/
-//TODO(b/157082794): Linkify to AppSearchManager once that API is public
public class AppSearchException extends Exception {
private final @AppSearchResult.ResultCode int mResultCode;
/**
* Initializes an {@link AppSearchException} with no message.
+ *
* @hide
*/
public AppSearchException(@AppSearchResult.ResultCode int resultCode) {
@@ -59,9 +60,7 @@ public class AppSearchException extends Exception {
return mResultCode;
}
- /**
- * Converts this {@link java.lang.Exception} into a failed {@link AppSearchResult}
- */
+ /** Converts this {@link java.lang.Exception} into a failed {@link AppSearchResult} */
@NonNull
public <T> AppSearchResult<T> toAppSearchResult() {
return AppSearchResult.newFailedResult(mResultCode, getMessage());
diff --git a/apex/appsearch/framework/java/android/app/appsearch/exceptions/IllegalSchemaException.java b/apex/appsearch/framework/java/android/app/appsearch/exceptions/IllegalSchemaException.java
index 6dd86f5e6de1..5f8da7fe067a 100644
--- a/apex/appsearch/framework/java/android/app/appsearch/exceptions/IllegalSchemaException.java
+++ b/apex/appsearch/framework/java/android/app/appsearch/exceptions/IllegalSchemaException.java
@@ -18,14 +18,12 @@ package android.app.appsearch.exceptions;
import android.annotation.NonNull;
-
/**
* Indicates that a {@link android.app.appsearch.AppSearchSchema} has logical inconsistencies such
* as unpopulated mandatory fields or illegal combinations of parameters.
*
* @hide
*/
-
public class IllegalSchemaException extends IllegalArgumentException {
/**
* Constructs a new {@link IllegalSchemaException}.
diff --git a/apex/appsearch/framework/java/android/app/appsearch/exceptions/IllegalSearchSpecException.java b/apex/appsearch/framework/java/android/app/appsearch/exceptions/IllegalSearchSpecException.java
index 3ef887f09eab..0b5dc2ece6f1 100644
--- a/apex/appsearch/framework/java/android/app/appsearch/exceptions/IllegalSearchSpecException.java
+++ b/apex/appsearch/framework/java/android/app/appsearch/exceptions/IllegalSearchSpecException.java
@@ -18,14 +18,12 @@ package android.app.appsearch.exceptions;
import android.annotation.NonNull;
-
/**
- * Indicates that a {@link android.app.appsearch.SearchResult} has logical inconsistencies such
- * as unpopulated mandatory fields or illegal combinations of parameters.
+ * Indicates that a {@link android.app.appsearch.SearchResult} has logical inconsistencies such as
+ * unpopulated mandatory fields or illegal combinations of parameters.
*
* @hide
*/
-
public class IllegalSearchSpecException extends IllegalArgumentException {
/**
* Constructs a new {@link IllegalSearchSpecException}.
diff --git a/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/AppSearchImpl.java b/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/AppSearchImpl.java
index e021544976b5..247089ba258b 100644
--- a/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/AppSearchImpl.java
+++ b/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/AppSearchImpl.java
@@ -16,13 +16,7 @@
package com.android.server.appsearch.external.localstorage;
-import android.os.Bundle;
-import android.util.Log;
-
-import com.android.internal.annotations.GuardedBy;
import android.annotation.NonNull;
-
-import com.android.internal.annotations.VisibleForTesting;
import android.annotation.WorkerThread;
import android.app.appsearch.AppSearchResult;
import android.app.appsearch.AppSearchSchema;
@@ -30,6 +24,12 @@ import android.app.appsearch.GenericDocument;
import android.app.appsearch.SearchResultPage;
import android.app.appsearch.SearchSpec;
import android.app.appsearch.exceptions.AppSearchException;
+import android.os.Bundle;
+import android.util.ArraySet;
+import android.util.Log;
+
+import com.android.internal.annotations.GuardedBy;
+import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.Preconditions;
import com.android.server.appsearch.external.localstorage.converter.GenericDocumentToProtoConverter;
import com.android.server.appsearch.external.localstorage.converter.SchemaToProtoConverter;
@@ -62,7 +62,6 @@ import com.google.android.icing.proto.StatusProto;
import java.io.File;
import java.util.Collections;
import java.util.HashMap;
-import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
@@ -77,55 +76,65 @@ import java.util.concurrent.locks.ReentrantReadWriteLock;
*
* <p>A single instance of {@link AppSearchImpl} can support all databases. Schemas and documents
* are physically saved together in {@link IcingSearchEngine}, but logically isolated:
+ *
* <ul>
- * <li>Rewrite SchemaType in SchemaProto by adding database name prefix and save into
- * SchemaTypes set in {@link #setSchema}.
- * <li>Rewrite namespace and SchemaType in DocumentProto by adding database name prefix and
- * save to namespaces set in {@link #putDocument}.
- * <li>Remove database name prefix when retrieve documents in {@link #getDocument} and
- * {@link #query}.
- * <li>Rewrite filters in {@link SearchSpecProto} to have all namespaces and schema types of
- * the queried database when user using empty filters in {@link #query}.
+ * <li>Rewrite SchemaType in SchemaProto by adding database name prefix and save into SchemaTypes
+ * set in {@link #setSchema}.
+ * <li>Rewrite namespace and SchemaType in DocumentProto by adding database name prefix and save
+ * to namespaces set in {@link #putDocument}.
+ * <li>Remove database name prefix when retrieve documents in {@link #getDocument} and {@link
+ * #query}.
+ * <li>Rewrite filters in {@link SearchSpecProto} to have all namespaces and schema types of the
+ * queried database when user using empty filters in {@link #query}.
* </ul>
*
* <p>Methods in this class belong to two groups, the query group and the mutate group.
+ *
* <ul>
- * <li>All methods are going to modify global parameters and data in Icing are executed under
- * WRITE lock to keep thread safety.
- * <li>All methods are going to access global parameters or query data from Icing are executed
- * under READ lock to improve query performance.
+ * <li>All methods are going to modify global parameters and data in Icing are executed under
+ * WRITE lock to keep thread safety.
+ * <li>All methods are going to access global parameters or query data from Icing are executed
+ * under READ lock to improve query performance.
* </ul>
*
* <p>This class is thread safe.
*
* @hide
*/
-
@WorkerThread
public final class AppSearchImpl {
private static final String TAG = "AppSearchImpl";
- private static final char DATABASE_DELIMITER = '/';
- @VisibleForTesting
- static final int OPTIMIZE_THRESHOLD_DOC_COUNT = 1000;
- @VisibleForTesting
- static final int OPTIMIZE_THRESHOLD_BYTES = 1_000_000; // 1MB
- @VisibleForTesting
- static final int CHECK_OPTIMIZE_INTERVAL = 100;
+ @VisibleForTesting static final char DATABASE_DELIMITER = '/';
+
+ @VisibleForTesting static final int OPTIMIZE_THRESHOLD_DOC_COUNT = 1000;
+ @VisibleForTesting static final int OPTIMIZE_THRESHOLD_BYTES = 1_000_000; // 1MB
+ @VisibleForTesting static final int CHECK_OPTIMIZE_INTERVAL = 100;
private final ReadWriteLock mReadWriteLock = new ReentrantReadWriteLock();
- private final IcingSearchEngine mIcingSearchEngine;
+
+ @GuardedBy("mReadWriteLock")
+ private final IcingSearchEngine mIcingSearchEngineLocked;
+
+ @GuardedBy("mReadWriteLock")
+ private final VisibilityStore mVisibilityStoreLocked;
// The map contains schemaTypes and namespaces for all database. All values in the map have
- // been already added database name prefix.
- private final Map<String, Set<String>> mSchemaMap = new HashMap<>();
- private final Map<String, Set<String>> mNamespaceMap = new HashMap<>();
+ // the database name prefix.
+ // TODO(b/172360376): Check if this can be replaced with an ArrayMap
+ @GuardedBy("mReadWriteLock")
+ private final Map<String, Set<String>> mSchemaMapLocked = new HashMap<>();
+
+ // TODO(b/172360376): Check if this can be replaced with an ArrayMap
+ @GuardedBy("mReadWriteLock")
+ private final Map<String, Set<String>> mNamespaceMapLocked = new HashMap<>();
/**
- * The counter to check when to call {@link #checkForOptimize(boolean)}. The interval is
+ * The counter to check when to call {@link #checkForOptimizeLocked(boolean)}. The interval is
* {@link #CHECK_OPTIMIZE_INTERVAL}.
*/
- private int mOptimizeIntervalCount = 0;
+ @GuardedBy("mReadWriteLock")
+ private int mOptimizeIntervalCountLocked = 0;
/**
* Creates and initializes an instance of {@link AppSearchImpl} which writes data to the given
@@ -134,44 +143,77 @@ public final class AppSearchImpl {
@NonNull
public static AppSearchImpl create(@NonNull File icingDir) throws AppSearchException {
Preconditions.checkNotNull(icingDir);
- return new AppSearchImpl(icingDir);
+ AppSearchImpl appSearchImpl = new AppSearchImpl(icingDir);
+ appSearchImpl.initializeVisibilityStore();
+ return appSearchImpl;
}
private AppSearchImpl(@NonNull File icingDir) throws AppSearchException {
boolean isReset = false;
mReadWriteLock.writeLock().lock();
+
try {
// We synchronize here because we don't want to call IcingSearchEngine.initialize() more
// than once. It's unnecessary and can be a costly operation.
- IcingSearchEngineOptions options = IcingSearchEngineOptions.newBuilder()
- .setBaseDir(icingDir.getAbsolutePath()).build();
- mIcingSearchEngine = new IcingSearchEngine(options);
+ IcingSearchEngineOptions options =
+ IcingSearchEngineOptions.newBuilder()
+ .setBaseDir(icingDir.getAbsolutePath())
+ .build();
+ mIcingSearchEngineLocked = new IcingSearchEngine(options);
- InitializeResultProto initializeResultProto = mIcingSearchEngine.initialize();
+ InitializeResultProto initializeResultProto = mIcingSearchEngineLocked.initialize();
SchemaProto schemaProto = null;
GetAllNamespacesResultProto getAllNamespacesResultProto = null;
try {
checkSuccess(initializeResultProto.getStatus());
- schemaProto = getSchemaProto();
- getAllNamespacesResultProto = mIcingSearchEngine.getAllNamespaces();
+ schemaProto = getSchemaProtoLocked();
+ getAllNamespacesResultProto = mIcingSearchEngineLocked.getAllNamespaces();
checkSuccess(getAllNamespacesResultProto.getStatus());
} catch (AppSearchException e) {
+ Log.w(TAG, "Error initializing, resetting IcingSearchEngine.", e);
// Some error. Reset and see if it fixes it.
reset();
isReset = true;
}
+
+ // Populate schema map
for (SchemaTypeConfigProto schema : schemaProto.getTypesList()) {
String qualifiedSchemaType = schema.getSchemaType();
- addToMap(mSchemaMap, getDatabaseName(qualifiedSchemaType), qualifiedSchemaType);
+ addToMap(
+ mSchemaMapLocked,
+ getDatabaseName(qualifiedSchemaType),
+ qualifiedSchemaType);
}
+
+ // Populate namespace map
for (String qualifiedNamespace : getAllNamespacesResultProto.getNamespacesList()) {
- addToMap(mNamespaceMap, getDatabaseName(qualifiedNamespace), qualifiedNamespace);
+ addToMap(
+ mNamespaceMapLocked,
+ getDatabaseName(qualifiedNamespace),
+ qualifiedNamespace);
}
+
// TODO(b/155939114): It's possible to optimize after init, which would reduce the time
// to when we're able to serve queries. Consider moving this optimize call out.
if (!isReset) {
- checkForOptimize(/* force= */ true);
+ checkForOptimizeLocked(/* force= */ true);
}
+
+ mVisibilityStoreLocked = new VisibilityStore(this);
+ } finally {
+ mReadWriteLock.writeLock().unlock();
+ }
+ }
+
+ /**
+ * Initialize the visibility store in AppSearchImpl.
+ *
+ * @throws AppSearchException on IcingSearchEngine error.
+ */
+ void initializeVisibilityStore() throws AppSearchException {
+ mReadWriteLock.writeLock().lock();
+ try {
+ mVisibilityStoreLocked.initialize();
} finally {
mReadWriteLock.writeLock().unlock();
}
@@ -182,35 +224,36 @@ public final class AppSearchImpl {
*
* <p>This method belongs to mutate group.
*
- * @param databaseName The name of the database where this schema lives.
- * @param schemas Schemas to set for this app.
+ * @param databaseName The name of the database where this schema lives.
+ * @param schemas Schemas to set for this app.
* @param forceOverride Whether to force-apply the schema even if it is incompatible. Documents
- * which do not comply with the new schema will be deleted.
+ * which do not comply with the new schema will be deleted.
* @throws AppSearchException on IcingSearchEngine error.
*/
- public void setSchema(@NonNull String databaseName, @NonNull Set<AppSearchSchema> schemas,
- boolean forceOverride) throws AppSearchException {
- SchemaProto schemaProto = getSchemaProto();
-
- SchemaProto.Builder existingSchemaBuilder = schemaProto.toBuilder();
+ public void setSchema(
+ @NonNull String databaseName,
+ @NonNull Set<AppSearchSchema> schemas,
+ boolean forceOverride)
+ throws AppSearchException {
+ mReadWriteLock.writeLock().lock();
+ try {
+ SchemaProto.Builder existingSchemaBuilder = getSchemaProtoLocked().toBuilder();
- SchemaProto.Builder newSchemaBuilder = SchemaProto.newBuilder();
- for (AppSearchSchema schema : schemas) {
- SchemaTypeConfigProto schemaTypeProto = SchemaToProtoConverter.convert(schema);
- newSchemaBuilder.addTypes(schemaTypeProto);
- }
+ SchemaProto.Builder newSchemaBuilder = SchemaProto.newBuilder();
+ for (AppSearchSchema schema : schemas) {
+ SchemaTypeConfigProto schemaTypeProto = SchemaToProtoConverter.convert(schema);
+ newSchemaBuilder.addTypes(schemaTypeProto);
+ }
- // Combine the existing schema (which may have types from other databases) with this
- // database's new schema. Modifies the existingSchemaBuilder.
- Set<String> newTypeNames = rewriteSchema(databaseName, existingSchemaBuilder,
- newSchemaBuilder.build());
+ // Combine the existing schema (which may have types from other databases) with this
+ // database's new schema. Modifies the existingSchemaBuilder.
+ RewrittenSchemaResults rewrittenSchemaResults =
+ rewriteSchema(databaseName, existingSchemaBuilder, newSchemaBuilder.build());
- SetSchemaResultProto setSchemaResultProto;
- mReadWriteLock.writeLock().lock();
- try {
// Apply schema
- setSchemaResultProto =
- mIcingSearchEngine.setSchema(existingSchemaBuilder.build(), forceOverride);
+ SetSchemaResultProto setSchemaResultProto =
+ mIcingSearchEngineLocked.setSchema(
+ existingSchemaBuilder.build(), forceOverride);
// Determine whether it succeeded.
try {
@@ -219,11 +262,12 @@ public final class AppSearchImpl {
// Improve the error message by merging in information about incompatible types.
if (setSchemaResultProto.getDeletedSchemaTypesCount() > 0
|| setSchemaResultProto.getIncompatibleSchemaTypesCount() > 0) {
- String newMessage = e.getMessage()
- + "\n Deleted types: "
- + setSchemaResultProto.getDeletedSchemaTypesList()
- + "\n Incompatible types: "
- + setSchemaResultProto.getIncompatibleSchemaTypesList();
+ String newMessage =
+ e.getMessage()
+ + "\n Deleted types: "
+ + setSchemaResultProto.getDeletedSchemaTypesList()
+ + "\n Incompatible types: "
+ + setSchemaResultProto.getIncompatibleSchemaTypesList();
throw new AppSearchException(e.getResultCode(), newMessage, e.getCause());
} else {
throw e;
@@ -231,16 +275,18 @@ public final class AppSearchImpl {
}
// Update derived data structures.
- mSchemaMap.put(databaseName, newTypeNames);
+ mSchemaMapLocked.put(databaseName, rewrittenSchemaResults.mRewrittenQualifiedTypes);
+ mVisibilityStoreLocked.updateSchemas(
+ databaseName, rewrittenSchemaResults.mDeletedQualifiedTypes);
// Determine whether to schedule an immediate optimize.
if (setSchemaResultProto.getDeletedSchemaTypesCount() > 0
|| (setSchemaResultProto.getIncompatibleSchemaTypesCount() > 0
- && forceOverride)) {
+ && forceOverride)) {
// Any existing schemas which is not in 'schemas' will be deleted, and all
// documents of these types were also deleted. And so well if we force override
// incompatible schemas.
- checkForOptimize(/* force= */true);
+ checkForOptimizeLocked(/* force= */ true);
}
} finally {
mReadWriteLock.writeLock().unlock();
@@ -248,28 +294,63 @@ public final class AppSearchImpl {
}
/**
+ * Update the visibility settings for this app.
+ *
+ * <p>This method belongs to the mutate group
+ *
+ * @param databaseName The name of the database where the visibility settings will apply.
+ * @param schemasHiddenFromPlatformSurfaces Schemas that should be hidden from platform surfaces
+ * @throws AppSearchException on IcingSearchEngine error
+ */
+ public void setVisibility(
+ @NonNull String databaseName, @NonNull Set<String> schemasHiddenFromPlatformSurfaces)
+ throws AppSearchException {
+ mReadWriteLock.writeLock().lock();
+ try {
+ String databasePrefix = getDatabasePrefix(databaseName);
+ Set<String> qualifiedSchemasHiddenFromPlatformSurface =
+ new ArraySet<>(schemasHiddenFromPlatformSurfaces.size());
+ for (String schema : schemasHiddenFromPlatformSurfaces) {
+ Set<String> existingSchemas = mSchemaMapLocked.get(databaseName);
+ if (existingSchemas == null || !existingSchemas.contains(databasePrefix + schema)) {
+ throw new AppSearchException(
+ AppSearchResult.RESULT_NOT_FOUND,
+ "Unknown schema(s): "
+ + schemasHiddenFromPlatformSurfaces
+ + " provided during setVisibility.");
+ }
+ qualifiedSchemasHiddenFromPlatformSurface.add(databasePrefix + schema);
+ }
+ mVisibilityStoreLocked.setVisibility(
+ databaseName, qualifiedSchemasHiddenFromPlatformSurface);
+ } finally {
+ mReadWriteLock.writeLock().lock();
+ }
+ }
+
+ /**
* Adds a document to the AppSearch index.
*
* <p>This method belongs to mutate group.
*
* @param databaseName The databaseName this document resides in.
- * @param document The document to index.
+ * @param document The document to index.
* @throws AppSearchException on IcingSearchEngine error.
*/
public void putDocument(@NonNull String databaseName, @NonNull GenericDocument document)
throws AppSearchException {
- DocumentProto.Builder documentBuilder = GenericDocumentToProtoConverter.convert(
- document).toBuilder();
+ DocumentProto.Builder documentBuilder =
+ GenericDocumentToProtoConverter.convert(document).toBuilder();
addPrefixToDocument(documentBuilder, getDatabasePrefix(databaseName));
PutResultProto putResultProto;
mReadWriteLock.writeLock().lock();
try {
- putResultProto = mIcingSearchEngine.put(documentBuilder.build());
- addToMap(mNamespaceMap, databaseName, documentBuilder.getNamespace());
+ putResultProto = mIcingSearchEngineLocked.put(documentBuilder.build());
+ addToMap(mNamespaceMapLocked, databaseName, documentBuilder.getNamespace());
// The existing documents with same URI will be deleted, so there maybe some resources
// could be released after optimize().
- checkForOptimize(/* force= */false);
+ checkForOptimizeLocked(/* force= */ false);
} finally {
mReadWriteLock.writeLock().unlock();
}
@@ -282,19 +363,20 @@ public final class AppSearchImpl {
* <p>This method belongs to query group.
*
* @param databaseName The databaseName this document resides in.
- * @param namespace The namespace this document resides in.
- * @param uri The URI of the document to get.
+ * @param namespace The namespace this document resides in.
+ * @param uri The URI of the document to get.
* @return The Document contents
* @throws AppSearchException on IcingSearchEngine error.
*/
@NonNull
- public GenericDocument getDocument(@NonNull String databaseName, @NonNull String namespace,
- @NonNull String uri) throws AppSearchException {
+ public GenericDocument getDocument(
+ @NonNull String databaseName, @NonNull String namespace, @NonNull String uri)
+ throws AppSearchException {
GetResultProto getResultProto;
mReadWriteLock.readLock().lock();
try {
- getResultProto = mIcingSearchEngine.get(
- getDatabasePrefix(databaseName) + namespace, uri);
+ getResultProto =
+ mIcingSearchEngineLocked.get(getDatabasePrefix(databaseName) + namespace, uri);
} finally {
mReadWriteLock.readLock().unlock();
}
@@ -310,19 +392,25 @@ public final class AppSearchImpl {
*
* <p>This method belongs to query group.
*
- * @param databaseName The databaseName this query for.
+ * @param databaseName The databaseName this query for.
* @param queryExpression Query String to search.
- * @param searchSpec Spec for setting filters, raw query etc.
- * @return The results of performing this search. It may contain an empty list of results if
- * no documents matched the query.
+ * @param searchSpec Spec for setting filters, raw query etc.
+ * @return The results of performing this search. It may contain an empty list of results if no
+ * documents matched the query.
* @throws AppSearchException on IcingSearchEngine error.
*/
@NonNull
public SearchResultPage query(
@NonNull String databaseName,
@NonNull String queryExpression,
- @NonNull SearchSpec searchSpec) throws AppSearchException {
- return doQuery(Collections.singleton(databaseName), queryExpression, searchSpec);
+ @NonNull SearchSpec searchSpec)
+ throws AppSearchException {
+ mReadWriteLock.readLock().lock();
+ try {
+ return doQueryLocked(Collections.singleton(databaseName), queryExpression, searchSpec);
+ } finally {
+ mReadWriteLock.readLock().unlock();
+ }
}
/**
@@ -332,45 +420,54 @@ public final class AppSearchImpl {
* <p>This method belongs to query group.
*
* @param queryExpression Query String to search.
- * @param searchSpec Spec for setting filters, raw query etc.
- * @return The results of performing this search. It may contain an empty list of results if
- * no documents matched the query.
+ * @param searchSpec Spec for setting filters, raw query etc.
+ * @return The results of performing this search. It may contain an empty list of results if no
+ * documents matched the query.
* @throws AppSearchException on IcingSearchEngine error.
*/
@NonNull
public SearchResultPage globalQuery(
- @NonNull String queryExpression,
- @NonNull SearchSpec searchSpec) throws AppSearchException {
- return doQuery(mNamespaceMap.keySet(), queryExpression, searchSpec);
+ @NonNull String queryExpression, @NonNull SearchSpec searchSpec)
+ throws AppSearchException {
+ // TODO(b/169883602): Check if the platform is querying us at a higher level. At this
+ // point, we should add all platform-surfaceable schemas assuming the querier has been
+ // verified.
+ mReadWriteLock.readLock().lock();
+ try {
+ // We use the mNamespaceMap.keySet here because it's the smaller set of valid databases
+ // that could exist.
+ return doQueryLocked(mNamespaceMapLocked.keySet(), queryExpression, searchSpec);
+ } finally {
+ mReadWriteLock.readLock().unlock();
+ }
}
- private SearchResultPage doQuery(
- @NonNull Set<String> databases, @NonNull String queryExpression,
+ @GuardedBy("mReadWriteLock")
+ private SearchResultPage doQueryLocked(
+ @NonNull Set<String> databases,
+ @NonNull String queryExpression,
@NonNull SearchSpec searchSpec)
throws AppSearchException {
- SearchSpecProto searchSpecProto =
- SearchSpecToProtoConverter.toSearchSpecProto(searchSpec);
- SearchSpecProto.Builder searchSpecBuilder = searchSpecProto.toBuilder()
- .setQuery(queryExpression);
+ SearchSpecProto searchSpecProto = SearchSpecToProtoConverter.toSearchSpecProto(searchSpec);
+ SearchSpecProto.Builder searchSpecBuilder =
+ searchSpecProto.toBuilder().setQuery(queryExpression);
ResultSpecProto resultSpec = SearchSpecToProtoConverter.toResultSpecProto(searchSpec);
ScoringSpecProto scoringSpec = SearchSpecToProtoConverter.toScoringSpecProto(searchSpec);
SearchResultProto searchResultProto;
- mReadWriteLock.readLock().lock();
- try {
- // rewriteSearchSpecForDatabases will return false if none of the databases have
- // documents, so we can return an empty SearchResult and skip sending request to Icing.
- // We use the mNamespaceMap.keySet here because it's the smaller set of valid databases
- // that could exist.
- if (!rewriteSearchSpecForDatabases(searchSpecBuilder, databases)) {
- return new SearchResultPage(Bundle.EMPTY);
- }
- searchResultProto = mIcingSearchEngine.search(
- searchSpecBuilder.build(), scoringSpec, resultSpec);
- } finally {
- mReadWriteLock.readLock().unlock();
+
+ // rewriteSearchSpecForDatabases will return false if none of the databases that the
+ // client is trying to search on exist, so we can return an empty SearchResult and skip
+ // sending request to Icing.
+ // We use the mNamespaceMap.keySet here because it's the smaller set of valid databases
+ // that could exist.
+ if (!rewriteSearchSpecForDatabasesLocked(searchSpecBuilder, databases)) {
+ return new SearchResultPage(Bundle.EMPTY);
}
+ searchResultProto =
+ mIcingSearchEngineLocked.search(searchSpecBuilder.build(), scoringSpec, resultSpec);
checkSuccess(searchResultProto.getStatus());
+
return rewriteSearchResultProto(searchResultProto);
}
@@ -385,11 +482,16 @@ public final class AppSearchImpl {
* @throws AppSearchException on IcingSearchEngine error.
*/
@NonNull
- public SearchResultPage getNextPage(long nextPageToken)
- throws AppSearchException {
- SearchResultProto searchResultProto = mIcingSearchEngine.getNextPage(nextPageToken);
- checkSuccess(searchResultProto.getStatus());
- return rewriteSearchResultProto(searchResultProto);
+ public SearchResultPage getNextPage(long nextPageToken) throws AppSearchException {
+ mReadWriteLock.readLock().lock();
+ try {
+ SearchResultProto searchResultProto =
+ mIcingSearchEngineLocked.getNextPage(nextPageToken);
+ checkSuccess(searchResultProto.getStatus());
+ return rewriteSearchResultProto(searchResultProto);
+ } finally {
+ mReadWriteLock.readLock().unlock();
+ }
}
/**
@@ -398,10 +500,15 @@ public final class AppSearchImpl {
* <p>This method belongs to query group.
*
* @param nextPageToken The token of pre-loaded results of previously executed query to be
- * Invalidated.
+ * Invalidated.
*/
public void invalidateNextPageToken(long nextPageToken) {
- mIcingSearchEngine.invalidateNextPageToken(nextPageToken);
+ mReadWriteLock.readLock().lock();
+ try {
+ mIcingSearchEngineLocked.invalidateNextPageToken(nextPageToken);
+ } finally {
+ mReadWriteLock.readLock().unlock();
+ }
}
/**
@@ -410,18 +517,18 @@ public final class AppSearchImpl {
* <p>This method belongs to mutate group.
*
* @param databaseName The databaseName the document is in.
- * @param namespace Namespace of the document to remove.
- * @param uri URI of the document to remove.
+ * @param namespace Namespace of the document to remove.
+ * @param uri URI of the document to remove.
* @throws AppSearchException on IcingSearchEngine error.
*/
- public void remove(@NonNull String databaseName, @NonNull String namespace,
- @NonNull String uri) throws AppSearchException {
+ public void remove(@NonNull String databaseName, @NonNull String namespace, @NonNull String uri)
+ throws AppSearchException {
String qualifiedNamespace = getDatabasePrefix(databaseName) + namespace;
DeleteResultProto deleteResultProto;
mReadWriteLock.writeLock().lock();
try {
- deleteResultProto = mIcingSearchEngine.delete(qualifiedNamespace, uri);
- checkForOptimize(/* force= */false);
+ deleteResultProto = mIcingSearchEngineLocked.delete(qualifiedNamespace, uri);
+ checkForOptimizeLocked(/* force= */ false);
} finally {
mReadWriteLock.writeLock().unlock();
}
@@ -433,39 +540,38 @@ public final class AppSearchImpl {
*
* <p>This method belongs to mutate group.
*
- * @param databaseName The databaseName the document is in.
+ * @param databaseName The databaseName the document is in.
* @param queryExpression Query String to search.
- * @param searchSpec Defines what and how to remove
+ * @param searchSpec Defines what and how to remove
* @throws AppSearchException on IcingSearchEngine error.
*/
- public void removeByQuery(@NonNull String databaseName, @NonNull String queryExpression,
+ public void removeByQuery(
+ @NonNull String databaseName,
+ @NonNull String queryExpression,
@NonNull SearchSpec searchSpec)
throws AppSearchException {
-
- SearchSpecProto searchSpecProto =
- SearchSpecToProtoConverter.toSearchSpecProto(searchSpec);
- SearchSpecProto.Builder searchSpecBuilder = searchSpecProto.toBuilder()
- .setQuery(queryExpression);
+ SearchSpecProto searchSpecProto = SearchSpecToProtoConverter.toSearchSpecProto(searchSpec);
+ SearchSpecProto.Builder searchSpecBuilder =
+ searchSpecProto.toBuilder().setQuery(queryExpression);
DeleteResultProto deleteResultProto;
mReadWriteLock.writeLock().lock();
try {
// Only rewrite SearchSpec for non empty database.
// rewriteSearchSpecForNonEmptyDatabase will return false for empty database, we
// should skip sending request to Icing and return in here.
- if (!rewriteSearchSpecForDatabases(searchSpecBuilder,
- Collections.singleton(databaseName))) {
+ if (!rewriteSearchSpecForDatabasesLocked(
+ searchSpecBuilder, Collections.singleton(databaseName))) {
return;
}
- deleteResultProto = mIcingSearchEngine.deleteByQuery(
- searchSpecBuilder.build());
- checkForOptimize(/* force= */true);
+ deleteResultProto = mIcingSearchEngineLocked.deleteByQuery(searchSpecBuilder.build());
+ checkForOptimizeLocked(/* force= */ true);
} finally {
mReadWriteLock.writeLock().unlock();
}
// It seems that the caller wants to get success if the data matching the query is not in
// the DB because it was not there or was successfully deleted.
- checkCodeOneOf(deleteResultProto.getStatus(),
- StatusProto.Code.OK, StatusProto.Code.NOT_FOUND);
+ checkCodeOneOf(
+ deleteResultProto.getStatus(), StatusProto.Code.OK, StatusProto.Code.NOT_FOUND);
}
/**
@@ -475,36 +581,53 @@ public final class AppSearchImpl {
*
* @throws AppSearchException on IcingSearchEngine error.
*/
- @VisibleForTesting
- public void reset() throws AppSearchException {
+ private void reset() throws AppSearchException {
ResetResultProto resetResultProto;
mReadWriteLock.writeLock().lock();
try {
- resetResultProto = mIcingSearchEngine.reset();
- mOptimizeIntervalCount = 0;
- mSchemaMap.clear();
- mNamespaceMap.clear();
+ resetResultProto = mIcingSearchEngineLocked.reset();
+ mOptimizeIntervalCountLocked = 0;
+ mSchemaMapLocked.clear();
+ mNamespaceMapLocked.clear();
+
+ // Must be called after everything else since VisibilityStore may repopulate
+ // IcingSearchEngine with an initial schema.
+ mVisibilityStoreLocked.handleReset();
} finally {
mReadWriteLock.writeLock().unlock();
}
checkSuccess(resetResultProto.getStatus());
}
+ /** Wrapper around schema changes */
+ @VisibleForTesting
+ static class RewrittenSchemaResults {
+ // Any database-qualified types that used to exist in the schema, but are deleted in the
+ // new one.
+ final Set<String> mDeletedQualifiedTypes = new ArraySet<>();
+
+ // Database-qualified types that were part of the new schema.
+ final Set<String> mRewrittenQualifiedTypes = new ArraySet<>();
+ }
+
/**
* Rewrites all types mentioned in the given {@code newSchema} to prepend {@code prefix}.
* Rewritten types will be added to the {@code existingSchema}.
*
- * @param databaseName The name of the database where this schema lives.
+ * @param databaseName The name of the database where this schema lives.
* @param existingSchema A schema that may contain existing types from across all database
- * instances. Will be mutated to contain the properly rewritten schema
- * types from {@code newSchema}.
- * @param newSchema Schema with types to add to the {@code existingSchema}.
- * @return a Set contains all remaining qualified schema type names in given database.
+ * instances. Will be mutated to contain the properly rewritten schema types from {@code
+ * newSchema}.
+ * @param newSchema Schema with types to add to the {@code existingSchema}.
+ * @return a RewrittenSchemaResults contains all qualified schema type names in the given
+ * database as well as a set of schema types that were deleted from the database.
*/
@VisibleForTesting
- Set<String> rewriteSchema(@NonNull String databaseName,
+ static RewrittenSchemaResults rewriteSchema(
+ @NonNull String databaseName,
@NonNull SchemaProto.Builder existingSchema,
- @NonNull SchemaProto newSchema) throws AppSearchException {
+ @NonNull SchemaProto newSchema)
+ throws AppSearchException {
String prefix = getDatabasePrefix(databaseName);
HashMap<String, SchemaTypeConfigProto> newTypesToProto = new HashMap<>();
// Rewrite the schema type to include the typePrefix.
@@ -523,8 +646,7 @@ public final class AppSearchImpl {
PropertyConfigProto.Builder propertyConfigBuilder =
typeConfigBuilder.getProperties(propertyIdx).toBuilder();
if (!propertyConfigBuilder.getSchemaType().isEmpty()) {
- String newPropertySchemaType =
- prefix + propertyConfigBuilder.getSchemaType();
+ String newPropertySchemaType = prefix + propertyConfigBuilder.getSchemaType();
propertyConfigBuilder.setSchemaType(newPropertySchemaType);
typeConfigBuilder.setProperties(propertyIdx, propertyConfigBuilder);
}
@@ -533,7 +655,9 @@ public final class AppSearchImpl {
newTypesToProto.put(newSchemaType, typeConfigBuilder.build());
}
- Set<String> newSchemaTypesName = newTypesToProto.keySet();
+ // newTypesToProto is modified below, so we need a copy first
+ RewrittenSchemaResults rewrittenSchemaResults = new RewrittenSchemaResults();
+ rewrittenSchemaResults.mRewrittenQualifiedTypes.addAll(newTypesToProto.keySet());
// Combine the existing schema (which may have types from other databases) with this
// database's new schema. Modifies the existingSchemaBuilder.
@@ -548,26 +672,26 @@ public final class AppSearchImpl {
// All types existing before but not in newSchema should be removed.
existingSchema.removeTypes(i);
--i;
+ rewrittenSchemaResults.mDeletedQualifiedTypes.add(schemaType);
}
}
// We've been removing existing types from newTypesToProto, so everything that remains is
// new.
existingSchema.addAllTypes(newTypesToProto.values());
- return newSchemaTypesName;
+ return rewrittenSchemaResults;
}
/**
- * Prepends {@code prefix} to all types and namespaces mentioned anywhere in
- * {@code documentBuilder}.
+ * Prepends {@code prefix} to all types and namespaces mentioned anywhere in {@code
+ * documentBuilder}.
*
* @param documentBuilder The document to mutate
- * @param prefix The prefix to add
+ * @param prefix The prefix to add
*/
@VisibleForTesting
- void addPrefixToDocument(
- @NonNull DocumentProto.Builder documentBuilder,
- @NonNull String prefix) {
+ static void addPrefixToDocument(
+ @NonNull DocumentProto.Builder documentBuilder, @NonNull String prefix) {
// Rewrite the type name to include/remove the prefix.
String newSchema = prefix + documentBuilder.getSchema();
documentBuilder.setSchema(newSchema);
@@ -595,27 +719,17 @@ public final class AppSearchImpl {
}
/**
- * Removes any database names from types and namespaces mentioned anywhere in
- * {@code documentBuilder}.
+ * Removes any database names from types and namespaces mentioned anywhere in {@code
+ * documentBuilder}.
*
* @param documentBuilder The document to mutate
*/
@VisibleForTesting
- void removeDatabasesFromDocument(@NonNull DocumentProto.Builder documentBuilder) {
- int delimiterIndex;
- if ((delimiterIndex = documentBuilder.getSchema().indexOf(DATABASE_DELIMITER)) != -1) {
- // Rewrite the type name to remove the prefix.
- // Add 1 to include the char size of the DATABASE_DELIMITER
- String newSchema = documentBuilder.getSchema().substring(delimiterIndex + 1);
- documentBuilder.setSchema(newSchema);
- }
-
- if ((delimiterIndex = documentBuilder.getNamespace().indexOf(DATABASE_DELIMITER)) != -1) {
- // Rewrite the namespace to remove the prefix.
- // Add 1 to include the char size of the DATABASE_DELIMITER
- String newNamespace = documentBuilder.getNamespace().substring(delimiterIndex + 1);
- documentBuilder.setNamespace(newNamespace);
- }
+ static void removeDatabasesFromDocument(@NonNull DocumentProto.Builder documentBuilder)
+ throws AppSearchException {
+ // Rewrite the type name and namespace to remove the prefix.
+ documentBuilder.setSchema(removeDatabasePrefix(documentBuilder.getSchema()));
+ documentBuilder.setNamespace(removeDatabasePrefix(documentBuilder.getNamespace()));
// Recurse into derived documents
for (int propertyIdx = 0;
@@ -639,8 +753,9 @@ public final class AppSearchImpl {
/**
* Rewrites the schemaTypeFilters and namespacesFilters that exist in {@code databaseNames}.
*
- * <p>If the searchSpec has empty filter lists, all existing databases from
- * {@code databaseNames} will be added.
+ * <p>If the searchSpec has empty filter lists, all existing databases from {@code
+ * databaseNames} will be added.
+ *
* <p>This method should be only called in query methods and get the READ lock to keep thread
* safety.
*
@@ -648,11 +763,11 @@ public final class AppSearchImpl {
*/
@VisibleForTesting
@GuardedBy("mReadWriteLock")
- boolean rewriteSearchSpecForDatabases(
+ boolean rewriteSearchSpecForDatabasesLocked(
@NonNull SearchSpecProto.Builder searchSpecBuilder,
@NonNull Set<String> databaseNames) {
// Create a copy since retainAll() modifies the original set.
- Set<String> existingDatabases = new HashSet<>(mNamespaceMap.keySet());
+ Set<String> existingDatabases = new ArraySet<>(mNamespaceMapLocked.keySet());
existingDatabases.retainAll(databaseNames);
if (existingDatabases.isEmpty()) {
@@ -669,29 +784,29 @@ public final class AppSearchImpl {
// Rewrite filters to include a database prefix.
for (String databaseName : existingDatabases) {
- Set<String> existingSchemaTypes = mSchemaMap.get(databaseName);
+ Set<String> existingSchemaTypes = mSchemaMapLocked.get(databaseName);
+ String databaseNamePrefix = getDatabasePrefix(databaseName);
if (schemaTypeFilters.isEmpty()) {
// Include all schema types
searchSpecBuilder.addAllSchemaTypeFilters(existingSchemaTypes);
} else {
// Qualify the given schema types
- for (String schemaType : schemaTypeFilters) {
- String qualifiedType = getDatabasePrefix(databaseName) + schemaType;
+ for (int i = 0; i < schemaTypeFilters.size(); i++) {
+ String qualifiedType = databaseNamePrefix + schemaTypeFilters.get(i);
if (existingSchemaTypes.contains(qualifiedType)) {
searchSpecBuilder.addSchemaTypeFilters(qualifiedType);
}
-
}
}
- Set<String> existingNamespaces = mNamespaceMap.get(databaseName);
+ Set<String> existingNamespaces = mNamespaceMapLocked.get(databaseName);
if (namespaceFilters.isEmpty()) {
// Include all namespaces
searchSpecBuilder.addAllNamespaceFilters(existingNamespaces);
} else {
// Qualify the given namespaces.
- for (String namespace : namespaceFilters) {
- String qualifiedNamespace = getDatabasePrefix(databaseName) + namespace;
+ for (int i = 0; i < namespaceFilters.size(); i++) {
+ String qualifiedNamespace = databaseNamePrefix + namespaceFilters.get(i);
if (existingNamespaces.contains(qualifiedNamespace)) {
searchSpecBuilder.addNamespaceFilters(qualifiedNamespace);
}
@@ -703,35 +818,71 @@ public final class AppSearchImpl {
}
@VisibleForTesting
- SchemaProto getSchemaProto() throws AppSearchException {
- GetSchemaResultProto schemaProto = mIcingSearchEngine.getSchema();
+ @GuardedBy("mReadWriteLock")
+ SchemaProto getSchemaProtoLocked() throws AppSearchException {
+ GetSchemaResultProto schemaProto = mIcingSearchEngineLocked.getSchema();
// TODO(b/161935693) check GetSchemaResultProto is success or not. Call reset() if it's not.
// TODO(b/161935693) only allow GetSchemaResultProto NOT_FOUND on first run
checkCodeOneOf(schemaProto.getStatus(), StatusProto.Code.OK, StatusProto.Code.NOT_FOUND);
return schemaProto.getSchema();
}
+ /** Returns true if {@code databaseName} has a {@code schemaType} */
+ @GuardedBy("mReadWriteLock")
+ boolean hasSchemaTypeLocked(@NonNull String databaseName, @NonNull String schemaType) {
+ Preconditions.checkNotNull(databaseName);
+ Preconditions.checkNotNull(schemaType);
+
+ Set<String> schemaTypes = mSchemaMapLocked.get(databaseName);
+ if (schemaTypes == null) {
+ return false;
+ }
+
+ return schemaTypes.contains(getDatabasePrefix(databaseName) + schemaType);
+ }
+
+ /** Returns a set of all databases AppSearchImpl knows about. */
+ @GuardedBy("mReadWriteLock")
@NonNull
- private String getDatabasePrefix(@NonNull String databaseName) {
+ Set<String> getDatabasesLocked() {
+ return mSchemaMapLocked.keySet();
+ }
+
+ @NonNull
+ private static String getDatabasePrefix(@NonNull String databaseName) {
// TODO(b/170370381): Reconsider the way we separate database names for security reasons.
return databaseName + DATABASE_DELIMITER;
}
@NonNull
- private String getDatabaseName(@NonNull String prefixedValue) throws AppSearchException {
+ private static String removeDatabasePrefix(@NonNull String prefixedString)
+ throws AppSearchException {
+ int delimiterIndex;
+ if ((delimiterIndex = prefixedString.indexOf(DATABASE_DELIMITER)) != -1) {
+ // Add 1 to include the char size of the DATABASE_DELIMITER
+ return prefixedString.substring(delimiterIndex + 1);
+ }
+ throw new AppSearchException(
+ AppSearchResult.RESULT_UNKNOWN_ERROR,
+ "The prefixed value doesn't contains a valid database name.");
+ }
+
+ @NonNull
+ private static String getDatabaseName(@NonNull String prefixedValue) throws AppSearchException {
int delimiterIndex = prefixedValue.indexOf(DATABASE_DELIMITER);
if (delimiterIndex == -1) {
- throw new AppSearchException(AppSearchResult.RESULT_UNKNOWN_ERROR,
+ throw new AppSearchException(
+ AppSearchResult.RESULT_UNKNOWN_ERROR,
"The databaseName prefixed value doesn't contains a valid database name.");
}
return prefixedValue.substring(0, delimiterIndex);
}
- @GuardedBy("mReadWriteLock")
- private void addToMap(Map<String, Set<String>> map, String databaseName, String prefixedValue) {
+ private static void addToMap(
+ Map<String, Set<String>> map, String databaseName, String prefixedValue) {
Set<String> values = map.get(databaseName);
if (values == null) {
- values = new HashSet<>();
+ values = new ArraySet<>();
map.put(databaseName, values);
}
values.add(prefixedValue);
@@ -742,15 +893,15 @@ public final class AppSearchImpl {
*
* @throws AppSearchException on error codes.
*/
- private void checkSuccess(StatusProto statusProto) throws AppSearchException {
+ private static void checkSuccess(StatusProto statusProto) throws AppSearchException {
checkCodeOneOf(statusProto, StatusProto.Code.OK);
}
/**
- * Checks the given status code is one of the provided codes, and throws an
- * {@link AppSearchException} if it is not.
+ * Checks the given status code is one of the provided codes, and throws an {@link
+ * AppSearchException} if it is not.
*/
- private void checkCodeOneOf(StatusProto statusProto, StatusProto.Code... codes)
+ private static void checkCodeOneOf(StatusProto statusProto, StatusProto.Code... codes)
throws AppSearchException {
for (int i = 0; i < codes.length; i++) {
if (codes[i] == statusProto.getCode()) {
@@ -774,27 +925,28 @@ public final class AppSearchImpl {
*
* <p>This method should be only called in mutate methods and get the WRITE lock to keep thread
* safety.
- * <p>{@link IcingSearchEngine#optimize()} should be called only if
- * {@link GetOptimizeInfoResultProto} shows there is enough resources could be released.
- * <p>{@link IcingSearchEngine#getOptimizeInfo()} should be called once per
- * {@link #CHECK_OPTIMIZE_INTERVAL} of remove executions.
+ *
+ * <p>{@link IcingSearchEngine#optimize()} should be called only if {@link
+ * GetOptimizeInfoResultProto} shows there is enough resources could be released.
+ *
+ * <p>{@link IcingSearchEngine#getOptimizeInfo()} should be called once per {@link
+ * #CHECK_OPTIMIZE_INTERVAL} of remove executions.
*
* @param force whether we should directly call {@link IcingSearchEngine#getOptimizeInfo()}.
*/
@GuardedBy("mReadWriteLock")
- private void checkForOptimize(boolean force) throws AppSearchException {
- ++mOptimizeIntervalCount;
- if (force || mOptimizeIntervalCount >= CHECK_OPTIMIZE_INTERVAL) {
- mOptimizeIntervalCount = 0;
- GetOptimizeInfoResultProto optimizeInfo = getOptimizeInfoResult();
+ private void checkForOptimizeLocked(boolean force) throws AppSearchException {
+ ++mOptimizeIntervalCountLocked;
+ if (force || mOptimizeIntervalCountLocked >= CHECK_OPTIMIZE_INTERVAL) {
+ mOptimizeIntervalCountLocked = 0;
+ GetOptimizeInfoResultProto optimizeInfo = getOptimizeInfoResultLocked();
checkSuccess(optimizeInfo.getStatus());
// Second threshold, decide when to call optimize().
if (optimizeInfo.getOptimizableDocs() >= OPTIMIZE_THRESHOLD_DOC_COUNT
- || optimizeInfo.getEstimatedOptimizableBytes()
- >= OPTIMIZE_THRESHOLD_BYTES) {
+ || optimizeInfo.getEstimatedOptimizableBytes() >= OPTIMIZE_THRESHOLD_BYTES) {
// TODO(b/155939114): call optimize in the same thread will slow down api calls
// significantly. Move this call to background.
- OptimizeResultProto optimizeResultProto = mIcingSearchEngine.optimize();
+ OptimizeResultProto optimizeResultProto = mIcingSearchEngineLocked.optimize();
checkSuccess(optimizeResultProto.getStatus());
}
// TODO(b/147699081): Return OptimizeResultProto & log lost data detail once we add
@@ -804,8 +956,8 @@ public final class AppSearchImpl {
}
/** Remove the rewritten schema types from any result documents. */
- private SearchResultPage rewriteSearchResultProto(
- @NonNull SearchResultProto searchResultProto) {
+ private static SearchResultPage rewriteSearchResultProto(
+ @NonNull SearchResultProto searchResultProto) throws AppSearchException {
SearchResultProto.Builder resultsBuilder = searchResultProto.toBuilder();
for (int i = 0; i < searchResultProto.getResultsCount(); i++) {
if (searchResultProto.getResults(i).hasDocument()) {
@@ -820,40 +972,48 @@ public final class AppSearchImpl {
return SearchResultToProtoConverter.convertToSearchResultPage(resultsBuilder);
}
+ @GuardedBy("mReadWriteLock")
+ @VisibleForTesting
+ GetOptimizeInfoResultProto getOptimizeInfoResultLocked() {
+ return mIcingSearchEngineLocked.getOptimizeInfo();
+ }
+
+ @GuardedBy("mReadWriteLock")
@VisibleForTesting
- GetOptimizeInfoResultProto getOptimizeInfoResult() {
- return mIcingSearchEngine.getOptimizeInfo();
+ VisibilityStore getVisibilityStoreLocked() {
+ return mVisibilityStoreLocked;
}
/**
- * Converts an erroneous status code to an AppSearchException. Callers should ensure that
- * the status code is not OK or WARNING_DATA_LOSS.
+ * Converts an erroneous status code to an AppSearchException. Callers should ensure that the
+ * status code is not OK or WARNING_DATA_LOSS.
*
* @param statusProto StatusProto with error code and message to translate into
- * AppSearchException.
+ * AppSearchException.
* @return AppSearchException with the parallel error code.
*/
- private AppSearchException statusProtoToAppSearchException(StatusProto statusProto) {
+ private static AppSearchException statusProtoToAppSearchException(StatusProto statusProto) {
switch (statusProto.getCode()) {
case INVALID_ARGUMENT:
- return new AppSearchException(AppSearchResult.RESULT_INVALID_ARGUMENT,
- statusProto.getMessage());
+ return new AppSearchException(
+ AppSearchResult.RESULT_INVALID_ARGUMENT, statusProto.getMessage());
case NOT_FOUND:
- return new AppSearchException(AppSearchResult.RESULT_NOT_FOUND,
- statusProto.getMessage());
+ return new AppSearchException(
+ AppSearchResult.RESULT_NOT_FOUND, statusProto.getMessage());
case FAILED_PRECONDITION:
// Fallthrough
case ABORTED:
// Fallthrough
case INTERNAL:
- return new AppSearchException(AppSearchResult.RESULT_INTERNAL_ERROR,
- statusProto.getMessage());
+ return new AppSearchException(
+ AppSearchResult.RESULT_INTERNAL_ERROR, statusProto.getMessage());
case OUT_OF_SPACE:
- return new AppSearchException(AppSearchResult.RESULT_OUT_OF_SPACE,
- statusProto.getMessage());
+ return new AppSearchException(
+ AppSearchResult.RESULT_OUT_OF_SPACE, statusProto.getMessage());
default:
// Some unknown/unsupported error
- return new AppSearchException(AppSearchResult.RESULT_UNKNOWN_ERROR,
+ return new AppSearchException(
+ AppSearchResult.RESULT_UNKNOWN_ERROR,
"Unknown IcingSearchEngine status code: " + statusProto.getCode());
}
}
diff --git a/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/VisibilityStore.java b/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/VisibilityStore.java
new file mode 100644
index 000000000000..47228221a1f5
--- /dev/null
+++ b/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/VisibilityStore.java
@@ -0,0 +1,257 @@
+/*
+ * 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 com.android.server.appsearch.external.localstorage;
+
+import android.annotation.NonNull;
+import android.app.appsearch.AppSearchResult;
+import android.app.appsearch.AppSearchSchema;
+import android.app.appsearch.GenericDocument;
+import android.app.appsearch.exceptions.AppSearchException;
+import android.util.ArrayMap;
+import android.util.ArraySet;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.util.Preconditions;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * Manages any visibility settings for all the databases that AppSearchImpl knows about. Persists
+ * the visibility settings and reloads them on initialization.
+ *
+ * <p>The VisibilityStore creates a document for each database. This document holds the visibility
+ * settings that apply to that database. The VisibilityStore also creates a schema for these
+ * documents and has its own database so that its data doesn't interfere with any clients' data. It
+ * persists the document and schema through AppSearchImpl.
+ *
+ * <p>These visibility settings are used to ensure AppSearch queries respect the clients' settings
+ * on who their data is visible to.
+ *
+ * <p>This class doesn't handle any locking itself. Its callers should handle the locking at a
+ * higher level.
+ *
+ * <p>NOTE: This class holds an instance of AppSearchImpl and AppSearchImpl holds an instance of
+ * this class. Take care to not cause any circular dependencies.
+ */
+class VisibilityStore {
+ // Schema type for documents that hold AppSearch's metadata, e.g. visibility settings
+ @VisibleForTesting static final String SCHEMA_TYPE = "Visibility";
+ // Property that holds the list of platform-hidden schemas, as part of the visibility
+ // settings.
+ @VisibleForTesting static final String PLATFORM_HIDDEN_PROPERTY = "platformHidden";
+ // Database name to prefix all visibility schemas and documents with. Special-cased to
+ // minimize the chance of collision with a client-supplied database.
+ @VisibleForTesting static final String DATABASE_NAME = "$$__AppSearch__Database";
+ // Namespace of documents that contain visibility settings
+ private static final String NAMESPACE = "namespace";
+ private final AppSearchImpl mAppSearchImpl;
+
+ // The map contains schemas that are platform-hidden for each database. All schemas in the map
+ // have a database name prefix.
+ private final Map<String, Set<String>> mPlatformHiddenMap = new ArrayMap<>();
+
+ /**
+ * Creates an uninitialized VisibilityStore object. Callers must also call {@link #initialize()}
+ * before using the object.
+ *
+ * @param appSearchImpl AppSearchImpl instance
+ */
+ VisibilityStore(@NonNull AppSearchImpl appSearchImpl) {
+ mAppSearchImpl = appSearchImpl;
+ }
+
+ /**
+ * Initializes schemas and member variables to track visibility settings.
+ *
+ * <p>This is kept separate from the constructor because this will call methods on
+ * AppSearchImpl. Some may even then recursively call back into VisibilityStore (for example,
+ * {@link AppSearchImpl#setSchema} will call {@link #updateSchemas}. We need to have both
+ * AppSearchImpl and VisibilityStore fully initialized for this call flow to work.
+ *
+ * @throws AppSearchException AppSearchException on AppSearchImpl error.
+ */
+ public void initialize() throws AppSearchException {
+ if (!mAppSearchImpl.hasSchemaTypeLocked(DATABASE_NAME, SCHEMA_TYPE)) {
+ // Schema type doesn't exist yet. Add it.
+ mAppSearchImpl.setSchema(
+ DATABASE_NAME,
+ Collections.singleton(
+ new AppSearchSchema.Builder(SCHEMA_TYPE)
+ .addProperty(
+ new AppSearchSchema.PropertyConfig.Builder(
+ PLATFORM_HIDDEN_PROPERTY)
+ .setDataType(
+ AppSearchSchema.PropertyConfig
+ .DATA_TYPE_STRING)
+ .setCardinality(
+ AppSearchSchema.PropertyConfig
+ .CARDINALITY_REPEATED)
+ .build())
+ .build()),
+ /*forceOverride=*/ false);
+ }
+
+ // Populate visibility settings map
+ for (String database : mAppSearchImpl.getDatabasesLocked()) {
+ if (database.equals(DATABASE_NAME)) {
+ // Our own database. Skip
+ continue;
+ }
+
+ try {
+ // Note: We use the other clients' database names as uris
+ GenericDocument document =
+ mAppSearchImpl.getDocument(DATABASE_NAME, NAMESPACE, /*uri=*/ database);
+
+ String[] schemas = document.getPropertyStringArray(PLATFORM_HIDDEN_PROPERTY);
+ mPlatformHiddenMap.put(database, new ArraySet<>(Arrays.asList(schemas)));
+ } catch (AppSearchException e) {
+ if (e.getResultCode() == AppSearchResult.RESULT_NOT_FOUND) {
+ // TODO(b/172068212): This indicates some desync error. We were expecting a
+ // document, but didn't find one. Should probably reset AppSearch instead of
+ // ignoring it.
+ continue;
+ }
+ // Otherwise, this is some other error we should pass up.
+ throw e;
+ }
+ }
+ }
+
+ /**
+ * Update visibility settings for the {@code databaseName}.
+ *
+ * @param schemasToRemove Database-prefixed schemas that should be removed
+ */
+ public void updateSchemas(@NonNull String databaseName, @NonNull Set<String> schemasToRemove)
+ throws AppSearchException {
+ Preconditions.checkNotNull(databaseName);
+ Preconditions.checkNotNull(schemasToRemove);
+
+ GenericDocument visibilityDocument;
+ try {
+ visibilityDocument =
+ mAppSearchImpl.getDocument(DATABASE_NAME, NAMESPACE, /*uri=*/ databaseName);
+ } catch (AppSearchException e) {
+ if (e.getResultCode() == AppSearchResult.RESULT_NOT_FOUND) {
+ // This might be the first time we're seeing visibility changes for a database.
+ // Create a new visibility document.
+ mAppSearchImpl.putDocument(
+ DATABASE_NAME,
+ new GenericDocument.Builder(/*uri=*/ databaseName, SCHEMA_TYPE)
+ .setNamespace(NAMESPACE)
+ .build());
+
+ // Since we know there was nothing that existed before, we don't need to remove
+ // anything either. Return early.
+ return;
+ }
+ // Otherwise, this is some real error we should pass up.
+ throw e;
+ }
+
+ String[] hiddenSchemas =
+ visibilityDocument.getPropertyStringArray(PLATFORM_HIDDEN_PROPERTY);
+ if (hiddenSchemas == null) {
+ // Nothing to remove.
+ return;
+ }
+
+ // Create a new set so we can remove from it.
+ Set<String> remainingSchemas = new ArraySet<>(Arrays.asList(hiddenSchemas));
+ boolean changed = remainingSchemas.removeAll(schemasToRemove);
+ if (!changed) {
+ // Nothing was actually removed. Can return early.
+ return;
+ }
+
+ // Update our persisted document
+ // TODO(b/171882200): Switch to a .toBuilder API when it's available.
+ GenericDocument.Builder newVisibilityDocument =
+ new GenericDocument.Builder(/*uri=*/ databaseName, SCHEMA_TYPE)
+ .setNamespace(NAMESPACE);
+ if (!remainingSchemas.isEmpty()) {
+ newVisibilityDocument.setPropertyString(
+ PLATFORM_HIDDEN_PROPERTY, remainingSchemas.toArray(new String[0]));
+ }
+ mAppSearchImpl.putDocument(DATABASE_NAME, newVisibilityDocument.build());
+
+ // Update derived data structures
+ mPlatformHiddenMap.put(databaseName, remainingSchemas);
+ }
+
+ /**
+ * Sets visibility settings for {@code databaseName}. Any previous visibility settings will be
+ * overwritten.
+ *
+ * @param databaseName Database name that owns the {@code platformHiddenSchemas}.
+ * @param platformHiddenSchemas Set of database-qualified schemas that should be hidden from the
+ * platform.
+ * @throws AppSearchException on AppSearchImpl error.
+ */
+ public void setVisibility(
+ @NonNull String databaseName, @NonNull Set<String> platformHiddenSchemas)
+ throws AppSearchException {
+ Preconditions.checkNotNull(databaseName);
+ Preconditions.checkNotNull(platformHiddenSchemas);
+
+ // Persist the document
+ GenericDocument.Builder visibilityDocument =
+ new GenericDocument.Builder(/*uri=*/ databaseName, SCHEMA_TYPE)
+ .setNamespace(NAMESPACE);
+ if (!platformHiddenSchemas.isEmpty()) {
+ visibilityDocument.setPropertyString(
+ PLATFORM_HIDDEN_PROPERTY, platformHiddenSchemas.toArray(new String[0]));
+ }
+ mAppSearchImpl.putDocument(DATABASE_NAME, visibilityDocument.build());
+
+ // Update derived data structures.
+ mPlatformHiddenMap.put(databaseName, platformHiddenSchemas);
+ }
+
+ /**
+ * Returns the set of database-qualified schemas in {@code databaseName} that are hidden from
+ * the platform.
+ *
+ * @param databaseName Database name to retrieve schemas for
+ * @return Set of database-qualified schemas that are hidden from the platform. Empty set if
+ * none exist.
+ */
+ @NonNull
+ public Set<String> getPlatformHiddenSchemas(@NonNull String databaseName) {
+ Preconditions.checkNotNull(databaseName);
+ Set<String> platformHiddenSchemas = mPlatformHiddenMap.get(databaseName);
+ if (platformHiddenSchemas == null) {
+ return Collections.emptySet();
+ }
+ return platformHiddenSchemas;
+ }
+
+ /**
+ * Handles an {@link AppSearchImpl#reset()} by clearing any cached state and resetting to a
+ * first-initialized state.
+ *
+ * @throws AppSearchException on AppSearchImpl error.
+ */
+ public void handleReset() throws AppSearchException {
+ mPlatformHiddenMap.clear();
+ initialize();
+ }
+}
diff --git a/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/converter/GenericDocumentToProtoConverter.java b/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/converter/GenericDocumentToProtoConverter.java
index 60684f09a202..8f4e7ff69d7c 100644
--- a/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/converter/GenericDocumentToProtoConverter.java
+++ b/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/converter/GenericDocumentToProtoConverter.java
@@ -17,8 +17,8 @@
package com.android.server.appsearch.external.localstorage.converter;
import android.annotation.NonNull;
-
import android.app.appsearch.GenericDocument;
+
import com.android.internal.util.Preconditions;
import com.google.android.icing.proto.DocumentProto;
@@ -30,9 +30,9 @@ import java.util.Collections;
/**
* Translates a {@link GenericDocument} into a {@link DocumentProto}.
+ *
* @hide
*/
-
public final class GenericDocumentToProtoConverter {
private GenericDocumentToProtoConverter() {}
@@ -42,7 +42,8 @@ public final class GenericDocumentToProtoConverter {
public static DocumentProto convert(@NonNull GenericDocument document) {
Preconditions.checkNotNull(document);
DocumentProto.Builder mProtoBuilder = DocumentProto.newBuilder();
- mProtoBuilder.setUri(document.getUri())
+ mProtoBuilder
+ .setUri(document.getUri())
.setSchema(document.getSchemaType())
.setNamespace(document.getNamespace())
.setScore(document.getScore())
diff --git a/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/converter/SchemaToProtoConverter.java b/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/converter/SchemaToProtoConverter.java
index 403711f29544..642c2a713930 100644
--- a/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/converter/SchemaToProtoConverter.java
+++ b/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/converter/SchemaToProtoConverter.java
@@ -17,34 +17,34 @@
package com.android.server.appsearch.external.localstorage.converter;
import android.annotation.NonNull;
-
import android.app.appsearch.AppSearchSchema;
+
import com.android.internal.util.Preconditions;
-import com.google.android.icing.proto.IndexingConfig;
import com.google.android.icing.proto.PropertyConfigProto;
import com.google.android.icing.proto.SchemaTypeConfigProto;
+import com.google.android.icing.proto.StringIndexingConfig;
import com.google.android.icing.proto.TermMatchType;
import java.util.List;
/**
* Translates an {@link AppSearchSchema} into a {@link SchemaTypeConfigProto}.
+ *
* @hide
*/
-
public final class SchemaToProtoConverter {
private SchemaToProtoConverter() {}
/**
- * Converts an {@link android.app.appsearch.AppSearchSchema} into a
- * {@link SchemaTypeConfigProto}.
+ * Converts an {@link android.app.appsearch.AppSearchSchema} into a {@link
+ * SchemaTypeConfigProto}.
*/
@NonNull
public static SchemaTypeConfigProto convert(@NonNull AppSearchSchema schema) {
Preconditions.checkNotNull(schema);
SchemaTypeConfigProto.Builder protoBuilder =
- SchemaTypeConfigProto.newBuilder().setSchemaType(schema.getSchemaTypeName());
+ SchemaTypeConfigProto.newBuilder().setSchemaType(schema.getSchemaType());
List<AppSearchSchema.PropertyConfig> properties = schema.getProperties();
for (int i = 0; i < properties.size(); i++) {
PropertyConfigProto propertyProto = convertProperty(properties.get(i));
@@ -57,9 +57,9 @@ public final class SchemaToProtoConverter {
private static PropertyConfigProto convertProperty(
@NonNull AppSearchSchema.PropertyConfig property) {
Preconditions.checkNotNull(property);
- PropertyConfigProto.Builder propertyConfigProto = PropertyConfigProto.newBuilder()
- .setPropertyName(property.getName());
- IndexingConfig.Builder indexingConfig = IndexingConfig.newBuilder();
+ PropertyConfigProto.Builder propertyConfigProto =
+ PropertyConfigProto.newBuilder().setPropertyName(property.getName());
+ StringIndexingConfig.Builder indexingConfig = StringIndexingConfig.newBuilder();
// Set dataType
@AppSearchSchema.PropertyConfig.DataType int dataType = property.getDataType();
@@ -104,17 +104,17 @@ public final class SchemaToProtoConverter {
indexingConfig.setTermMatchType(termMatchTypeProto);
// Set tokenizerType
- @AppSearchSchema.PropertyConfig.TokenizerType int tokenizerType =
- property.getTokenizerType();
- IndexingConfig.TokenizerType.Code tokenizerTypeProto =
- IndexingConfig.TokenizerType.Code.forNumber(tokenizerType);
+ @AppSearchSchema.PropertyConfig.TokenizerType
+ int tokenizerType = property.getTokenizerType();
+ StringIndexingConfig.TokenizerType.Code tokenizerTypeProto =
+ StringIndexingConfig.TokenizerType.Code.forNumber(tokenizerType);
if (tokenizerTypeProto == null) {
throw new IllegalArgumentException("Invalid tokenizerType: " + tokenizerType);
}
indexingConfig.setTokenizerType(tokenizerTypeProto);
// Build!
- propertyConfigProto.setIndexingConfig(indexingConfig);
+ propertyConfigProto.setStringIndexingConfig(indexingConfig);
return propertyConfigProto.build();
}
}
diff --git a/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/converter/SearchResultToProtoConverter.java b/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/converter/SearchResultToProtoConverter.java
index 4310b4216266..b91a393cab4a 100644
--- a/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/converter/SearchResultToProtoConverter.java
+++ b/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/converter/SearchResultToProtoConverter.java
@@ -16,13 +16,11 @@
package com.android.server.appsearch.external.localstorage.converter;
-import android.os.Bundle;
-
import android.annotation.NonNull;
-
import android.app.appsearch.GenericDocument;
import android.app.appsearch.SearchResult;
import android.app.appsearch.SearchResultPage;
+import android.os.Bundle;
import com.google.android.icing.proto.SearchResultProto;
import com.google.android.icing.proto.SearchResultProtoOrBuilder;
@@ -36,11 +34,9 @@ import java.util.ArrayList;
*
* @hide
*/
-
public class SearchResultToProtoConverter {
private SearchResultToProtoConverter() {}
-
/** Translate a {@link SearchResultProto} into {@link SearchResultPage}. */
@NonNull
public static SearchResultPage convertToSearchResultPage(
@@ -68,8 +64,9 @@ public class SearchResultToProtoConverter {
for (int i = 0; i < proto.getSnippet().getEntriesCount(); i++) {
SnippetProto.EntryProto entry = proto.getSnippet().getEntries(i);
for (int j = 0; j < entry.getSnippetMatchesCount(); j++) {
- Bundle matchInfoBundle = convertToMatchInfoBundle(
- entry.getSnippetMatches(j), entry.getPropertyName());
+ Bundle matchInfoBundle =
+ convertToMatchInfoBundle(
+ entry.getSnippetMatches(j), entry.getPropertyName());
matchList.add(matchInfoBundle);
}
}
diff --git a/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/converter/SearchSpecToProtoConverter.java b/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/converter/SearchSpecToProtoConverter.java
index 14822dcdc793..814ee4f7636a 100644
--- a/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/converter/SearchSpecToProtoConverter.java
+++ b/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/converter/SearchSpecToProtoConverter.java
@@ -17,8 +17,8 @@
package com.android.server.appsearch.external.localstorage.converter;
import android.annotation.NonNull;
-
import android.app.appsearch.SearchSpec;
+
import com.android.internal.util.Preconditions;
import com.google.android.icing.proto.ResultSpecProto;
@@ -28,9 +28,9 @@ import com.google.android.icing.proto.TermMatchType;
/**
* Translates a {@link SearchSpec} into icing search protos.
+ *
* @hide
*/
-
public final class SearchSpecToProtoConverter {
private SearchSpecToProtoConverter() {}
@@ -38,9 +38,10 @@ public final class SearchSpecToProtoConverter {
@NonNull
public static SearchSpecProto toSearchSpecProto(@NonNull SearchSpec spec) {
Preconditions.checkNotNull(spec);
- SearchSpecProto.Builder protoBuilder = SearchSpecProto.newBuilder()
- .addAllSchemaTypeFilters(spec.getSchemas())
- .addAllNamespaceFilters(spec.getNamespaces());
+ SearchSpecProto.Builder protoBuilder =
+ SearchSpecProto.newBuilder()
+ .addAllSchemaTypeFilters(spec.getSchemaTypes())
+ .addAllNamespaceFilters(spec.getNamespaces());
@SearchSpec.TermMatch int termMatchCode = spec.getTermMatch();
TermMatchType.Code termMatchCodeProto = TermMatchType.Code.forNumber(termMatchCode);
@@ -57,7 +58,7 @@ public final class SearchSpecToProtoConverter {
public static ResultSpecProto toResultSpecProto(@NonNull SearchSpec spec) {
Preconditions.checkNotNull(spec);
return ResultSpecProto.newBuilder()
- .setNumPerPage(spec.getNumPerPage())
+ .setNumPerPage(spec.getResultCountPerPage())
.setSnippetSpec(
ResultSpecProto.SnippetSpecProto.newBuilder()
.setNumToSnippet(spec.getSnippetCount())
@@ -84,8 +85,8 @@ public final class SearchSpecToProtoConverter {
ScoringSpecProto.RankingStrategy.Code rankingStrategyCodeProto =
ScoringSpecProto.RankingStrategy.Code.forNumber(rankingStrategyCode);
if (rankingStrategyCodeProto == null) {
- throw new IllegalArgumentException("Invalid result ranking strategy: "
- + rankingStrategyCode);
+ throw new IllegalArgumentException(
+ "Invalid result ranking strategy: " + rankingStrategyCode);
}
protoBuilder.setRankBy(rankingStrategyCodeProto);
diff --git a/apex/appsearch/synced_jetpack_changeid.txt b/apex/appsearch/synced_jetpack_changeid.txt
new file mode 100644
index 000000000000..a2bf0d504a1f
--- /dev/null
+++ b/apex/appsearch/synced_jetpack_changeid.txt
@@ -0,0 +1 @@
+I2decd83fab4c4d58fe38c9970f804046479c942c
diff --git a/apex/jobscheduler/framework/java/android/app/job/JobInfo.java b/apex/jobscheduler/framework/java/android/app/job/JobInfo.java
index c2d530d00058..2c8a5589ca51 100644
--- a/apex/jobscheduler/framework/java/android/app/job/JobInfo.java
+++ b/apex/jobscheduler/framework/java/android/app/job/JobInfo.java
@@ -1506,56 +1506,16 @@ public class JobInfo implements Parcelable {
* @return The job object to hand to the JobScheduler. This object is immutable.
*/
public JobInfo build() {
- // Check that network estimates require network type
- if ((mNetworkDownloadBytes > 0 || mNetworkUploadBytes > 0) && mNetworkRequest == null) {
- throw new IllegalArgumentException(
- "Can't provide estimated network usage without requiring a network");
- }
- // We can't serialize network specifiers
- if (mIsPersisted && mNetworkRequest != null
- && mNetworkRequest.networkCapabilities.getNetworkSpecifier() != null) {
- throw new IllegalArgumentException(
- "Network specifiers aren't supported for persistent jobs");
- }
- // Check that a deadline was not set on a periodic job.
- if (mIsPeriodic) {
- if (mMaxExecutionDelayMillis != 0L) {
- throw new IllegalArgumentException("Can't call setOverrideDeadline() on a " +
- "periodic job.");
- }
- if (mMinLatencyMillis != 0L) {
- throw new IllegalArgumentException("Can't call setMinimumLatency() on a " +
- "periodic job");
- }
- if (mTriggerContentUris != null) {
- throw new IllegalArgumentException("Can't call addTriggerContentUri() on a " +
- "periodic job");
- }
- }
- if (mIsPersisted) {
- if (mTriggerContentUris != null) {
- throw new IllegalArgumentException("Can't call addTriggerContentUri() on a " +
- "persisted job");
- }
- if (!mTransientExtras.isEmpty()) {
- throw new IllegalArgumentException("Can't call setTransientExtras() on a " +
- "persisted job");
- }
- if (mClipData != null) {
- throw new IllegalArgumentException("Can't call setClipData() on a " +
- "persisted job");
- }
- }
- if ((mFlags & FLAG_IMPORTANT_WHILE_FOREGROUND) != 0 && mHasEarlyConstraint) {
- throw new IllegalArgumentException("An important while foreground job cannot "
- + "have a time delay");
- }
+ // This check doesn't need to be inside enforceValidity. It's an unnecessary legacy
+ // check that would ideally be phased out instead.
if (mBackoffPolicySet && (mConstraintFlags & CONSTRAINT_FLAG_DEVICE_IDLE) != 0) {
throw new IllegalArgumentException("An idle mode job will not respect any" +
" back-off policy, so calling setBackoffCriteria with" +
" setRequiresDeviceIdle is an error.");
}
- return new JobInfo(this);
+ JobInfo jobInfo = new JobInfo(this);
+ jobInfo.enforceValidity();
+ return jobInfo;
}
/**
@@ -1570,6 +1530,59 @@ public class JobInfo implements Parcelable {
}
/**
+ * @hide
+ */
+ public void enforceValidity() {
+ // Check that network estimates require network type
+ if ((networkDownloadBytes > 0 || networkUploadBytes > 0) && networkRequest == null) {
+ throw new IllegalArgumentException(
+ "Can't provide estimated network usage without requiring a network");
+ }
+
+ // Check that a deadline was not set on a periodic job.
+ if (isPeriodic) {
+ if (maxExecutionDelayMillis != 0L) {
+ throw new IllegalArgumentException(
+ "Can't call setOverrideDeadline() on a periodic job.");
+ }
+ if (minLatencyMillis != 0L) {
+ throw new IllegalArgumentException(
+ "Can't call setMinimumLatency() on a periodic job");
+ }
+ if (triggerContentUris != null) {
+ throw new IllegalArgumentException(
+ "Can't call addTriggerContentUri() on a periodic job");
+ }
+ }
+
+ if (isPersisted) {
+ // We can't serialize network specifiers
+ if (networkRequest != null
+ && networkRequest.networkCapabilities.getNetworkSpecifier() != null) {
+ throw new IllegalArgumentException(
+ "Network specifiers aren't supported for persistent jobs");
+ }
+ if (triggerContentUris != null) {
+ throw new IllegalArgumentException(
+ "Can't call addTriggerContentUri() on a persisted job");
+ }
+ if (!transientExtras.isEmpty()) {
+ throw new IllegalArgumentException(
+ "Can't call setTransientExtras() on a persisted job");
+ }
+ if (clipData != null) {
+ throw new IllegalArgumentException(
+ "Can't call setClipData() on a persisted job");
+ }
+ }
+
+ if ((flags & FLAG_IMPORTANT_WHILE_FOREGROUND) != 0 && hasEarlyConstraint) {
+ throw new IllegalArgumentException(
+ "An important while foreground job cannot have a time delay");
+ }
+ }
+
+ /**
* Convert a priority integer into a human readable string for debugging.
* @hide
*/
diff --git a/apex/jobscheduler/framework/java/android/app/job/JobServiceEngine.java b/apex/jobscheduler/framework/java/android/app/job/JobServiceEngine.java
index ab94da843635..3d43d20e7955 100644
--- a/apex/jobscheduler/framework/java/android/app/job/JobServiceEngine.java
+++ b/apex/jobscheduler/framework/java/android/app/job/JobServiceEngine.java
@@ -17,7 +17,6 @@
package android.app.job;
import android.app.Service;
-import android.content.Context;
import android.content.Intent;
import android.os.Handler;
import android.os.IBinder;
@@ -26,8 +25,6 @@ import android.os.Message;
import android.os.RemoteException;
import android.util.Log;
-import com.android.internal.annotations.GuardedBy;
-
import java.lang.ref.WeakReference;
/**
@@ -206,8 +203,7 @@ public abstract class JobServiceEngine {
/**
* Call in to engine to report that a job has finished executing. See
- * {@link JobService#jobFinished(JobParameters, boolean)} JobService.jobFinished} for more
- * information.
+ * {@link JobService#jobFinished(JobParameters, boolean)} for more information.
*/
public void jobFinished(JobParameters params, boolean needsReschedule) {
if (params == null) {
diff --git a/apex/jobscheduler/service/java/com/android/server/DeviceIdleController.java b/apex/jobscheduler/service/java/com/android/server/DeviceIdleController.java
index 9835e18d0bfd..99892527721a 100644
--- a/apex/jobscheduler/service/java/com/android/server/DeviceIdleController.java
+++ b/apex/jobscheduler/service/java/com/android/server/DeviceIdleController.java
@@ -884,13 +884,12 @@ public class DeviceIdleController extends SystemService
private static final String KEY_MAX_IDLE_TIMEOUT = "max_idle_to";
private static final String KEY_IDLE_FACTOR = "idle_factor";
private static final String KEY_MIN_TIME_TO_ALARM = "min_time_to_alarm";
- // TODO(166121524): update flag names
- private static final String KEY_MAX_TEMP_APP_WHITELIST_DURATION =
- "max_temp_app_whitelist_duration";
- private static final String KEY_MMS_TEMP_APP_WHITELIST_DURATION =
- "mms_temp_app_whitelist_duration";
- private static final String KEY_SMS_TEMP_APP_WHITELIST_DURATION =
- "sms_temp_app_whitelist_duration";
+ private static final String KEY_MAX_TEMP_APP_ALLOWLIST_DURATION_MS =
+ "max_temp_app_allowlist_duration_ms";
+ private static final String KEY_MMS_TEMP_APP_ALLOWLIST_DURATION_MS =
+ "mms_temp_app_allowlist_duration_ms";
+ private static final String KEY_SMS_TEMP_APP_ALLOWLIST_DURATION_MS =
+ "sms_temp_app_allowlist_duration_ms";
private static final String KEY_NOTIFICATION_ALLOWLIST_DURATION_MS =
"notification_allowlist_duration_ms";
/**
@@ -949,9 +948,9 @@ public class DeviceIdleController extends SystemService
private static final float DEFAULT_IDLE_FACTOR = 2f;
private static final long DEFAULT_MIN_TIME_TO_ALARM =
!COMPRESS_TIME ? 30 * 60 * 1000L : 6 * 60 * 1000L;
- private static final long DEFAULT_MAX_TEMP_APP_WHITELIST_DURATION = 5 * 60 * 1000L;
- private static final long DEFAULT_MMS_TEMP_APP_WHITELIST_DURATION = 60 * 1000L;
- private static final long DEFAULT_SMS_TEMP_APP_WHITELIST_DURATION = 20 * 1000L;
+ private static final long DEFAULT_MAX_TEMP_APP_ALLOWLIST_DURATION_MS = 5 * 60 * 1000L;
+ private static final long DEFAULT_MMS_TEMP_APP_ALLOWLIST_DURATION_MS = 60 * 1000L;
+ private static final long DEFAULT_SMS_TEMP_APP_ALLOWLIST_DURATION_MS = 20 * 1000L;
private static final long DEFAULT_NOTIFICATION_ALLOWLIST_DURATION_MS = 30 * 1000L;
private static final boolean DEFAULT_WAIT_FOR_UNLOCK = true;
private static final float DEFAULT_PRE_IDLE_FACTOR_LONG = 1.67f;
@@ -1142,21 +1141,21 @@ public class DeviceIdleController extends SystemService
* Max amount of time to temporarily whitelist an app when it receives a high priority
* tickle.
*
- * @see #KEY_MAX_TEMP_APP_WHITELIST_DURATION
+ * @see #KEY_MAX_TEMP_APP_ALLOWLIST_DURATION_MS
*/
- public long MAX_TEMP_APP_WHITELIST_DURATION = DEFAULT_MAX_TEMP_APP_WHITELIST_DURATION;
+ public long MAX_TEMP_APP_ALLOWLIST_DURATION_MS = DEFAULT_MAX_TEMP_APP_ALLOWLIST_DURATION_MS;
/**
* Amount of time we would like to whitelist an app that is receiving an MMS.
- * @see #KEY_MMS_TEMP_APP_WHITELIST_DURATION
+ * @see #KEY_MMS_TEMP_APP_ALLOWLIST_DURATION_MS
*/
- public long MMS_TEMP_APP_WHITELIST_DURATION = DEFAULT_MMS_TEMP_APP_WHITELIST_DURATION;
+ public long MMS_TEMP_APP_ALLOWLIST_DURATION_MS = DEFAULT_MMS_TEMP_APP_ALLOWLIST_DURATION_MS;
/**
* Amount of time we would like to whitelist an app that is receiving an SMS.
- * @see #KEY_SMS_TEMP_APP_WHITELIST_DURATION
+ * @see #KEY_SMS_TEMP_APP_ALLOWLIST_DURATION_MS
*/
- public long SMS_TEMP_APP_WHITELIST_DURATION = DEFAULT_SMS_TEMP_APP_WHITELIST_DURATION;
+ public long SMS_TEMP_APP_ALLOWLIST_DURATION_MS = DEFAULT_SMS_TEMP_APP_ALLOWLIST_DURATION_MS;
/**
* Amount of time we would like to whitelist an app that is handling a
@@ -1303,20 +1302,20 @@ public class DeviceIdleController extends SystemService
MIN_TIME_TO_ALARM = properties.getLong(
KEY_MIN_TIME_TO_ALARM, DEFAULT_MIN_TIME_TO_ALARM);
break;
- case KEY_MAX_TEMP_APP_WHITELIST_DURATION:
- MAX_TEMP_APP_WHITELIST_DURATION = properties.getLong(
- KEY_MAX_TEMP_APP_WHITELIST_DURATION,
- DEFAULT_MAX_TEMP_APP_WHITELIST_DURATION);
+ case KEY_MAX_TEMP_APP_ALLOWLIST_DURATION_MS:
+ MAX_TEMP_APP_ALLOWLIST_DURATION_MS = properties.getLong(
+ KEY_MAX_TEMP_APP_ALLOWLIST_DURATION_MS,
+ DEFAULT_MAX_TEMP_APP_ALLOWLIST_DURATION_MS);
break;
- case KEY_MMS_TEMP_APP_WHITELIST_DURATION:
- MMS_TEMP_APP_WHITELIST_DURATION = properties.getLong(
- KEY_MMS_TEMP_APP_WHITELIST_DURATION,
- DEFAULT_MMS_TEMP_APP_WHITELIST_DURATION);
+ case KEY_MMS_TEMP_APP_ALLOWLIST_DURATION_MS:
+ MMS_TEMP_APP_ALLOWLIST_DURATION_MS = properties.getLong(
+ KEY_MMS_TEMP_APP_ALLOWLIST_DURATION_MS,
+ DEFAULT_MMS_TEMP_APP_ALLOWLIST_DURATION_MS);
break;
- case KEY_SMS_TEMP_APP_WHITELIST_DURATION:
- SMS_TEMP_APP_WHITELIST_DURATION = properties.getLong(
- KEY_SMS_TEMP_APP_WHITELIST_DURATION,
- DEFAULT_SMS_TEMP_APP_WHITELIST_DURATION);
+ case KEY_SMS_TEMP_APP_ALLOWLIST_DURATION_MS:
+ SMS_TEMP_APP_ALLOWLIST_DURATION_MS = properties.getLong(
+ KEY_SMS_TEMP_APP_ALLOWLIST_DURATION_MS,
+ DEFAULT_SMS_TEMP_APP_ALLOWLIST_DURATION_MS);
break;
case KEY_NOTIFICATION_ALLOWLIST_DURATION_MS:
NOTIFICATION_ALLOWLIST_DURATION_MS = properties.getLong(
@@ -1438,16 +1437,16 @@ public class DeviceIdleController extends SystemService
TimeUtils.formatDuration(MIN_TIME_TO_ALARM, pw);
pw.println();
- pw.print(" "); pw.print(KEY_MAX_TEMP_APP_WHITELIST_DURATION); pw.print("=");
- TimeUtils.formatDuration(MAX_TEMP_APP_WHITELIST_DURATION, pw);
+ pw.print(" "); pw.print(KEY_MAX_TEMP_APP_ALLOWLIST_DURATION_MS); pw.print("=");
+ TimeUtils.formatDuration(MAX_TEMP_APP_ALLOWLIST_DURATION_MS, pw);
pw.println();
- pw.print(" "); pw.print(KEY_MMS_TEMP_APP_WHITELIST_DURATION); pw.print("=");
- TimeUtils.formatDuration(MMS_TEMP_APP_WHITELIST_DURATION, pw);
+ pw.print(" "); pw.print(KEY_MMS_TEMP_APP_ALLOWLIST_DURATION_MS); pw.print("=");
+ TimeUtils.formatDuration(MMS_TEMP_APP_ALLOWLIST_DURATION_MS, pw);
pw.println();
- pw.print(" "); pw.print(KEY_SMS_TEMP_APP_WHITELIST_DURATION); pw.print("=");
- TimeUtils.formatDuration(SMS_TEMP_APP_WHITELIST_DURATION, pw);
+ pw.print(" "); pw.print(KEY_SMS_TEMP_APP_ALLOWLIST_DURATION_MS); pw.print("=");
+ TimeUtils.formatDuration(SMS_TEMP_APP_ALLOWLIST_DURATION_MS, pw);
pw.println();
pw.print(" "); pw.print(KEY_NOTIFICATION_ALLOWLIST_DURATION_MS); pw.print("=");
@@ -1804,29 +1803,29 @@ public class DeviceIdleController extends SystemService
public long whitelistAppTemporarily(String packageName, int userId, String reason)
throws RemoteException {
// At least 10 seconds.
- long duration = Math.max(10_000L, mConstants.MAX_TEMP_APP_WHITELIST_DURATION / 2);
- addPowerSaveTempWhitelistAppChecked(packageName, duration, userId, reason);
- return duration;
+ long durationMs = Math.max(10_000L, mConstants.MAX_TEMP_APP_ALLOWLIST_DURATION_MS / 2);
+ addPowerSaveTempAllowlistAppChecked(packageName, durationMs, userId, reason);
+ return durationMs;
}
@Override
public void addPowerSaveTempWhitelistApp(String packageName, long duration,
int userId, String reason) throws RemoteException {
- addPowerSaveTempWhitelistAppChecked(packageName, duration, userId, reason);
+ addPowerSaveTempAllowlistAppChecked(packageName, duration, userId, reason);
}
@Override public long addPowerSaveTempWhitelistAppForMms(String packageName,
int userId, String reason) throws RemoteException {
- long duration = mConstants.MMS_TEMP_APP_WHITELIST_DURATION;
- addPowerSaveTempWhitelistAppChecked(packageName, duration, userId, reason);
- return duration;
+ long durationMs = mConstants.MMS_TEMP_APP_ALLOWLIST_DURATION_MS;
+ addPowerSaveTempAllowlistAppChecked(packageName, durationMs, userId, reason);
+ return durationMs;
}
@Override public long addPowerSaveTempWhitelistAppForSms(String packageName,
int userId, String reason) throws RemoteException {
- long duration = mConstants.SMS_TEMP_APP_WHITELIST_DURATION;
- addPowerSaveTempWhitelistAppChecked(packageName, duration, userId, reason);
- return duration;
+ long durationMs = mConstants.SMS_TEMP_APP_ALLOWLIST_DURATION_MS;
+ addPowerSaveTempAllowlistAppChecked(packageName, durationMs, userId, reason);
+ return durationMs;
}
@Override public void exitIdle(String reason) {
@@ -1900,7 +1899,7 @@ public class DeviceIdleController extends SystemService
@Override
public void addPowerSaveTempWhitelistApp(int callingUid, String packageName,
long duration, int userId, boolean sync, String reason) {
- addPowerSaveTempWhitelistAppInternal(callingUid, packageName, duration,
+ addPowerSaveTempAllowlistAppInternal(callingUid, packageName, duration,
userId, sync, reason);
}
@@ -2617,7 +2616,7 @@ public class DeviceIdleController extends SystemService
}
}
- void addPowerSaveTempWhitelistAppChecked(String packageName, long duration,
+ void addPowerSaveTempAllowlistAppChecked(String packageName, long duration,
int userId, String reason) throws RemoteException {
getContext().enforceCallingPermission(
Manifest.permission.CHANGE_DEVICE_IDLE_TEMP_WHITELIST,
@@ -2632,14 +2631,14 @@ public class DeviceIdleController extends SystemService
"addPowerSaveTempWhitelistApp", null);
final long token = Binder.clearCallingIdentity();
try {
- addPowerSaveTempWhitelistAppInternal(callingUid,
+ addPowerSaveTempAllowlistAppInternal(callingUid,
packageName, duration, userId, true, reason);
} finally {
Binder.restoreCallingIdentity(token);
}
}
- void removePowerSaveTempWhitelistAppChecked(String packageName, int userId)
+ void removePowerSaveTempAllowlistAppChecked(String packageName, int userId)
throws RemoteException {
getContext().enforceCallingPermission(
Manifest.permission.CHANGE_DEVICE_IDLE_TEMP_WHITELIST,
@@ -2654,7 +2653,7 @@ public class DeviceIdleController extends SystemService
"removePowerSaveTempWhitelistApp", null);
final long token = Binder.clearCallingIdentity();
try {
- removePowerSaveTempWhitelistAppInternal(packageName, userId);
+ removePowerSaveTempAllowlistAppInternal(packageName, userId);
} finally {
Binder.restoreCallingIdentity(token);
}
@@ -2664,7 +2663,7 @@ public class DeviceIdleController extends SystemService
* Adds an app to the temporary whitelist and resets the endTime for granting the
* app an exemption to access network and acquire wakelocks.
*/
- void addPowerSaveTempWhitelistAppInternal(int callingUid, String packageName,
+ void addPowerSaveTempAllowlistAppInternal(int callingUid, String packageName,
long duration, int userId, boolean sync, String reason) {
try {
int uid = getContext().getPackageManager().getPackageUidAsUser(packageName, userId);
@@ -2690,7 +2689,7 @@ public class DeviceIdleController extends SystemService
+ " is not on whitelist");
}
}
- duration = Math.min(duration, mConstants.MAX_TEMP_APP_WHITELIST_DURATION);
+ duration = Math.min(duration, mConstants.MAX_TEMP_APP_ALLOWLIST_DURATION_MS);
Pair<MutableLong, String> entry = mTempWhitelistAppIdEndTimes.get(appId);
final boolean newEntry = entry == null;
// Set the new end time
@@ -2728,7 +2727,7 @@ public class DeviceIdleController extends SystemService
/**
* Removes an app from the temporary whitelist and notifies the observers.
*/
- private void removePowerSaveTempWhitelistAppInternal(String packageName, int userId) {
+ private void removePowerSaveTempAllowlistAppInternal(String packageName, int userId) {
try {
final int uid = getContext().getPackageManager().getPackageUidAsUser(
packageName, userId);
@@ -4354,9 +4353,9 @@ public class DeviceIdleController extends SystemService
if (arg != null) {
try {
if (removePkg) {
- removePowerSaveTempWhitelistAppChecked(arg, shell.userId);
+ removePowerSaveTempAllowlistAppChecked(arg, shell.userId);
} else {
- addPowerSaveTempWhitelistAppChecked(arg, duration, shell.userId, "shell");
+ addPowerSaveTempAllowlistAppChecked(arg, duration, shell.userId, "shell");
}
} catch (Exception e) {
pw.println("Failed: " + e);
diff --git a/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java b/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java
index fe96952d83f9..255e2f6d8779 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java
@@ -1054,6 +1054,7 @@ public class JobSchedulerService extends com.android.server.SystemService
public int scheduleAsPackage(JobInfo job, JobWorkItem work, int uId, String packageName,
int userId, String tag) {
+ // Rate limit excessive schedule() calls.
final String servicePkg = job.getService().getPackageName();
if (job.isPersisted() && (packageName == null || packageName.equals(servicePkg))) {
// Only limit schedule calls for persisted jobs scheduled by the app itself.
@@ -1358,8 +1359,7 @@ public class JobSchedulerService extends com.android.server.SystemService
for (int i=0; i<mActiveServices.size(); i++) {
JobServiceContext jsc = mActiveServices.get(i);
final JobStatus executing = jsc.getRunningJobLocked();
- if (executing != null
- && (executing.getFlags() & JobInfo.FLAG_WILL_BE_FOREGROUND) == 0) {
+ if (executing != null && !executing.canRunInDoze()) {
jsc.cancelExecutingJobLocked(JobParameters.REASON_DEVICE_IDLE,
"cancelled due to doze");
}
@@ -1411,7 +1411,7 @@ public class JobSchedulerService extends com.android.server.SystemService
final JobServiceContext jsc = mActiveServices.get(i);
final JobStatus job = jsc.getRunningJobLocked();
if (job != null
- && (job.getJob().getFlags() & JobInfo.FLAG_WILL_BE_FOREGROUND) == 0
+ && !job.canRunInDoze()
&& !job.dozeWhitelisted
&& !job.uidActive) {
// We will report active if we have a job running and it is not an exception
@@ -2600,6 +2600,7 @@ public class JobSchedulerService extends com.android.server.SystemService
// job that runs one of the app's services, as well as verifying that the
// named service properly requires the BIND_JOB_SERVICE permission
private void enforceValidJobRequest(int uid, JobInfo job) {
+ job.enforceValidity();
final PackageManager pm = getContext()
.createContextAsUser(UserHandle.getUserHandleForUid(uid), 0)
.getPackageManager();
diff --git a/apex/jobscheduler/service/java/com/android/server/job/controllers/BackgroundJobsController.java b/apex/jobscheduler/service/java/com/android/server/job/controllers/BackgroundJobsController.java
index 44c8fcff8c63..f647db901f48 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/controllers/BackgroundJobsController.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/controllers/BackgroundJobsController.java
@@ -189,8 +189,7 @@ public final class BackgroundJobsController extends StateController {
final String packageName = jobStatus.getSourcePackageName();
final boolean canRun = !mAppStateTracker.areJobsRestricted(uid, packageName,
- (jobStatus.getInternalFlags() & JobStatus.INTERNAL_FLAG_HAS_FOREGROUND_EXEMPTION)
- != 0);
+ jobStatus.canRunInBatterySaver());
final boolean isActive;
if (activeState == UNKNOWN) {
diff --git a/apex/jobscheduler/service/java/com/android/server/job/controllers/ConnectivityController.java b/apex/jobscheduler/service/java/com/android/server/job/controllers/ConnectivityController.java
index 67997cf31501..6ddafadaa871 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/controllers/ConnectivityController.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/controllers/ConnectivityController.java
@@ -464,7 +464,7 @@ public final class ConnectivityController extends RestrictingController implemen
NetworkCapabilities capabilities) {
// TODO: consider matching against non-active networks
- final boolean ignoreBlocked = (jobStatus.getFlags() & JobInfo.FLAG_WILL_BE_FOREGROUND) != 0;
+ final boolean ignoreBlocked = jobStatus.shouldIgnoreNetworkBlocking();
final NetworkInfo info = mConnManager.getNetworkInfoForUid(network,
jobStatus.getSourceUid(), ignoreBlocked);
diff --git a/apex/jobscheduler/service/java/com/android/server/job/controllers/JobStatus.java b/apex/jobscheduler/service/java/com/android/server/job/controllers/JobStatus.java
index 00dbb8235d29..8f6c68dad36c 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/controllers/JobStatus.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/controllers/JobStatus.java
@@ -470,7 +470,7 @@ public final class JobStatus {
}
this.requiredConstraints = requiredConstraints;
mRequiredConstraintsOfInterest = requiredConstraints & CONSTRAINTS_OF_INTEREST;
- mReadyNotDozing = (job.getFlags() & JobInfo.FLAG_WILL_BE_FOREGROUND) != 0;
+ mReadyNotDozing = canRunInDoze();
if (standbyBucket == RESTRICTED_INDEX) {
addDynamicConstraints(DYNAMIC_RESTRICTED_CONSTRAINTS);
} else {
@@ -1036,6 +1036,22 @@ public final class JobStatus {
mPersistedUtcTimes = null;
}
+ /**
+ * @return true if the job is exempted from Doze restrictions and therefore allowed to run
+ * in Doze.
+ */
+ public boolean canRunInDoze() {
+ return (getFlags() & JobInfo.FLAG_WILL_BE_FOREGROUND) != 0;
+ }
+
+ boolean canRunInBatterySaver() {
+ return (getInternalFlags() & INTERNAL_FLAG_HAS_FOREGROUND_EXEMPTION) != 0;
+ }
+
+ boolean shouldIgnoreNetworkBlocking() {
+ return (getFlags() & JobInfo.FLAG_WILL_BE_FOREGROUND) != 0;
+ }
+
/** @return true if the constraint was changed, false otherwise. */
boolean setChargingConstraintSatisfied(boolean state) {
return setConstraintSatisfied(CONSTRAINT_CHARGING, state);
@@ -1086,7 +1102,7 @@ public final class JobStatus {
dozeWhitelisted = whitelisted;
if (setConstraintSatisfied(CONSTRAINT_DEVICE_NOT_DOZING, state)) {
// The constraint was changed. Update the ready flag.
- mReadyNotDozing = state || (job.getFlags() & JobInfo.FLAG_WILL_BE_FOREGROUND) != 0;
+ mReadyNotDozing = state || canRunInDoze();
return true;
}
return false;
@@ -1771,9 +1787,11 @@ public final class JobStatus {
pw.print(prefix); pw.print(" readyDeadlineSatisfied: ");
pw.println(mReadyDeadlineSatisfied);
}
- pw.print(prefix);
- pw.print(" readyDynamicSatisfied: ");
- pw.println(mReadyDynamicSatisfied);
+ if (mDynamicConstraints != 0) {
+ pw.print(prefix);
+ pw.print(" readyDynamicSatisfied: ");
+ pw.println(mReadyDynamicSatisfied);
+ }
pw.print(prefix);
pw.print(" readyComponentEnabled: ");
pw.println(serviceInfo != null);
diff --git a/apex/jobscheduler/service/java/com/android/server/job/controllers/QuotaController.java b/apex/jobscheduler/service/java/com/android/server/job/controllers/QuotaController.java
index 7d7de3be8249..1d72b42d824d 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/controllers/QuotaController.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/controllers/QuotaController.java
@@ -1679,42 +1679,47 @@ public final class QuotaController extends StateController {
// Update job bookkeeping out of band.
JobSchedulerBackgroundThread.getHandler().post(() -> {
final int bucketIndex = JobSchedulerService.standbyBucketToBucketIndex(bucket);
- if (DEBUG) {
- Slog.i(TAG, "Moving pkg " + string(userId, packageName) + " to bucketIndex "
- + bucketIndex);
- }
- List<JobStatus> restrictedChanges = new ArrayList<>();
- synchronized (mLock) {
- ArraySet<JobStatus> jobs = mTrackedJobs.get(userId, packageName);
- if (jobs == null || jobs.size() == 0) {
- return;
- }
- for (int i = jobs.size() - 1; i >= 0; i--) {
- JobStatus js = jobs.valueAt(i);
- // Effective standby bucket can change after this in some situations so
- // use the real bucket so that the job is tracked by the controllers.
- if ((bucketIndex == RESTRICTED_INDEX
- || js.getStandbyBucket() == RESTRICTED_INDEX)
- && bucketIndex != js.getStandbyBucket()) {
- restrictedChanges.add(js);
- }
- js.setStandbyBucket(bucketIndex);
- }
- Timer timer = mPkgTimers.get(userId, packageName);
- if (timer != null && timer.isActive()) {
- timer.rescheduleCutoff();
- }
- if (maybeUpdateConstraintForPkgLocked(userId, packageName)) {
- mStateChangedListener.onControllerStateChanged();
- }
- }
- if (restrictedChanges.size() > 0) {
- mStateChangedListener.onRestrictedBucketChanged(restrictedChanges);
- }
+ updateStandbyBucket(userId, packageName, bucketIndex);
});
}
}
+ @VisibleForTesting
+ void updateStandbyBucket(
+ final int userId, final @NonNull String packageName, final int bucketIndex) {
+ if (DEBUG) {
+ Slog.i(TAG, "Moving pkg " + string(userId, packageName)
+ + " to bucketIndex " + bucketIndex);
+ }
+ List<JobStatus> restrictedChanges = new ArrayList<>();
+ synchronized (mLock) {
+ ArraySet<JobStatus> jobs = mTrackedJobs.get(userId, packageName);
+ if (jobs == null || jobs.size() == 0) {
+ return;
+ }
+ for (int i = jobs.size() - 1; i >= 0; i--) {
+ JobStatus js = jobs.valueAt(i);
+ // Effective standby bucket can change after this in some situations so
+ // use the real bucket so that the job is tracked by the controllers.
+ if ((bucketIndex == RESTRICTED_INDEX || js.getStandbyBucket() == RESTRICTED_INDEX)
+ && bucketIndex != js.getStandbyBucket()) {
+ restrictedChanges.add(js);
+ }
+ js.setStandbyBucket(bucketIndex);
+ }
+ Timer timer = mPkgTimers.get(userId, packageName);
+ if (timer != null && timer.isActive()) {
+ timer.rescheduleCutoff();
+ }
+ if (maybeUpdateConstraintForPkgLocked(userId, packageName)) {
+ mStateChangedListener.onControllerStateChanged();
+ }
+ }
+ if (restrictedChanges.size() > 0) {
+ mStateChangedListener.onRestrictedBucketChanged(restrictedChanges);
+ }
+ }
+
private final class DeleteTimingSessionsFunctor implements Consumer<List<TimingSession>> {
private final Predicate<TimingSession> mTooOld = new Predicate<TimingSession>() {
public boolean test(TimingSession ts) {
diff --git a/cmds/statsd/src/atoms.proto b/cmds/statsd/src/atoms.proto
index a9037701fa01..8363e9f3191d 100644
--- a/cmds/statsd/src/atoms.proto
+++ b/cmds/statsd/src/atoms.proto
@@ -42,6 +42,7 @@ import "frameworks/base/core/proto/android/server/job/enums.proto";
import "frameworks/base/core/proto/android/server/location/enums.proto";
import "frameworks/base/core/proto/android/service/procstats_enum.proto";
import "frameworks/base/core/proto/android/service/usb.proto";
+import "frameworks/base/core/proto/android/stats/camera/camera.proto";
import "frameworks/base/core/proto/android/stats/connectivity/network_stack.proto";
import "frameworks/base/core/proto/android/stats/connectivity/tethering.proto";
import "frameworks/base/core/proto/android/stats/dnsresolver/dns_resolver.proto";
@@ -512,6 +513,7 @@ message Atom {
WifiScanReported wifi_scan_reported = 325 [(module) = "wifi"];
WifiPnoScanReported wifi_pno_scan_reported = 326 [(module) = "wifi"];
TifTuneStateChanged tif_tune_changed = 327 [(module) = "framework"];
+ AutoRotateReported auto_rotate_reported = 328 [(module) = "framework"];
// StatsdStats tracks platform atoms with ids upto 500.
// Update StatsdStats::kMaxPushedAtomId when atom ids here approach that value.
@@ -9950,10 +9952,12 @@ message DisplayJankReported {
* frameworks/base/services/core/java/com/android/server/camera/CameraServiceProxy.java
*/
message CameraActionEvent {
- // Camera session duration
+ // Camera session duration in milliseconds if action is SESSION.
+ // 0 if action is OPEN or CLOSE.
optional int64 duration_millis = 1;
- // Camera API level used
+ // Camera API level used.
+ // 1 for camera1 API, and 2 for camera2 API.
optional int32 api_level = 2;
// Name of client package
@@ -9967,6 +9971,56 @@ message CameraActionEvent {
EXTERNAL = 3;
}
optional Facing facing = 4;
+
+ // Camera ID
+ optional string camera_id = 5;
+
+ // Camera action type
+ enum Action {
+ UNKNOWN_ACTION = 0;
+ OPEN = 1;
+ CLOSE = 2;
+ SESSION = 3;
+ }
+ optional Action action = 6;
+
+ // Whether the client is accessing camera using ndk
+ optional bool is_ndk = 7;
+
+ // Action OPEN: Open latency
+ // Action CLOSE: Close latency
+ // Action SESSION: Camera session creation duration.
+ // If this entry is reusing an existing session, the value is -1.
+ optional int32 latency_millis = 8;
+
+ // session type: 0 for normal mode, 1 for constrained high speed mode
+ optional int32 operating_mode = 9;
+
+ // If actioh is SESSION: number of internal reconfigurations
+ // Else: 0
+ optional int32 internal_reconfig = 10;
+
+ // Number of requests for this capture session. Only applicable to SESSION
+ // action.
+ optional int64 request_count = 11;
+ // Number of result errors. Only applicable to SESSION action.
+ optional int64 result_error_count = 12;
+ // Whether the device runs into error state.
+ optional bool device_error = 13;
+
+ // If action is SESSION: Stream states
+ // Else: stream_count = 0
+ optional int32 stream_count = 14;
+ optional android.stats.camera.CameraStreamProto stream_1 = 15
+ [(android.os.statsd.log_mode) = MODE_BYTES];
+ optional android.stats.camera.CameraStreamProto stream_2 = 16
+ [(android.os.statsd.log_mode) = MODE_BYTES];
+ optional android.stats.camera.CameraStreamProto stream_3 = 17
+ [(android.os.statsd.log_mode) = MODE_BYTES];
+ optional android.stats.camera.CameraStreamProto stream_4 = 18
+ [(android.os.statsd.log_mode) = MODE_BYTES];
+ optional android.stats.camera.CameraStreamProto stream_5 = 19
+ [(android.os.statsd.log_mode) = MODE_BYTES];
}
/**
@@ -12114,6 +12168,33 @@ message HdmiCecMessageReported {
}
/**
+ * Logs when an auto rotate event occurs while smart auto rotate is enabled.
+ */
+message AutoRotateReported {
+ enum Orientation {
+ UNKNOWN = 1;
+ ROTATION_0 = 2;
+ ROTATION_90 = 3;
+ ROTATION_180 = 4;
+ ROTATION_270 = 5;
+ DISABLED = 6;
+ UNAVAILABLE = 7;
+ FAILURE = 8;
+ }
+
+ // Orientation of the device when a rotation was detected.
+ optional Orientation current_orientation = 1;
+ // The orientation of the phone after rotation before going through the recommendation service.
+ optional Orientation proposed_orientation = 2;
+ // Orientation recommended by the smart autorotate service component outside of the platform. It
+ // may or may not match the proposed_orientation. Can be disabled or unavailable if the
+ // recommendation service is disabled or unavailable. Will be unknown if the service failed.
+ optional Orientation recommended_orientation = 3;
+ // Time taken to calculate the rotation recommendation.
+ optional int64 recommendation_process_duration_millis = 4;
+}
+
+/**
* Pushes TLS handshake counters from Conscrypt.
* Pulled from:
* external/conscrypt/common/src/main/java/org/conscrypt/ConscryptEngineSocket.java
diff --git a/config/preloaded-classes b/config/preloaded-classes
index bbdb5e9be99e..8d2f1434b12f 100644
--- a/config/preloaded-classes
+++ b/config/preloaded-classes
@@ -6749,6 +6749,7 @@ android.sysprop.-$$Lambda$TelephonyProperties$illdaSIVv8AlxP9uc8NqC3Ta1tA
android.sysprop.-$$Lambda$TelephonyProperties$klELuV5zVSqFveC5l6c3FSJmLAU
android.sysprop.-$$Lambda$TelephonyProperties$pFU8zg4eHAdooeRLJg1WBG52cKk
android.sysprop.-$$Lambda$TelephonyProperties$sXc3eBCFirzHWb9pvClH7EsiM_Q
+android.stats.camera.nano.CameraStreamProto
android.sysprop.AdbProperties
android.sysprop.ApexProperties
android.sysprop.ContactsProperties
diff --git a/core/api/current.txt b/core/api/current.txt
index 821717a195a1..9f7f3917a11f 100644
--- a/core/api/current.txt
+++ b/core/api/current.txt
@@ -12105,6 +12105,8 @@ package android.content.pm {
method public abstract android.content.pm.PermissionInfo getPermissionInfo(@NonNull String, int) throws android.content.pm.PackageManager.NameNotFoundException;
method @Deprecated public abstract int getPreferredActivities(@NonNull java.util.List<android.content.IntentFilter>, @NonNull java.util.List<android.content.ComponentName>, @Nullable String);
method @Deprecated @NonNull public abstract java.util.List<android.content.pm.PackageInfo> getPreferredPackages(int);
+ method @NonNull public android.content.pm.PackageManager.Property getProperty(@NonNull String, @NonNull String) throws android.content.pm.PackageManager.NameNotFoundException;
+ method @NonNull public android.content.pm.PackageManager.Property getProperty(@NonNull String, @NonNull android.content.ComponentName) throws android.content.pm.PackageManager.NameNotFoundException;
method @NonNull public abstract android.content.pm.ProviderInfo getProviderInfo(@NonNull android.content.ComponentName, int) throws android.content.pm.PackageManager.NameNotFoundException;
method @NonNull public abstract android.content.pm.ActivityInfo getReceiverInfo(@NonNull android.content.ComponentName, int) throws android.content.pm.PackageManager.NameNotFoundException;
method @NonNull public abstract android.content.res.Resources getResourcesForActivity(@NonNull android.content.ComponentName) throws android.content.pm.PackageManager.NameNotFoundException;
@@ -12137,6 +12139,8 @@ package android.content.pm {
method public boolean isPackageSuspended();
method @CheckResult public abstract boolean isPermissionRevokedByPolicy(@NonNull String, @NonNull String);
method public abstract boolean isSafeMode();
+ method @NonNull public java.util.List<android.content.pm.PackageManager.Property> queryActivityProperty(@NonNull String);
+ method @NonNull public java.util.List<android.content.pm.PackageManager.Property> queryApplicationProperty(@NonNull String);
method @NonNull public abstract java.util.List<android.content.pm.ResolveInfo> queryBroadcastReceivers(@NonNull android.content.Intent, int);
method @NonNull public abstract java.util.List<android.content.pm.ProviderInfo> queryContentProviders(@Nullable String, int, int);
method @NonNull public abstract java.util.List<android.content.pm.InstrumentationInfo> queryInstrumentation(@NonNull String, int);
@@ -12145,6 +12149,9 @@ package android.content.pm {
method @NonNull public abstract java.util.List<android.content.pm.ResolveInfo> queryIntentContentProviders(@NonNull android.content.Intent, int);
method @NonNull public abstract java.util.List<android.content.pm.ResolveInfo> queryIntentServices(@NonNull android.content.Intent, int);
method @NonNull public abstract java.util.List<android.content.pm.PermissionInfo> queryPermissionsByGroup(@NonNull String, int) throws android.content.pm.PackageManager.NameNotFoundException;
+ method @NonNull public java.util.List<android.content.pm.PackageManager.Property> queryProviderProperty(@NonNull String);
+ method @NonNull public java.util.List<android.content.pm.PackageManager.Property> queryReceiverProperty(@NonNull String);
+ method @NonNull public java.util.List<android.content.pm.PackageManager.Property> queryServiceProperty(@NonNull String);
method @Deprecated public abstract void removePackageFromPreferred(@NonNull String);
method public abstract void removePermission(@NonNull String);
method @RequiresPermission(value="android.permission.WHITELIST_RESTRICTED_PERMISSIONS", conditional=true) public boolean removeWhitelistedRestrictedPermission(@NonNull String, @NonNull String, int);
@@ -12333,7 +12340,7 @@ package android.content.pm {
field public static final int SIGNATURE_SECOND_NOT_SIGNED = -2; // 0xfffffffe
field public static final int SIGNATURE_UNKNOWN_PACKAGE = -4; // 0xfffffffc
field public static final int SYNCHRONOUS = 2; // 0x2
- field @Nullable public static final java.util.List<java.security.cert.Certificate> TRUST_ALL;
+ field @NonNull public static final java.util.List<java.security.cert.Certificate> TRUST_ALL;
field @NonNull public static final java.util.List<java.security.cert.Certificate> TRUST_NONE;
field public static final int VERIFICATION_ALLOW = 1; // 0x1
field public static final int VERIFICATION_REJECT = -1; // 0xffffffff
@@ -12345,6 +12352,25 @@ package android.content.pm {
ctor public PackageManager.NameNotFoundException(String);
}
+ public static final class PackageManager.Property implements android.os.Parcelable {
+ method public int describeContents();
+ method public boolean getBoolean();
+ method @Nullable public String getClassName();
+ method public float getFloat();
+ method public int getInteger();
+ method @NonNull public String getName();
+ method @NonNull public String getPackageName();
+ method public int getResourceId();
+ method @Nullable public String getString();
+ method public boolean isBoolean();
+ method public boolean isFloat();
+ method public boolean isInteger();
+ method public boolean isResourceId();
+ method public boolean isString();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.content.pm.PackageManager.Property> CREATOR;
+ }
+
@Deprecated public class PackageStats implements android.os.Parcelable {
ctor @Deprecated public PackageStats(String);
ctor @Deprecated public PackageStats(android.os.Parcel);
@@ -46192,12 +46218,6 @@ package android.telephony {
field public static final int SCAN_TYPE_PERIODIC = 1; // 0x1
}
- public final class PhoneCapability implements android.os.Parcelable {
- method public int describeContents();
- method public void writeToParcel(@NonNull android.os.Parcel, int);
- field @NonNull public static final android.os.Parcelable.Creator<android.telephony.PhoneCapability> CREATOR;
- }
-
public class PhoneNumberFormattingTextWatcher implements android.text.TextWatcher {
ctor public PhoneNumberFormattingTextWatcher();
ctor public PhoneNumberFormattingTextWatcher(String);
@@ -46266,10 +46286,10 @@ package android.telephony {
public class PhoneStateListener {
ctor public PhoneStateListener();
- ctor @Deprecated public PhoneStateListener(@NonNull java.util.concurrent.Executor);
+ ctor public PhoneStateListener(@NonNull java.util.concurrent.Executor);
method public void onActiveDataSubscriptionIdChanged(int);
method public void onBarringInfoChanged(@NonNull android.telephony.BarringInfo);
- method @RequiresPermission(android.Manifest.permission.READ_PRECISE_PHONE_STATE) public void onCallDisconnectCauseChanged(int, int);
+ method @RequiresPermission("android.permission.READ_PRECISE_PHONE_STATE") public void onCallDisconnectCauseChanged(int, int);
method public void onCallForwardingIndicatorChanged(boolean);
method public void onCallStateChanged(int, String);
method public void onCellInfoChanged(java.util.List<android.telephony.CellInfo>);
@@ -46277,144 +46297,36 @@ package android.telephony {
method public void onDataActivity(int);
method public void onDataConnectionStateChanged(int);
method public void onDataConnectionStateChanged(int, int);
- method @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public void onDisplayInfoChanged(@NonNull android.telephony.TelephonyDisplayInfo);
+ method @RequiresPermission("android.permission.READ_PHONE_STATE") public void onDisplayInfoChanged(@NonNull android.telephony.TelephonyDisplayInfo);
method public void onEmergencyNumberListChanged(@NonNull java.util.Map<java.lang.Integer,java.util.List<android.telephony.emergency.EmergencyNumber>>);
- method @RequiresPermission(android.Manifest.permission.READ_PRECISE_PHONE_STATE) public void onImsCallDisconnectCauseChanged(@NonNull android.telephony.ims.ImsReasonInfo);
+ method @RequiresPermission("android.permission.READ_PRECISE_PHONE_STATE") public void onImsCallDisconnectCauseChanged(@NonNull android.telephony.ims.ImsReasonInfo);
method public void onMessageWaitingIndicatorChanged(boolean);
- method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void onPreciseDataConnectionStateChanged(@NonNull android.telephony.PreciseDataConnectionState);
+ method @RequiresPermission("android.permission.MODIFY_PHONE_STATE") public void onPreciseDataConnectionStateChanged(@NonNull android.telephony.PreciseDataConnectionState);
method public void onRegistrationFailed(@NonNull android.telephony.CellIdentity, @NonNull String, int, int, int);
method public void onServiceStateChanged(android.telephony.ServiceState);
method @Deprecated public void onSignalStrengthChanged(int);
method public void onSignalStrengthsChanged(android.telephony.SignalStrength);
method public void onUserMobileDataStateChanged(boolean);
- field @Deprecated public static final int LISTEN_ACTIVE_DATA_SUBSCRIPTION_ID_CHANGE = 4194304; // 0x400000
- field @Deprecated @RequiresPermission(android.Manifest.permission.READ_PRECISE_PHONE_STATE) public static final int LISTEN_BARRING_INFO = -2147483648; // 0x80000000
- field @Deprecated @RequiresPermission(android.Manifest.permission.READ_PRECISE_PHONE_STATE) public static final int LISTEN_CALL_DISCONNECT_CAUSES = 33554432; // 0x2000000
- field @Deprecated public static final int LISTEN_CALL_FORWARDING_INDICATOR = 8; // 0x8
- field @Deprecated public static final int LISTEN_CALL_STATE = 32; // 0x20
- field @Deprecated public static final int LISTEN_CELL_INFO = 1024; // 0x400
- field @Deprecated public static final int LISTEN_CELL_LOCATION = 16; // 0x10
- field @Deprecated public static final int LISTEN_DATA_ACTIVITY = 128; // 0x80
- field @Deprecated public static final int LISTEN_DATA_CONNECTION_STATE = 64; // 0x40
- field @Deprecated public static final int LISTEN_DISPLAY_INFO_CHANGED = 1048576; // 0x100000
- field @Deprecated public static final int LISTEN_EMERGENCY_NUMBER_LIST = 16777216; // 0x1000000
- field @Deprecated @RequiresPermission(android.Manifest.permission.READ_PRECISE_PHONE_STATE) public static final int LISTEN_IMS_CALL_DISCONNECT_CAUSES = 134217728; // 0x8000000
- field @Deprecated public static final int LISTEN_MESSAGE_WAITING_INDICATOR = 4; // 0x4
+ field public static final int LISTEN_ACTIVE_DATA_SUBSCRIPTION_ID_CHANGE = 4194304; // 0x400000
+ field @RequiresPermission(android.Manifest.permission.READ_PRECISE_PHONE_STATE) public static final int LISTEN_BARRING_INFO = -2147483648; // 0x80000000
+ field @RequiresPermission("android.permission.READ_PRECISE_PHONE_STATE") public static final int LISTEN_CALL_DISCONNECT_CAUSES = 33554432; // 0x2000000
+ field public static final int LISTEN_CALL_FORWARDING_INDICATOR = 8; // 0x8
+ field public static final int LISTEN_CALL_STATE = 32; // 0x20
+ field public static final int LISTEN_CELL_INFO = 1024; // 0x400
+ field public static final int LISTEN_CELL_LOCATION = 16; // 0x10
+ field public static final int LISTEN_DATA_ACTIVITY = 128; // 0x80
+ field public static final int LISTEN_DATA_CONNECTION_STATE = 64; // 0x40
+ field public static final int LISTEN_DISPLAY_INFO_CHANGED = 1048576; // 0x100000
+ field public static final int LISTEN_EMERGENCY_NUMBER_LIST = 16777216; // 0x1000000
+ field @RequiresPermission("android.permission.READ_PRECISE_PHONE_STATE") public static final int LISTEN_IMS_CALL_DISCONNECT_CAUSES = 134217728; // 0x8000000
+ field public static final int LISTEN_MESSAGE_WAITING_INDICATOR = 4; // 0x4
field public static final int LISTEN_NONE = 0; // 0x0
- field @Deprecated @RequiresPermission(android.Manifest.permission.READ_PRECISE_PHONE_STATE) public static final int LISTEN_PRECISE_DATA_CONNECTION_STATE = 4096; // 0x1000
- field @Deprecated @RequiresPermission(android.Manifest.permission.READ_PRECISE_PHONE_STATE) public static final int LISTEN_REGISTRATION_FAILURE = 1073741824; // 0x40000000
- field @Deprecated public static final int LISTEN_SERVICE_STATE = 1; // 0x1
+ field @RequiresPermission("android.permission.READ_PRECISE_PHONE_STATE") public static final int LISTEN_PRECISE_DATA_CONNECTION_STATE = 4096; // 0x1000
+ field @RequiresPermission(android.Manifest.permission.READ_PRECISE_PHONE_STATE) public static final int LISTEN_REGISTRATION_FAILURE = 1073741824; // 0x40000000
+ field public static final int LISTEN_SERVICE_STATE = 1; // 0x1
field @Deprecated public static final int LISTEN_SIGNAL_STRENGTH = 2; // 0x2
- field @Deprecated public static final int LISTEN_SIGNAL_STRENGTHS = 256; // 0x100
- field @Deprecated public static final int LISTEN_USER_MOBILE_DATA_STATE = 524288; // 0x80000
- }
-
- public static interface PhoneStateListener.ActiveDataSubscriptionIdChangedListener {
- method @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public void onActiveDataSubscriptionIdChanged(int);
- }
-
- public static interface PhoneStateListener.AlwaysReportedSignalStrengthsChangedListener {
- method @RequiresPermission("android.permission.LISTEN_ALWAYS_REPORTED_SIGNAL_STRENGTH") public void onSignalStrengthsChanged(@NonNull android.telephony.SignalStrength);
- }
-
- public static interface PhoneStateListener.BarringInfoChangedListener {
- method @RequiresPermission(allOf={android.Manifest.permission.READ_PRECISE_PHONE_STATE, android.Manifest.permission.ACCESS_FINE_LOCATION}) public void onBarringInfoChanged(@NonNull android.telephony.BarringInfo);
- }
-
- public static interface PhoneStateListener.CallDisconnectCauseChangedListener {
- method @RequiresPermission(android.Manifest.permission.READ_PRECISE_PHONE_STATE) public void onCallDisconnectCauseChanged(int, int);
- }
-
- public static interface PhoneStateListener.CallForwardingIndicatorChangedListener {
- method @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public void onCallForwardingIndicatorChanged(boolean);
- }
-
- public static interface PhoneStateListener.CallStateChangedListener {
- method @RequiresPermission(android.Manifest.permission.READ_CALL_LOG) public void onCallStateChanged(int, @Nullable String);
- }
-
- public static interface PhoneStateListener.CarrierNetworkChangeListener {
- method public void onCarrierNetworkChange(boolean);
- }
-
- public static interface PhoneStateListener.CellInfoChangedListener {
- method @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) public void onCellInfoChanged(@NonNull java.util.List<android.telephony.CellInfo>);
- }
-
- public static interface PhoneStateListener.CellLocationChangedListener {
- method @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) public void onCellLocationChanged(@NonNull android.telephony.CellLocation);
- }
-
- public static interface PhoneStateListener.DataActivationStateChangedListener {
- method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void onDataActivationStateChanged(int);
- }
-
- public static interface PhoneStateListener.DataActivityListener {
- method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void onDataActivity(int);
- }
-
- public static interface PhoneStateListener.DataConnectionStateChangedListener {
- method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void onDataConnectionStateChanged(int, int);
- }
-
- public static interface PhoneStateListener.DisplayInfoChangedListener {
- method @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public void onDisplayInfoChanged(@NonNull android.telephony.TelephonyDisplayInfo);
- }
-
- public static interface PhoneStateListener.EmergencyNumberListChangedListener {
- method @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public void onEmergencyNumberListChanged(@NonNull java.util.Map<java.lang.Integer,java.util.List<android.telephony.emergency.EmergencyNumber>>);
- }
-
- public static interface PhoneStateListener.ImsCallDisconnectCauseChangedListener {
- method @RequiresPermission(android.Manifest.permission.READ_PRECISE_PHONE_STATE) public void onImsCallDisconnectCauseChanged(@NonNull android.telephony.ims.ImsReasonInfo);
- }
-
- public static interface PhoneStateListener.MessageWaitingIndicatorChangedListener {
- method @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public void onMessageWaitingIndicatorChanged(boolean);
- }
-
- public static interface PhoneStateListener.PhoneCapabilityChangedListener {
- method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void onPhoneCapabilityChanged(@NonNull android.telephony.PhoneCapability);
- }
-
- public static interface PhoneStateListener.PhysicalChannelConfigChangedListener {
- method @RequiresPermission(android.Manifest.permission.READ_PRECISE_PHONE_STATE) public void onPhysicalChannelConfigChanged(@NonNull java.util.List<android.telephony.PhysicalChannelConfig>);
- }
-
- public static interface PhoneStateListener.PreciseDataConnectionStateChangedListener {
- method @RequiresPermission(android.Manifest.permission.READ_PRECISE_PHONE_STATE) public void onPreciseDataConnectionStateChanged(@NonNull android.telephony.PreciseDataConnectionState);
- }
-
- public static interface PhoneStateListener.RegistrationFailedListener {
- method @RequiresPermission(allOf={android.Manifest.permission.READ_PRECISE_PHONE_STATE, android.Manifest.permission.ACCESS_FINE_LOCATION}) public void onRegistrationFailed(@NonNull android.telephony.CellIdentity, @NonNull String, int, int, int);
- }
-
- public static interface PhoneStateListener.ServiceStateChangedListener {
- method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void onServiceStateChanged(@NonNull android.telephony.ServiceState);
- }
-
- public static interface PhoneStateListener.SignalStrengthsChangedListener {
- method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void onSignalStrengthsChanged(@NonNull android.telephony.SignalStrength);
- }
-
- public static interface PhoneStateListener.UserMobileDataStateChangedListener {
- method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void onUserMobileDataStateChanged(boolean);
- }
-
- public final class PhysicalChannelConfig implements android.os.Parcelable {
- method public int describeContents();
- method public int getCellBandwidthDownlink();
- method public int getChannelNumber();
- method public int getConnectionStatus();
- method public int getNetworkType();
- method @IntRange(from=0, to=1007) public int getPhysicalCellId();
- method public void writeToParcel(@NonNull android.os.Parcel, int);
- field public static final int CHANNEL_NUMBER_UNKNOWN = -1; // 0xffffffff
- field public static final int CONNECTION_PRIMARY_SERVING = 1; // 0x1
- field public static final int CONNECTION_SECONDARY_SERVING = 2; // 0x2
- field public static final int CONNECTION_UNKNOWN = -1; // 0xffffffff
- field @NonNull public static final android.os.Parcelable.Creator<android.telephony.PhysicalChannelConfig> CREATOR;
- field public static final int PHYSICAL_CELL_ID_UNKNOWN = -1; // 0xffffffff
+ field public static final int LISTEN_SIGNAL_STRENGTHS = 256; // 0x100
+ field public static final int LISTEN_USER_MOBILE_DATA_STATE = 524288; // 0x80000
}
public final class PreciseDataConnectionState implements android.os.Parcelable {
@@ -46926,8 +46838,7 @@ package android.telephony {
method public boolean isVoicemailVibrationEnabled(android.telecom.PhoneAccountHandle);
method public boolean isWorldPhone();
method @Deprecated public void listen(android.telephony.PhoneStateListener, int);
- method @Deprecated public void listen(long, @NonNull android.telephony.PhoneStateListener);
- method public void registerPhoneStateListener(@NonNull java.util.concurrent.Executor, @NonNull android.telephony.PhoneStateListener);
+ method public void listen(long, @NonNull android.telephony.PhoneStateListener);
method @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) public void requestCellInfoUpdate(@NonNull java.util.concurrent.Executor, @NonNull android.telephony.TelephonyManager.CellInfoCallback);
method @RequiresPermission(allOf={android.Manifest.permission.MODIFY_PHONE_STATE, android.Manifest.permission.ACCESS_FINE_LOCATION}) public android.telephony.NetworkScan requestNetworkScan(android.telephony.NetworkScanRequest, java.util.concurrent.Executor, android.telephony.TelephonyScanManager.NetworkScanCallback);
method public void sendDialerSpecialCode(String);
@@ -46949,7 +46860,6 @@ package android.telephony {
method @Deprecated public void setVoicemailRingtoneUri(android.telecom.PhoneAccountHandle, android.net.Uri);
method @Deprecated public void setVoicemailVibrationEnabled(android.telecom.PhoneAccountHandle, boolean);
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void switchMultiSimConfig(int);
- method public void unregisterPhoneStateListener(@NonNull android.telephony.PhoneStateListener);
method public void updateAvailableNetworks(@NonNull java.util.List<android.telephony.AvailableNetworkInfo>, @Nullable java.util.concurrent.Executor, @Nullable java.util.function.Consumer<java.lang.Integer>);
field public static final String ACTION_CARRIER_MESSAGING_CLIENT_SERVICE = "android.telephony.action.CARRIER_MESSAGING_CLIENT_SERVICE";
field public static final String ACTION_CONFIGURE_VOICEMAIL = "android.telephony.action.CONFIGURE_VOICEMAIL";
diff --git a/core/api/system-current.txt b/core/api/system-current.txt
index a56b39675c36..505d246e4df8 100644
--- a/core/api/system-current.txt
+++ b/core/api/system-current.txt
@@ -2280,6 +2280,7 @@ package android.content.pm {
field public static final int PROTECTION_FLAG_DOCUMENTER = 262144; // 0x40000
field public static final int PROTECTION_FLAG_INCIDENT_REPORT_APPROVER = 1048576; // 0x100000
field public static final int PROTECTION_FLAG_OEM = 16384; // 0x4000
+ field public static final int PROTECTION_FLAG_RECENTS = 33554432; // 0x2000000
field public static final int PROTECTION_FLAG_RETAIL_DEMO = 16777216; // 0x1000000
field public static final int PROTECTION_FLAG_SYSTEM_TEXT_CLASSIFIER = 65536; // 0x10000
field public static final int PROTECTION_FLAG_WELLBEING = 131072; // 0x20000
@@ -4389,7 +4390,7 @@ package android.media {
}
public class MediaPlayer implements android.media.AudioRouting android.media.VolumeAutomation {
- method @RequiresPermission("android.permission.BIND_IMS_SERVICE") public void setOnRtpRxNoticeListener(@NonNull android.content.Context, @NonNull android.media.MediaPlayer.OnRtpRxNoticeListener, @Nullable android.os.Handler);
+ method @RequiresPermission(android.Manifest.permission.BIND_IMS_SERVICE) public void setOnRtpRxNoticeListener(@NonNull android.content.Context, @NonNull android.media.MediaPlayer.OnRtpRxNoticeListener, @Nullable android.os.Handler);
}
public static interface MediaPlayer.OnRtpRxNoticeListener {
@@ -8963,11 +8964,8 @@ package android.service.attestation {
public abstract class ImpressionAttestationService extends android.app.Service {
ctor public ImpressionAttestationService();
method @NonNull public final android.os.IBinder onBind(@NonNull android.content.Intent);
- method @Nullable public abstract android.service.attestation.ImpressionToken onGenerateImpressionToken(@NonNull android.hardware.HardwareBuffer, @NonNull android.graphics.Rect, @NonNull String);
- method public abstract int onVerifyImpressionToken(@NonNull android.service.attestation.ImpressionToken);
- field public static final int VERIFICATION_STATUS_APP_DECLARED = 2; // 0x2
- field public static final int VERIFICATION_STATUS_OS_VERIFIED = 1; // 0x1
- field public static final int VERIFICATION_STATUS_UNKNOWN = 0; // 0x0
+ method @Nullable public abstract android.service.attestation.ImpressionToken onGenerateImpressionToken(@NonNull String, @NonNull android.hardware.HardwareBuffer, @NonNull android.graphics.Rect, @NonNull String);
+ method public abstract boolean onVerifyImpressionToken(@NonNull String, @NonNull android.service.attestation.ImpressionToken);
}
public final class ImpressionToken implements android.os.Parcelable {
@@ -10213,6 +10211,25 @@ package android.telephony {
field @NonNull public static final android.os.Parcelable.Creator<android.telephony.DataSpecificRegistrationInfo> CREATOR;
}
+ public final class DataThrottlingRequest implements android.os.Parcelable {
+ method public int describeContents();
+ method public long getCompletionDurationMillis();
+ method public int getDataThrottlingAction();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.telephony.DataThrottlingRequest> CREATOR;
+ field public static final int DATA_THROTTLING_ACTION_HOLD = 3; // 0x3
+ field public static final int DATA_THROTTLING_ACTION_NO_DATA_THROTTLING = 0; // 0x0
+ field public static final int DATA_THROTTLING_ACTION_THROTTLE_PRIMARY_CARRIER = 2; // 0x2
+ field public static final int DATA_THROTTLING_ACTION_THROTTLE_SECONDARY_CARRIER = 1; // 0x1
+ }
+
+ public static final class DataThrottlingRequest.Builder {
+ ctor public DataThrottlingRequest.Builder();
+ method @NonNull public android.telephony.DataThrottlingRequest build();
+ method @NonNull public android.telephony.DataThrottlingRequest.Builder setCompletionDurationMillis(long);
+ method @NonNull public android.telephony.DataThrottlingRequest.Builder setDataThrottlingAction(int);
+ }
+
public final class ImsiEncryptionInfo implements android.os.Parcelable {
method public int describeContents();
method @Nullable public String getKeyIdentifier();
@@ -10350,83 +10367,35 @@ package android.telephony {
method public void onOutgoingEmergencyCall(@NonNull android.telephony.emergency.EmergencyNumber, int);
method @Deprecated public void onOutgoingEmergencySms(@NonNull android.telephony.emergency.EmergencyNumber);
method public void onOutgoingEmergencySms(@NonNull android.telephony.emergency.EmergencyNumber, int);
- method @RequiresPermission(android.Manifest.permission.READ_PRECISE_PHONE_STATE) public void onPreciseCallStateChanged(@NonNull android.telephony.PreciseCallState);
+ method public void onPhysicalChannelConfigurationChanged(@NonNull java.util.List<android.telephony.PhysicalChannelConfig>);
+ method @RequiresPermission("android.permission.READ_PRECISE_PHONE_STATE") public void onPreciseCallStateChanged(@NonNull android.telephony.PreciseCallState);
method public void onRadioPowerStateChanged(int);
method public void onSrvccStateChanged(int);
method public void onVoiceActivationStateChanged(int);
- field @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public static final int EVENT_ACTIVE_DATA_SUBSCRIPTION_ID_CHANGED = 23; // 0x17
- field @RequiresPermission("android.permission.LISTEN_ALWAYS_REPORTED_SIGNAL_STRENGTH") public static final int EVENT_ALWAYS_REPORTED_SIGNAL_STRENGTH_CHANGED = 10; // 0xa
- field @RequiresPermission(allOf={android.Manifest.permission.READ_PRECISE_PHONE_STATE, android.Manifest.permission.ACCESS_FINE_LOCATION}) public static final int EVENT_BARRING_INFO_CHANGED = 32; // 0x20
- field @RequiresPermission(android.Manifest.permission.READ_PRECISE_PHONE_STATE) public static final int EVENT_CALL_ATTRIBUTES_CHANGED = 27; // 0x1b
- field @RequiresPermission(android.Manifest.permission.READ_PRECISE_PHONE_STATE) public static final int EVENT_CALL_DISCONNECT_CAUSE_CHANGED = 26; // 0x1a
- field @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public static final int EVENT_CALL_FORWARDING_INDICATOR_CHANGED = 4; // 0x4
- field @RequiresPermission(android.Manifest.permission.READ_CALL_LOG) public static final int EVENT_CALL_STATE_CHANGED = 6; // 0x6
- field public static final int EVENT_CARRIER_NETWORK_CHANGED = 17; // 0x11
- field @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) public static final int EVENT_CELL_INFO_CHANGED = 11; // 0xb
- field @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) public static final int EVENT_CELL_LOCATION_CHANGED = 5; // 0x5
- field public static final int EVENT_DATA_ACTIVATION_STATE_CHANGED = 19; // 0x13
- field public static final int EVENT_DATA_ACTIVITY_CHANGED = 8; // 0x8
- field @Deprecated @RequiresPermission(android.Manifest.permission.READ_PRECISE_PHONE_STATE) public static final int EVENT_DATA_CONNECTION_REAL_TIME_INFO_CHANGED = 14; // 0xe
- field public static final int EVENT_DATA_CONNECTION_STATE_CHANGED = 7; // 0x7
- field @RequiresPermission(android.Manifest.permission.READ_PRECISE_PHONE_STATE) public static final int EVENT_DATA_ENABLED_CHANGED = 34; // 0x22
- field public static final int EVENT_DISPLAY_INFO_CHANGED = 21; // 0x15
- field @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public static final int EVENT_EMERGENCY_NUMBER_LIST_CHANGED = 25; // 0x19
- field @RequiresPermission(android.Manifest.permission.READ_PRECISE_PHONE_STATE) public static final int EVENT_IMS_CALL_DISCONNECT_CAUSE_CHANGED = 28; // 0x1c
- field @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public static final int EVENT_MESSAGE_WAITING_INDICATOR_CHANGED = 3; // 0x3
- field @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public static final int EVENT_OEM_HOOK_RAW = 15; // 0xf
- field @RequiresPermission(android.Manifest.permission.READ_ACTIVE_EMERGENCY_SESSION) public static final int EVENT_OUTGOING_EMERGENCY_CALL = 29; // 0x1d
- field @RequiresPermission(android.Manifest.permission.READ_ACTIVE_EMERGENCY_SESSION) public static final int EVENT_OUTGOING_EMERGENCY_SMS = 30; // 0x1e
- field public static final int EVENT_PHONE_CAPABILITY_CHANGED = 22; // 0x16
- field @RequiresPermission(android.Manifest.permission.READ_PRECISE_PHONE_STATE) public static final int EVENT_PHYSICAL_CHANNEL_CONFIG_CHANGED = 33; // 0x21
- field @RequiresPermission(android.Manifest.permission.READ_PRECISE_PHONE_STATE) public static final int EVENT_PRECISE_CALL_STATE_CHANGED = 12; // 0xc
- field @RequiresPermission(android.Manifest.permission.READ_PRECISE_PHONE_STATE) public static final int EVENT_PRECISE_DATA_CONNECTION_STATE_CHANGED = 13; // 0xd
- field @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public static final int EVENT_RADIO_POWER_STATE_CHANGED = 24; // 0x18
- field @RequiresPermission(allOf={android.Manifest.permission.READ_PRECISE_PHONE_STATE, android.Manifest.permission.ACCESS_FINE_LOCATION}) public static final int EVENT_REGISTRATION_FAILURE = 31; // 0x1f
- field public static final int EVENT_SERVICE_STATE_CHANGED = 1; // 0x1
- field public static final int EVENT_SIGNAL_STRENGTHS_CHANGED = 9; // 0x9
- field public static final int EVENT_SIGNAL_STRENGTH_CHANGED = 2; // 0x2
- field @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public static final int EVENT_SRVCC_STATE_CHANGED = 16; // 0x10
- field public static final int EVENT_USER_MOBILE_DATA_STATE_CHANGED = 20; // 0x14
- field @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public static final int EVENT_VOICE_ACTIVATION_STATE_CHANGED = 18; // 0x12
- field @Deprecated @RequiresPermission(android.Manifest.permission.READ_PRECISE_PHONE_STATE) public static final int LISTEN_CALL_ATTRIBUTES_CHANGED = 67108864; // 0x4000000
- field @Deprecated @RequiresPermission(android.Manifest.permission.READ_ACTIVE_EMERGENCY_SESSION) public static final int LISTEN_OUTGOING_EMERGENCY_CALL = 268435456; // 0x10000000
- field @Deprecated @RequiresPermission(android.Manifest.permission.READ_ACTIVE_EMERGENCY_SESSION) public static final int LISTEN_OUTGOING_EMERGENCY_SMS = 536870912; // 0x20000000
- field @Deprecated @RequiresPermission(android.Manifest.permission.READ_PRECISE_PHONE_STATE) public static final int LISTEN_PRECISE_CALL_STATE = 2048; // 0x800
- field @Deprecated @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public static final int LISTEN_RADIO_POWER_STATE_CHANGED = 8388608; // 0x800000
- field @Deprecated @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public static final int LISTEN_SRVCC_STATE_CHANGED = 16384; // 0x4000
- field @Deprecated @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public static final int LISTEN_VOICE_ACTIVATION_STATE = 131072; // 0x20000
- }
-
- public static interface PhoneStateListener.CallAttributesChangedListener {
- method @RequiresPermission(android.Manifest.permission.READ_PRECISE_PHONE_STATE) public void onCallAttributesChanged(@NonNull android.telephony.CallAttributes);
+ field @RequiresPermission("android.permission.READ_PRECISE_PHONE_STATE") public static final int LISTEN_CALL_ATTRIBUTES_CHANGED = 67108864; // 0x4000000
+ field @RequiresPermission(android.Manifest.permission.READ_ACTIVE_EMERGENCY_SESSION) public static final int LISTEN_OUTGOING_EMERGENCY_CALL = 268435456; // 0x10000000
+ field @RequiresPermission(android.Manifest.permission.READ_ACTIVE_EMERGENCY_SESSION) public static final int LISTEN_OUTGOING_EMERGENCY_SMS = 536870912; // 0x20000000
+ field @RequiresPermission(android.Manifest.permission.READ_PRECISE_PHONE_STATE) public static final long LISTEN_PHYSICAL_CHANNEL_CONFIGURATION = 4294967296L; // 0x100000000L
+ field @RequiresPermission("android.permission.READ_PRECISE_PHONE_STATE") public static final int LISTEN_PRECISE_CALL_STATE = 2048; // 0x800
+ field @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public static final int LISTEN_RADIO_POWER_STATE_CHANGED = 8388608; // 0x800000
+ field @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public static final int LISTEN_SRVCC_STATE_CHANGED = 16384; // 0x4000
+ field @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public static final int LISTEN_VOICE_ACTIVATION_STATE = 131072; // 0x20000
}
- public static interface PhoneStateListener.DataEnabledChangedListener {
- method @RequiresPermission(android.Manifest.permission.READ_PRECISE_PHONE_STATE) public void onDataEnabledChanged(boolean, int);
- }
-
- public static interface PhoneStateListener.OutgoingEmergencyCallListener {
- method @RequiresPermission(android.Manifest.permission.READ_ACTIVE_EMERGENCY_SESSION) public void onOutgoingEmergencyCall(@NonNull android.telephony.emergency.EmergencyNumber, int);
- }
-
- public static interface PhoneStateListener.OutgoingEmergencySmsListener {
- method @RequiresPermission(android.Manifest.permission.READ_ACTIVE_EMERGENCY_SESSION) public void onOutgoingEmergencySms(@NonNull android.telephony.emergency.EmergencyNumber, int);
- }
-
- public static interface PhoneStateListener.PreciseCallStateChangedListener {
- method @RequiresPermission(android.Manifest.permission.READ_PRECISE_PHONE_STATE) public void onPreciseCallStateChanged(@NonNull android.telephony.PreciseCallState);
- }
-
- public static interface PhoneStateListener.RadioPowerStateChangedListener {
- method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void onRadioPowerStateChanged(int);
- }
-
- public static interface PhoneStateListener.SrvccStateChangedListener {
- method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void onSrvccStateChanged(int);
- }
-
- public static interface PhoneStateListener.VoiceActivationStateChangedListener {
- method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void onVoiceActivationStateChanged(int);
+ public final class PhysicalChannelConfig implements android.os.Parcelable {
+ method public int describeContents();
+ method public int getCellBandwidthDownlink();
+ method public int getChannelNumber();
+ method public int getConnectionStatus();
+ method public int getNetworkType();
+ method @IntRange(from=0, to=1007) public int getPhysicalCellId();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field public static final int CHANNEL_NUMBER_UNKNOWN = -1; // 0xffffffff
+ field public static final int CONNECTION_PRIMARY_SERVING = 1; // 0x1
+ field public static final int CONNECTION_SECONDARY_SERVING = 2; // 0x2
+ field public static final int CONNECTION_UNKNOWN = -1; // 0xffffffff
+ field @NonNull public static final android.os.Parcelable.Creator<android.telephony.PhysicalChannelConfig> CREATOR;
+ field public static final int PHYSICAL_CELL_ID_UNKNOWN = -1; // 0xffffffff
}
public final class PinResult implements android.os.Parcelable {
@@ -10836,6 +10805,7 @@ package android.telephony {
method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public int getSimCardState(int);
method @Nullable @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public java.util.Locale getSimLocale();
method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public long getSupportedRadioAccessFamily();
+ method @NonNull @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public java.util.List<android.telephony.RadioAccessSpecifier> getSystemSelectionChannels();
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public java.util.List<android.telephony.TelephonyHistogram> getTelephonyHistograms();
method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public android.telephony.UiccSlotInfo[] getUiccSlotsInfo();
method @Nullable public android.os.Bundle getVisualVoicemailSettings();
@@ -10879,6 +10849,7 @@ package android.telephony {
method @RequiresPermission(android.Manifest.permission.READ_ACTIVE_EMERGENCY_SESSION) public void resetOtaEmergencyNumberDbFilePath();
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean resetRadioConfig();
method @RequiresPermission(android.Manifest.permission.CONNECTIVITY_INTERNAL) public void resetSettings();
+ method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public int sendThermalMitigationRequest(@NonNull android.telephony.ThermalMitigationRequest);
method @Deprecated @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public int setAllowedCarriers(int, java.util.List<android.service.carrier.CarrierIdentifier>);
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean setAllowedNetworkTypes(long);
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setCallForwarding(@NonNull android.telephony.CallForwardingInfo, @Nullable java.util.concurrent.Executor, @Nullable java.util.function.Consumer<java.lang.Integer>);
@@ -10996,6 +10967,11 @@ package android.telephony {
field public static final int SRVCC_STATE_HANDOVER_FAILED = 2; // 0x2
field public static final int SRVCC_STATE_HANDOVER_NONE = -1; // 0xffffffff
field public static final int SRVCC_STATE_HANDOVER_STARTED = 0; // 0x0
+ field public static final int THERMAL_MITIGATION_RESULT_INVALID_STATE = 3; // 0x3
+ field public static final int THERMAL_MITIGATION_RESULT_MODEM_ERROR = 1; // 0x1
+ field public static final int THERMAL_MITIGATION_RESULT_MODEM_NOT_AVAILABLE = 2; // 0x2
+ field public static final int THERMAL_MITIGATION_RESULT_SUCCESS = 0; // 0x0
+ field public static final int THERMAL_MITIGATION_RESULT_UNKNOWN_ERROR = 4; // 0x4
}
public static interface TelephonyManager.CallForwardingInfoCallback {
@@ -11015,6 +10991,24 @@ package android.telephony {
field public static final int ERROR_UNKNOWN = 0; // 0x0
}
+ public final class ThermalMitigationRequest implements android.os.Parcelable {
+ method public int describeContents();
+ method @Nullable public android.telephony.DataThrottlingRequest getDataThrottlingRequest();
+ method public int getThermalMitigationAction();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.telephony.ThermalMitigationRequest> CREATOR;
+ field public static final int THERMAL_MITIGATION_ACTION_DATA_THROTTLING = 0; // 0x0
+ field public static final int THERMAL_MITIGATION_ACTION_RADIO_OFF = 2; // 0x2
+ field public static final int THERMAL_MITIGATION_ACTION_VOICE_ONLY = 1; // 0x1
+ }
+
+ public static final class ThermalMitigationRequest.Builder {
+ ctor public ThermalMitigationRequest.Builder();
+ method @NonNull public android.telephony.ThermalMitigationRequest build();
+ method @NonNull public android.telephony.ThermalMitigationRequest.Builder setDataThrottlingRequest(@NonNull android.telephony.DataThrottlingRequest);
+ method @NonNull public android.telephony.ThermalMitigationRequest.Builder setThermalMitigationAction(int);
+ }
+
public final class UiccAccessRule implements android.os.Parcelable {
ctor public UiccAccessRule(byte[], @Nullable String, long);
method public int describeContents();
diff --git a/core/api/test-current.txt b/core/api/test-current.txt
index fda7c203226c..52a79bae6324 100644
--- a/core/api/test-current.txt
+++ b/core/api/test-current.txt
@@ -302,8 +302,10 @@ package android.app {
method public void destroy();
method @NonNull public android.os.ParcelFileDescriptor[] executeShellCommandRwe(@NonNull String);
method @Deprecated public boolean grantRuntimePermission(String, String, android.os.UserHandle);
+ method public boolean injectInputEvent(@NonNull android.view.InputEvent, boolean, boolean);
method @Deprecated public boolean revokeRuntimePermission(String, String, android.os.UserHandle);
method public void syncInputTransactions();
+ method public void syncInputTransactions(boolean);
}
public class UiModeManager {
diff --git a/core/java/android/accessibilityservice/AccessibilityServiceInfo.java b/core/java/android/accessibilityservice/AccessibilityServiceInfo.java
index b1b9f4161ee5..b15fa27485be 100644
--- a/core/java/android/accessibilityservice/AccessibilityServiceInfo.java
+++ b/core/java/android/accessibilityservice/AccessibilityServiceInfo.java
@@ -650,7 +650,6 @@ public class AccessibilityServiceInfo implements Parcelable {
0);
flags = asAttributes.getInt(
com.android.internal.R.styleable.AccessibilityService_accessibilityFlags, 0);
- flags |= FLAG_REQUEST_2_FINGER_PASSTHROUGH;
mSettingsActivityName = asAttributes.getString(
com.android.internal.R.styleable.AccessibilityService_settingsActivity);
if (asAttributes.getBoolean(com.android.internal.R.styleable
diff --git a/core/java/android/app/AppOpsManager.java b/core/java/android/app/AppOpsManager.java
index d9f34d856f7c..cdfe41e85917 100644
--- a/core/java/android/app/AppOpsManager.java
+++ b/core/java/android/app/AppOpsManager.java
@@ -34,6 +34,7 @@ import android.compat.annotation.UnsupportedAppUsage;
import android.content.ComponentName;
import android.content.ContentResolver;
import android.content.Context;
+import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.ParceledListSlice;
import android.database.DatabaseUtils;
@@ -7617,7 +7618,7 @@ public class AppOpsManager {
// Only collect app-ops when the proxy is trusted
&& (mContext.checkPermission(Manifest.permission.UPDATE_APP_OPS_STATS, -1,
myUid) == PackageManager.PERMISSION_GRANTED
- || isTrustedVoiceServiceProxy(mContext.getOpPackageName(), op))) {
+ || isTrustedVoiceServiceProxy(mContext, mContext.getOpPackageName(), op))) {
collectNotedOpSync(op, proxiedAttributionTag);
}
}
@@ -7628,30 +7629,43 @@ public class AppOpsManager {
}
}
- private boolean isTrustedVoiceServiceProxy(String packageName, int code) {
+ /**
+ * Checks if the voice recognition service is a trust proxy.
+ *
+ * @return {@code true} if the package is a trust voice recognition service proxy
+ * @hide
+ */
+ public static boolean isTrustedVoiceServiceProxy(Context context, String packageName,
+ int code) {
// This is a workaround for R QPR, new API change is not allowed. We only allow the current
// voice recognizer is also the voice interactor to noteproxy op.
if (code != OP_RECORD_AUDIO) {
return false;
}
final String voiceRecognitionComponent = Settings.Secure.getString(
- mContext.getContentResolver(), Settings.Secure.VOICE_RECOGNITION_SERVICE);
- final String voiceInteractionComponent = Settings.Secure.getString(
- mContext.getContentResolver(), Settings.Secure.VOICE_INTERACTION_SERVICE);
+ context.getContentResolver(), Settings.Secure.VOICE_RECOGNITION_SERVICE);
final String voiceRecognitionServicePackageName =
getComponentPackageNameFromString(voiceRecognitionComponent);
- final String voiceInteractionServicePackageName =
- getComponentPackageNameFromString(voiceInteractionComponent);
- return Objects.equals(packageName, voiceRecognitionServicePackageName) && Objects.equals(
- voiceRecognitionServicePackageName, voiceInteractionServicePackageName);
+ return (Objects.equals(packageName, voiceRecognitionServicePackageName))
+ && isPackagePreInstalled(context, packageName);
}
- private String getComponentPackageNameFromString(String from) {
+ private static String getComponentPackageNameFromString(String from) {
ComponentName componentName = from != null ? ComponentName.unflattenFromString(from) : null;
return componentName != null ? componentName.getPackageName() : "";
}
+ private static boolean isPackagePreInstalled(Context context, String packageName) {
+ try {
+ final PackageManager pm = context.getPackageManager();
+ final ApplicationInfo info = pm.getApplicationInfo(packageName, 0);
+ return ((info.flags & ApplicationInfo.FLAG_SYSTEM) != 0);
+ } catch (PackageManager.NameNotFoundException e) {
+ return false;
+ }
+ }
+
/**
* Do a quick check for whether an application might be able to perform an operation.
* This is <em>not</em> a security check; you must use {@link #noteOp(String, int, String,
diff --git a/core/java/android/app/ApplicationPackageManager.java b/core/java/android/app/ApplicationPackageManager.java
index 7cef93fe7547..34437afb614a 100644
--- a/core/java/android/app/ApplicationPackageManager.java
+++ b/core/java/android/app/ApplicationPackageManager.java
@@ -58,6 +58,8 @@ import android.content.pm.PackageInfo;
import android.content.pm.PackageInstaller;
import android.content.pm.PackageItemInfo;
import android.content.pm.PackageManager;
+import android.content.pm.PackageManager.NameNotFoundException;
+import android.content.pm.PackageManager.Property;
import android.content.pm.ParceledListSlice;
import android.content.pm.PermissionGroupInfo;
import android.content.pm.PermissionInfo;
@@ -3551,4 +3553,112 @@ public class ApplicationPackageManager extends PackageManager {
throw e.rethrowAsRuntimeException();
}
}
+
+ @Override
+ public Property getProperty(String propertyName, String packageName)
+ throws NameNotFoundException {
+ Objects.requireNonNull(packageName);
+ Objects.requireNonNull(propertyName);
+ try {
+ final Property property = mPM.getProperty(propertyName, packageName, null);
+ if (property == null) {
+ throw new NameNotFoundException();
+ }
+ return property;
+ } catch (RemoteException e) {
+ throw e.rethrowAsRuntimeException();
+ }
+ }
+
+ @Override
+ public Property getProperty(String propertyName, ComponentName component)
+ throws NameNotFoundException {
+ Objects.requireNonNull(component);
+ Objects.requireNonNull(propertyName);
+ try {
+ final Property property = mPM.getProperty(
+ propertyName, component.getPackageName(), component.getClassName());
+ if (property == null) {
+ throw new NameNotFoundException();
+ }
+ return property;
+ } catch (RemoteException e) {
+ throw e.rethrowAsRuntimeException();
+ }
+ }
+
+ @Override
+ public List<Property> queryApplicationProperty(String propertyName) {
+ Objects.requireNonNull(propertyName);
+ try {
+ final ParceledListSlice<Property> parceledList =
+ mPM.queryProperty(propertyName, TYPE_APPLICATION);
+ if (parceledList == null) {
+ return Collections.emptyList();
+ }
+ return parceledList.getList();
+ } catch (RemoteException e) {
+ throw e.rethrowAsRuntimeException();
+ }
+ }
+
+ @Override
+ public List<Property> queryActivityProperty(String propertyName) {
+ Objects.requireNonNull(propertyName);
+ try {
+ final ParceledListSlice<Property> parceledList =
+ mPM.queryProperty(propertyName, TYPE_ACTIVITY);
+ if (parceledList == null) {
+ return Collections.emptyList();
+ }
+ return parceledList.getList();
+ } catch (RemoteException e) {
+ throw e.rethrowAsRuntimeException();
+ }
+ }
+
+ @Override
+ public List<Property> queryProviderProperty(String propertyName) {
+ Objects.requireNonNull(propertyName);
+ try {
+ final ParceledListSlice<Property> parceledList =
+ mPM.queryProperty(propertyName, TYPE_PROVIDER);
+ if (parceledList == null) {
+ return Collections.emptyList();
+ }
+ return parceledList.getList();
+ } catch (RemoteException e) {
+ throw e.rethrowAsRuntimeException();
+ }
+ }
+
+ @Override
+ public List<Property> queryReceiverProperty(String propertyName) {
+ Objects.requireNonNull(propertyName);
+ try {
+ final ParceledListSlice<Property> parceledList =
+ mPM.queryProperty(propertyName, TYPE_RECEIVER);
+ if (parceledList == null) {
+ return Collections.emptyList();
+ }
+ return parceledList.getList();
+ } catch (RemoteException e) {
+ throw e.rethrowAsRuntimeException();
+ }
+ }
+
+ @Override
+ public List<Property> queryServiceProperty(String propertyName) {
+ Objects.requireNonNull(propertyName);
+ try {
+ final ParceledListSlice<Property> parceledList =
+ mPM.queryProperty(propertyName, TYPE_SERVICE);
+ if (parceledList == null) {
+ return Collections.emptyList();
+ }
+ return parceledList.getList();
+ } catch (RemoteException e) {
+ throw e.rethrowAsRuntimeException();
+ }
+ }
}
diff --git a/core/java/android/app/IUiAutomationConnection.aidl b/core/java/android/app/IUiAutomationConnection.aidl
index 9eeb9f6a95bf..ec7d7832dc82 100644
--- a/core/java/android/app/IUiAutomationConnection.aidl
+++ b/core/java/android/app/IUiAutomationConnection.aidl
@@ -36,8 +36,8 @@ import android.os.ParcelFileDescriptor;
interface IUiAutomationConnection {
void connect(IAccessibilityServiceClient client, int flags);
void disconnect();
- boolean injectInputEvent(in InputEvent event, boolean sync);
- void syncInputTransactions();
+ boolean injectInputEvent(in InputEvent event, boolean sync, boolean waitForAnimations);
+ void syncInputTransactions(boolean waitForAnimations);
boolean setRotation(int rotation);
Bitmap takeScreenshot(in Rect crop);
boolean clearWindowContentFrameStats(int windowId);
diff --git a/core/java/android/app/Instrumentation.java b/core/java/android/app/Instrumentation.java
index 3e249bb24dd6..e9d63d2bc788 100644
--- a/core/java/android/app/Instrumentation.java
+++ b/core/java/android/app/Instrumentation.java
@@ -1119,7 +1119,8 @@ public class Instrumentation {
}
try {
WindowManagerGlobal.getWindowManagerService().injectInputAfterTransactionsApplied(event,
- InputManager.INJECT_INPUT_EVENT_MODE_WAIT_FOR_FINISH);
+ InputManager.INJECT_INPUT_EVENT_MODE_WAIT_FOR_FINISH,
+ true /* waitForAnimations */);
} catch (RemoteException e) {
}
}
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index e40247ba2d9a..2bf5368b691b 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -4888,12 +4888,6 @@ public class Notification implements Parcelable
mN.mUsesStandardHeader = false;
}
- private RemoteViews applyStandardTemplate(int resId, int viewType,
- TemplateBindResult result) {
- return applyStandardTemplate(resId,
- mParams.reset().viewType(viewType).fillTextsFrom(this), result);
- }
-
private RemoteViews applyStandardTemplate(int resId, StandardTemplateParams p,
TemplateBindResult result) {
p.headerless(resId == getBaseLayoutResource()
@@ -4907,7 +4901,7 @@ public class Notification implements Parcelable
bindNotificationHeader(contentView, p);
bindLargeIconAndApplyMargin(contentView, p, result);
boolean showProgress = handleProgressBar(contentView, ex, p);
- if (p.title != null && p.title.length() > 0) {
+ if (p.title != null && p.title.length() > 0 && !p.mHasCustomContent) {
contentView.setViewVisibility(R.id.title, View.VISIBLE);
contentView.setTextViewText(R.id.title, processTextSpans(p.title));
setTextViewColorPrimary(contentView, R.id.title, p);
@@ -5302,6 +5296,12 @@ public class Notification implements Parcelable
contentView.setViewVisibility(R.id.app_name_text, View.GONE);
return false;
}
+ if (p.mHeaderless && !p.mHasCustomContent) {
+ contentView.setViewVisibility(R.id.app_name_text, View.GONE);
+ // the headerless template will have the TITLE in this position; return true to
+ // keep the divider visible between that title and the next text element.
+ return true;
+ }
contentView.setViewVisibility(R.id.app_name_text, View.VISIBLE);
contentView.setTextViewText(R.id.app_name_text, loadHeaderAppName());
if (isColorized(p)) {
@@ -5356,12 +5356,6 @@ public class Notification implements Parcelable
snoozeEnabled ? 0 : R.dimen.notification_content_margin);
}
- private RemoteViews applyStandardTemplateWithActions(int layoutId, int viewType,
- TemplateBindResult result) {
- return applyStandardTemplateWithActions(layoutId,
- mParams.reset().viewType(viewType).fillTextsFrom(this), result);
- }
-
private static List<Notification.Action> filterOutContextualActions(
List<Notification.Action> actions) {
List<Notification.Action> nonContextualActions = new ArrayList<>();
@@ -5499,8 +5493,10 @@ public class Notification implements Parcelable
return styleView;
}
}
- return applyStandardTemplate(getBaseLayoutResource(),
- StandardTemplateParams.VIEW_TYPE_NORMAL, null /* result */);
+ StandardTemplateParams p = mParams.reset()
+ .viewType(StandardTemplateParams.VIEW_TYPE_NORMAL)
+ .fillTextsFrom(this);
+ return applyStandardTemplate(getBaseLayoutResource(), p, null /* result */);
}
private boolean useExistingRemoteView() {
@@ -5520,14 +5516,27 @@ public class Notification implements Parcelable
result = mStyle.makeBigContentView();
hideLine1Text(result);
}
- if (result == null) {
- result = applyStandardTemplateWithActions(getBigBaseLayoutResource(),
- StandardTemplateParams.VIEW_TYPE_BIG, null /* result */);
+ if (result == null && bigContentViewRequired()) {
+ StandardTemplateParams p = mParams.reset()
+ .viewType(StandardTemplateParams.VIEW_TYPE_BIG)
+ .fillTextsFrom(this);
+ result = applyStandardTemplateWithActions(getBigBaseLayoutResource(), p,
+ null /* result */);
}
makeHeaderExpanded(result);
return result;
}
+ private boolean bigContentViewRequired() {
+ // If the big content view has no content, we can exempt the app from having to show it.
+ // TODO(b/173550917): add an UNDO style then force this requirement on apps targeting S
+ boolean exempt = mN.contentView != null && mN.bigContentView == null
+ && mStyle == null && mActions.size() == 0
+ && mN.extras.getCharSequence(EXTRA_TITLE) == null
+ && mN.extras.getCharSequence(EXTRA_TEXT) == null;
+ return !exempt;
+ }
+
/**
* Construct a RemoteViews for the final notification header only. This will not be
* colorized.
@@ -8693,18 +8702,24 @@ public class Notification implements Parcelable
return makeStandardTemplateWithCustomContent(headsUpContentView);
}
TemplateBindResult result = new TemplateBindResult();
+ StandardTemplateParams p = mBuilder.mParams.reset()
+ .viewType(StandardTemplateParams.VIEW_TYPE_HEADS_UP)
+ .hasCustomContent(headsUpContentView != null)
+ .fillTextsFrom(mBuilder);
RemoteViews remoteViews = mBuilder.applyStandardTemplateWithActions(
- mBuilder.getHeadsUpBaseLayoutResource(),
- StandardTemplateParams.VIEW_TYPE_HEADS_UP, result);
+ mBuilder.getHeadsUpBaseLayoutResource(), p, result);
buildIntoRemoteViewContent(remoteViews, headsUpContentView, result, true);
return remoteViews;
}
private RemoteViews makeStandardTemplateWithCustomContent(RemoteViews customContent) {
TemplateBindResult result = new TemplateBindResult();
+ StandardTemplateParams p = mBuilder.mParams.reset()
+ .viewType(StandardTemplateParams.VIEW_TYPE_NORMAL)
+ .hasCustomContent(customContent != null)
+ .fillTextsFrom(mBuilder);
RemoteViews remoteViews = mBuilder.applyStandardTemplate(
- mBuilder.getBaseLayoutResource(),
- StandardTemplateParams.VIEW_TYPE_NORMAL, result);
+ mBuilder.getBaseLayoutResource(), p, result);
buildIntoRemoteViewContent(remoteViews, customContent, result, true);
return remoteViews;
}
@@ -8714,9 +8729,12 @@ public class Notification implements Parcelable
? mBuilder.mN.contentView
: mBuilder.mN.bigContentView;
TemplateBindResult result = new TemplateBindResult();
+ StandardTemplateParams p = mBuilder.mParams.reset()
+ .viewType(StandardTemplateParams.VIEW_TYPE_BIG)
+ .hasCustomContent(bigContentView != null)
+ .fillTextsFrom(mBuilder);
RemoteViews remoteViews = mBuilder.applyStandardTemplateWithActions(
- mBuilder.getBigBaseLayoutResource(),
- StandardTemplateParams.VIEW_TYPE_BIG, result);
+ mBuilder.getBigBaseLayoutResource(), p, result);
buildIntoRemoteViewContent(remoteViews, bigContentView, result, false);
return remoteViews;
}
@@ -11029,6 +11047,7 @@ public class Notification implements Parcelable
int mViewType = VIEW_TYPE_UNSPECIFIED;
boolean mHeaderless;
+ boolean mHasCustomContent;
boolean hasProgress = true;
CharSequence title;
CharSequence text;
@@ -11042,6 +11061,7 @@ public class Notification implements Parcelable
final StandardTemplateParams reset() {
mViewType = VIEW_TYPE_UNSPECIFIED;
mHeaderless = false;
+ mHasCustomContent = false;
hasProgress = true;
title = null;
text = null;
@@ -11068,6 +11088,11 @@ public class Notification implements Parcelable
return this;
}
+ final StandardTemplateParams hasCustomContent(boolean hasCustomContent) {
+ this.mHasCustomContent = hasCustomContent;
+ return this;
+ }
+
final StandardTemplateParams title(CharSequence title) {
this.title = title;
return this;
diff --git a/core/java/android/app/PendingIntent.java b/core/java/android/app/PendingIntent.java
index f76a75749480..9dbf1ff6f7c9 100644
--- a/core/java/android/app/PendingIntent.java
+++ b/core/java/android/app/PendingIntent.java
@@ -179,6 +179,12 @@ public final class PendingIntent implements Parcelable {
* extras change, and don't care that any entities that received your
* previous PendingIntent will be able to launch it with your new
* extras even if they are not explicitly given to it.
+ *
+ * <p>{@link #FLAG_UPDATE_CURRENT} still works even if {@link
+ * #FLAG_IMMUTABLE} is set - the creator of the PendingIntent can always
+ * update the PendingIntent itself. The IMMUTABLE flag only limits the
+ * ability to alter the semantics of the intent that is sent by {@link
+ * #send} by the invoker of {@link #send}.
*/
public static final int FLAG_UPDATE_CURRENT = 1<<27;
@@ -187,6 +193,11 @@ public final class PendingIntent implements Parcelable {
* This means that the additional intent argument passed to the send
* methods to fill in unpopulated properties of this intent will be
* ignored.
+ *
+ * <p>{@link #FLAG_IMMUTABLE} only limits the ability to alter the
+ * semantics of the intent that is sent by {@link #send} by the invoker of
+ * {@link #send}. The creator of the PendingIntent can always update the
+ * PendingIntent itself via {@link #FLAG_UPDATE_CURRENT}.
*/
public static final int FLAG_IMMUTABLE = 1<<26;
diff --git a/core/java/android/app/TEST_MAPPING b/core/java/android/app/TEST_MAPPING
index b0307d1eb939..d2be8a4a6597 100644
--- a/core/java/android/app/TEST_MAPPING
+++ b/core/java/android/app/TEST_MAPPING
@@ -33,10 +33,10 @@
},
{
"file_patterns": ["(/|^)AppOpsManager.java"],
- "name": "CtsStatsdHostTestCases",
+ "name": "CtsStatsdAtomHostTestCases",
"options": [
{
- "include-filter": "android.cts.statsd.atom.UidAtomTests#testAppOps"
+ "include-filter": "android.cts.statsdatom.appops.AppOpsTests#testAppOps"
}
]
},
diff --git a/core/java/android/app/TaskInfo.java b/core/java/android/app/TaskInfo.java
index da8ac96ef40b..ca67dba45dd0 100644
--- a/core/java/android/app/TaskInfo.java
+++ b/core/java/android/app/TaskInfo.java
@@ -221,6 +221,12 @@ public class TaskInfo {
*/
public Rect parentBounds;
+ /**
+ * Whether this task is focused.
+ * @hide
+ */
+ public boolean isFocused;
+
TaskInfo() {
// Do nothing
}
@@ -304,7 +310,8 @@ public class TaskInfo {
&& equalsLetterboxParams(that)
&& pictureInPictureParams == that.pictureInPictureParams
&& getWindowingMode() == that.getWindowingMode()
- && Objects.equals(taskDescription, that.taskDescription);
+ && Objects.equals(taskDescription, that.taskDescription)
+ && isFocused == that.isFocused;
}
private boolean equalsLetterboxParams(TaskInfo that) {
@@ -350,6 +357,7 @@ public class TaskInfo {
positionInParent = source.readTypedObject(Point.CREATOR);
parentTaskId = source.readInt();
parentBounds = source.readTypedObject(Rect.CREATOR);
+ isFocused = source.readBoolean();
}
/**
@@ -385,6 +393,7 @@ public class TaskInfo {
dest.writeTypedObject(positionInParent, flags);
dest.writeInt(parentTaskId);
dest.writeTypedObject(parentBounds, flags);
+ dest.writeBoolean(isFocused);
}
@Override
@@ -407,8 +416,9 @@ public class TaskInfo {
+ " launchCookies" + launchCookies
+ " letterboxActivityBounds=" + letterboxActivityBounds
+ " positionInParent=" + positionInParent
- + " parentTaskId: " + parentTaskId
- + " parentBounds: " + parentBounds
+ + " parentTaskId=" + parentTaskId
+ + " parentBounds=" + parentBounds
+ + " isFocused=" + isFocused
+ "}";
}
}
diff --git a/core/java/android/app/UiAutomation.java b/core/java/android/app/UiAutomation.java
index 1b0fd9edf4f8..787393ed0f6c 100644
--- a/core/java/android/app/UiAutomation.java
+++ b/core/java/android/app/UiAutomation.java
@@ -695,6 +695,9 @@ public final class UiAutomation {
/**
* A method for injecting an arbitrary input event.
+ *
+ * This method waits for all window container animations and surface operations to complete.
+ *
* <p>
* <strong>Note:</strong> It is caller's responsibility to recycle the event.
* </p>
@@ -704,12 +707,34 @@ public final class UiAutomation {
* @return Whether event injection succeeded.
*/
public boolean injectInputEvent(InputEvent event, boolean sync) {
+ return injectInputEvent(event, sync, true /* waitForAnimations */);
+ }
+
+ /**
+ * A method for injecting an arbitrary input event, optionally waiting for window animations to
+ * complete.
+ * <p>
+ * <strong>Note:</strong> It is caller's responsibility to recycle the event.
+ * </p>
+ *
+ * @param event The event to inject.
+ * @param sync Whether to inject the event synchronously.
+ * @param waitForAnimations Whether to wait for all window container animations and surface
+ * operations to complete.
+ * @return Whether event injection succeeded.
+ *
+ * @hide
+ */
+ @TestApi
+ public boolean injectInputEvent(@NonNull InputEvent event, boolean sync,
+ boolean waitForAnimations) {
try {
if (DEBUG) {
- Log.i(LOG_TAG, "Injecting: " + event + " sync: " + sync);
+ Log.i(LOG_TAG, "Injecting: " + event + " sync: " + sync + " waitForAnimations: "
+ + waitForAnimations);
}
// Calling out without a lock held.
- return mUiAutomationConnection.injectInputEvent(event, sync);
+ return mUiAutomationConnection.injectInputEvent(event, sync, waitForAnimations);
} catch (RemoteException re) {
Log.e(LOG_TAG, "Error while injecting input event!", re);
}
@@ -726,7 +751,26 @@ public final class UiAutomation {
public void syncInputTransactions() {
try {
// Calling out without a lock held.
- mUiAutomationConnection.syncInputTransactions();
+ mUiAutomationConnection.syncInputTransactions(true /* waitForAnimations */);
+ } catch (RemoteException re) {
+ Log.e(LOG_TAG, "Error while syncing input transactions!", re);
+ }
+ }
+
+ /**
+ * A request for WindowManagerService to wait until all input information has been sent from
+ * WindowManager to native InputManager and optionally wait for animations to complete.
+ *
+ * @param waitForAnimations Whether to wait for all window container animations and surface
+ * operations to complete.
+ *
+ * @hide
+ */
+ @TestApi
+ public void syncInputTransactions(boolean waitForAnimations) {
+ try {
+ // Calling out without a lock held.
+ mUiAutomationConnection.syncInputTransactions(waitForAnimations);
} catch (RemoteException re) {
Log.e(LOG_TAG, "Error while syncing input transactions!", re);
}
diff --git a/core/java/android/app/UiAutomationConnection.java b/core/java/android/app/UiAutomationConnection.java
index 290e12191de8..7036b6e7dbc9 100644
--- a/core/java/android/app/UiAutomationConnection.java
+++ b/core/java/android/app/UiAutomationConnection.java
@@ -124,7 +124,7 @@ public final class UiAutomationConnection extends IUiAutomationConnection.Stub {
}
@Override
- public boolean injectInputEvent(InputEvent event, boolean sync) {
+ public boolean injectInputEvent(InputEvent event, boolean sync, boolean waitForAnimations) {
synchronized (mLock) {
throwIfCalledByNotTrustedUidLocked();
throwIfShutdownLocked();
@@ -134,7 +134,8 @@ public final class UiAutomationConnection extends IUiAutomationConnection.Stub {
: InputManager.INJECT_INPUT_EVENT_MODE_ASYNC;
final long identity = Binder.clearCallingIdentity();
try {
- return mWindowManager.injectInputAfterTransactionsApplied(event, mode);
+ return mWindowManager.injectInputAfterTransactionsApplied(event, mode,
+ waitForAnimations);
} catch (RemoteException e) {
} finally {
Binder.restoreCallingIdentity(identity);
@@ -143,7 +144,7 @@ public final class UiAutomationConnection extends IUiAutomationConnection.Stub {
}
@Override
- public void syncInputTransactions() {
+ public void syncInputTransactions(boolean waitForAnimations) {
synchronized (mLock) {
throwIfCalledByNotTrustedUidLocked();
throwIfShutdownLocked();
@@ -151,12 +152,11 @@ public final class UiAutomationConnection extends IUiAutomationConnection.Stub {
}
try {
- mWindowManager.syncInputTransactions();
+ mWindowManager.syncInputTransactions(waitForAnimations);
} catch (RemoteException e) {
}
}
-
@Override
public boolean setRotation(int rotation) {
synchronized (mLock) {
diff --git a/core/java/android/app/people/PeopleSpaceTile.java b/core/java/android/app/people/PeopleSpaceTile.java
new file mode 100644
index 000000000000..f5674e5cd0ce
--- /dev/null
+++ b/core/java/android/app/people/PeopleSpaceTile.java
@@ -0,0 +1,273 @@
+/*
+ * 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.app.people;
+
+import android.annotation.NonNull;
+import android.content.Intent;
+import android.content.pm.ShortcutInfo;
+import android.graphics.drawable.Icon;
+import android.net.Uri;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.service.notification.StatusBarNotification;
+
+/**
+ * The People Space tile contains all relevant information to render a tile in People Space: namely
+ * the data of any visible conversation notification associated, associated statuses, and the last
+ * interaction time.
+ *
+ * @hide
+ */
+public class PeopleSpaceTile implements Parcelable {
+
+ private String mId;
+ private CharSequence mUserName;
+ private Icon mUserIcon;
+ private int mUid;
+ private Uri mContactUri;
+ private String mPackageName;
+ private long mLastInteractionTimestamp;
+ private boolean mIsImportantConversation;
+ private boolean mIsHiddenConversation;
+ private StatusBarNotification mNotification;
+ private Intent mIntent;
+ // TODO: add a List of the Status objects once created
+
+ private PeopleSpaceTile(Builder b) {
+ mId = b.mId;
+ mUserName = b.mUserName;
+ mUserIcon = b.mUserIcon;
+ mContactUri = b.mContactUri;
+ mUid = b.mUid;
+ mPackageName = b.mPackageName;
+ mLastInteractionTimestamp = b.mLastInteractionTimestamp;
+ mIsImportantConversation = b.mIsImportantConversation;
+ mIsHiddenConversation = b.mIsHiddenConversation;
+ mNotification = b.mNotification;
+ mIntent = b.mIntent;
+ }
+
+ public String getId() {
+ return mId;
+ }
+
+ public CharSequence getUserName() {
+ return mUserName;
+ }
+
+ public Icon getUserIcon() {
+ return mUserIcon;
+ }
+
+ /** Returns the Uri associated with the user in Android Contacts database. */
+ public Uri getContactUri() {
+ return mContactUri;
+ }
+
+ public int getUid() {
+ return mUid;
+ }
+
+ public String getPackageName() {
+ return mPackageName;
+ }
+
+ /** Returns the timestamp of the last interaction. */
+ public long getLastInteractionTimestamp() {
+ return mLastInteractionTimestamp;
+ }
+
+ /**
+ * Whether the conversation is important.
+ */
+ public boolean isImportantConversation() {
+ return mIsImportantConversation;
+ }
+
+ /**
+ * Whether the conversation should be hidden.
+ */
+ public boolean isHiddenConversation() {
+ return mIsHiddenConversation;
+ }
+
+ /**
+ * If a notification is currently active that maps to the relevant shortcut ID, provides the
+ * {@link StatusBarNotification} associated.
+ */
+ public StatusBarNotification getNotification() {
+ return mNotification;
+ }
+
+ /**
+ * Provides an intent to launch. If present, we should manually launch the intent on tile
+ * click, rather than calling {@link android.content.pm.LauncherApps} to launch the shortcut ID.
+ *
+ * <p>This field should only be used if manually constructing a tile without an associated
+ * shortcut to launch (i.e. birthday tiles).
+ */
+ public Intent getIntent() {
+ return mIntent;
+ }
+
+ /** Builder to create a {@link PeopleSpaceTile}. */
+ public static class Builder {
+ private String mId;
+ private CharSequence mUserName;
+ private Icon mUserIcon;
+ private Uri mContactUri;
+ private int mUid;
+ private String mPackageName;
+ private long mLastInteractionTimestamp;
+ private boolean mIsImportantConversation;
+ private boolean mIsHiddenConversation;
+ private StatusBarNotification mNotification;
+ private Intent mIntent;
+
+ /** Builder for use only if a shortcut is not available for the tile. */
+ public Builder(String id, String userName, Icon userIcon, Intent intent) {
+ mId = id;
+ mUserName = userName;
+ mUserIcon = userIcon;
+ mIntent = intent;
+ mPackageName = intent == null ? null : intent.getPackage();
+ }
+
+ public Builder(ShortcutInfo info) {
+ mId = info.getId();
+ mUserName = info.getLabel();
+ mUserIcon = info.getIcon();
+ mUid = info.getUserId();
+ mPackageName = info.getPackage();
+ }
+
+ /** Sets the ID for the tile. */
+ public Builder setId(String id) {
+ mId = id;
+ return this;
+ }
+
+ /** Sets the user name. */
+ public Builder setUserName(CharSequence userName) {
+ mUserName = userName;
+ return this;
+ }
+
+ /** Sets the icon shown for the user. */
+ public Builder setUserIcon(Icon userIcon) {
+ mUserIcon = userIcon;
+ return this;
+ }
+
+ /** Sets the Uri associated with the user in Android Contacts database. */
+ public Builder setContactUri(Uri uri) {
+ mContactUri = uri;
+ return this;
+ }
+
+ /** Sets the associated uid. */
+ public Builder setUid(int uid) {
+ mUid = uid;
+ return this;
+ }
+
+ /** Sets the package shown that provided the information. */
+ public Builder setPackageName(String packageName) {
+ mPackageName = packageName;
+ return this;
+ }
+
+ /** Sets the last interaction timestamp. */
+ public Builder setLastInteractionTimestamp(long lastInteractionTimestamp) {
+ mLastInteractionTimestamp = lastInteractionTimestamp;
+ return this;
+ }
+
+ /** Sets whether the conversation is important. */
+ public Builder setIsImportantConversation(boolean isImportantConversation) {
+ mIsImportantConversation = isImportantConversation;
+ return this;
+ }
+
+ /** Sets whether the conversation is hidden. */
+ public Builder setIsHiddenConversation(boolean isHiddenConversation) {
+ mIsHiddenConversation = isHiddenConversation;
+ return this;
+ }
+
+ /** Sets the associated notification. */
+ public Builder setNotification(StatusBarNotification notification) {
+ mNotification = notification;
+ return this;
+ }
+
+ /** Sets an intent to launch on click. */
+ public Builder setIntent(Intent intent) {
+ mIntent = intent;
+ return this;
+ }
+
+ /** Builds a {@link PeopleSpaceTile}. */
+ @NonNull
+ public PeopleSpaceTile build() {
+ return new PeopleSpaceTile(this);
+ }
+ }
+
+ private PeopleSpaceTile(Parcel in) {
+ mId = in.readString();
+ mUserName = in.readCharSequence();
+ mUserIcon = in.readParcelable(Icon.class.getClassLoader());
+ mUid = in.readInt();
+ mPackageName = in.readString();
+ mLastInteractionTimestamp = in.readLong();
+ mIsImportantConversation = in.readBoolean();
+ mIsHiddenConversation = in.readBoolean();
+ mNotification = in.readParcelable(StatusBarNotification.class.getClassLoader());
+ mIntent = in.readParcelable(Intent.class.getClassLoader());
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeString(mId);
+ dest.writeCharSequence(mUserName);
+ dest.writeParcelable(mUserIcon, flags);
+ dest.writeInt(mUid);
+ dest.writeString(mPackageName);
+ dest.writeLong(mLastInteractionTimestamp);
+ dest.writeParcelable(mNotification, flags);
+ dest.writeBoolean(mIsImportantConversation);
+ dest.writeBoolean(mIsHiddenConversation);
+ dest.writeParcelable(mIntent, flags);
+ }
+
+ public static final @android.annotation.NonNull
+ Creator<PeopleSpaceTile> CREATOR = new Creator<PeopleSpaceTile>() {
+ public PeopleSpaceTile createFromParcel(Parcel source) {
+ return new PeopleSpaceTile(source);
+ }
+
+ public PeopleSpaceTile[] newArray(int size) {
+ return new PeopleSpaceTile[size];
+ }
+ };
+}
diff --git a/core/java/android/bluetooth/BluetoothCodecStatus.java b/core/java/android/bluetooth/BluetoothCodecStatus.java
index 3a65aaa0d16c..7764ebeb2e33 100644
--- a/core/java/android/bluetooth/BluetoothCodecStatus.java
+++ b/core/java/android/bluetooth/BluetoothCodecStatus.java
@@ -18,7 +18,6 @@ package android.bluetooth;
import android.annotation.Nullable;
import android.compat.annotation.UnsupportedAppUsage;
-import android.os.Build;
import android.os.Parcel;
import android.os.Parcelable;
@@ -40,7 +39,7 @@ public final class BluetoothCodecStatus implements Parcelable {
* This extra represents the current codec status of the A2DP
* profile.
*/
- @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
+ @UnsupportedAppUsage
public static final String EXTRA_CODEC_STATUS =
"android.bluetooth.extra.CODEC_STATUS";
@@ -199,7 +198,7 @@ public final class BluetoothCodecStatus implements Parcelable {
*
* @return the current codec configuration
*/
- @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
+ @UnsupportedAppUsage
public @Nullable BluetoothCodecConfig getCodecConfig() {
return mCodecConfig;
}
@@ -209,7 +208,7 @@ public final class BluetoothCodecStatus implements Parcelable {
*
* @return an array with the codecs local capabilities
*/
- @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
+ @UnsupportedAppUsage
public @Nullable BluetoothCodecConfig[] getCodecsLocalCapabilities() {
return mCodecsLocalCapabilities;
}
@@ -219,7 +218,7 @@ public final class BluetoothCodecStatus implements Parcelable {
*
* @return an array with the codecs selectable capabilities
*/
- @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
+ @UnsupportedAppUsage
public @Nullable BluetoothCodecConfig[] getCodecsSelectableCapabilities() {
return mCodecsSelectableCapabilities;
}
diff --git a/core/java/android/content/pm/IPackageManager.aidl b/core/java/android/content/pm/IPackageManager.aidl
index d66a42a6232a..f634b8a54a0f 100644
--- a/core/java/android/content/pm/IPackageManager.aidl
+++ b/core/java/android/content/pm/IPackageManager.aidl
@@ -38,6 +38,7 @@ import android.content.pm.InstrumentationInfo;
import android.content.pm.KeySet;
import android.content.pm.ModuleInfo;
import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
import android.content.pm.ParceledListSlice;
import android.content.pm.ProviderInfo;
import android.content.pm.PermissionGroupInfo;
@@ -797,4 +798,7 @@ interface IPackageManager {
IBinder getHoldLockToken();
void holdLock(in IBinder token, in int durationMs);
+
+ PackageManager.Property getProperty(String propertyName, String packageName, String className);
+ ParceledListSlice queryProperty(String propertyName, int componentType);
}
diff --git a/core/java/android/content/pm/PackageManager.aidl b/core/java/android/content/pm/PackageManager.aidl
new file mode 100644
index 000000000000..31365a19f286
--- /dev/null
+++ b/core/java/android/content/pm/PackageManager.aidl
@@ -0,0 +1,20 @@
+/*
+**
+** 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.content.pm;
+
+parcelable PackageManager.Property;
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index cc484deeee49..044b3b2e8284 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -64,6 +64,8 @@ import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
+import android.os.Parcel;
+import android.os.Parcelable;
import android.os.PersistableBundle;
import android.os.RemoteException;
import android.os.UserHandle;
@@ -75,6 +77,7 @@ import android.permission.PermissionManager;
import android.util.AndroidException;
import android.util.Log;
+import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.ArrayUtils;
import dalvik.system.VMRuntime;
@@ -116,6 +119,243 @@ public abstract class PackageManager {
}
/**
+ * A property value set within the manifest.
+ * <p>
+ * The value of a property will only have a single type, as defined by
+ * the property itself.
+ */
+ public static final class Property implements Parcelable {
+ private static final int TYPE_BOOLEAN = 1;
+ private static final int TYPE_FLOAT = 2;
+ private static final int TYPE_INTEGER = 3;
+ private static final int TYPE_RESOURCE = 4;
+ private static final int TYPE_STRING = 5;
+ private final String mName;
+ private final int mType;
+ private final String mClassName;
+ private final String mPackageName;
+ private boolean mBooleanValue;
+ private float mFloatValue;
+ private int mIntegerValue;
+ private String mStringValue;
+
+ /** @hide */
+ @VisibleForTesting
+ public Property(@NonNull String name, int type,
+ @NonNull String packageName, @Nullable String className) {
+ assert name != null;
+ assert type >= TYPE_BOOLEAN && type <= TYPE_STRING;
+ assert packageName != null;
+ this.mName = name;
+ this.mType = type;
+ this.mPackageName = packageName;
+ this.mClassName = className;
+ }
+ /** @hide */
+ public Property(@NonNull String name, boolean value,
+ String packageName, String className) {
+ this(name, TYPE_BOOLEAN, packageName, className);
+ mBooleanValue = value;
+ }
+ /** @hide */
+ public Property(@NonNull String name, float value,
+ String packageName, String className) {
+ this(name, TYPE_FLOAT, packageName, className);
+ mFloatValue = value;
+ }
+ /** @hide */
+ public Property(@NonNull String name, int value, boolean isResource,
+ String packageName, String className) {
+ this(name, isResource ? TYPE_RESOURCE : TYPE_INTEGER, packageName, className);
+ mIntegerValue = value;
+ }
+ /** @hide */
+ public Property(@NonNull String name, String value,
+ String packageName, String className) {
+ this(name, TYPE_STRING, packageName, className);
+ mStringValue = value;
+ }
+
+ /** @hide */
+ @VisibleForTesting
+ public int getType() {
+ return mType;
+ }
+
+ /**
+ * Returns the name of the property.
+ */
+ @NonNull public String getName() {
+ return mName;
+ }
+
+ /**
+ * Returns the name of the package where this this property was defined.
+ */
+ @NonNull public String getPackageName() {
+ return mPackageName;
+ }
+
+ /**
+ * Returns the classname of the component where this property was defined.
+ * <p>If the property was defined within and &lt;application&gt; tag, retutrns
+ * {@code null}
+ */
+ @Nullable public String getClassName() {
+ return mClassName;
+ }
+
+ /**
+ * Returns the boolean value set for the property.
+ * <p>If the property is not of a boolean type, returns {@code false}.
+ */
+ public boolean getBoolean() {
+ return mBooleanValue;
+ }
+
+ /**
+ * Returns {@code true} if the property is a boolean type. Otherwise {@code false}.
+ */
+ public boolean isBoolean() {
+ return mType == TYPE_BOOLEAN;
+ }
+
+ /**
+ * Returns the float value set for the property.
+ * <p>If the property is not of a float type, returns {@code 0.0}.
+ */
+ public float getFloat() {
+ return mFloatValue;
+ }
+
+ /**
+ * Returns {@code true} if the property is a float type. Otherwise {@code false}.
+ */
+ public boolean isFloat() {
+ return mType == TYPE_FLOAT;
+ }
+
+ /**
+ * Returns the integer value set for the property.
+ * <p>If the property is not of an integer type, returns {@code 0}.
+ */
+ public int getInteger() {
+ return mType == TYPE_INTEGER ? mIntegerValue : 0;
+ }
+
+ /**
+ * Returns {@code true} if the property is an integer type. Otherwise {@code false}.
+ */
+ public boolean isInteger() {
+ return mType == TYPE_INTEGER;
+ }
+
+ /**
+ * Returns the a resource id set for the property.
+ * <p>If the property is not of a resource id type, returns {@code 0}.
+ */
+ public int getResourceId() {
+ return mType == TYPE_RESOURCE ? mIntegerValue : 0;
+ }
+
+ /**
+ * Returns {@code true} if the property is a resource id type. Otherwise {@code false}.
+ */
+ public boolean isResourceId() {
+ return mType == TYPE_RESOURCE;
+ }
+
+ /**
+ * Returns the a String value set for the property.
+ * <p>If the property is not a String type, returns {@code null}.
+ */
+ @Nullable public String getString() {
+ return mStringValue;
+ }
+
+ /**
+ * Returns {@code true} if the property is a String type. Otherwise {@code false}.
+ */
+ public boolean isString() {
+ return mType == TYPE_STRING;
+ }
+
+ /**
+ * Adds a mapping from the given key to this property's value in the provided
+ * {@link android.os.Bundle}. If the provided {@link android.os.Bundle} is
+ * {@code null}, creates a new {@link android.os.Bundle}.
+ * @hide
+ */
+ public Bundle toBundle(Bundle outBundle) {
+ final Bundle b = outBundle == null ? new Bundle() : outBundle;
+ if (mType == TYPE_BOOLEAN) {
+ b.putBoolean(mName, mBooleanValue);
+ } else if (mType == TYPE_FLOAT) {
+ b.putFloat(mName, mFloatValue);
+ } else if (mType == TYPE_INTEGER) {
+ b.putInt(mName, mIntegerValue);
+ } else if (mType == TYPE_RESOURCE) {
+ b.putInt(mName, mIntegerValue);
+ } else if (mType == TYPE_STRING) {
+ b.putString(mName, mStringValue);
+ }
+ return b;
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(@NonNull Parcel dest, int flags) {
+ dest.writeString(mName);
+ dest.writeInt(mType);
+ dest.writeString(mPackageName);
+ dest.writeString(mClassName);
+ if (mType == TYPE_BOOLEAN) {
+ dest.writeBoolean(mBooleanValue);
+ } else if (mType == TYPE_FLOAT) {
+ dest.writeFloat(mFloatValue);
+ } else if (mType == TYPE_INTEGER) {
+ dest.writeInt(mIntegerValue);
+ } else if (mType == TYPE_RESOURCE) {
+ dest.writeInt(mIntegerValue);
+ } else if (mType == TYPE_STRING) {
+ dest.writeString(mStringValue);
+ }
+ }
+
+ @NonNull
+ public static final Creator<Property> CREATOR = new Creator<Property>() {
+ @Override
+ public Property createFromParcel(@NonNull Parcel source) {
+ final String name = source.readString();
+ final int type = source.readInt();
+ final String packageName = source.readString();
+ final String className = source.readString();
+ if (type == TYPE_BOOLEAN) {
+ return new Property(name, source.readBoolean(), packageName, className);
+ } else if (type == TYPE_FLOAT) {
+ return new Property(name, source.readFloat(), packageName, className);
+ } else if (type == TYPE_INTEGER) {
+ return new Property(name, source.readInt(), false, packageName, className);
+ } else if (type == TYPE_RESOURCE) {
+ return new Property(name, source.readInt(), true, packageName, className);
+ } else if (type == TYPE_STRING) {
+ return new Property(name, source.readString(), packageName, className);
+ }
+ return null;
+ }
+
+ @Override
+ public Property[] newArray(int size) {
+ return new Property[size];
+ }
+ };
+ }
+
+ /**
* Listener for changes in permissions granted to a UID.
*
* @hide
@@ -130,6 +370,41 @@ public abstract class PackageManager {
public void onPermissionsChanged(int uid);
}
+ /** @hide */
+ public static final int TYPE_UNKNOWN = 0;
+ /** @hide */
+ public static final int TYPE_ACTIVITY = 1;
+ /** @hide */
+ public static final int TYPE_RECEIVER = 2;
+ /** @hide */
+ public static final int TYPE_SERVICE = 3;
+ /** @hide */
+ public static final int TYPE_PROVIDER = 4;
+ /** @hide */
+ public static final int TYPE_APPLICATION = 5;
+ /** @hide */
+ @IntDef(prefix = { "TYPE_" }, value = {
+ TYPE_UNKNOWN,
+ TYPE_ACTIVITY,
+ TYPE_RECEIVER,
+ TYPE_SERVICE,
+ TYPE_PROVIDER,
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface ComponentType {}
+
+ /** @hide */
+ @IntDef(prefix = { "TYPE_" }, value = {
+ TYPE_UNKNOWN,
+ TYPE_ACTIVITY,
+ TYPE_RECEIVER,
+ TYPE_SERVICE,
+ TYPE_PROVIDER,
+ TYPE_APPLICATION,
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface PropertyLocation {}
+
/**
* As a guiding principle:
* <p>
@@ -8124,7 +8399,7 @@ public abstract class PackageManager {
* Trust any Installer to provide checksums for the package.
* @see #requestChecksums
*/
- public static final @Nullable List<Certificate> TRUST_ALL = Collections.singletonList(null);
+ public static final @NonNull List<Certificate> TRUST_ALL = Collections.singletonList(null);
/**
* Don't trust any Installer to provide checksums for the package.
@@ -8363,6 +8638,87 @@ public abstract class PackageManager {
}
/**
+ * Returns the property defined in the given package's &lt;appliction&gt; tag.
+ *
+ * @throws NameNotFoundException if either the given package is not installed or if the
+ * given property is not defined within the &lt;application&gt; tag.
+ */
+ @NonNull
+ public Property getProperty(@NonNull String propertyName, @NonNull String packageName)
+ throws NameNotFoundException {
+ throw new UnsupportedOperationException(
+ "getProperty not implemented in subclass");
+ }
+
+ /**
+ * Returns the property defined in the given component declaration.
+ *
+ * @throws NameNotFoundException if either the given component does not exist or if the
+ * given property is not defined within the component declaration.
+ */
+ @NonNull
+ public Property getProperty(@NonNull String propertyName, @NonNull ComponentName component)
+ throws NameNotFoundException {
+ throw new UnsupportedOperationException(
+ "getProperty not implemented in subclass");
+ }
+
+ /**
+ * Returns the property definition for all &lt;application&gt; tags.
+ * <p>If the property is not defined with any &lt;application&gt; tag,
+ * returns and empty list.
+ */
+ @NonNull
+ public List<Property> queryApplicationProperty(@NonNull String propertyName) {
+ throw new UnsupportedOperationException(
+ "qeuryApplicationProperty not implemented in subclass");
+ }
+
+ /**
+ * Returns the property definition for all &lt;activity&gt; and &lt;activity-alias&gt; tags.
+ * <p>If the property is not defined with any &lt;activity&gt; and &lt;activity-alias&gt; tag,
+ * returns and empty list.
+ */
+ @NonNull
+ public List<Property> queryActivityProperty(@NonNull String propertyName) {
+ throw new UnsupportedOperationException(
+ "qeuryActivityProperty not implemented in subclass");
+ }
+
+ /**
+ * Returns the property definition for all &lt;provider&gt; tags.
+ * <p>If the property is not defined with any &lt;provider&gt; tag,
+ * returns and empty list.
+ */
+ @NonNull
+ public List<Property> queryProviderProperty(@NonNull String propertyName) {
+ throw new UnsupportedOperationException(
+ "qeuryProviderProperty not implemented in subclass");
+ }
+
+ /**
+ * Returns the property definition for all &lt;receiver&gt; tags.
+ * <p>If the property is not defined with any &lt;receiver&gt; tag,
+ * returns and empty list.
+ */
+ @NonNull
+ public List<Property> queryReceiverProperty(@NonNull String propertyName) {
+ throw new UnsupportedOperationException(
+ "qeuryReceiverProperty not implemented in subclass");
+ }
+
+ /**
+ * Returns the property definition for all &lt;service&gt; tags.
+ * <p>If the property is not defined with any &lt;service&gt; tag,
+ * returns and empty list.
+ */
+ @NonNull
+ public List<Property> queryServiceProperty(@NonNull String propertyName) {
+ throw new UnsupportedOperationException(
+ "qeuryServiceProperty not implemented in subclass");
+ }
+
+ /**
* Grants implicit visibility of the package that provides an authority to a querying UID.
*
* @throws SecurityException when called by a package other than the contacts provider
diff --git a/core/java/android/content/pm/PermissionInfo.java b/core/java/android/content/pm/PermissionInfo.java
index c6450ffdf91c..cd9ba6a5b451 100644
--- a/core/java/android/content/pm/PermissionInfo.java
+++ b/core/java/android/content/pm/PermissionInfo.java
@@ -251,6 +251,16 @@ public class PermissionInfo extends PackageItemInfo implements Parcelable {
@SystemApi
public static final int PROTECTION_FLAG_RETAIL_DEMO = 0x1000000;
+ /**
+ * Additional flag for {@link #protectionLevel}, corresponding
+ * to the <code>recents</code> value of
+ * {@link android.R.attr#protectionLevel}.
+ *
+ * @hide
+ */
+ @SystemApi
+ public static final int PROTECTION_FLAG_RECENTS = 0x2000000;
+
/** @hide */
@IntDef(flag = true, prefix = { "PROTECTION_FLAG_" }, value = {
PROTECTION_FLAG_PRIVILEGED,
@@ -274,6 +284,7 @@ public class PermissionInfo extends PackageItemInfo implements Parcelable {
PROTECTION_FLAG_APP_PREDICTOR,
PROTECTION_FLAG_COMPANION,
PROTECTION_FLAG_RETAIL_DEMO,
+ PROTECTION_FLAG_RECENTS,
})
@Retention(RetentionPolicy.SOURCE)
public @interface ProtectionFlags {}
@@ -532,6 +543,9 @@ public class PermissionInfo extends PackageItemInfo implements Parcelable {
if ((level & PermissionInfo.PROTECTION_FLAG_RETAIL_DEMO) != 0) {
protLevel.append("|retailDemo");
}
+ if ((level & PermissionInfo.PROTECTION_FLAG_RECENTS) != 0) {
+ protLevel.append("|recents");
+ }
return protLevel.toString();
}
diff --git a/core/java/android/content/pm/parsing/ParsingPackage.java b/core/java/android/content/pm/parsing/ParsingPackage.java
index 9cda4d33503b..814759956772 100644
--- a/core/java/android/content/pm/parsing/ParsingPackage.java
+++ b/core/java/android/content/pm/parsing/ParsingPackage.java
@@ -23,6 +23,7 @@ import android.content.Intent;
import android.content.pm.ConfigurationInfo;
import android.content.pm.FeatureGroupInfo;
import android.content.pm.FeatureInfo;
+import android.content.pm.PackageManager.Property;
import android.content.pm.PackageParser;
import android.content.pm.parsing.component.ParsedActivity;
import android.content.pm.parsing.component.ParsedAttribution;
@@ -75,6 +76,9 @@ public interface ParsingPackage extends ParsingPackageRead {
ParsingPackage addPreferredActivityFilter(String className, ParsedIntentInfo intentInfo);
+ /** Add a property to the application scope */
+ ParsingPackage addProperty(Property property);
+
ParsingPackage addProtectedBroadcast(String protectedBroadcast);
ParsingPackage addProvider(ParsedProvider parsedProvider);
diff --git a/core/java/android/content/pm/parsing/ParsingPackageImpl.java b/core/java/android/content/pm/parsing/ParsingPackageImpl.java
index 2a15e0260c1a..b826b7a80e4e 100644
--- a/core/java/android/content/pm/parsing/ParsingPackageImpl.java
+++ b/core/java/android/content/pm/parsing/ParsingPackageImpl.java
@@ -31,6 +31,7 @@ import android.content.pm.ConfigurationInfo;
import android.content.pm.FeatureGroupInfo;
import android.content.pm.FeatureInfo;
import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager.Property;
import android.content.pm.PackageParser;
import android.content.pm.parsing.component.ParsedActivity;
import android.content.pm.parsing.component.ParsedAttribution;
@@ -273,6 +274,9 @@ public class ParsingPackageImpl implements ParsingPackage, Parcelable {
@Nullable
private Bundle metaData;
+ @NonNull
+ private Map<String, Property> mProperties = emptyMap();
+
@Nullable
@DataClass.ParcelWith(ForInternedString.class)
protected String volumeUuid;
@@ -623,6 +627,15 @@ public class ParsingPackageImpl implements ParsingPackage, Parcelable {
}
@Override
+ public ParsingPackageImpl addProperty(@Nullable Property property) {
+ if (property == null) {
+ return this;
+ }
+ this.mProperties = CollectionUtils.add(this.mProperties, property.getName(), property);
+ return this;
+ }
+
+ @Override
public ParsingPackageImpl addProtectedBroadcast(String protectedBroadcast) {
if (!this.protectedBroadcasts.contains(protectedBroadcast)) {
this.protectedBroadcasts = CollectionUtils.add(this.protectedBroadcasts,
@@ -1172,6 +1185,7 @@ public class ParsingPackageImpl implements ParsingPackage, Parcelable {
dest.writeInt(this.gwpAsanMode);
dest.writeSparseIntArray(this.minExtensionVersions);
dest.writeLong(this.mBooleans);
+ dest.writeMap(this.mProperties);
}
public ParsingPackageImpl(Parcel in) {
@@ -1290,7 +1304,7 @@ public class ParsingPackageImpl implements ParsingPackage, Parcelable {
this.gwpAsanMode = in.readInt();
this.minExtensionVersions = in.readSparseIntArray();
this.mBooleans = in.readLong();
-
+ this.mProperties = in.createTypedArrayMap(Property.CREATOR);
assignDerivedFields();
}
@@ -1528,6 +1542,12 @@ public class ParsingPackageImpl implements ParsingPackage, Parcelable {
@NonNull
@Override
+ public Map<String, Property> getProperties() {
+ return mProperties;
+ }
+
+ @NonNull
+ @Override
public Set<String> getUpgradeKeySets() {
return upgradeKeySets;
}
diff --git a/core/java/android/content/pm/parsing/ParsingPackageRead.java b/core/java/android/content/pm/parsing/ParsingPackageRead.java
index acd6305a1442..13ae7a28360e 100644
--- a/core/java/android/content/pm/parsing/ParsingPackageRead.java
+++ b/core/java/android/content/pm/parsing/ParsingPackageRead.java
@@ -25,6 +25,7 @@ import android.content.pm.ConfigurationInfo;
import android.content.pm.FeatureGroupInfo;
import android.content.pm.FeatureInfo;
import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager.Property;
import android.content.pm.PackageParser;
import android.content.pm.ServiceInfo;
import android.content.pm.parsing.component.ParsedActivity;
@@ -43,8 +44,6 @@ import android.util.Pair;
import android.util.SparseArray;
import android.util.SparseIntArray;
-import com.android.internal.R;
-
import java.security.PublicKey;
import java.util.List;
import java.util.Map;
@@ -204,6 +203,12 @@ public interface ParsingPackageRead extends Parcelable {
List<String> getRequestedPermissions();
/**
+ * Returns the properties set on the application
+ */
+ @NonNull
+ Map<String, Property> getProperties();
+
+ /**
* Whether or not the app requested explicitly resizeable Activities.
* A null value means nothing was explicitly requested.
*/
diff --git a/core/java/android/content/pm/parsing/ParsingPackageUtils.java b/core/java/android/content/pm/parsing/ParsingPackageUtils.java
index 6196854526e0..eae7d452ff74 100644
--- a/core/java/android/content/pm/parsing/ParsingPackageUtils.java
+++ b/core/java/android/content/pm/parsing/ParsingPackageUtils.java
@@ -42,6 +42,7 @@ import android.content.pm.FeatureGroupInfo;
import android.content.pm.FeatureInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
+import android.content.pm.PackageManager.Property;
import android.content.pm.PackageParser;
import android.content.pm.PackageParser.PackageParserException;
import android.content.pm.PackageParser.SigningDetails;
@@ -51,6 +52,7 @@ import android.content.pm.parsing.component.ParsedActivity;
import android.content.pm.parsing.component.ParsedActivityUtils;
import android.content.pm.parsing.component.ParsedAttribution;
import android.content.pm.parsing.component.ParsedAttributionUtils;
+import android.content.pm.parsing.component.ParsedComponent;
import android.content.pm.parsing.component.ParsedInstrumentation;
import android.content.pm.parsing.component.ParsedInstrumentationUtils;
import android.content.pm.parsing.component.ParsedIntentInfo;
@@ -699,12 +701,19 @@ public class ParsingPackageUtils {
// note: application meta-data is stored off to the side, so it can
// remain null in the primary copy (we like to avoid extra copies because
// it can be large)
- ParseResult<Bundle> metaDataResult = parseMetaData(pkg, res, parser,
- pkg.getMetaData(), input);
- if (metaDataResult.isSuccess()) {
- pkg.setMetaData(metaDataResult.getResult());
+ ParseResult<Property> metaDataResult = parseMetaData(pkg, null, res,
+ parser, "<meta-data>", input);
+ if (metaDataResult.isSuccess() && metaDataResult.getResult() != null) {
+ pkg.setMetaData(metaDataResult.getResult().toBundle(pkg.getMetaData()));
}
return metaDataResult;
+ case "property":
+ ParseResult<Property> propertyResult = parseMetaData(pkg, null, res,
+ parser, "<property>", input);
+ if (propertyResult.isSuccess()) {
+ pkg.addProperty(propertyResult.getResult());
+ }
+ return propertyResult;
case "uses-static-library":
return parseUsesStaticLibrary(input, pkg, res, parser);
case "uses-library":
@@ -2085,13 +2094,19 @@ public class ParsingPackageUtils {
// note: application meta-data is stored off to the side, so it can
// remain null in the primary copy (we like to avoid extra copies because
// it can be large)
- ParseResult<Bundle> metaDataResult = parseMetaData(pkg, res, parser,
- pkg.getMetaData(), input);
- if (metaDataResult.isSuccess()) {
- pkg.setMetaData(metaDataResult.getResult());
+ final ParseResult<Property> metaDataResult = parseMetaData(pkg, null, res,
+ parser, "<meta-data>", input);
+ if (metaDataResult.isSuccess() && metaDataResult.getResult() != null) {
+ pkg.setMetaData(metaDataResult.getResult().toBundle(pkg.getMetaData()));
}
-
return metaDataResult;
+ case "property":
+ final ParseResult<Property> propertyResult = parseMetaData(pkg, null, res,
+ parser, "<property>", input);
+ if (propertyResult.isSuccess()) {
+ pkg.addProperty(propertyResult.getResult());
+ }
+ return propertyResult;
case "static-library":
return parseStaticLibrary(pkg, res, parser, input);
case "library":
@@ -2736,57 +2751,60 @@ public class ParsingPackageUtils {
: input.error("must have at least one '.' separator");
}
- public static ParseResult<Bundle> parseMetaData(ParsingPackage pkg, Resources res,
- XmlResourceParser parser, Bundle data, ParseInput input) {
+ /**
+ * Parse a meta data defined on the enclosing tag.
+ * <p>Meta data can be defined by either &lt;meta-data&gt; or &lt;property&gt; elements.
+ */
+ public static ParseResult<Property> parseMetaData(ParsingPackage pkg, ParsedComponent component,
+ Resources res, XmlResourceParser parser, String tagName, ParseInput input) {
TypedArray sa = res.obtainAttributes(parser, R.styleable.AndroidManifestMetaData);
try {
- if (data == null) {
- data = new Bundle();
- }
-
- String name = TextUtils.safeIntern(
+ final Property property;
+ final String name = TextUtils.safeIntern(
nonConfigString(0, R.styleable.AndroidManifestMetaData_name, sa));
if (name == null) {
- return input.error("<meta-data> requires an android:name attribute");
+ return input.error(tagName + " requires an android:name attribute");
}
+ final String packageName = pkg.getPackageName();
+ final String className = component != null ? component.getName() : null;
TypedValue v = sa.peekValue(R.styleable.AndroidManifestMetaData_resource);
if (v != null && v.resourceId != 0) {
- //Slog.i(TAG, "Meta data ref " + name + ": " + v);
- data.putInt(name, v.resourceId);
+ property = new Property(name, v.resourceId, true, packageName, className);
} else {
v = sa.peekValue(R.styleable.AndroidManifestMetaData_value);
- //Slog.i(TAG, "Meta data " + name + ": " + v);
if (v != null) {
if (v.type == TypedValue.TYPE_STRING) {
- CharSequence cs = v.coerceToString();
- data.putString(name, cs != null ? cs.toString() : null);
+ final CharSequence cs = v.coerceToString();
+ final String stringValue = cs != null ? cs.toString() : null;
+ property = new Property(name, stringValue, packageName, className);
} else if (v.type == TypedValue.TYPE_INT_BOOLEAN) {
- data.putBoolean(name, v.data != 0);
+ property = new Property(name, v.data != 0, packageName, className);
} else if (v.type >= TypedValue.TYPE_FIRST_INT
&& v.type <= TypedValue.TYPE_LAST_INT) {
- data.putInt(name, v.data);
+ property = new Property(name, v.data, false, packageName, className);
} else if (v.type == TypedValue.TYPE_FLOAT) {
- data.putFloat(name, v.getFloat());
+ property = new Property(name, v.getFloat(), packageName, className);
} else {
if (!PackageParser.RIGID_PARSER) {
Slog.w(TAG,
- "<meta-data> only supports string, integer, float, color, "
+ tagName + " only supports string, integer, float, color, "
+ "boolean, and resource reference types: "
+ parser.getName() + " at "
+ pkg.getBaseApkPath() + " "
+ parser.getPositionDescription());
+ property = null;
} else {
- return input.error("<meta-data> only supports string, integer, float, "
+ return input.error(tagName + " only supports string, integer, float, "
+ "color, boolean, and resource reference types");
}
}
} else {
- return input.error("<meta-data> requires an android:value "
+ return input.error(tagName + " requires an android:value "
+ "or android:resource attribute");
}
}
- return input.success(data);
+ return input.success(property);
} finally {
sa.recycle();
}
diff --git a/core/java/android/content/pm/parsing/component/ParsedActivityUtils.java b/core/java/android/content/pm/parsing/component/ParsedActivityUtils.java
index 511ee5d9580d..0d7198d4aa4a 100644
--- a/core/java/android/content/pm/parsing/component/ParsedActivityUtils.java
+++ b/core/java/android/content/pm/parsing/component/ParsedActivityUtils.java
@@ -356,6 +356,8 @@ public class ParsedActivityUtils {
result = intentResult;
} else if (parser.getName().equals("meta-data")) {
result = ParsedComponentUtils.addMetaData(activity, pkg, resources, parser, input);
+ } else if (parser.getName().equals("property")) {
+ result = ParsedComponentUtils.addProperty(activity, pkg, resources, parser, input);
} else if (!isReceiver && !isAlias && parser.getName().equals("preferred")) {
ParseResult<ParsedIntentInfo> intentResult = parseIntentFilter(pkg, activity,
true /*allowImplicitEphemeralVisibility*/, visibleToEphemeral,
diff --git a/core/java/android/content/pm/parsing/component/ParsedComponent.java b/core/java/android/content/pm/parsing/component/ParsedComponent.java
index 6323d6921394..4aed77ae641b 100644
--- a/core/java/android/content/pm/parsing/component/ParsedComponent.java
+++ b/core/java/android/content/pm/parsing/component/ParsedComponent.java
@@ -18,10 +18,13 @@ package android.content.pm.parsing.component;
import static android.content.pm.parsing.ParsingPackageImpl.sForInternedString;
+import static java.util.Collections.emptyMap;
+
import android.annotation.CallSuper;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.ComponentName;
+import android.content.pm.PackageManager.Property;
import android.os.Bundle;
import android.os.Parcel;
import android.os.Parcelable;
@@ -35,6 +38,7 @@ import com.android.internal.util.Parcelling.BuiltIn.ForInternedString;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
+import java.util.Map;
/** @hide */
public abstract class ParsedComponent implements Parcelable {
@@ -70,6 +74,8 @@ public abstract class ParsedComponent implements Parcelable {
@Nullable
protected Bundle metaData;
+ private Map<String, Property> mProperties = emptyMap();
+
ParsedComponent() {
}
@@ -96,6 +102,11 @@ public abstract class ParsedComponent implements Parcelable {
this.intents = CollectionUtils.add(this.intents, intent);
}
+ /** Add a property to the component */
+ public void addProperty(@NonNull Property property) {
+ this.mProperties = CollectionUtils.add(this.mProperties, property.getName(), property);
+ }
+
@NonNull
public List<ParsedIntentInfo> getIntents() {
return intents != null ? intents : Collections.emptyList();
@@ -142,6 +153,7 @@ public abstract class ParsedComponent implements Parcelable {
sForInternedString.parcel(this.packageName, dest, flags);
sForIntentInfos.parcel(this.getIntents(), dest, flags);
dest.writeBundle(this.metaData);
+ dest.writeMap(this.mProperties);
}
protected ParsedComponent(Parcel in) {
@@ -160,6 +172,7 @@ public abstract class ParsedComponent implements Parcelable {
this.packageName = sForInternedString.unparcel(in);
this.intents = sForIntentInfos.unparcel(in);
this.metaData = in.readBundle(boot);
+ this.mProperties = in.createTypedArrayMap(Property.CREATOR);
}
@NonNull
@@ -205,4 +218,9 @@ public abstract class ParsedComponent implements Parcelable {
public Bundle getMetaData() {
return metaData;
}
+
+ @NonNull
+ public Map<String, Property> getProperties() {
+ return mProperties;
+ }
}
diff --git a/core/java/android/content/pm/parsing/component/ParsedComponentUtils.java b/core/java/android/content/pm/parsing/component/ParsedComponentUtils.java
index dd2fb5bd2d78..46b941955fc7 100644
--- a/core/java/android/content/pm/parsing/component/ParsedComponentUtils.java
+++ b/core/java/android/content/pm/parsing/component/ParsedComponentUtils.java
@@ -19,6 +19,7 @@ package android.content.pm.parsing.component;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.pm.PackageManager;
+import android.content.pm.PackageManager.Property;
import android.content.pm.parsing.ParsingPackage;
import android.content.pm.parsing.ParsingPackageUtils;
import android.content.pm.parsing.ParsingUtils;
@@ -97,13 +98,29 @@ class ParsedComponentUtils {
static ParseResult<Bundle> addMetaData(ParsedComponent component, ParsingPackage pkg,
Resources resources, XmlResourceParser parser, ParseInput input) {
- ParseResult<Bundle> result = ParsingPackageUtils.parseMetaData(pkg, resources,
- parser, component.metaData, input);
+ ParseResult<Property> result = ParsingPackageUtils.parseMetaData(pkg, component,
+ resources, parser, "<meta-data>", input);
if (result.isError()) {
return input.error(result);
}
- Bundle bundle = result.getResult();
- component.metaData = bundle;
- return input.success(bundle);
+ final Property property = result.getResult();
+ if (property != null) {
+ component.metaData = property.toBundle(component.metaData);
+ }
+ return input.success(component.metaData);
+ }
+
+ static ParseResult<Property> addProperty(ParsedComponent component, ParsingPackage pkg,
+ Resources resources, XmlResourceParser parser, ParseInput input) {
+ ParseResult<Property> result = ParsingPackageUtils.parseMetaData(pkg, component,
+ resources, parser, "<property>", input);
+ if (result.isError()) {
+ return input.error(result);
+ }
+ final Property property = result.getResult();
+ if (property != null) {
+ component.addProperty(property);
+ }
+ return input.success(property);
}
}
diff --git a/core/java/android/content/pm/parsing/component/ParsedProviderUtils.java b/core/java/android/content/pm/parsing/component/ParsedProviderUtils.java
index 37cbeca1d23a..90691f1686aa 100644
--- a/core/java/android/content/pm/parsing/component/ParsedProviderUtils.java
+++ b/core/java/android/content/pm/parsing/component/ParsedProviderUtils.java
@@ -180,6 +180,9 @@ public class ParsedProviderUtils {
case "meta-data":
result = ParsedComponentUtils.addMetaData(provider, pkg, res, parser, input);
break;
+ case "property":
+ result = ParsedComponentUtils.addProperty(provider, pkg, res, parser, input);
+ break;
case "grant-uri-permission": {
result = parseGrantUriPermission(provider, pkg, res, parser, input);
break;
diff --git a/core/java/android/content/pm/parsing/component/ParsedServiceUtils.java b/core/java/android/content/pm/parsing/component/ParsedServiceUtils.java
index afe3c5494fcb..739bee2fb7d9 100644
--- a/core/java/android/content/pm/parsing/component/ParsedServiceUtils.java
+++ b/core/java/android/content/pm/parsing/component/ParsedServiceUtils.java
@@ -145,6 +145,10 @@ public class ParsedServiceUtils {
case "meta-data":
parseResult = ParsedComponentUtils.addMetaData(service, pkg, res, parser, input);
break;
+ case "property":
+ parseResult =
+ ParsedComponentUtils.addProperty(service, pkg, res, parser, input);
+ break;
default:
parseResult = ParsingUtils.unknownTag(tag, pkg, parser, input);
break;
diff --git a/core/java/android/hardware/CameraSessionStats.java b/core/java/android/hardware/CameraSessionStats.java
new file mode 100644
index 000000000000..f34e2bf5ddc2
--- /dev/null
+++ b/core/java/android/hardware/CameraSessionStats.java
@@ -0,0 +1,202 @@
+/*
+ * 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.hardware;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.util.ArrayList;
+import java.util.List;
+/**
+ * The camera action state used for passing camera usage information from
+ * camera service to camera service proxy .
+ *
+ * Include camera id, facing, state, client apk name, apiLevel, isNdk,
+ * and session/stream statistics.
+ *
+ * @hide
+ */
+public class CameraSessionStats implements Parcelable {
+ public static final int CAMERA_STATE_OPEN = 0;
+ public static final int CAMERA_STATE_ACTIVE = 1;
+ public static final int CAMERA_STATE_IDLE = 2;
+ public static final int CAMERA_STATE_CLOSED = 3;
+
+ /**
+ * Values for notifyCameraState facing
+ */
+ public static final int CAMERA_FACING_BACK = 0;
+ public static final int CAMERA_FACING_FRONT = 1;
+ public static final int CAMERA_FACING_EXTERNAL = 2;
+
+ /**
+ * Values for notifyCameraState api level
+ */
+ public static final int CAMERA_API_LEVEL_1 = 1;
+ public static final int CAMERA_API_LEVEL_2 = 2;
+
+ private String mCameraId;
+ private int mFacing;
+ private int mNewCameraState;
+ private String mClientName;
+ private int mApiLevel;
+ private boolean mIsNdk;
+ private int mLatencyMs;
+ private int mSessionType;
+ private int mInternalReconfigure;
+ private long mRequestCount;
+ private long mResultErrorCount;
+ private boolean mDeviceError;
+ private ArrayList<CameraStreamStats> mStreamStats;
+
+ public CameraSessionStats() {
+ mFacing = -1;
+ mNewCameraState = -1;
+ mApiLevel = -1;
+ mIsNdk = false;
+ mLatencyMs = -1;
+ mSessionType = -1;
+ mInternalReconfigure = -1;
+ mRequestCount = 0;
+ mResultErrorCount = 0;
+ mDeviceError = false;
+ mStreamStats = new ArrayList<CameraStreamStats>();
+ }
+
+ public CameraSessionStats(String cameraId, int facing, int newCameraState,
+ String clientName, int apiLevel, boolean isNdk, int creationDuration,
+ int sessionType, int internalReconfigure) {
+ mCameraId = cameraId;
+ mFacing = facing;
+ mNewCameraState = newCameraState;
+ mClientName = clientName;
+ mApiLevel = apiLevel;
+ mIsNdk = isNdk;
+ mLatencyMs = creationDuration;
+ mSessionType = sessionType;
+ mInternalReconfigure = internalReconfigure;
+ mStreamStats = new ArrayList<CameraStreamStats>();
+ }
+
+ public static final @android.annotation.NonNull Parcelable.Creator<CameraSessionStats> CREATOR =
+ new Parcelable.Creator<CameraSessionStats>() {
+ @Override
+ public CameraSessionStats createFromParcel(Parcel in) {
+ return new CameraSessionStats(in);
+ }
+
+ @Override
+ public CameraSessionStats[] newArray(int size) {
+ return new CameraSessionStats[size];
+ }
+ };
+
+ private CameraSessionStats(Parcel in) {
+ readFromParcel(in);
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeString(mCameraId);
+ dest.writeInt(mFacing);
+ dest.writeInt(mNewCameraState);
+ dest.writeString(mClientName);
+ dest.writeInt(mApiLevel);
+ dest.writeBoolean(mIsNdk);
+ dest.writeInt(mLatencyMs);
+ dest.writeInt(mSessionType);
+ dest.writeInt(mInternalReconfigure);
+ dest.writeLong(mRequestCount);
+ dest.writeLong(mResultErrorCount);
+ dest.writeBoolean(mDeviceError);
+ dest.writeTypedList(mStreamStats);
+ }
+
+ public void readFromParcel(Parcel in) {
+ mCameraId = in.readString();
+ mFacing = in.readInt();
+ mNewCameraState = in.readInt();
+ mClientName = in.readString();
+ mApiLevel = in.readInt();
+ mIsNdk = in.readBoolean();
+ mLatencyMs = in.readInt();
+ mSessionType = in.readInt();
+ mInternalReconfigure = in.readInt();
+ mRequestCount = in.readLong();
+ mResultErrorCount = in.readLong();
+ mDeviceError = in.readBoolean();
+
+ ArrayList<CameraStreamStats> streamStats = new ArrayList<CameraStreamStats>();
+ in.readTypedList(streamStats, CameraStreamStats.CREATOR);
+ mStreamStats = streamStats;
+ }
+
+ public String getCameraId() {
+ return mCameraId;
+ }
+
+ public int getFacing() {
+ return mFacing;
+ }
+
+ public int getNewCameraState() {
+ return mNewCameraState;
+ }
+
+ public String getClientName() {
+ return mClientName;
+ }
+
+ public int getApiLevel() {
+ return mApiLevel;
+ }
+
+ public boolean isNdk() {
+ return mIsNdk;
+ }
+
+ public int getLatencyMs() {
+ return mLatencyMs;
+ }
+
+ public int getSessionType() {
+ return mSessionType;
+ }
+
+ public int getInternalReconfigureCount() {
+ return mInternalReconfigure;
+ }
+
+ public long getRequestCount() {
+ return mRequestCount;
+ }
+
+ public long getResultErrorCount() {
+ return mResultErrorCount;
+ }
+
+ public boolean getDeviceErrorFlag() {
+ return mDeviceError;
+ }
+
+ public List<CameraStreamStats> getStreamStats() {
+ return mStreamStats;
+ }
+}
diff --git a/core/java/android/hardware/CameraStreamStats.java b/core/java/android/hardware/CameraStreamStats.java
new file mode 100644
index 000000000000..ae801b639d51
--- /dev/null
+++ b/core/java/android/hardware/CameraStreamStats.java
@@ -0,0 +1,169 @@
+/*
+ * 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.hardware;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.util.Log;
+
+import java.util.ArrayList;
+/**
+ * The camera stream statistics used for passing camera stream information from
+ * camera service to camera service proxy.
+ *
+ * Include camera stream configuration, request/error counts, startup latency,
+ * and latency/jitter histograms.
+ *
+ * @hide
+ */
+public class CameraStreamStats implements Parcelable {
+
+ private int mWidth;
+ private int mHeight;
+ private int mFormat;
+ private int mDataSpace;
+ private long mUsage;
+ private long mRequestCount;
+ private long mErrorCount;
+ private int mStartLatencyMs;
+ private int mMaxHalBuffers;
+ private int mMaxAppBuffers;
+
+ private static final String TAG = "CameraStreamStats";
+
+ public CameraStreamStats() {
+ mWidth = 0;
+ mHeight = 0;
+ mFormat = 0;
+ mDataSpace = 0;
+ mUsage = 0;
+ mRequestCount = 0;
+ mErrorCount = 0;
+ mStartLatencyMs = 0;
+ mMaxHalBuffers = 0;
+ mMaxAppBuffers = 0;
+ }
+
+ public CameraStreamStats(int width, int height, int format,
+ int dataSpace, long usage, long requestCount, long errorCount,
+ int startLatencyMs, int maxHalBuffers, int maxAppBuffers) {
+ mWidth = width;
+ mHeight = height;
+ mFormat = format;
+ mDataSpace = dataSpace;
+ mUsage = usage;
+ mRequestCount = requestCount;
+ mErrorCount = errorCount;
+ mStartLatencyMs = startLatencyMs;
+ mMaxHalBuffers = maxHalBuffers;
+ mMaxAppBuffers = maxAppBuffers;
+ }
+
+ public static final @android.annotation.NonNull Parcelable.Creator<CameraStreamStats> CREATOR =
+ new Parcelable.Creator<CameraStreamStats>() {
+ @Override
+ public CameraStreamStats createFromParcel(Parcel in) {
+ try {
+ CameraStreamStats streamStats = new CameraStreamStats(in);
+ return streamStats;
+ } catch (Exception e) {
+ Log.e(TAG, "Exception creating CameraStreamStats from parcel", e);
+ return null;
+ }
+ }
+
+ @Override
+ public CameraStreamStats[] newArray(int size) {
+ return new CameraStreamStats[size];
+ }
+ };
+
+ private CameraStreamStats(Parcel in) {
+ readFromParcel(in);
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeInt(mWidth);
+ dest.writeInt(mHeight);
+ dest.writeInt(mFormat);
+ dest.writeInt(mDataSpace);
+ dest.writeLong(mUsage);
+ dest.writeLong(mRequestCount);
+ dest.writeLong(mErrorCount);
+ dest.writeInt(mStartLatencyMs);
+ dest.writeInt(mMaxHalBuffers);
+ dest.writeInt(mMaxAppBuffers);
+ }
+
+ public void readFromParcel(Parcel in) {
+ mWidth = in.readInt();
+ mHeight = in.readInt();
+ mFormat = in.readInt();
+ mDataSpace = in.readInt();
+ mUsage = in.readLong();
+ mRequestCount = in.readLong();
+ mErrorCount = in.readLong();
+ mStartLatencyMs = in.readInt();
+ mMaxHalBuffers = in.readInt();
+ mMaxAppBuffers = in.readInt();
+ }
+
+ public int getWidth() {
+ return mWidth;
+ }
+
+ public int getHeight() {
+ return mHeight;
+ }
+
+ public int getFormat() {
+ return mFormat;
+ }
+
+ public int getDataSpace() {
+ return mDataSpace;
+ }
+
+ public long getUsage() {
+ return mUsage;
+ }
+
+ public long getRequestCount() {
+ return mRequestCount;
+ }
+
+ public long getErrorCount() {
+ return mErrorCount;
+ }
+
+ public int getStartLatencyMs() {
+ return mStartLatencyMs;
+ }
+
+ public int getMaxHalBuffers() {
+ return mMaxHalBuffers;
+ }
+
+ public int getMaxAppBuffers() {
+ return mMaxAppBuffers;
+ }
+}
diff --git a/core/java/android/hardware/camera2/impl/CameraCaptureSessionImpl.java b/core/java/android/hardware/camera2/impl/CameraCaptureSessionImpl.java
index b6f4bd3c4c28..9a9163c724ff 100644
--- a/core/java/android/hardware/camera2/impl/CameraCaptureSessionImpl.java
+++ b/core/java/android/hardware/camera2/impl/CameraCaptureSessionImpl.java
@@ -27,6 +27,7 @@ import android.hardware.camera2.utils.TaskDrainer;
import android.hardware.camera2.utils.TaskSingleDrainer;
import android.os.Binder;
import android.os.Handler;
+import android.os.SystemClock;
import android.util.Log;
import android.view.Surface;
@@ -1002,7 +1003,7 @@ public class CameraCaptureSessionImpl extends CameraCaptureSession
// begin transition to unconfigured
mDeviceImpl.configureStreamsChecked(/*inputConfig*/null, /*outputs*/null,
/*operatingMode*/ ICameraDeviceUser.NORMAL_MODE,
- /*sessionParams*/ null);
+ /*sessionParams*/ null, SystemClock.uptimeMillis());
} catch (CameraAccessException e) {
// OK: do not throw checked exceptions.
Log.e(TAG, mIdString + "Exception while unconfiguring outputs: ", e);
diff --git a/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java b/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java
index 819d966e3bfe..f564ad7436de 100644
--- a/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java
+++ b/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java
@@ -45,6 +45,7 @@ import android.os.IBinder;
import android.os.Looper;
import android.os.RemoteException;
import android.os.ServiceSpecificException;
+import android.os.SystemClock;
import android.util.Log;
import android.util.Range;
import android.util.Size;
@@ -374,7 +375,8 @@ public class CameraDeviceImpl extends CameraDevice
outputConfigs.add(new OutputConfiguration(s));
}
configureStreamsChecked(/*inputConfig*/null, outputConfigs,
- /*operatingMode*/ICameraDeviceUser.NORMAL_MODE, /*sessionParams*/ null);
+ /*operatingMode*/ICameraDeviceUser.NORMAL_MODE, /*sessionParams*/ null,
+ SystemClock.uptimeMillis());
}
@@ -395,12 +397,15 @@ public class CameraDeviceImpl extends CameraDevice
* @param operatingMode If the stream configuration is for a normal session,
* a constrained high speed session, or something else.
* @param sessionParams Session parameters.
+ * @param createSessionStartTimeMs The timestamp when session creation starts, measured by
+ * uptimeMillis().
* @return whether or not the configuration was successful
*
* @throws CameraAccessException if there were any unexpected problems during configuration
*/
public boolean configureStreamsChecked(InputConfiguration inputConfig,
- List<OutputConfiguration> outputs, int operatingMode, CaptureRequest sessionParams)
+ List<OutputConfiguration> outputs, int operatingMode, CaptureRequest sessionParams,
+ long createSessionStartTime)
throws CameraAccessException {
// Treat a null input the same an empty list
if (outputs == null) {
@@ -479,9 +484,10 @@ public class CameraDeviceImpl extends CameraDevice
int offlineStreamIds[];
if (sessionParams != null) {
offlineStreamIds = mRemoteDevice.endConfigure(operatingMode,
- sessionParams.getNativeCopy());
+ sessionParams.getNativeCopy(), createSessionStartTime);
} else {
- offlineStreamIds = mRemoteDevice.endConfigure(operatingMode, null);
+ offlineStreamIds = mRemoteDevice.endConfigure(operatingMode, null,
+ createSessionStartTime);
}
mOfflineSupport.clear();
@@ -650,6 +656,7 @@ public class CameraDeviceImpl extends CameraDevice
List<OutputConfiguration> outputConfigurations,
CameraCaptureSession.StateCallback callback, Executor executor,
int operatingMode, CaptureRequest sessionParams) throws CameraAccessException {
+ long createSessionStartTime = SystemClock.uptimeMillis();
synchronized(mInterfaceLock) {
if (DEBUG) {
Log.d(TAG, "createCaptureSessionInternal");
@@ -677,7 +684,7 @@ public class CameraDeviceImpl extends CameraDevice
try {
// configure streams and then block until IDLE
configureSuccess = configureStreamsChecked(inputConfig, outputConfigurations,
- operatingMode, sessionParams);
+ operatingMode, sessionParams, createSessionStartTime);
if (configureSuccess == true && inputConfig != null) {
input = mRemoteDevice.getInputSurface();
}
diff --git a/core/java/android/hardware/camera2/impl/ICameraDeviceUserWrapper.java b/core/java/android/hardware/camera2/impl/ICameraDeviceUserWrapper.java
index fa7301bb72c3..ba4395f70214 100644
--- a/core/java/android/hardware/camera2/impl/ICameraDeviceUserWrapper.java
+++ b/core/java/android/hardware/camera2/impl/ICameraDeviceUserWrapper.java
@@ -110,11 +110,11 @@ public class ICameraDeviceUserWrapper {
}
}
- public int[] endConfigure(int operatingMode, CameraMetadataNative sessionParams)
- throws CameraAccessException {
+ public int[] endConfigure(int operatingMode, CameraMetadataNative sessionParams,
+ long startTimeMs) throws CameraAccessException {
try {
return mRemoteDevice.endConfigure(operatingMode, (sessionParams == null) ?
- new CameraMetadataNative() : sessionParams);
+ new CameraMetadataNative() : sessionParams, startTimeMs);
} catch (Throwable t) {
CameraManager.throwAsPublicException(t);
throw new UnsupportedOperationException("Unexpected exception", t);
diff --git a/core/java/android/hardware/display/DisplayManagerInternal.java b/core/java/android/hardware/display/DisplayManagerInternal.java
index defcab7c3035..5a03adee4eab 100644
--- a/core/java/android/hardware/display/DisplayManagerInternal.java
+++ b/core/java/android/hardware/display/DisplayManagerInternal.java
@@ -65,6 +65,12 @@ public abstract class DisplayManagerInternal {
public abstract boolean isProximitySensorAvailable();
/**
+ * Returns the id of the {@link com.android.server.display.DisplayGroup} to which the provided
+ * display belongs.
+ */
+ public abstract int getDisplayGroupId(int displayId);
+
+ /**
* Screenshot for internal system-only use such as rotation, etc. This method includes
* secure layers and the result should never be exposed to non-system applications.
* This method does not apply any rotation and provides the output in natural orientation.
diff --git a/core/java/android/hardware/hdmi/HdmiControlManager.java b/core/java/android/hardware/hdmi/HdmiControlManager.java
index f1534d95a16c..eef4089ac336 100644
--- a/core/java/android/hardware/hdmi/HdmiControlManager.java
+++ b/core/java/android/hardware/hdmi/HdmiControlManager.java
@@ -832,6 +832,22 @@ public final class HdmiControlManager {
}
/**
+ * For CEC source devices (OTT/STB/Audio system): toggle the power status of the HDMI-connected
+ * display and follow the display's new power status.
+ * For all other devices: no functionality.
+ *
+ * @hide
+ */
+ @RequiresPermission(android.Manifest.permission.HDMI_CEC)
+ public void toggleAndFollowTvPower() {
+ try {
+ mService.toggleAndFollowTvPower();
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
* Controls whether volume control commands via HDMI CEC are enabled.
*
* <p>When disabled:
diff --git a/core/java/android/hardware/hdmi/HdmiControlServiceWrapper.java b/core/java/android/hardware/hdmi/HdmiControlServiceWrapper.java
index fab56b8cea49..202e0907f803 100644
--- a/core/java/android/hardware/hdmi/HdmiControlServiceWrapper.java
+++ b/core/java/android/hardware/hdmi/HdmiControlServiceWrapper.java
@@ -67,6 +67,11 @@ public final class HdmiControlServiceWrapper {
}
@Override
+ public void toggleAndFollowTvPower() {
+ HdmiControlServiceWrapper.this.toggleAndFollowTvPower();
+ }
+
+ @Override
public void queryDisplayStatus(IHdmiControlCallback callback) {
HdmiControlServiceWrapper.this.queryDisplayStatus(callback);
}
@@ -360,6 +365,9 @@ public final class HdmiControlServiceWrapper {
public void oneTouchPlay(IHdmiControlCallback callback) {}
/** @hide */
+ public void toggleAndFollowTvPower() {}
+
+ /** @hide */
public void queryDisplayStatus(IHdmiControlCallback callback) {}
/** @hide */
diff --git a/core/java/android/hardware/hdmi/IHdmiControlService.aidl b/core/java/android/hardware/hdmi/IHdmiControlService.aidl
index af9d3accd00e..6d0c688f701e 100644
--- a/core/java/android/hardware/hdmi/IHdmiControlService.aidl
+++ b/core/java/android/hardware/hdmi/IHdmiControlService.aidl
@@ -42,6 +42,7 @@ interface IHdmiControlService {
int[] getSupportedTypes();
HdmiDeviceInfo getActiveSource();
void oneTouchPlay(IHdmiControlCallback callback);
+ void toggleAndFollowTvPower();
void queryDisplayStatus(IHdmiControlCallback callback);
void addHdmiControlStatusChangeListener(IHdmiControlStatusChangeListener listener);
void removeHdmiControlStatusChangeListener(IHdmiControlStatusChangeListener listener);
diff --git a/core/java/android/net/LinkProperties.java b/core/java/android/net/LinkProperties.java
index 923b9b76a1a5..81e6e788734b 100644
--- a/core/java/android/net/LinkProperties.java
+++ b/core/java/android/net/LinkProperties.java
@@ -81,8 +81,10 @@ public final class LinkProperties implements Parcelable {
private final transient boolean mParcelSensitiveFields;
private static final int MIN_MTU = 68;
- /* package-visibility - Used in other files (such as Ikev2VpnProfile) as minimum iface MTU. */
- static final int MIN_MTU_V6 = 1280;
+
+ /** @hide */
+ public static final int MIN_MTU_V6 = 1280;
+
private static final int MAX_MTU = 10000;
private static final int INET6_ADDR_LENGTH = 16;
diff --git a/core/java/android/net/NetworkCapabilities.java b/core/java/android/net/NetworkCapabilities.java
index f806b565b127..40bb8bf11d0b 100644
--- a/core/java/android/net/NetworkCapabilities.java
+++ b/core/java/android/net/NetworkCapabilities.java
@@ -339,10 +339,14 @@ public final class NetworkCapabilities implements Parcelable {
public static final int NET_CAPABILITY_PARTIAL_CONNECTIVITY = 24;
/**
+ * Indicates that this network is temporarily unmetered.
+ * <p>
* This capability will be set for networks that are generally metered, but are currently
* unmetered, e.g., because the user is in a particular area. This capability can be changed at
* any time. When it is removed, applications are responsible for stopping any data transfer
* that should not occur on a metered network.
+ * Note that most apps should use {@link #NET_CAPABILITY_NOT_METERED} instead. For more
+ * information, see https://developer.android.com/about/versions/11/features/5g#meteredness.
*/
public static final int NET_CAPABILITY_TEMPORARILY_NOT_METERED = 25;
@@ -370,8 +374,8 @@ public final class NetworkCapabilities implements Parcelable {
| (1 << NET_CAPABILITY_FOREGROUND)
| (1 << NET_CAPABILITY_NOT_CONGESTED)
| (1 << NET_CAPABILITY_NOT_SUSPENDED)
- | (1 << NET_CAPABILITY_PARTIAL_CONNECTIVITY
- | (1 << NET_CAPABILITY_TEMPORARILY_NOT_METERED));
+ | (1 << NET_CAPABILITY_PARTIAL_CONNECTIVITY)
+ | (1 << NET_CAPABILITY_TEMPORARILY_NOT_METERED);
/**
* Network capabilities that are not allowed in NetworkRequests. This exists because the
@@ -1802,21 +1806,27 @@ public final class NetworkCapabilities implements Parcelable {
sb.append(" OwnerUid: ").append(mOwnerUid);
}
- if (mAdministratorUids.length == 0) {
- sb.append(" AdministratorUids: ").append(Arrays.toString(mAdministratorUids));
+ if (!ArrayUtils.isEmpty(mAdministratorUids)) {
+ sb.append(" AdminUids: ").append(Arrays.toString(mAdministratorUids));
+ }
+
+ if (mRequestorUid != Process.INVALID_UID) {
+ sb.append(" RequestorUid: ").append(mRequestorUid);
+ }
+
+ if (mRequestorPackageName != null) {
+ sb.append(" RequestorPkg: ").append(mRequestorPackageName);
}
if (null != mSSID) {
sb.append(" SSID: ").append(mSSID);
}
+
if (mPrivateDnsBroken) {
- sb.append(" Private DNS is broken");
+ sb.append(" PrivateDnsBroken");
}
- sb.append(" RequestorUid: ").append(mRequestorUid);
- sb.append(" RequestorPackageName: ").append(mRequestorPackageName);
-
sb.append("]");
return sb.toString();
}
diff --git a/core/java/android/net/vcn/VcnGatewayConnectionConfig.java b/core/java/android/net/vcn/VcnGatewayConnectionConfig.java
new file mode 100644
index 000000000000..8160edc87440
--- /dev/null
+++ b/core/java/android/net/vcn/VcnGatewayConnectionConfig.java
@@ -0,0 +1,86 @@
+/*
+ * 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.net.vcn;
+
+import android.annotation.NonNull;
+
+/**
+ * This class represents a configuration for a connection to a Virtual Carrier Network gateway.
+ *
+ * <p>Each VcnGatewayConnectionConfig represents a single logical connection to a carrier gateway,
+ * and may provide one or more telephony services (as represented by network capabilities). Each
+ * gateway is expected to provide mobility for a given session as the device roams across {@link
+ * Network}s.
+ *
+ * <p>A VCN connection based on this configuration will be brought up dynamically based on device
+ * settings, and filed NetworkRequests. Underlying networks will be selected based on the services
+ * required by this configuration (as represented by network capabilities), and must be part of the
+ * subscription group under which this configuration is registered (see {@link
+ * VcnManager#setVcnConfig}).
+ *
+ * <p>Services that can be provided by a VCN network, or required for underlying networks are
+ * limited to services provided by cellular networks:
+ *
+ * <ul>
+ * <li>{@link android.net.NetworkCapabilities.NET_CAPABILITY_MMS}
+ * <li>{@link android.net.NetworkCapabilities.NET_CAPABILITY_SUPL}
+ * <li>{@link android.net.NetworkCapabilities.NET_CAPABILITY_DUN}
+ * <li>{@link android.net.NetworkCapabilities.NET_CAPABILITY_FOTA}
+ * <li>{@link android.net.NetworkCapabilities.NET_CAPABILITY_IMS}
+ * <li>{@link android.net.NetworkCapabilities.NET_CAPABILITY_CBS}
+ * <li>{@link android.net.NetworkCapabilities.NET_CAPABILITY_IA}
+ * <li>{@link android.net.NetworkCapabilities.NET_CAPABILITY_RCS}
+ * <li>{@link android.net.NetworkCapabilities.NET_CAPABILITY_XCAP}
+ * <li>{@link android.net.NetworkCapabilities.NET_CAPABILITY_EIMS}
+ * <li>{@link android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET}
+ * <li>{@link android.net.NetworkCapabilities.NET_CAPABILITY_MCX}
+ * </ul>
+ *
+ * @hide
+ */
+public final class VcnGatewayConnectionConfig {
+ private VcnGatewayConnectionConfig() {
+ validate();
+ }
+
+ // TODO: Implement getters, validators, etc
+
+ /**
+ * Validates this configuration
+ *
+ * @hide
+ */
+ private void validate() {
+ // TODO: implement validation logic
+ }
+
+ // Parcelable methods
+
+ /** This class is used to incrementally build {@link VcnGatewayConnectionConfig} objects */
+ public static class Builder {
+ // TODO: Implement this builder
+
+ /**
+ * Builds and validates the VcnGatewayConnectionConfig
+ *
+ * @return an immutable VcnGatewayConnectionConfig instance
+ */
+ @NonNull
+ public VcnGatewayConnectionConfig build() {
+ return new VcnGatewayConnectionConfig();
+ }
+ }
+}
diff --git a/core/java/android/os/strictmode/UntaggedSocketViolation.java b/core/java/android/os/strictmode/UntaggedSocketViolation.java
index 3b1ef253b2d2..c34d6e821f7a 100644
--- a/core/java/android/os/strictmode/UntaggedSocketViolation.java
+++ b/core/java/android/os/strictmode/UntaggedSocketViolation.java
@@ -18,7 +18,7 @@ package android.os.strictmode;
public final class UntaggedSocketViolation extends Violation {
/** @hide */
public UntaggedSocketViolation() {
- super("Untagged socket detected; use TrafficStats.setThreadSocketTag() to "
+ super("Untagged socket detected; use TrafficStats.setTrafficStatsTag() to "
+ "track all network usage");
}
}
diff --git a/core/java/android/service/attestation/IImpressionAttestationService.aidl b/core/java/android/service/attestation/IImpressionAttestationService.aidl
index 8e858b8aea77..fcbc51febada 100644
--- a/core/java/android/service/attestation/IImpressionAttestationService.aidl
+++ b/core/java/android/service/attestation/IImpressionAttestationService.aidl
@@ -18,8 +18,8 @@ package android.service.attestation;
import android.graphics.Rect;
import android.hardware.HardwareBuffer;
-import android.service.attestation.ImpressionToken;
import android.os.RemoteCallback;
+import android.service.attestation.ImpressionToken;
/**
* Service used to handle impression attestation requests.
@@ -31,22 +31,26 @@ oneway interface IImpressionAttestationService {
* Generates the impression token that can be used to validate that the system generated the
* token.
*
- * @param screenshot The token for the window where the view is shown.
+ * @param salt The salt to use when generating the hmac. This should be unique to the caller so
+ * the token cannot be verified by any other process.
+ * @param screenshot The screenshot to generate the hash and add to the token.
* @param bounds The size and position of the content being attested in the window.
* @param hashAlgorithm The String for the hashing algorithm to use based on values in
* {@link #SERVICE_META_DATA_KEY_AVAILABLE_ALGORITHMS}.
* @param Callback The callback invoked to send back the impression token.
*/
- void generateImpressionToken(in HardwareBuffer screenshot, in Rect bounds,
+ void generateImpressionToken(in String salt, in HardwareBuffer screenshot, in Rect bounds,
in String hashAlgorithm, in RemoteCallback callback);
/**
* Call to verify that the impressionToken passed in was generated by the system. The result
- * will be sent in the callback as an integer with the key {@link #EXTRA_VERIFICATION_STATUS}
- * and will be one of the values in {@link VerificationStatus}.
+ * will be sent in the callback as a boolean with the key {@link #EXTRA_VERIFICATION_STATUS}.
*
+ * @param salt The salt value to use when verifying the hmac. This should be the same value that
+ * was passed to {@link generateImpressionToken()} to generate the token.
* @param impressionToken The token to verify that it was generated by the system.
* @param callback The callback invoked to send back the verification status.
*/
- void verifyImpressionToken(in ImpressionToken impressionToken, in RemoteCallback callback);
+ void verifyImpressionToken(in String salt, in ImpressionToken impressionToken,
+ in RemoteCallback callback);
}
diff --git a/core/java/android/service/attestation/ImpressionAttestationService.java b/core/java/android/service/attestation/ImpressionAttestationService.java
index 923ab7a65d1b..05ad5f02efe5 100644
--- a/core/java/android/service/attestation/ImpressionAttestationService.java
+++ b/core/java/android/service/attestation/ImpressionAttestationService.java
@@ -18,7 +18,6 @@ package android.service.attestation;
import static com.android.internal.util.function.pooled.PooledLambda.obtainMessage;
-import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
@@ -50,22 +49,10 @@ public abstract class ImpressionAttestationService extends Service {
public static final String EXTRA_VERIFICATION_STATUS =
"android.service.attestation.extra.VERIFICATION_STATUS";
- /** @hide */
- @IntDef(prefix = {"VERIFICATION_STATUS_"}, value = {
- VERIFICATION_STATUS_UNKNOWN,
- VERIFICATION_STATUS_OS_VERIFIED,
- VERIFICATION_STATUS_APP_DECLARED
- })
- public @interface VerificationStatus {
- }
-
- public static final int VERIFICATION_STATUS_UNKNOWN = 0;
- public static final int VERIFICATION_STATUS_OS_VERIFIED = 1;
- public static final int VERIFICATION_STATUS_APP_DECLARED = 2;
-
/**
* Manifest metadata key for the resource string array containing the names of all impression
* attestation algorithms provided by the service.
+ *
* @hide
*/
public static final String SERVICE_META_DATA_KEY_AVAILABLE_ALGORITHMS =
@@ -74,6 +61,7 @@ public abstract class ImpressionAttestationService extends Service {
/**
* The {@link Intent} action that must be declared as handled by a service in its manifest
* for the system to recognize it as an impression attestation providing service.
+ *
* @hide
*/
public static final String SERVICE_INTERFACE =
@@ -102,6 +90,8 @@ public abstract class ImpressionAttestationService extends Service {
* Generates the impression token that can be used to validate that the system
* generated the token.
*
+ * @param salt The salt to use when generating the hmac. This should be unique to the
+ * caller so the token cannot be verified by any other process.
* @param screenshot The screenshot buffer for the content to attest.
* @param bounds The size and position of the content being attested in the window.
* @param hashAlgorithm The String for the hashing algorithm to use based values in
@@ -110,51 +100,57 @@ public abstract class ImpressionAttestationService extends Service {
* Returns null when the arguments sent are invalid.
*/
@Nullable
- public abstract ImpressionToken onGenerateImpressionToken(@NonNull HardwareBuffer screenshot,
- @NonNull Rect bounds, @NonNull String hashAlgorithm);
+ public abstract ImpressionToken onGenerateImpressionToken(@NonNull String salt,
+ @NonNull HardwareBuffer screenshot, @NonNull Rect bounds,
+ @NonNull String hashAlgorithm);
/**
* Call to verify that the impressionToken passed in was generated by the system.
*
+ * @param salt The salt value to use when verifying the hmac. This should be the
+ * same value that was passed to
+ * {@link #onGenerateImpressionToken(String,
+ * HardwareBuffer, Rect, String)} to
+ * generate the token.
* @param impressionToken The token to verify that it was generated by the system.
- * @return A {@link VerificationStatus} about whether the token was generated by the system.
+ * @return true if the token can be verified that it was generated by the system.
*/
- public abstract @VerificationStatus int onVerifyImpressionToken(
+ public abstract boolean onVerifyImpressionToken(@NonNull String salt,
@NonNull ImpressionToken impressionToken);
- private void generateImpressionToken(HardwareBuffer screenshot, Rect bounds,
+ private void generateImpressionToken(String salt, HardwareBuffer screenshot, Rect bounds,
String hashAlgorithm, RemoteCallback callback) {
- ImpressionToken impressionToken = onGenerateImpressionToken(screenshot, bounds,
+ ImpressionToken impressionToken = onGenerateImpressionToken(salt, screenshot, bounds,
hashAlgorithm);
final Bundle data = new Bundle();
data.putParcelable(EXTRA_IMPRESSION_TOKEN, impressionToken);
callback.sendResult(data);
}
- private void verifyImpressionToken(ImpressionToken impressionToken,
+ private void verifyImpressionToken(String salt, ImpressionToken impressionToken,
RemoteCallback callback) {
- @VerificationStatus int verificationStatus = onVerifyImpressionToken(impressionToken);
+ boolean verificationStatus = onVerifyImpressionToken(salt, impressionToken);
final Bundle data = new Bundle();
- data.putInt(EXTRA_VERIFICATION_STATUS, verificationStatus);
+ data.putBoolean(EXTRA_VERIFICATION_STATUS, verificationStatus);
callback.sendResult(data);
}
private final class ImpressionAttestationServiceWrapper extends
IImpressionAttestationService.Stub {
@Override
- public void generateImpressionToken(HardwareBuffer screenshot, Rect bounds,
+ public void generateImpressionToken(String salt, HardwareBuffer screenshot, Rect bounds,
String hashAlgorithm, RemoteCallback callback) {
mHandler.sendMessage(
obtainMessage(ImpressionAttestationService::generateImpressionToken,
- ImpressionAttestationService.this, screenshot, bounds, hashAlgorithm,
- callback));
+ ImpressionAttestationService.this, salt, screenshot, bounds,
+ hashAlgorithm, callback));
}
@Override
- public void verifyImpressionToken(ImpressionToken impressionToken,
+ public void verifyImpressionToken(String salt, ImpressionToken impressionToken,
RemoteCallback callback) {
mHandler.sendMessage(obtainMessage(ImpressionAttestationService::verifyImpressionToken,
- ImpressionAttestationService.this, impressionToken, callback));
+ ImpressionAttestationService.this, salt, impressionToken, callback));
}
}
}
diff --git a/core/java/android/service/quicksettings/TileService.java b/core/java/android/service/quicksettings/TileService.java
index b4b5819c7d5f..53290e2ede5a 100644
--- a/core/java/android/service/quicksettings/TileService.java
+++ b/core/java/android/service/quicksettings/TileService.java
@@ -176,6 +176,9 @@ public class TileService extends Service {
@Override
public void onDestroy() {
+ // As this call will come asynchronously in the main thread, prevent calls from the binder
+ // being processed after this.
+ mHandler.removeCallbacksAndMessages(null);
if (mListening) {
onStopListening();
mListening = false;
diff --git a/core/java/android/telephony/PhoneStateListener.java b/core/java/android/telephony/PhoneStateListener.java
index bfa3123c9d84..479a0c16c747 100644
--- a/core/java/android/telephony/PhoneStateListener.java
+++ b/core/java/android/telephony/PhoneStateListener.java
@@ -17,10 +17,7 @@
package android.telephony;
import android.Manifest;
-import android.annotation.CallbackExecutor;
-import android.annotation.IntDef;
import android.annotation.NonNull;
-import android.annotation.Nullable;
import android.annotation.RequiresPermission;
import android.annotation.SystemApi;
import android.compat.annotation.ChangeId;
@@ -31,27 +28,17 @@ import android.os.Handler;
import android.os.HandlerExecutor;
import android.os.Looper;
import android.telephony.Annotation.CallState;
-import android.telephony.Annotation.DataActivityType;
-import android.telephony.Annotation.DisconnectCauses;
-import android.telephony.Annotation.NetworkType;
-import android.telephony.Annotation.PreciseDisconnectCauses;
import android.telephony.Annotation.RadioPowerState;
import android.telephony.Annotation.SimActivationState;
import android.telephony.Annotation.SrvccState;
import android.telephony.emergency.EmergencyNumber;
import android.telephony.ims.ImsReasonInfo;
-import android.telephony.NetworkRegistrationInfo.Domain;
-import android.telephony.TelephonyManager.DataEnabledReason;
-import android.telephony.TelephonyManager.DataState;
-import android.util.Log;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.telephony.IPhoneStateListener;
import dalvik.system.VMRuntime;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
import java.lang.ref.WeakReference;
import java.util.List;
import java.util.Map;
@@ -126,9 +113,7 @@ public class PhoneStateListener {
*
* @see #onServiceStateChanged
* @see ServiceState
- * @deprecated Use {@link ServiceStateChangedListener} instead.
*/
- @Deprecated
public static final int LISTEN_SERVICE_STATE = 0x00000001;
/**
@@ -136,7 +121,8 @@ public class PhoneStateListener {
* {@more}
*
* @see #onSignalStrengthChanged
- * @deprecated Use {@link SignalStrengthsChangedListener} instead.
+ *
+ * @deprecated by {@link #LISTEN_SIGNAL_STRENGTHS}
*/
@Deprecated
public static final int LISTEN_SIGNAL_STRENGTH = 0x00000002;
@@ -152,9 +138,7 @@ public class PhoneStateListener {
* voicemail icon.
*
* @see #onMessageWaitingIndicatorChanged
- * @deprecated Use {@link MessageWaitingIndicatorChangedListener} instead.
*/
- @Deprecated
public static final int LISTEN_MESSAGE_WAITING_INDICATOR = 0x00000004;
/**
@@ -165,9 +149,7 @@ public class PhoneStateListener {
* {@link TelephonyManager#hasCarrierPrivileges}).
*
* @see #onCallForwardingIndicatorChanged
- * @deprecated Use {@link CallForwardingIndicatorChangedListener} instead.
*/
- @Deprecated
public static final int LISTEN_CALL_FORWARDING_INDICATOR = 0x00000008;
/**
@@ -183,9 +165,7 @@ public class PhoneStateListener {
* instead.
*
* @see #onCellLocationChanged
- * @deprecated Use {@link CellLocationChangedListener} instead.
*/
- @Deprecated
public static final int LISTEN_CELL_LOCATION = 0x00000010;
/**
@@ -193,18 +173,14 @@ public class PhoneStateListener {
* {@more}
*
* @see #onCallStateChanged
- * @deprecated Use {@link CallStateChangedListener} instead.
*/
- @Deprecated
public static final int LISTEN_CALL_STATE = 0x00000020;
/**
* Listen for changes to the data connection state (cellular).
*
* @see #onDataConnectionStateChanged
- * @deprecated Use {@link DataConnectionStateChangedListener} instead.
*/
- @Deprecated
public static final int LISTEN_DATA_CONNECTION_STATE = 0x00000040;
/**
@@ -215,9 +191,7 @@ public class PhoneStateListener {
* data-traffic icon.
*
* @see #onDataActivity
- * @deprecated Use {@link DataActivityListener} instead.
*/
- @Deprecated
public static final int LISTEN_DATA_ACTIVITY = 0x00000080;
/**
@@ -227,9 +201,7 @@ public class PhoneStateListener {
* icon.
*
* @see #onSignalStrengthsChanged
- * @deprecated Use {@link SignalStrengthsChangedListener} instead.
*/
- @Deprecated
public static final int LISTEN_SIGNAL_STRENGTHS = 0x00000100;
/**
@@ -239,9 +211,7 @@ public class PhoneStateListener {
* @see #onSignalStrengthsChanged
*
* @hide
- * @deprecated Use {@link AlwaysReportedSignalStrengthsChangedListener} instead.
*/
- @Deprecated
@RequiresPermission(android.Manifest.permission.LISTEN_ALWAYS_REPORTED_SIGNAL_STRENGTH)
public static final int LISTEN_ALWAYS_REPORTED_SIGNAL_STRENGTH = 0x00000200;
@@ -252,9 +222,7 @@ public class PhoneStateListener {
* permission.
*
* @see #onCellInfoChanged
- * @deprecated Use {@link CellInfoChangedListener} instead.
*/
- @Deprecated
public static final int LISTEN_CELL_INFO = 0x00000400;
/**
@@ -266,10 +234,8 @@ public class PhoneStateListener {
* (see {@link TelephonyManager#hasCarrierPrivileges}).
*
* @hide
- * @deprecated Use {@link PreciseCallStateChangedListener} instead.
*/
- @Deprecated
- @RequiresPermission(android.Manifest.permission.READ_PRECISE_PHONE_STATE)
+ @RequiresPermission((android.Manifest.permission.READ_PRECISE_PHONE_STATE))
@SystemApi
public static final int LISTEN_PRECISE_CALL_STATE = 0x00000800;
@@ -281,10 +247,8 @@ public class PhoneStateListener {
* (see {@link TelephonyManager#hasCarrierPrivileges}).
*
* @see #onPreciseDataConnectionStateChanged
- * @deprecated Use {@link PreciseDataConnectionStateChangedListener} instead.
*/
- @Deprecated
- @RequiresPermission(android.Manifest.permission.READ_PRECISE_PHONE_STATE)
+ @RequiresPermission((android.Manifest.permission.READ_PRECISE_PHONE_STATE))
public static final int LISTEN_PRECISE_DATA_CONNECTION_STATE = 0x00001000;
/**
@@ -294,7 +258,7 @@ public class PhoneStateListener {
* READ_PRECISE_PHONE_STATE}
* @see #onDataConnectionRealTimeInfoChanged(DataConnectionRealTimeInfo)
*
- * @deprecated Use {@link TelephonyManager#requestModemActivityInfo} instead.
+ * @deprecated Use {@link TelephonyManager#getModemActivityInfo()}
* @hide
*/
@Deprecated
@@ -307,9 +271,7 @@ public class PhoneStateListener {
*
* @see #onServiceStateChanged(ServiceState)
* @hide
- * @deprecated Use {@link SrvccStateChangedListener} instead.
*/
- @Deprecated
@SystemApi
@RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
public static final int LISTEN_SRVCC_STATE_CHANGED = 0x00004000;
@@ -327,11 +289,10 @@ public class PhoneStateListener {
/**
* Listen for carrier network changes indicated by a carrier app.
*
- * @see android.service.carrier.CarrierService#notifyCarrierNetworkChange(boolean)
+ * @see #onCarrierNetworkRequest
+ * @see TelephonyManager#notifyCarrierNetworkChange(boolean)
* @hide
- * @deprecated Use {@link CarrierNetworkChangeListener} instead.
*/
- @Deprecated
public static final int LISTEN_CARRIER_NETWORK_CHANGE = 0x00010000;
/**
@@ -350,9 +311,7 @@ public class PhoneStateListener {
*
* @see #onVoiceActivationStateChanged
* @hide
- * @deprecated Use {@link VoiceActivationStateChangedListener} instead.
*/
- @Deprecated
@SystemApi
@RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
public static final int LISTEN_VOICE_ACTIVATION_STATE = 0x00020000;
@@ -364,24 +323,20 @@ public class PhoneStateListener {
* @see TelephonyManager#SIM_ACTIVATION_STATE_DEACTIVATED
* @see TelephonyManager#SIM_ACTIVATION_STATE_RESTRICTED
* @see TelephonyManager#SIM_ACTIVATION_STATE_UNKNOWN
- *
+ * {@more}
* Example: TelephonyManager#SIM_ACTIVATION_STATE_ACTIVATED indicates data service has been
* fully activated
*
* @see #onDataActivationStateChanged
* @hide
- * @deprecated Use {@link DataActivationStateChangedListener} instead.
*/
- @Deprecated
public static final int LISTEN_DATA_ACTIVATION_STATE = 0x00040000;
/**
* Listen for changes to the user mobile data state
*
* @see #onUserMobileDataStateChanged
- * @deprecated Use {@link UserMobileDataStateChangedListener} instead.
*/
- @Deprecated
public static final int LISTEN_USER_MOBILE_DATA_STATE = 0x00080000;
/**
@@ -392,9 +347,7 @@ public class PhoneStateListener {
* {@link TelephonyManager#hasCarrierPrivileges}).
*
* @see #onDisplayInfoChanged
- * @deprecated Use {@link DisplayInfoChangedListener} instead.
*/
- @Deprecated
public static final int LISTEN_DISPLAY_INFO_CHANGED = 0x00100000;
/**
@@ -402,9 +355,7 @@ public class PhoneStateListener {
*
* @see #onPhoneCapabilityChanged
* @hide
- * @deprecated Use {@link PhoneCapabilityChangedListener} instead.
*/
- @Deprecated
public static final int LISTEN_PHONE_CAPABILITY_CHANGE = 0x00200000;
/**
@@ -414,19 +365,17 @@ public class PhoneStateListener {
* subscription user selected as default data subscription in DSDS mode.
*
* @see #onActiveDataSubscriptionIdChanged
- * @deprecated Use {@link ActiveDataSubscriptionIdChangedListener} instead.
*/
- @Deprecated
public static final int LISTEN_ACTIVE_DATA_SUBSCRIPTION_ID_CHANGE = 0x00400000;
/**
* Listen for changes to the radio power state.
*
+ * <p>Requires permission {@link android.Manifest.permission#READ_PRIVILEGED_PHONE_STATE}
+ *
* @see #onRadioPowerStateChanged
* @hide
- * @deprecated Use {@link RadioPowerStateChangedListener} instead.
*/
- @Deprecated
@SystemApi
@RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
public static final int LISTEN_RADIO_POWER_STATE_CHANGED = 0x00800000;
@@ -436,10 +385,7 @@ public class PhoneStateListener {
*
* <p>Requires permission {@link android.Manifest.permission#READ_PHONE_STATE} or the calling
* app has carrier privileges (see {@link TelephonyManager#hasCarrierPrivileges}).
- *
- * @deprecated Use {@link EmergencyNumberListChangedListener} instead.
*/
- @Deprecated
public static final int LISTEN_EMERGENCY_NUMBER_LIST = 0x01000000;
/**
@@ -450,10 +396,8 @@ public class PhoneStateListener {
* or the calling app has carrier privileges
* (see {@link TelephonyManager#hasCarrierPrivileges}).
*
- * @deprecated Use {@link CallDisconnectCauseChangedListener} instead.
*/
- @Deprecated
- @RequiresPermission(android.Manifest.permission.READ_PRECISE_PHONE_STATE)
+ @RequiresPermission((android.Manifest.permission.READ_PRECISE_PHONE_STATE))
public static final int LISTEN_CALL_DISCONNECT_CAUSES = 0x02000000;
/**
@@ -465,11 +409,9 @@ public class PhoneStateListener {
*
* @see #onCallAttributesChanged
* @hide
- * @deprecated Use {@link CallAttributesChangedListener} instead.
*/
- @Deprecated
@SystemApi
- @RequiresPermission(android.Manifest.permission.READ_PRECISE_PHONE_STATE)
+ @RequiresPermission((android.Manifest.permission.READ_PRECISE_PHONE_STATE))
public static final int LISTEN_CALL_ATTRIBUTES_CHANGED = 0x04000000;
/**
@@ -481,20 +423,18 @@ public class PhoneStateListener {
* (see {@link TelephonyManager#hasCarrierPrivileges}).
*
* @see #onImsCallDisconnectCauseChanged(ImsReasonInfo)
- * @deprecated Use {@link ImsCallDisconnectCauseChangedListener} instead.
*/
- @Deprecated
- @RequiresPermission(android.Manifest.permission.READ_PRECISE_PHONE_STATE)
+ @RequiresPermission((android.Manifest.permission.READ_PRECISE_PHONE_STATE))
public static final int LISTEN_IMS_CALL_DISCONNECT_CAUSES = 0x08000000;
/**
* Listen for the emergency number placed from an outgoing call.
*
+ * <p>Requires permission {@link android.Manifest.permission#READ_ACTIVE_EMERGENCY_SESSION}
+ *
* @see #onOutgoingEmergencyCall
* @hide
- * @deprecated Use {@link OutgoingEmergencyCallListener} instead.
*/
- @Deprecated
@SystemApi
@RequiresPermission(Manifest.permission.READ_ACTIVE_EMERGENCY_SESSION)
public static final int LISTEN_OUTGOING_EMERGENCY_CALL = 0x10000000;
@@ -502,11 +442,11 @@ public class PhoneStateListener {
/**
* Listen for the emergency number placed from an outgoing SMS.
*
+ * <p>Requires permission {@link android.Manifest.permission#READ_ACTIVE_EMERGENCY_SESSION}
+ *
* @see #onOutgoingEmergencySms
* @hide
- * @deprecated Use {@link OutgoingEmergencySmsListener} instead.
*/
- @Deprecated
@SystemApi
@RequiresPermission(Manifest.permission.READ_ACTIVE_EMERGENCY_SESSION)
public static final int LISTEN_OUTGOING_EMERGENCY_SMS = 0x20000000;
@@ -525,9 +465,7 @@ public class PhoneStateListener {
* of whether the calling app has carrier privileges.
*
* @see #onRegistrationFailed
- * @deprecated Use {@link RegistrationFailedListener} instead.
*/
- @Deprecated
@RequiresPermission(Manifest.permission.READ_PRECISE_PHONE_STATE)
public static final int LISTEN_REGISTRATION_FAILURE = 0x40000000;
@@ -541,525 +479,19 @@ public class PhoneStateListener {
* of whether the calling app has carrier privileges.
*
* @see #onBarringInfoChanged
- * @deprecated Use {@link BarringInfoChangedListener} instead.
*/
- @Deprecated
@RequiresPermission(Manifest.permission.READ_PRECISE_PHONE_STATE)
public static final int LISTEN_BARRING_INFO = 0x80000000;
/**
- * Event for changes to the network service state (cellular).
- *
- * @see ServiceStateChangedListener#onServiceStateChanged
- * @see ServiceState
- *
- * @hide
- */
- @SystemApi
- public static final int EVENT_SERVICE_STATE_CHANGED = 1;
-
- /**
- * Event for changes to the network signal strength (cellular).
- *
- * @see SignalStrengthsChangedListener#onSignalStrengthsChanged
- *
- * @hide
- */
- @SystemApi
- public static final int EVENT_SIGNAL_STRENGTH_CHANGED = 2;
-
- /**
- * Event for changes to the message-waiting indicator.
- *
- * Requires Permission: {@link android.Manifest.permission#READ_PHONE_STATE} or that
- * the calling app has carrier privileges (see
- * {@link TelephonyManager#hasCarrierPrivileges}).
- * <p>
- * Example: The status bar uses this to determine when to display the
- * voicemail icon.
- *
- * @see MessageWaitingIndicatorChangedListener#onMessageWaitingIndicatorChanged
- *
- * @hide
- */
- @SystemApi
- @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
- public static final int EVENT_MESSAGE_WAITING_INDICATOR_CHANGED = 3;
-
- /**
- * Event for changes to the call-forwarding indicator.
- *
- * Requires Permission: {@link android.Manifest.permission#READ_PHONE_STATE} or that
- * the calling app has carrier privileges (see
- * {@link TelephonyManager#hasCarrierPrivileges}).
- *
- * @see CallForwardingIndicatorChangedListener#onCallForwardingIndicatorChanged
- *
- * @hide
- */
- @SystemApi
- @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
- public static final int EVENT_CALL_FORWARDING_INDICATOR_CHANGED = 4;
-
- /**
- * Event for changes to the device's cell location. Note that
- * this will result in frequent callbacks to the listener.
- *
- * If you need regular location updates but want more control over
- * the update interval or location precision, you can set up a listener
- * through the {@link android.location.LocationManager location manager}
- * instead.
- *
- * @see CellLocationChangedListener#onCellLocationChanged
- *
- * @hide
- */
- @SystemApi
- @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION)
- public static final int EVENT_CELL_LOCATION_CHANGED = 5;
-
- /**
- * Event for changes to the device call state.
- *
- * @see CallStateChangedListener#onCallStateChanged
- *
- * @hide
- */
- @SystemApi
- @RequiresPermission(android.Manifest.permission.READ_CALL_LOG)
- public static final int EVENT_CALL_STATE_CHANGED = 6;
-
- /**
- * Event for changes to the data connection state (cellular).
- *
- * @see DataConnectionStateChangedListener#onDataConnectionStateChanged
- *
- * @hide
- */
- @SystemApi
- public static final int EVENT_DATA_CONNECTION_STATE_CHANGED = 7;
-
- /**
- * Event for changes to the direction of data traffic on the data
- * connection (cellular).
- *
- * Example: The status bar uses this to display the appropriate
- * data-traffic icon.
- *
- * @see DataActivityListener#onDataActivity
- *
- * @hide
- */
- @SystemApi
- public static final int EVENT_DATA_ACTIVITY_CHANGED = 8;
-
- /**
- * Event for changes to the network signal strengths (cellular).
- * <p>
- * Example: The status bar uses this to control the signal-strength
- * icon.
- *
- * @see SignalStrengthsChangedListener#onSignalStrengthsChanged
- *
- * @hide
- */
- @SystemApi
- public static final int EVENT_SIGNAL_STRENGTHS_CHANGED = 9;
-
- /**
- * Event for changes of the network signal strengths (cellular) always reported from modem,
- * even in some situations such as the screen of the device is off.
- *
- * @see AlwaysReportedSignalStrengthsChangedListener#onSignalStrengthsChanged
- *
- * @hide
- */
- @SystemApi
- @RequiresPermission(android.Manifest.permission.LISTEN_ALWAYS_REPORTED_SIGNAL_STRENGTH)
- public static final int EVENT_ALWAYS_REPORTED_SIGNAL_STRENGTH_CHANGED = 10;
-
- /**
- * Event for changes to observed cell info.
- *
- * @see CellInfoChangedListener#onCellInfoChanged
- *
- * @hide
- */
- @SystemApi
- @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION)
- public static final int EVENT_CELL_INFO_CHANGED = 11;
-
- /**
- * Event for {@link android.telephony.Annotation.PreciseCallStates} of ringing,
- * background and foreground calls.
- *
- * <p>Requires permission {@link android.Manifest.permission#READ_PRECISE_PHONE_STATE}
- * or the calling app has carrier privileges
- * (see {@link TelephonyManager#hasCarrierPrivileges}).
- *
- * @see PreciseCallStateChangedListener#onPreciseCallStateChanged
- *
- * @hide
- */
- @SystemApi
- @RequiresPermission(android.Manifest.permission.READ_PRECISE_PHONE_STATE)
- public static final int EVENT_PRECISE_CALL_STATE_CHANGED = 12;
-
- /**
- * Event for {@link PreciseDataConnectionState} on the data connection (cellular).
- *
- * <p>Requires permission {@link android.Manifest.permission#READ_PRECISE_PHONE_STATE}
- * or the calling app has carrier privileges
- * (see {@link TelephonyManager#hasCarrierPrivileges}).
- *
- * @see PreciseDataConnectionStateChangedListener#onPreciseDataConnectionStateChanged
- *
- * @hide
- */
- @SystemApi
- @RequiresPermission(android.Manifest.permission.READ_PRECISE_PHONE_STATE)
- public static final int EVENT_PRECISE_DATA_CONNECTION_STATE_CHANGED = 13;
-
- /**
- * Event for real time info for all data connections (cellular)).
- *
- * @see #onDataConnectionRealTimeInfoChanged(DataConnectionRealTimeInfo)
- *
- * @deprecated Use {@link TelephonyManager#requestModemActivityInfo}
- * @hide
- */
- @Deprecated
- @SystemApi
- @RequiresPermission(android.Manifest.permission.READ_PRECISE_PHONE_STATE)
- public static final int EVENT_DATA_CONNECTION_REAL_TIME_INFO_CHANGED = 14;
-
- /**
- * Event for OEM hook raw event
- *
- * @see #onOemHookRawEvent
- *
- * @hide
- */
- @SystemApi
- @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
- public static final int EVENT_OEM_HOOK_RAW = 15;
-
- /**
- * Event for changes to the SRVCC state of the active call.
- *
- * @see SrvccStateChangedListener#onSrvccStateChanged
- *
- * @hide
- */
- @SystemApi
- @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
- public static final int EVENT_SRVCC_STATE_CHANGED = 16;
-
- /**
- * Event for carrier network changes indicated by a carrier app.
- *
- * @see android.service.carrier.CarrierService#notifyCarrierNetworkChange(boolean)
- * @see CarrierNetworkChangeListener#onCarrierNetworkChange
- *
- * @hide
- */
- @SystemApi
- public static final int EVENT_CARRIER_NETWORK_CHANGED = 17;
-
- /**
- * Event for changes to the sim voice activation state
- *
- * @see TelephonyManager#SIM_ACTIVATION_STATE_ACTIVATING
- * @see TelephonyManager#SIM_ACTIVATION_STATE_ACTIVATED
- * @see TelephonyManager#SIM_ACTIVATION_STATE_DEACTIVATED
- * @see TelephonyManager#SIM_ACTIVATION_STATE_RESTRICTED
- * @see TelephonyManager#SIM_ACTIVATION_STATE_UNKNOWN
- *
- * Example: TelephonyManager#SIM_ACTIVATION_STATE_ACTIVATED indicates voice service has been
- * fully activated
- *
- * @see VoiceActivationStateChangedListener#onVoiceActivationStateChanged
- *
- * @hide
- */
- @SystemApi
- @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
- public static final int EVENT_VOICE_ACTIVATION_STATE_CHANGED = 18;
-
- /**
- * Event for changes to the sim data activation state
- * @see TelephonyManager#SIM_ACTIVATION_STATE_ACTIVATING
- * @see TelephonyManager#SIM_ACTIVATION_STATE_ACTIVATED
- * @see TelephonyManager#SIM_ACTIVATION_STATE_DEACTIVATED
- * @see TelephonyManager#SIM_ACTIVATION_STATE_RESTRICTED
- * @see TelephonyManager#SIM_ACTIVATION_STATE_UNKNOWN
- *
- * Example: TelephonyManager#SIM_ACTIVATION_STATE_ACTIVATED indicates data service has been
- * fully activated
- *
- * @see DataActivationStateChangedListener#onDataActivationStateChanged
- * @hide
- */
- @SystemApi
- public static final int EVENT_DATA_ACTIVATION_STATE_CHANGED = 19;
-
- /**
- * Event for changes to the user mobile data state
- *
- * @see UserMobileDataStateChangedListener#onUserMobileDataStateChanged
- *
- * @hide
- */
- @SystemApi
- public static final int EVENT_USER_MOBILE_DATA_STATE_CHANGED = 20;
-
- /**
- * Event for display info changed event.
- *
- * @see DisplayInfoChangedListener#onDisplayInfoChanged
- *
- * @hide
- */
- @SystemApi
- public static final int EVENT_DISPLAY_INFO_CHANGED = 21;
-
- /**
- * Event for changes to the phone capability.
- *
- * @see PhoneCapabilityChangedListener#onPhoneCapabilityChanged
- *
- * @hide
- */
- @SystemApi
- public static final int EVENT_PHONE_CAPABILITY_CHANGED = 22;
-
- /**
- * Event for changes to active data subscription ID. Active data subscription is
- * the current subscription used to setup Cellular Internet data. For example,
- * it could be the current active opportunistic subscription in use, or the
- * subscription user selected as default data subscription in DSDS mode.
- *
- * <p>Requires permission {@link android.Manifest.permission#READ_PHONE_STATE} or the calling
- * app has carrier privileges (see {@link TelephonyManager#hasCarrierPrivileges}).
- *
- * @see ActiveDataSubscriptionIdChangedListener#onActiveDataSubscriptionIdChanged
- *
- * @hide
- */
- @SystemApi
- @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
- public static final int EVENT_ACTIVE_DATA_SUBSCRIPTION_ID_CHANGED = 23;
-
- /**
- * Event for changes to the radio power state.
- *
- * @see RadioPowerStateChangedListener#onRadioPowerStateChanged
- *
- * @hide
- */
- @SystemApi
- @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
- public static final int EVENT_RADIO_POWER_STATE_CHANGED = 24;
-
- /**
- * Event for changes to emergency number list based on all active subscriptions.
- *
- * <p>Requires permission {@link android.Manifest.permission#READ_PHONE_STATE} or the calling
- * app has carrier privileges (see {@link TelephonyManager#hasCarrierPrivileges}).
- *
- * @see EmergencyNumberListChangedListener#onEmergencyNumberListChanged
- *
- * @hide
- */
- @SystemApi
- @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
- public static final int EVENT_EMERGENCY_NUMBER_LIST_CHANGED = 25;
-
- /**
- * Event for call disconnect causes which contains {@link DisconnectCause} and
- * {@link PreciseDisconnectCause}.
- *
- * <p>Requires permission {@link android.Manifest.permission#READ_PRECISE_PHONE_STATE}
- * or the calling app has carrier privileges
- * (see {@link TelephonyManager#hasCarrierPrivileges}).
- *
- * @see CallDisconnectCauseChangedListener#onCallDisconnectCauseChanged
- *
- * @hide
- */
- @SystemApi
- @RequiresPermission(android.Manifest.permission.READ_PRECISE_PHONE_STATE)
- public static final int EVENT_CALL_DISCONNECT_CAUSE_CHANGED = 26;
-
- /**
- * Event for changes to the call attributes of a currently active call.
- *
- * <p>Requires permission {@link android.Manifest.permission#READ_PRECISE_PHONE_STATE}
- * or the calling app has carrier privileges
- * (see {@link TelephonyManager#hasCarrierPrivileges}).
- *
- * @see CallAttributesChangedListener#onCallAttributesChanged
+ * Listen for changes to the physical channel configuration.
*
+ * @see #onPhysicalChannelConfigurationChanged
* @hide
*/
@SystemApi
@RequiresPermission(android.Manifest.permission.READ_PRECISE_PHONE_STATE)
- public static final int EVENT_CALL_ATTRIBUTES_CHANGED = 27;
-
- /**
- * Event for IMS call disconnect causes which contains
- * {@link android.telephony.ims.ImsReasonInfo}
- *
- * <p>Requires permission {@link android.Manifest.permission#READ_PRECISE_PHONE_STATE}
- * or the calling app has carrier privileges
- * (see {@link TelephonyManager#hasCarrierPrivileges}).
- *
- * @see ImsCallDisconnectCauseChangedListener#onImsCallDisconnectCauseChanged(ImsReasonInfo)
- *
- * @hide
- */
- @SystemApi
- @RequiresPermission(android.Manifest.permission.READ_PRECISE_PHONE_STATE)
- public static final int EVENT_IMS_CALL_DISCONNECT_CAUSE_CHANGED = 28;
-
- /**
- * Event for the emergency number placed from an outgoing call.
- *
- * @see OutgoingEmergencyCallListener#onOutgoingEmergencyCall
- *
- * @hide
- */
- @SystemApi
- @RequiresPermission(Manifest.permission.READ_ACTIVE_EMERGENCY_SESSION)
- public static final int EVENT_OUTGOING_EMERGENCY_CALL = 29;
-
- /**
- * Event for the emergency number placed from an outgoing SMS.
- *
- * @see OutgoingEmergencySmsListener#onOutgoingEmergencySms
- *
- * @hide
- */
- @SystemApi
- @RequiresPermission(Manifest.permission.READ_ACTIVE_EMERGENCY_SESSION)
- public static final int EVENT_OUTGOING_EMERGENCY_SMS = 30;
-
- /**
- * Event for registration failures.
- *
- * Event for indications that a registration procedure has failed in either the CS or PS
- * domain. This indication does not necessarily indicate a change of service state, which should
- * be tracked via {@link #EVENT_SERVICE_STATE_CHANGED}.
- *
- * <p>Requires permission {@link android.Manifest.permission#READ_PRECISE_PHONE_STATE} or
- * the calling app has carrier privileges (see {@link TelephonyManager#hasCarrierPrivileges}).
- *
- * <p>Also requires the {@link Manifest.permission#ACCESS_FINE_LOCATION} permission, regardless
- * of whether the calling app has carrier privileges.
- *
- * @see RegistrationFailedListener#onRegistrationFailed
- *
- * @hide
- */
- @SystemApi
- @RequiresPermission(allOf = {
- Manifest.permission.READ_PRECISE_PHONE_STATE,
- Manifest.permission.ACCESS_FINE_LOCATION
- })
- public static final int EVENT_REGISTRATION_FAILURE = 31;
-
- /**
- * Event for Barring Information for the current registered / camped cell.
- *
- * <p>Requires permission {@link android.Manifest.permission#READ_PRECISE_PHONE_STATE} or
- * the calling app has carrier privileges (see {@link TelephonyManager#hasCarrierPrivileges}).
- *
- * <p>Also requires the {@link Manifest.permission#ACCESS_FINE_LOCATION} permission, regardless
- * of whether the calling app has carrier privileges.
- *
- * @see BarringInfoChangedListener#onBarringInfoChanged
- *
- * @hide
- */
- @SystemApi
- @RequiresPermission(allOf = {
- Manifest.permission.READ_PRECISE_PHONE_STATE,
- Manifest.permission.ACCESS_FINE_LOCATION
- })
- public static final int EVENT_BARRING_INFO_CHANGED = 32;
-
- /**
- * Event for changes to the physical channel configuration.
- *
- * <p>Requires permission {@link android.Manifest.permission#READ_PRECISE_PHONE_STATE}
- * or the calling app has carrier privileges
- * (see {@link TelephonyManager#hasCarrierPrivileges}).
- *
- * @see PhysicalChannelConfigChangedListener#onPhysicalChannelConfigChanged
- *
- * @hide
- */
- @SystemApi
- @RequiresPermission(Manifest.permission.READ_PRECISE_PHONE_STATE)
- public static final int EVENT_PHYSICAL_CHANNEL_CONFIG_CHANGED = 33;
-
-
- /**
- * Event for changes to the data enabled.
- *
- * Event for indications that the enabled status of current data has changed.
- *
- * <p>Requires permission {@link android.Manifest.permission#READ_PRECISE_PHONE_STATE}
- * or the calling app has carrier privileges
- * (see {@link TelephonyManager#hasCarrierPrivileges}).
- *
- * @see DataEnabledChangedListener#onDataEnabledChanged
- *
- * @hide
- */
- @SystemApi
- @RequiresPermission(Manifest.permission.READ_PRECISE_PHONE_STATE)
- public static final int EVENT_DATA_ENABLED_CHANGED = 34;
-
- /** @hide */
- @IntDef(prefix = { "EVENT_" }, value = {
- EVENT_SERVICE_STATE_CHANGED,
- EVENT_SIGNAL_STRENGTH_CHANGED,
- EVENT_MESSAGE_WAITING_INDICATOR_CHANGED,
- EVENT_CALL_FORWARDING_INDICATOR_CHANGED,
- EVENT_CELL_LOCATION_CHANGED,
- EVENT_CALL_STATE_CHANGED,
- EVENT_DATA_CONNECTION_STATE_CHANGED,
- EVENT_DATA_ACTIVITY_CHANGED,
- EVENT_SIGNAL_STRENGTHS_CHANGED,
- EVENT_ALWAYS_REPORTED_SIGNAL_STRENGTH_CHANGED,
- EVENT_CELL_INFO_CHANGED,
- EVENT_PRECISE_CALL_STATE_CHANGED,
- EVENT_PRECISE_DATA_CONNECTION_STATE_CHANGED,
- EVENT_DATA_CONNECTION_REAL_TIME_INFO_CHANGED,
- EVENT_OEM_HOOK_RAW,
- EVENT_SRVCC_STATE_CHANGED,
- EVENT_CARRIER_NETWORK_CHANGED,
- EVENT_VOICE_ACTIVATION_STATE_CHANGED,
- EVENT_DATA_ACTIVATION_STATE_CHANGED,
- EVENT_USER_MOBILE_DATA_STATE_CHANGED,
- EVENT_DISPLAY_INFO_CHANGED,
- EVENT_PHONE_CAPABILITY_CHANGED,
- EVENT_ACTIVE_DATA_SUBSCRIPTION_ID_CHANGED,
- EVENT_RADIO_POWER_STATE_CHANGED,
- EVENT_EMERGENCY_NUMBER_LIST_CHANGED,
- EVENT_CALL_DISCONNECT_CAUSE_CHANGED,
- EVENT_CALL_ATTRIBUTES_CHANGED,
- EVENT_IMS_CALL_DISCONNECT_CAUSE_CHANGED,
- EVENT_OUTGOING_EMERGENCY_CALL,
- EVENT_OUTGOING_EMERGENCY_SMS,
- EVENT_REGISTRATION_FAILURE,
- EVENT_BARRING_INFO_CHANGED,
- EVENT_PHYSICAL_CHANNEL_CONFIG_CHANGED,
- EVENT_DATA_ENABLED_CHANGED
- })
- @Retention(RetentionPolicy.SOURCE)
- public @interface TelephonyEvent {}
+ public static final long LISTEN_PHYSICAL_CHANNEL_CONFIGURATION = 0x100000000L;
/*
* Subscription used to listen to the phone state changes
@@ -1072,13 +504,9 @@ public class PhoneStateListener {
/**
* @hide
*/
- //TODO: The maxTargetSdk should be S if the build time tool updates it.
@VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
- @UnsupportedAppUsage(
- maxTargetSdk = Build.VERSION_CODES.R,
- publicAlternatives = "Use {@code TelephonyManager#registerPhoneStateListener(" +
- "Executor, PhoneStateListener)} instead")
- public IPhoneStateListener callback;
+ @UnsupportedAppUsage
+ public final IPhoneStateListener callback;
/**
* Create a PhoneStateListener for the Phone with the default subscription.
@@ -1135,737 +563,17 @@ public class PhoneStateListener {
* The Executor must not be null.
*
* @param executor a non-null Executor that will execute callbacks for the PhoneStateListener.
- * @deprecated Use
- * {@link TelephonyManager#registerPhoneStateListener(Executor, PhoneStateListener)} instead.
*/
- @Deprecated
public PhoneStateListener(@NonNull Executor executor) {
this(null, executor);
}
- /**
- * @hide
- */
- public void setExecutor(@NonNull @CallbackExecutor Executor executor) {
- if (executor == null) {
+ private PhoneStateListener(Integer subId, Executor e) {
+ if (e == null) {
throw new IllegalArgumentException("PhoneStateListener Executor must be non-null");
}
- callback = new IPhoneStateListenerStub(this, executor);
- }
-
- private PhoneStateListener(Integer subId, Executor e) {
- setExecutor(e);
mSubId = subId;
- }
-
- /**
- * Interface for service state listener.
- */
- public interface ServiceStateChangedListener {
- /**
- * Callback invoked when device service state changes on the registered subscription.
- * Note, the registration subscription ID comes from {@link TelephonyManager} object
- * which registers PhoneStateListener by
- * {@link TelephonyManager#registerPhoneStateListener(Executor, PhoneStateListener)}.
- * If this TelephonyManager object was created with
- * {@link TelephonyManager#createForSubscriptionId(int)}, then the callback applies to the
- * subscription ID. Otherwise, this callback applies to
- * {@link SubscriptionManager#getDefaultSubscriptionId()}.
- *
- * The instance of {@link ServiceState} passed as an argument here will have various
- * levels of location information stripped from it depending on the location permissions
- * that your app holds.
- * Only apps holding the {@link Manifest.permission#ACCESS_FINE_LOCATION} permission will
- * receive all the information in {@link ServiceState}.
- *
- * @see ServiceState#STATE_EMERGENCY_ONLY
- * @see ServiceState#STATE_IN_SERVICE
- * @see ServiceState#STATE_OUT_OF_SERVICE
- * @see ServiceState#STATE_POWER_OFF
- */
- @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
- public void onServiceStateChanged(@NonNull ServiceState serviceState);
- }
-
- /**
- * Interface for message waiting indicator listener.
- */
- public interface MessageWaitingIndicatorChangedListener {
- /**
- * Callback invoked when the message-waiting indicator changes on the registered
- * subscription.
- * Note, the registration subscription ID comes from {@link TelephonyManager} object by
- * {@link TelephonyManager#registerPhoneStateListener(Executor, PhoneStateListener)}.
- * If this TelephonyManager object was created with
- * {@link TelephonyManager#createForSubscriptionId(int)}, then the callback applies to the
- * subscription ID. Otherwise, this callback applies to
- * {@link SubscriptionManager#getDefaultSubscriptionId()}.
- */
- @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
- public void onMessageWaitingIndicatorChanged(boolean mwi);
- }
-
- /**
- * Interface for call-forwarding indicator listener.
- */
- public interface CallForwardingIndicatorChangedListener {
- /**
- * Callback invoked when the call-forwarding indicator changes on the registered
- * subscription.
- * Note, the registration subscription ID comes from {@link TelephonyManager} object
- * which registers PhoneStateListener by
- * {@link TelephonyManager#registerPhoneStateListener(Executor, PhoneStateListener)}.
- * If this TelephonyManager object was created with
- * {@link TelephonyManager#createForSubscriptionId(int)}, then the callback applies to the
- * subscription ID. Otherwise, this callback applies to
- * {@link SubscriptionManager#getDefaultSubscriptionId()}.
- */
- @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
- public void onCallForwardingIndicatorChanged(boolean cfi);
- }
-
- /**
- * Interface for device cell location listener.
- */
- public interface CellLocationChangedListener {
- /**
- * Callback invoked when device cell location changes on the registered subscription.
- * Note, the registration subscription ID comes from {@link TelephonyManager} object
- * which registers PhoneStateListener by
- * {@link TelephonyManager#registerPhoneStateListener(Executor, PhoneStateListener)}.
- * If this TelephonyManager object was created with
- * {@link TelephonyManager#createForSubscriptionId(int)}, then the callback applies to the
- * subscription ID. Otherwise, this callback applies to
- * {@link SubscriptionManager#getDefaultSubscriptionId()}.
- */
- @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION)
- public void onCellLocationChanged(@NonNull CellLocation location);
- }
-
- /**
- * Interface for call state listener.
- */
- public interface CallStateChangedListener {
- /**
- * Callback invoked when device call state changes.
- * <p>
- * Reports the state of Telephony (mobile) calls on the device for the registered s
- * ubscription.
- * <p>
- * Note: the registration subscription ID comes from {@link TelephonyManager} object
- * which registers PhoneStateListener by
- * {@link TelephonyManager#registerPhoneStateListener(Executor, PhoneStateListener)}.
- * If this TelephonyManager object was created with
- * {@link TelephonyManager#createForSubscriptionId(int)}, then the callback applies to the
- * subscription ID. Otherwise, this callback applies to
- * {@link SubscriptionManager#getDefaultSubscriptionId()}.
- * <p>
- * Note: The state returned here may differ from that returned by
- * {@link TelephonyManager#getCallState()}. Receivers of this callback should be aware that
- * calling {@link TelephonyManager#getCallState()} from within this callback may return a
- * different state than the callback reports.
- *
- * @param state call state
- * @param phoneNumber call phone number. If application does not have
- * {@link android.Manifest.permission#READ_CALL_LOG} permission or carrier
- * privileges (see {@link TelephonyManager#hasCarrierPrivileges}), an empty string will be
- * passed as an argument.
- */
- @RequiresPermission(android.Manifest.permission.READ_CALL_LOG)
- public void onCallStateChanged(@CallState int state, @Nullable String phoneNumber);
- }
-
- /**
- * Interface for data connection state listener.
- */
- public interface DataConnectionStateChangedListener {
- /**
- * Callback invoked when connection state changes on the registered subscription.
- * Note, the registration subscription ID comes from {@link TelephonyManager} object
- * which registers PhoneStateListener by
- * {@link TelephonyManager#registerPhoneStateListener(Executor, PhoneStateListener)}.
- * If this TelephonyManager object was created with
- * {@link TelephonyManager#createForSubscriptionId(int)}, then the callback applies to the
- * subscription ID. Otherwise, this callback applies to
- * {@link SubscriptionManager#getDefaultSubscriptionId()}.
- *
- * @see TelephonyManager#DATA_DISCONNECTED
- * @see TelephonyManager#DATA_CONNECTING
- * @see TelephonyManager#DATA_CONNECTED
- * @see TelephonyManager#DATA_SUSPENDED
- *
- * @param state is the current state of data connection.
- * @param networkType is the current network type of data connection.
- */
- @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
- public void onDataConnectionStateChanged(@DataState int state,
- @NetworkType int networkType);
- }
-
- /**
- * Interface for data activity state listener.
- */
- public interface DataActivityListener {
- /**
- * Callback invoked when data activity state changes on the registered subscription.
- * Note, the registration subscription ID comes from {@link TelephonyManager} object
- * which registers PhoneStateListener by
- * {@link TelephonyManager#registerPhoneStateListener(Executor, PhoneStateListener)}.
- * If this TelephonyManager object was created with
- * {@link TelephonyManager#createForSubscriptionId(int)}, then the callback applies to the
- * subscription ID. Otherwise, this callback applies to
- * {@link SubscriptionManager#getDefaultSubscriptionId()}.
- *
- * @see TelephonyManager#DATA_ACTIVITY_NONE
- * @see TelephonyManager#DATA_ACTIVITY_IN
- * @see TelephonyManager#DATA_ACTIVITY_OUT
- * @see TelephonyManager#DATA_ACTIVITY_INOUT
- * @see TelephonyManager#DATA_ACTIVITY_DORMANT
- */
- @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
- public void onDataActivity(@DataActivityType int direction);
- }
-
- /**
- * Interface for network signal strengths listener.
- */
- public interface SignalStrengthsChangedListener {
- /**
- * Callback invoked when network signal strengths changes on the registered subscription.
- * Note, the registration subscription ID comes from {@link TelephonyManager} object
- * which registers PhoneStateListener by
- * {@link TelephonyManager#registerPhoneStateListener(Executor, PhoneStateListener)}.
- * If this TelephonyManager object was created with
- * {@link TelephonyManager#createForSubscriptionId(int)}, then the callback applies to the
- * subscription ID. Otherwise, this callback applies to
- * {@link SubscriptionManager#getDefaultSubscriptionId()}.
- */
- @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
- public void onSignalStrengthsChanged(@NonNull SignalStrength signalStrength);
- }
-
- /**
- * Interface for network signal strengths listener which always reported from modem.
- */
- public interface AlwaysReportedSignalStrengthsChangedListener {
- /**
- * Callback always invoked from modem when network signal strengths changes on the
- * registered subscription.
- * Note, the registration subscription ID comes from {@link TelephonyManager} object
- * which registers PhoneStateListener by
- * {@link TelephonyManager#registerPhoneStateListener(Executor, PhoneStateListener)}.
- * If this TelephonyManager object was created with
- * {@link TelephonyManager#createForSubscriptionId(int)}, then the callback applies to the
- * subscription ID. Otherwise, this callback applies to
- * {@link SubscriptionManager#getDefaultSubscriptionId()}.
- */
- @RequiresPermission(android.Manifest.permission.LISTEN_ALWAYS_REPORTED_SIGNAL_STRENGTH)
- public void onSignalStrengthsChanged(@NonNull SignalStrength signalStrength);
- }
-
- /**
- * Interface for cell info listener.
- */
- public interface CellInfoChangedListener {
- /**
- * Callback invoked when a observed cell info has changed or new cells have been added
- * or removed on the registered subscription.
- * Note, the registration subscription ID s from {@link TelephonyManager} object
- * which registersPhoneStateListener by
- * {@link TelephonyManager#registerPhoneStateListener(Executor, PhoneStateListener)}.
- * If this TelephonyManager object was created with
- * {@link TelephonyManager#createForSubscriptionId(int)}, then the callback applies to the
- * subscription ID. Otherwise, this callback applies to
- * {@link SubscriptionManager#getDefaultSubscriptionId()}.
- *
- * @param cellInfo is the list of currently visible cells.
- */
- @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION)
- public void onCellInfoChanged(@NonNull List<CellInfo> cellInfo);
- }
-
- /**
- * Interface for precise device call state listener.
- *
- * @hide
- */
- @SystemApi
- public interface PreciseCallStateChangedListener {
- /**
- * Callback invoked when precise device call state changes on the registered subscription.
- * Note, the registration subscription ID comes from {@link TelephonyManager} object
- * which registers PhoneStateListener by
- * {@link TelephonyManager#registerPhoneStateListener(Executor, PhoneStateListener)}.
- * If this TelephonyManager object was created with
- * {@link TelephonyManager#createForSubscriptionId(int)}, then the callback applies to the
- * subscription ID. Otherwise, this callback applies to
- * {@link SubscriptionManager#getDefaultSubscriptionId()}.
- *
- * @param callState {@link PreciseCallState}
- */
- @RequiresPermission(android.Manifest.permission.READ_PRECISE_PHONE_STATE)
- public void onPreciseCallStateChanged(@NonNull PreciseCallState callState);
- }
-
- /**
- * Interface for call disconnect cause listener.
- */
- public interface CallDisconnectCauseChangedListener {
- /**
- * Callback invoked when call disconnect cause changes on the registered subscription.
- * Note, the registration subscription ID comes from {@link TelephonyManager} object
- * which registers PhoneStateListener by
- * {@link TelephonyManager#registerPhoneStateListener(Executor, PhoneStateListener)}.
- * If this TelephonyManager object was created with
- * {@link TelephonyManager#createForSubscriptionId(int)}, then the callback applies to the
- * subscription ID. Otherwise, this callback applies to
- * {@link SubscriptionManager#getDefaultSubscriptionId()}.
- *
- * @param disconnectCause {@link DisconnectCause}.
- * @param preciseDisconnectCause {@link PreciseDisconnectCause}.
- */
- @RequiresPermission(android.Manifest.permission.READ_PRECISE_PHONE_STATE)
- public void onCallDisconnectCauseChanged(@DisconnectCauses int disconnectCause,
- @PreciseDisconnectCauses int preciseDisconnectCause);
- }
-
- /**
- * Interface for IMS call disconnect cause listener.
- */
- public interface ImsCallDisconnectCauseChangedListener {
- /**
- * Callback invoked when IMS call disconnect cause changes on the registered subscription.
- * Note, the registration subscription ID comes from {@link TelephonyManager} object
- * which registers PhoneStateListener by
- * {@link TelephonyManager#registerPhoneStateListener(Executor, PhoneStateListener)}.
- * If this TelephonyManager object was created with
- * {@link TelephonyManager#createForSubscriptionId(int)}, then the callback applies to the
- * subscription ID. Otherwise, this callback applies to
- * {@link SubscriptionManager#getDefaultSubscriptionId()}.
- *
- * @param imsReasonInfo {@link ImsReasonInfo} contains details on why IMS call failed.
- *
- */
- @RequiresPermission(android.Manifest.permission.READ_PRECISE_PHONE_STATE)
- public void onImsCallDisconnectCauseChanged(@NonNull ImsReasonInfo imsReasonInfo);
- }
-
- /**
- * Interface for precise data connection state listener.
- */
- public interface PreciseDataConnectionStateChangedListener {
- /**
- * Callback providing update about the default/internet data connection on the registered
- * subscription.
- *
- * Note, the registration subscription ID comes from {@link TelephonyManager} object
- * which registers PhoneStateListener by
- * {@link TelephonyManager#registerPhoneStateListener(Executor, PhoneStateListener)}.
- * If this TelephonyManager object was created with
- * {@link TelephonyManager#createForSubscriptionId(int)}, then the callback applies to the
- * subscription ID. Otherwise, this callback applies to
- * {@link SubscriptionManager#getDefaultSubscriptionId()}.
- *
- * <p>Requires permission {@link android.Manifest.permission#READ_PRECISE_PHONE_STATE}
- * or the calling app has carrier privileges
- * (see {@link TelephonyManager#hasCarrierPrivileges}).
- *
- * @param dataConnectionState {@link PreciseDataConnectionState}
- */
- @RequiresPermission(android.Manifest.permission.READ_PRECISE_PHONE_STATE)
- public void onPreciseDataConnectionStateChanged(
- @NonNull PreciseDataConnectionState dataConnectionState);
- }
-
- /**
- * Interface for Single Radio Voice Call Continuity listener.
- *
- * @hide
- */
- @SystemApi
- public interface SrvccStateChangedListener {
- /**
- * Callback invoked when there has been a change in the Single Radio Voice Call Continuity
- * (SRVCC) state for the currently active call on the registered subscription.
- *
- * Note, the registration subscription ID comes from {@link TelephonyManager} object
- * which registers PhoneStateListener by
- * {@link TelephonyManager#registerPhoneStateListener(Executor, PhoneStateListener)}.
- * If this TelephonyManager object was created with
- * {@link TelephonyManager#createForSubscriptionId(int)}, then the callback applies to the
- * subscription ID. Otherwise, this callback applies to
- * {@link SubscriptionManager#getDefaultSubscriptionId()}.
- */
- @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
- public void onSrvccStateChanged(@SrvccState int srvccState);
- }
-
- /**
- * Interface for SIM voice activation state listener.
- *
- * @hide
- */
- @SystemApi
- public interface VoiceActivationStateChangedListener {
- /**
- * Callback invoked when the SIM voice activation state has changed on the registered
- * subscription.
- * Note, the registration subscription ID comes from {@link TelephonyManager} object
- * which registers PhoneStateListener by
- * {@link TelephonyManager#registerPhoneStateListener(Executor, PhoneStateListener)}.
- * If this TelephonyManager object was created with
- * {@link TelephonyManager#createForSubscriptionId(int)}, then the callback applies to the
- * subscription ID. Otherwise, this callback applies to
- * {@link SubscriptionManager#getDefaultSubscriptionId()}.
- *
- * @param state is the current SIM voice activation state
- */
- @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
- public void onVoiceActivationStateChanged(@SimActivationState int state);
-
- }
-
- /**
- * Interface for SIM data activation state listener.
- */
- public interface DataActivationStateChangedListener {
- /**
- * Callback invoked when the SIM data activation state has changed on the registered
- * subscription.
- * Note, the registration subscription ID comes from {@link TelephonyManager} object
- * which registers PhoneStateListener by
- * {@link TelephonyManager#registerPhoneStateListener(Executor, PhoneStateListener)}.
- * If this TelephonyManager object was created with
- * {@link TelephonyManager#createForSubscriptionId(int)}, then the callback applies to the
- * subscription ID. Otherwise, this callback applies to
- * {@link SubscriptionManager#getDefaultSubscriptionId()}.
- *
- * @param state is the current SIM data activation state
- */
- @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
- public void onDataActivationStateChanged(@SimActivationState int state);
- }
-
- /**
- * Interface for user mobile data state listener.
- */
- public interface UserMobileDataStateChangedListener {
- /**
- * Callback invoked when the user mobile data state has changed on the registered
- * subscription.
- * Note, the registration subscription ID comes from {@link TelephonyManager} object
- * which registers PhoneStateListener by
- * {@link TelephonyManager#registerPhoneStateListener(Executor, PhoneStateListener)}.
- * If this TelephonyManager object was created with
- * {@link TelephonyManager#createForSubscriptionId(int)}, then the callback applies to the
- * subscription ID. Otherwise, this callback applies to
- * {@link SubscriptionManager#getDefaultSubscriptionId()}.
- *
- * @param enabled indicates whether the current user mobile data state is enabled or
- * disabled.
- */
- @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
- public void onUserMobileDataStateChanged(boolean enabled);
- }
-
- /**
- * Interface for display info listener.
- */
- public interface DisplayInfoChangedListener {
- /**
- * Callback invoked when the display info has changed on the registered subscription.
- * <p> The {@link TelephonyDisplayInfo} contains status information shown to the user
- * based on carrier policy.
- *
- * @param telephonyDisplayInfo The display information.
- */
- @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
- public void onDisplayInfoChanged(@NonNull TelephonyDisplayInfo telephonyDisplayInfo);
- }
-
- /**
- * Interface for the current emergency number list listener.
- */
- public interface EmergencyNumberListChangedListener {
- /**
- * Callback invoked when the current emergency number list has changed on the registered
- * subscription.
- *
- * Note, the registered subscription is associated with {@link TelephonyManager} object
- * on which
- * {@link TelephonyManager#registerPhoneStateListener(Executor, PhoneStateListener)}
- * was called.
- * If this TelephonyManager object was created with
- * {@link TelephonyManager#createForSubscriptionId(int)}, then the callback applies to the
- * given subscription ID. Otherwise, this callback applies to
- * {@link SubscriptionManager#getDefaultSubscriptionId()}.
- *
- * @param emergencyNumberList Map associating all active subscriptions on the device with
- * the list of emergency numbers originating from that
- * subscription.
- * If there are no active subscriptions, the map will contain a
- * single entry with
- * {@link SubscriptionManager#INVALID_SUBSCRIPTION_ID} as
- * the key and a list of emergency numbers as the value. If no
- * emergency number information is available, the value will be
- * empty.
- */
- @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
- public void onEmergencyNumberListChanged(
- @NonNull Map<Integer, List<EmergencyNumber>> emergencyNumberList);
- }
-
- /**
- * Interface for outgoing emergency call listener.
- *
- * @hide
- */
- @SystemApi
- public interface OutgoingEmergencyCallListener {
- /**
- * Callback invoked when an outgoing call is placed to an emergency number.
- *
- * This method will be called when an emergency call is placed on any subscription
- * (including the no-SIM case), regardless of which subscription this listener was
- * registered on.
- *
- * The default implementation of this method calls
- * {@link #onOutgoingEmergencyCall(EmergencyNumber)} for backwards compatibility purposes.
- * Do not call {@code super(...)} from within your implementation unless you want
- * {@link #onOutgoingEmergencyCall(EmergencyNumber)} to be called as well.
- *
- * @param placedEmergencyNumber The {@link EmergencyNumber} the emergency call was
- * placed to.
- * @param subscriptionId The subscription ID used to place the emergency call. If the
- * emergency call was placed without a valid subscription
- * (e.g. when there are no SIM cards in the device), this will be
- * equal to {@link SubscriptionManager#INVALID_SUBSCRIPTION_ID}.
- */
- @RequiresPermission(Manifest.permission.READ_ACTIVE_EMERGENCY_SESSION)
- public void onOutgoingEmergencyCall(@NonNull EmergencyNumber placedEmergencyNumber,
- int subscriptionId);
- }
-
- /**
- * Interface for outgoing emergency sms listener.
- *
- * @hide
- */
- @SystemApi
- public interface OutgoingEmergencySmsListener {
- /**
- * Smsback invoked when an outgoing sms is sent to an emergency number.
- *
- * This method will be called when an emergency sms is sent on any subscription,
- * regardless of which subscription this listener was registered on.
- *
- * The default implementation of this method calls
- * {@link #onOutgoingEmergencySms(EmergencyNumber)} for backwards compatibility purposes. Do
- * not call {@code super(...)} from within your implementation unless you want
- * {@link #onOutgoingEmergencySms(EmergencyNumber)} to be called as well.
- *
- * @param sentEmergencyNumber The {@link EmergencyNumber} the emergency sms was sent to.
- * @param subscriptionId The subscription ID used to send the emergency sms.
- */
- @RequiresPermission(Manifest.permission.READ_ACTIVE_EMERGENCY_SESSION)
- public void onOutgoingEmergencySms(@NonNull EmergencyNumber sentEmergencyNumber,
- int subscriptionId);
- }
-
- /**
- * Interface for phone capability listener.
- *
- */
- public interface PhoneCapabilityChangedListener {
- /**
- * Callback invoked when phone capability changes.
- * Note, this callback triggers regardless of registered subscription.
- *
- * @param capability the new phone capability
- */
- @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
- public void onPhoneCapabilityChanged(@NonNull PhoneCapability capability);
- }
-
- /**
- * Interface for active data subscription ID listener.
- */
- public interface ActiveDataSubscriptionIdChangedListener {
- /**
- * Callback invoked when active data subscription ID changes.
- * Note, this callback triggers regardless of registered subscription.
- *
- * @param subId current subscription used to setup Cellular Internet data.
- * For example, it could be the current active opportunistic subscription
- * in use, or the subscription user selected as default data subscription in
- * DSDS mode.
- */
- @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
- public void onActiveDataSubscriptionIdChanged(int subId);
- }
-
- /**
- * Interface for modem radio power state listener.
- *
- * @hide
- */
- @SystemApi
- public interface RadioPowerStateChangedListener {
- /**
- * Callback invoked when modem radio power state changes on the registered subscription.
- * Note, the registration subscription ID comes from {@link TelephonyManager} object
- * which registers PhoneStateListener by
- * {@link TelephonyManager#registerPhoneStateListener(Executor, PhoneStateListener)}.
- * If this TelephonyManager object was created with
- * {@link TelephonyManager#createForSubscriptionId(int)}, then the callback applies to the
- * subscription ID. Otherwise, this callback applies to
- * {@link SubscriptionManager#getDefaultSubscriptionId()}.
- *
- * @param state the modem radio power state
- */
- @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
- public void onRadioPowerStateChanged(@RadioPowerState int state);
- }
-
- /**
- * Interface for carrier network listener.
- */
- public interface CarrierNetworkChangeListener {
- /**
- * Callback invoked when telephony has received notice from a carrier
- * app that a network action that could result in connectivity loss
- * has been requested by an app using
- * {@link android.service.carrier.CarrierService#notifyCarrierNetworkChange(boolean)}
- *
- * This is optional and is only used to allow the system to provide alternative UI while
- * telephony is performing an action that may result in intentional, temporary network
- * lack of connectivity.
- *
- * Note, this callback is pinned to the registered subscription and will be invoked when
- * the notifying carrier app has carrier privilege rule on the registered
- * subscription. {@link android.telephony.TelephonyManager#hasCarrierPrivileges}
- *
- * @param active If the carrier network change is or shortly will be active,
- * {@code true} indicate that showing alternative UI, {@code false} otherwise.
- */
- public void onCarrierNetworkChange(boolean active);
- }
-
- /**
- * Interface for registration failures listener.
- */
- public interface RegistrationFailedListener {
- /**
- * Report that Registration or a Location/Routing/Tracking Area update has failed.
- *
- * <p>Indicate whenever a registration procedure, including a location, routing, or tracking
- * area update fails. This includes procedures that do not necessarily result in a change of
- * the modem's registration status. If the modem's registration status changes, that is
- * reflected in the onNetworkStateChanged() and subsequent
- * get{Voice/Data}RegistrationState().
- *
- * <p>Because registration failures are ephemeral, this callback is not sticky.
- * Registrants will not receive the most recent past value when registering.
- *
- * @param cellIdentity the CellIdentity, which must include the globally unique identifier
- * for the cell (for example, all components of the CGI or ECGI).
- * @param chosenPlmn a 5 or 6 digit alphanumeric PLMN (MCC|MNC) among those broadcast by the
- * cell that was chosen for the failed registration attempt.
- * @param domain DOMAIN_CS, DOMAIN_PS or both in case of a combined procedure.
- * @param causeCode the primary failure cause code of the procedure.
- * For GSM/UMTS (MM), values are in TS 24.008 Sec 10.5.95
- * For GSM/UMTS (GMM), values are in TS 24.008 Sec 10.5.147
- * For LTE (EMM), cause codes are TS 24.301 Sec 9.9.3.9
- * For NR (5GMM), cause codes are TS 24.501 Sec 9.11.3.2
- * Integer.MAX_VALUE if this value is unused.
- * @param additionalCauseCode the cause code of any secondary/combined procedure
- * if appropriate. For UMTS, if a combined attach succeeds for
- * PS only, then the GMM cause code shall be included as an
- * additionalCauseCode. For LTE (ESM), cause codes are in
- * TS 24.301 9.9.4.4. Integer.MAX_VALUE if this value is unused.
- */
- @RequiresPermission(allOf = {
- Manifest.permission.READ_PRECISE_PHONE_STATE,
- Manifest.permission.ACCESS_FINE_LOCATION
- })
- public void onRegistrationFailed(@NonNull CellIdentity cellIdentity,
- @NonNull String chosenPlmn, @Domain int domain,
- int causeCode, int additionalCauseCode);
- }
-
- /**
- * Interface for call attributes listener.
- *
- * @hide
- */
- @SystemApi
- public interface CallAttributesChangedListener {
- /**
- * Callback invoked when the call attributes changes on the registered subscription.
- * Note, the registration subscription ID comes from {@link TelephonyManager} object
- * which registers PhoneStateListener by
- * {@link TelephonyManager#registerPhoneStateListener(Executor, PhoneStateListener)}.
- * If this TelephonyManager object was created with
- * {@link TelephonyManager#createForSubscriptionId(int)}, then the callback applies to the
- * subscription ID. Otherwise, this callback applies to
- * {@link SubscriptionManager#getDefaultSubscriptionId()}.
- *
- * @param callAttributes the call attributes
- */
- @RequiresPermission(Manifest.permission.READ_PRECISE_PHONE_STATE)
- void onCallAttributesChanged(@NonNull CallAttributes callAttributes);
- }
-
- /**
- * Interface for barring information listener.
- */
- public interface BarringInfoChangedListener {
- /**
- * Report updated barring information for the current camped/registered cell.
- *
- * <p>Barring info is provided for all services applicable to the current camped/registered
- * cell, for the registered PLMN and current access class/access category.
- *
- * @param barringInfo for all services on the current cell.
- * @see android.telephony.BarringInfo
- */
- @RequiresPermission(allOf = {
- Manifest.permission.READ_PRECISE_PHONE_STATE,
- Manifest.permission.ACCESS_FINE_LOCATION
- })
- public void onBarringInfoChanged(@NonNull BarringInfo barringInfo);
- }
-
- /**
- * Interface for current physical channel configuration listener.
- */
- public interface PhysicalChannelConfigChangedListener {
- /**
- * Callback invoked when the current physical channel configuration has changed
- *
- * @param configs List of the current {@link PhysicalChannelConfig}s
- */
- @RequiresPermission(Manifest.permission.READ_PRECISE_PHONE_STATE)
- public void onPhysicalChannelConfigChanged(@NonNull List<PhysicalChannelConfig> configs);
- }
-
- /**
- * Interface for data enabled listener.
- *
- * @hide
- */
- @SystemApi
- public interface DataEnabledChangedListener {
- /**
- * Callback invoked when the data enabled changes.
- *
- * @param enabled {@code true} if data is enabled, otherwise disabled.
- * @param reason Reason for data enabled/disabled.
- * See {@link TelephonyManager.DataEnabledReason}.
- */
- @RequiresPermission(Manifest.permission.READ_PRECISE_PHONE_STATE)
- public void onDataEnabledChanged(boolean enabled,
- @DataEnabledReason int reason);
+ callback = new IPhoneStateListenerStub(this, e);
}
/**
@@ -1999,7 +707,6 @@ public class PhoneStateListener {
* same as above, but with the network type. Both called.
*/
public void onDataConnectionStateChanged(int state, int networkType) {
- // default implementation empty
}
/**
@@ -2047,7 +754,6 @@ public class PhoneStateListener {
* @param cellInfo is the list of currently visible cells.
*/
public void onCellInfoChanged(List<CellInfo> cellInfo) {
- // default implementation empty
}
/**
@@ -2061,7 +767,7 @@ public class PhoneStateListener {
* @param callState {@link PreciseCallState}
* @hide
*/
- @RequiresPermission(android.Manifest.permission.READ_PRECISE_PHONE_STATE)
+ @RequiresPermission((android.Manifest.permission.READ_PRECISE_PHONE_STATE))
@SystemApi
public void onPreciseCallStateChanged(@NonNull PreciseCallState callState) {
// default implementation empty
@@ -2080,9 +786,9 @@ public class PhoneStateListener {
* @param preciseDisconnectCause {@link PreciseDisconnectCause}.
*
*/
- @RequiresPermission(android.Manifest.permission.READ_PRECISE_PHONE_STATE)
- public void onCallDisconnectCauseChanged(@DisconnectCauses int disconnectCause,
- @PreciseDisconnectCauses int preciseDisconnectCause) {
+ @RequiresPermission((android.Manifest.permission.READ_PRECISE_PHONE_STATE))
+ public void onCallDisconnectCauseChanged(@Annotation.DisconnectCauses int disconnectCause,
+ int preciseDisconnectCause) {
// default implementation empty
}
@@ -2098,7 +804,7 @@ public class PhoneStateListener {
* @param imsReasonInfo {@link ImsReasonInfo} contains details on why IMS call failed.
*
*/
- @RequiresPermission(android.Manifest.permission.READ_PRECISE_PHONE_STATE)
+ @RequiresPermission((android.Manifest.permission.READ_PRECISE_PHONE_STATE))
public void onImsCallDisconnectCauseChanged(@NonNull ImsReasonInfo imsReasonInfo) {
// default implementation empty
}
@@ -2120,7 +826,7 @@ public class PhoneStateListener {
*
* @param dataConnectionState {@link PreciseDataConnectionState}
*/
- @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
+ @RequiresPermission((android.Manifest.permission.MODIFY_PHONE_STATE))
public void onPreciseDataConnectionStateChanged(
@NonNull PreciseDataConnectionState dataConnectionState) {
// default implementation empty
@@ -2158,7 +864,6 @@ public class PhoneStateListener {
*/
@SystemApi
public void onSrvccStateChanged(@SrvccState int srvccState) {
- // default implementation empty
}
@@ -2177,7 +882,6 @@ public class PhoneStateListener {
*/
@SystemApi
public void onVoiceActivationStateChanged(@SimActivationState int state) {
- // default implementation empty
}
/**
@@ -2194,7 +898,6 @@ public class PhoneStateListener {
* @hide
*/
public void onDataActivationStateChanged(@SimActivationState int state) {
- // default implementation empty
}
/**
@@ -2222,7 +925,7 @@ public class PhoneStateListener {
*
* @param telephonyDisplayInfo The display information.
*/
- @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
+ @RequiresPermission((android.Manifest.permission.READ_PHONE_STATE))
public void onDisplayInfoChanged(@NonNull TelephonyDisplayInfo telephonyDisplayInfo) {
// default implementation empty
}
@@ -2355,7 +1058,7 @@ public class PhoneStateListener {
* @param capability the new phone capability
* @hide
*/
- public void onPhoneCapabilityChanged(@NonNull PhoneCapability capability) {
+ public void onPhoneCapabilityChanged(PhoneCapability capability) {
// default implementation empty
}
@@ -2399,8 +1102,7 @@ public class PhoneStateListener {
* subId. Otherwise, this callback applies to
* {@link SubscriptionManager#getDefaultSubscriptionId()}.
*
- * Requires permission {@link android.Manifest.permission#READ_PRIVILEGED_PHONE_STATE}
- *
+ * @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE}
* @param state the modem radio power state
* @hide
*/
@@ -2476,6 +1178,18 @@ public class PhoneStateListener {
}
/**
+ * Callback invoked when the current physical channel configuration has changed
+ *
+ * @param configs List of the current {@link PhysicalChannelConfig}s
+ * @hide
+ */
+ @SystemApi
+ public void onPhysicalChannelConfigurationChanged(
+ @NonNull List<PhysicalChannelConfig> configs) {
+ // default implementation empty
+ }
+
+ /**
* The callback methods need to be called on the handler thread where
* this object was created. If the binder did that for us it'd be nice.
*
@@ -2498,6 +1212,7 @@ public class PhoneStateListener {
public void onServiceStateChanged(ServiceState serviceState) {
PhoneStateListener psl = mPhoneStateListenerWeakRef.get();
if (psl == null) return;
+
Binder.withCleanCallingIdentity(
() -> mExecutor.execute(() -> psl.onServiceStateChanged(serviceState)));
}
@@ -2505,6 +1220,7 @@ public class PhoneStateListener {
public void onSignalStrengthChanged(int asu) {
PhoneStateListener psl = mPhoneStateListenerWeakRef.get();
if (psl == null) return;
+
Binder.withCleanCallingIdentity(
() -> mExecutor.execute(() -> psl.onSignalStrengthChanged(asu)));
}
@@ -2512,6 +1228,7 @@ public class PhoneStateListener {
public void onMessageWaitingIndicatorChanged(boolean mwi) {
PhoneStateListener psl = mPhoneStateListenerWeakRef.get();
if (psl == null) return;
+
Binder.withCleanCallingIdentity(
() -> mExecutor.execute(() -> psl.onMessageWaitingIndicatorChanged(mwi)));
}
@@ -2519,6 +1236,7 @@ public class PhoneStateListener {
public void onCallForwardingIndicatorChanged(boolean cfi) {
PhoneStateListener psl = mPhoneStateListenerWeakRef.get();
if (psl == null) return;
+
Binder.withCleanCallingIdentity(
() -> mExecutor.execute(() -> psl.onCallForwardingIndicatorChanged(cfi)));
}
@@ -2530,6 +1248,7 @@ public class PhoneStateListener {
cellIdentity == null ? CellLocation.getEmpty() : cellIdentity.asCellLocation();
PhoneStateListener psl = mPhoneStateListenerWeakRef.get();
if (psl == null) return;
+
Binder.withCleanCallingIdentity(
() -> mExecutor.execute(() -> psl.onCellLocationChanged(location)));
}
@@ -2537,6 +1256,7 @@ public class PhoneStateListener {
public void onCallStateChanged(int state, String incomingNumber) {
PhoneStateListener psl = mPhoneStateListenerWeakRef.get();
if (psl == null) return;
+
Binder.withCleanCallingIdentity(
() -> mExecutor.execute(() -> psl.onCallStateChanged(state, incomingNumber)));
}
@@ -2544,6 +1264,7 @@ public class PhoneStateListener {
public void onDataConnectionStateChanged(int state, int networkType) {
PhoneStateListener psl = mPhoneStateListenerWeakRef.get();
if (psl == null) return;
+
if (state == TelephonyManager.DATA_DISCONNECTING
&& VMRuntime.getRuntime().getTargetSdkVersion() < Build.VERSION_CODES.R) {
Binder.withCleanCallingIdentity(() -> mExecutor.execute(
@@ -2564,6 +1285,7 @@ public class PhoneStateListener {
public void onDataActivity(int direction) {
PhoneStateListener psl = mPhoneStateListenerWeakRef.get();
if (psl == null) return;
+
Binder.withCleanCallingIdentity(
() -> mExecutor.execute(() -> psl.onDataActivity(direction)));
}
@@ -2571,6 +1293,7 @@ public class PhoneStateListener {
public void onSignalStrengthsChanged(SignalStrength signalStrength) {
PhoneStateListener psl = mPhoneStateListenerWeakRef.get();
if (psl == null) return;
+
Binder.withCleanCallingIdentity(
() -> mExecutor.execute(() -> psl.onSignalStrengthsChanged(signalStrength)));
}
@@ -2578,6 +1301,7 @@ public class PhoneStateListener {
public void onCellInfoChanged(List<CellInfo> cellInfo) {
PhoneStateListener psl = mPhoneStateListenerWeakRef.get();
if (psl == null) return;
+
Binder.withCleanCallingIdentity(
() -> mExecutor.execute(() -> psl.onCellInfoChanged(cellInfo)));
}
@@ -2585,6 +1309,7 @@ public class PhoneStateListener {
public void onPreciseCallStateChanged(PreciseCallState callState) {
PhoneStateListener psl = mPhoneStateListenerWeakRef.get();
if (psl == null) return;
+
Binder.withCleanCallingIdentity(
() -> mExecutor.execute(() -> psl.onPreciseCallStateChanged(callState)));
}
@@ -2592,6 +1317,7 @@ public class PhoneStateListener {
public void onCallDisconnectCauseChanged(int disconnectCause, int preciseDisconnectCause) {
PhoneStateListener psl = mPhoneStateListenerWeakRef.get();
if (psl == null) return;
+
Binder.withCleanCallingIdentity(
() -> mExecutor.execute(() -> psl.onCallDisconnectCauseChanged(
disconnectCause, preciseDisconnectCause)));
@@ -2601,6 +1327,7 @@ public class PhoneStateListener {
PreciseDataConnectionState dataConnectionState) {
PhoneStateListener psl = mPhoneStateListenerWeakRef.get();
if (psl == null) return;
+
Binder.withCleanCallingIdentity(
() -> mExecutor.execute(
() -> psl.onPreciseDataConnectionStateChanged(dataConnectionState)));
@@ -2618,6 +1345,7 @@ public class PhoneStateListener {
public void onSrvccStateChanged(int state) {
PhoneStateListener psl = mPhoneStateListenerWeakRef.get();
if (psl == null) return;
+
Binder.withCleanCallingIdentity(
() -> mExecutor.execute(() -> psl.onSrvccStateChanged(state)));
}
@@ -2625,6 +1353,7 @@ public class PhoneStateListener {
public void onVoiceActivationStateChanged(int activationState) {
PhoneStateListener psl = mPhoneStateListenerWeakRef.get();
if (psl == null) return;
+
Binder.withCleanCallingIdentity(
() -> mExecutor.execute(
() -> psl.onVoiceActivationStateChanged(activationState)));
@@ -2633,6 +1362,7 @@ public class PhoneStateListener {
public void onDataActivationStateChanged(int activationState) {
PhoneStateListener psl = mPhoneStateListenerWeakRef.get();
if (psl == null) return;
+
Binder.withCleanCallingIdentity(
() -> mExecutor.execute(
() -> psl.onDataActivationStateChanged(activationState)));
@@ -2641,6 +1371,7 @@ public class PhoneStateListener {
public void onUserMobileDataStateChanged(boolean enabled) {
PhoneStateListener psl = mPhoneStateListenerWeakRef.get();
if (psl == null) return;
+
Binder.withCleanCallingIdentity(
() -> mExecutor.execute(
() -> psl.onUserMobileDataStateChanged(enabled)));
@@ -2649,6 +1380,7 @@ public class PhoneStateListener {
public void onDisplayInfoChanged(TelephonyDisplayInfo telephonyDisplayInfo) {
PhoneStateListener psl = mPhoneStateListenerWeakRef.get();
if (psl == null) return;
+
Binder.withCleanCallingIdentity(
() -> mExecutor.execute(
() -> psl.onDisplayInfoChanged(telephonyDisplayInfo)));
@@ -2657,6 +1389,7 @@ public class PhoneStateListener {
public void onOemHookRawEvent(byte[] rawData) {
PhoneStateListener psl = mPhoneStateListenerWeakRef.get();
if (psl == null) return;
+
Binder.withCleanCallingIdentity(
() -> mExecutor.execute(() -> psl.onOemHookRawEvent(rawData)));
}
@@ -2664,6 +1397,7 @@ public class PhoneStateListener {
public void onCarrierNetworkChange(boolean active) {
PhoneStateListener psl = mPhoneStateListenerWeakRef.get();
if (psl == null) return;
+
Binder.withCleanCallingIdentity(
() -> mExecutor.execute(() -> psl.onCarrierNetworkChange(active)));
}
@@ -2671,6 +1405,7 @@ public class PhoneStateListener {
public void onEmergencyNumberListChanged(Map emergencyNumberList) {
PhoneStateListener psl = mPhoneStateListenerWeakRef.get();
if (psl == null) return;
+
Binder.withCleanCallingIdentity(
() -> mExecutor.execute(
() -> psl.onEmergencyNumberListChanged(emergencyNumberList)));
@@ -2680,6 +1415,7 @@ public class PhoneStateListener {
int subscriptionId) {
PhoneStateListener psl = mPhoneStateListenerWeakRef.get();
if (psl == null) return;
+
Binder.withCleanCallingIdentity(
() -> mExecutor.execute(
() -> psl.onOutgoingEmergencyCall(placedEmergencyNumber,
@@ -2690,6 +1426,7 @@ public class PhoneStateListener {
int subscriptionId) {
PhoneStateListener psl = mPhoneStateListenerWeakRef.get();
if (psl == null) return;
+
Binder.withCleanCallingIdentity(
() -> mExecutor.execute(
() -> psl.onOutgoingEmergencySms(sentEmergencyNumber, subscriptionId)));
@@ -2698,6 +1435,7 @@ public class PhoneStateListener {
public void onPhoneCapabilityChanged(PhoneCapability capability) {
PhoneStateListener psl = mPhoneStateListenerWeakRef.get();
if (psl == null) return;
+
Binder.withCleanCallingIdentity(
() -> mExecutor.execute(() -> psl.onPhoneCapabilityChanged(capability)));
}
@@ -2705,6 +1443,7 @@ public class PhoneStateListener {
public void onRadioPowerStateChanged(@RadioPowerState int state) {
PhoneStateListener psl = mPhoneStateListenerWeakRef.get();
if (psl == null) return;
+
Binder.withCleanCallingIdentity(
() -> mExecutor.execute(() -> psl.onRadioPowerStateChanged(state)));
}
@@ -2712,6 +1451,7 @@ public class PhoneStateListener {
public void onCallAttributesChanged(CallAttributes callAttributes) {
PhoneStateListener psl = mPhoneStateListenerWeakRef.get();
if (psl == null) return;
+
Binder.withCleanCallingIdentity(
() -> mExecutor.execute(() -> psl.onCallAttributesChanged(callAttributes)));
}
@@ -2719,6 +1459,7 @@ public class PhoneStateListener {
public void onActiveDataSubIdChanged(int subId) {
PhoneStateListener psl = mPhoneStateListenerWeakRef.get();
if (psl == null) return;
+
Binder.withCleanCallingIdentity(
() -> mExecutor.execute(() -> psl.onActiveDataSubscriptionIdChanged(subId)));
}
@@ -2726,51 +1467,44 @@ public class PhoneStateListener {
public void onImsCallDisconnectCauseChanged(ImsReasonInfo disconnectCause) {
PhoneStateListener psl = mPhoneStateListenerWeakRef.get();
if (psl == null) return;
+
Binder.withCleanCallingIdentity(
() -> mExecutor.execute(
() -> psl.onImsCallDisconnectCauseChanged(disconnectCause)));
+
}
public void onRegistrationFailed(@NonNull CellIdentity cellIdentity,
- @NonNull String chosenPlmn, int domain, int causeCode, int additionalCauseCode) {
+ @NonNull String chosenPlmn, int domain,
+ int causeCode, int additionalCauseCode) {
PhoneStateListener psl = mPhoneStateListenerWeakRef.get();
if (psl == null) return;
+
Binder.withCleanCallingIdentity(
() -> mExecutor.execute(() -> psl.onRegistrationFailed(
- cellIdentity, chosenPlmn, domain, causeCode, additionalCauseCode)));
+ cellIdentity, chosenPlmn, domain, causeCode, additionalCauseCode)));
// default implementation empty
}
public void onBarringInfoChanged(BarringInfo barringInfo) {
PhoneStateListener psl = mPhoneStateListenerWeakRef.get();
if (psl == null) return;
+
Binder.withCleanCallingIdentity(
() -> mExecutor.execute(() -> psl.onBarringInfoChanged(barringInfo)));
}
- public void onPhysicalChannelConfigChanged(List<PhysicalChannelConfig> configs) {
+ public void onPhysicalChannelConfigurationChanged(List<PhysicalChannelConfig> configs) {
PhoneStateListener psl = mPhoneStateListenerWeakRef.get();
- PhysicalChannelConfigChangedListener listener =
- (PhysicalChannelConfigChangedListener) mPhoneStateListenerWeakRef.get();
- if (listener == null) return;
- Binder.withCleanCallingIdentity(
- () -> mExecutor.execute(() -> listener.onPhysicalChannelConfigChanged(
- configs)));
- }
-
- public void onDataEnabledChanged(boolean enabled, @DataEnabledReason int reason) {
- if ((mPhoneStateListenerWeakRef.get() instanceof DataEnabledChangedListener)) {
- DataEnabledChangedListener listener =
- (DataEnabledChangedListener) mPhoneStateListenerWeakRef.get();
- if (listener == null) return;
+ if (psl == null) return;
- Binder.withCleanCallingIdentity(
- () -> mExecutor.execute(() -> listener.onDataEnabledChanged(
- enabled, reason)));
- }
+ Binder.withCleanCallingIdentity(
+ () -> mExecutor.execute(
+ () -> psl.onPhysicalChannelConfigurationChanged(configs)));
}
}
+
private void log(String s) {
Rlog.d(LOG_TAG, s);
}
diff --git a/core/java/android/telephony/TelephonyRegistryManager.java b/core/java/android/telephony/TelephonyRegistryManager.java
index c706e2179f19..24ed29a66654 100644
--- a/core/java/android/telephony/TelephonyRegistryManager.java
+++ b/core/java/android/telephony/TelephonyRegistryManager.java
@@ -15,7 +15,6 @@
*/
package android.telephony;
-import android.annotation.CallbackExecutor;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.RequiresPermission;
@@ -25,9 +24,6 @@ import android.compat.annotation.EnabledAfter;
import android.content.Context;
import android.os.Binder;
import android.os.Build;
-import android.os.Handler;
-import android.os.HandlerExecutor;
-import android.os.Looper;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.telephony.Annotation.CallState;
@@ -41,7 +37,6 @@ import android.telephony.Annotation.SimActivationState;
import android.telephony.Annotation.SrvccState;
import android.telephony.emergency.EmergencyNumber;
import android.telephony.ims.ImsReasonInfo;
-import android.util.ArraySet;
import android.util.Log;
import com.android.internal.telephony.IOnSubscriptionsChangedListener;
@@ -50,7 +45,6 @@ import com.android.internal.telephony.ITelephonyRegistry;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
-import java.util.Set;
import java.util.concurrent.Executor;
/**
@@ -212,7 +206,7 @@ public class TelephonyRegistryManager {
}
/**
- * To check the SDK version for {@link #listenWithEventList}.
+ * To check the SDK version for {@link #listenForSubscriber}.
*/
@ChangeId
@EnabledAfter(targetSdkVersion = Build.VERSION_CODES.P)
@@ -224,23 +218,23 @@ public class TelephonyRegistryManager {
* @param pkg Package name
* @param featureId Feature ID
* @param listener Listener providing callback
- * @param events List events
+ * @param events Events
* @param notifyNow Whether to notify instantly
*/
- public void listenWithEventList(int subId, @NonNull String pkg, @NonNull String featureId,
- @NonNull PhoneStateListener listener, @NonNull int[] events, boolean notifyNow) {
+ public void listenForSubscriber(int subId, @NonNull String pkg, @NonNull String featureId,
+ @NonNull PhoneStateListener listener, long events, boolean notifyNow) {
try {
// subId from PhoneStateListener is deprecated Q on forward, use the subId from
// TelephonyManager instance. Keep using subId from PhoneStateListener for pre-Q.
if (Compatibility.isChangeEnabled(LISTEN_CODE_CHANGE)) {
// Since mSubId in PhoneStateListener is deprecated from Q on forward, this is
// the only place to set mSubId and its for "informational" only.
- listener.mSubId = (events.length == 0)
+ listener.mSubId = (events == PhoneStateListener.LISTEN_NONE)
? SubscriptionManager.INVALID_SUBSCRIPTION_ID : subId;
} else if (listener.mSubId != null) {
subId = listener.mSubId;
}
- sRegistry.listenWithEventList(
+ sRegistry.listenForSubscriber(
subId, pkg, featureId, listener.callback, events, notifyNow);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
@@ -777,349 +771,13 @@ public class TelephonyRegistryManager {
* @param subId the subId
* @param configs a list of {@link PhysicalChannelConfig}, the configs of physical channel.
*/
- public void notifyPhysicalChannelConfigForSubscriber(
+ public void notifyPhysicalChannelConfigurationForSubscriber(
int subId, List<PhysicalChannelConfig> configs) {
try {
- sRegistry.notifyPhysicalChannelConfigForSubscriber(subId, configs);
+ sRegistry.notifyPhysicalChannelConfigurationForSubscriber(subId, configs);
} catch (RemoteException ex) {
// system server crash
}
}
- public @NonNull Set<Integer> getEventsFromListener(@NonNull PhoneStateListener listener) {
-
- Set<Integer> eventList = new ArraySet<>();
-
- if (listener instanceof PhoneStateListener.ServiceStateChangedListener) {
- eventList.add(PhoneStateListener.EVENT_SERVICE_STATE_CHANGED);
- }
-
- if (listener instanceof PhoneStateListener.MessageWaitingIndicatorChangedListener) {
- eventList.add(PhoneStateListener.EVENT_MESSAGE_WAITING_INDICATOR_CHANGED);
- }
-
- if (listener instanceof PhoneStateListener.CallForwardingIndicatorChangedListener) {
- eventList.add(PhoneStateListener.EVENT_CALL_FORWARDING_INDICATOR_CHANGED);
- }
-
- if (listener instanceof PhoneStateListener.CellLocationChangedListener) {
- eventList.add(PhoneStateListener.EVENT_CELL_LOCATION_CHANGED);
- }
-
- if (listener instanceof PhoneStateListener.CallStateChangedListener) {
- eventList.add(PhoneStateListener.EVENT_CALL_STATE_CHANGED);
- }
-
- if (listener instanceof PhoneStateListener.DataConnectionStateChangedListener) {
- eventList.add(PhoneStateListener.EVENT_DATA_CONNECTION_STATE_CHANGED);
- }
-
- if (listener instanceof PhoneStateListener.DataActivityListener) {
- eventList.add(PhoneStateListener.EVENT_DATA_ACTIVITY_CHANGED);
- }
-
- if (listener instanceof PhoneStateListener.SignalStrengthsChangedListener) {
- eventList.add(PhoneStateListener.EVENT_SIGNAL_STRENGTHS_CHANGED);
- }
-
- if (listener instanceof PhoneStateListener.AlwaysReportedSignalStrengthsChangedListener) {
- eventList.add(PhoneStateListener.EVENT_ALWAYS_REPORTED_SIGNAL_STRENGTH_CHANGED);
- }
-
- if (listener instanceof PhoneStateListener.CellInfoChangedListener) {
- eventList.add(PhoneStateListener.EVENT_CELL_INFO_CHANGED);
- }
-
- if (listener instanceof PhoneStateListener.PreciseCallStateChangedListener) {
- eventList.add(PhoneStateListener.EVENT_PRECISE_CALL_STATE_CHANGED);
- }
-
- if (listener instanceof PhoneStateListener.CallDisconnectCauseChangedListener) {
- eventList.add(PhoneStateListener.EVENT_CALL_DISCONNECT_CAUSE_CHANGED);
- }
-
- if (listener instanceof PhoneStateListener.ImsCallDisconnectCauseChangedListener) {
- eventList.add(PhoneStateListener.EVENT_IMS_CALL_DISCONNECT_CAUSE_CHANGED);
- }
-
- if (listener instanceof PhoneStateListener.PreciseDataConnectionStateChangedListener) {
- eventList.add(PhoneStateListener.EVENT_PRECISE_DATA_CONNECTION_STATE_CHANGED);
- }
-
- if (listener instanceof PhoneStateListener.SrvccStateChangedListener) {
- eventList.add(PhoneStateListener.EVENT_SRVCC_STATE_CHANGED);
- }
-
- if (listener instanceof PhoneStateListener.VoiceActivationStateChangedListener) {
- eventList.add(PhoneStateListener.EVENT_VOICE_ACTIVATION_STATE_CHANGED);
- }
-
- if (listener instanceof PhoneStateListener.DataActivationStateChangedListener) {
- eventList.add(PhoneStateListener.EVENT_DATA_ACTIVATION_STATE_CHANGED);
- }
-
- if (listener instanceof PhoneStateListener.UserMobileDataStateChangedListener) {
- eventList.add(PhoneStateListener.EVENT_USER_MOBILE_DATA_STATE_CHANGED);
- }
-
- if (listener instanceof PhoneStateListener.DisplayInfoChangedListener) {
- eventList.add(PhoneStateListener.EVENT_DISPLAY_INFO_CHANGED);
- }
-
- if (listener instanceof PhoneStateListener.EmergencyNumberListChangedListener) {
- eventList.add(PhoneStateListener.EVENT_EMERGENCY_NUMBER_LIST_CHANGED);
- }
-
- if (listener instanceof PhoneStateListener.OutgoingEmergencyCallListener) {
- eventList.add(PhoneStateListener.EVENT_OUTGOING_EMERGENCY_CALL);
- }
-
- if (listener instanceof PhoneStateListener.OutgoingEmergencySmsListener) {
- eventList.add(PhoneStateListener.EVENT_OUTGOING_EMERGENCY_SMS);
- }
-
- if (listener instanceof PhoneStateListener.PhoneCapabilityChangedListener) {
- eventList.add(PhoneStateListener.EVENT_PHONE_CAPABILITY_CHANGED);
- }
-
- if (listener instanceof PhoneStateListener.ActiveDataSubscriptionIdChangedListener) {
- eventList.add(PhoneStateListener.EVENT_ACTIVE_DATA_SUBSCRIPTION_ID_CHANGED);
- }
-
- if (listener instanceof PhoneStateListener.RadioPowerStateChangedListener) {
- eventList.add(PhoneStateListener.EVENT_RADIO_POWER_STATE_CHANGED);
- }
-
- if (listener instanceof PhoneStateListener.CarrierNetworkChangeListener) {
- eventList.add(PhoneStateListener.EVENT_CARRIER_NETWORK_CHANGED);
- }
-
- if (listener instanceof PhoneStateListener.RegistrationFailedListener) {
- eventList.add(PhoneStateListener.EVENT_REGISTRATION_FAILURE);
- }
-
- if (listener instanceof PhoneStateListener.CallAttributesChangedListener) {
- eventList.add(PhoneStateListener.EVENT_CALL_ATTRIBUTES_CHANGED);
- }
-
- if (listener instanceof PhoneStateListener.BarringInfoChangedListener) {
- eventList.add(PhoneStateListener.EVENT_BARRING_INFO_CHANGED);
- }
-
- if (listener instanceof PhoneStateListener.PhysicalChannelConfigChangedListener) {
- eventList.add(PhoneStateListener.EVENT_PHYSICAL_CHANNEL_CONFIG_CHANGED);
- }
-
- if (listener instanceof PhoneStateListener.DataEnabledChangedListener) {
- eventList.add(PhoneStateListener.EVENT_DATA_ENABLED_CHANGED);
- }
-
- return eventList;
- }
-
- private @NonNull Set<Integer> getEventsFromBitmask(int eventMask) {
-
- Set<Integer> eventList = new ArraySet<>();
-
- if ((eventMask & PhoneStateListener.LISTEN_SERVICE_STATE) != 0) {
- eventList.add(PhoneStateListener.EVENT_SERVICE_STATE_CHANGED);
- }
-
- if ((eventMask & PhoneStateListener.LISTEN_SIGNAL_STRENGTH) != 0) {
- eventList.add(PhoneStateListener.EVENT_SIGNAL_STRENGTH_CHANGED);
- }
-
- if ((eventMask & PhoneStateListener.LISTEN_MESSAGE_WAITING_INDICATOR) != 0) {
- eventList.add(PhoneStateListener.EVENT_MESSAGE_WAITING_INDICATOR_CHANGED);
- }
-
- if ((eventMask & PhoneStateListener.LISTEN_CALL_FORWARDING_INDICATOR) != 0) {
- eventList.add(PhoneStateListener.EVENT_CALL_FORWARDING_INDICATOR_CHANGED);
- }
-
- if ((eventMask & PhoneStateListener.LISTEN_CELL_LOCATION) != 0) {
- eventList.add(PhoneStateListener.EVENT_CELL_LOCATION_CHANGED);
- }
-
- if ((eventMask & PhoneStateListener.LISTEN_CALL_STATE) != 0) {
- eventList.add(PhoneStateListener.EVENT_CALL_STATE_CHANGED);
- }
-
- if ((eventMask & PhoneStateListener.LISTEN_DATA_CONNECTION_STATE) != 0) {
- eventList.add(PhoneStateListener.EVENT_DATA_CONNECTION_STATE_CHANGED);
- }
-
- if ((eventMask & PhoneStateListener.LISTEN_DATA_ACTIVITY) != 0) {
- eventList.add(PhoneStateListener.EVENT_DATA_ACTIVITY_CHANGED);
- }
-
- if ((eventMask & PhoneStateListener.LISTEN_SIGNAL_STRENGTHS) != 0) {
- eventList.add(PhoneStateListener.EVENT_SIGNAL_STRENGTHS_CHANGED);
- }
-
- if ((eventMask & PhoneStateListener.LISTEN_ALWAYS_REPORTED_SIGNAL_STRENGTH) != 0) {
- eventList.add(PhoneStateListener.EVENT_ALWAYS_REPORTED_SIGNAL_STRENGTH_CHANGED);
- }
-
- if ((eventMask & PhoneStateListener.LISTEN_CELL_INFO) != 0) {
- eventList.add(PhoneStateListener.EVENT_CELL_INFO_CHANGED);
- }
-
- if ((eventMask & PhoneStateListener.LISTEN_PRECISE_CALL_STATE) != 0) {
- eventList.add(PhoneStateListener.EVENT_PRECISE_CALL_STATE_CHANGED);
- }
-
- if ((eventMask & PhoneStateListener.LISTEN_PRECISE_DATA_CONNECTION_STATE) != 0) {
- eventList.add(PhoneStateListener.EVENT_PRECISE_DATA_CONNECTION_STATE_CHANGED);
- }
-
- if ((eventMask & PhoneStateListener.LISTEN_DATA_CONNECTION_REAL_TIME_INFO) != 0) {
- eventList.add(PhoneStateListener.EVENT_DATA_CONNECTION_REAL_TIME_INFO_CHANGED);
- }
-
- if ((eventMask & PhoneStateListener.LISTEN_OEM_HOOK_RAW_EVENT) != 0) {
- eventList.add(PhoneStateListener.EVENT_OEM_HOOK_RAW);
- }
-
- if ((eventMask & PhoneStateListener.LISTEN_SRVCC_STATE_CHANGED) != 0) {
- eventList.add(PhoneStateListener.EVENT_SRVCC_STATE_CHANGED);
- }
-
- if ((eventMask & PhoneStateListener.LISTEN_CARRIER_NETWORK_CHANGE) != 0) {
- eventList.add(PhoneStateListener.EVENT_CARRIER_NETWORK_CHANGED);
- }
-
- if ((eventMask & PhoneStateListener.LISTEN_VOICE_ACTIVATION_STATE) != 0) {
- eventList.add(PhoneStateListener.EVENT_VOICE_ACTIVATION_STATE_CHANGED);
- }
-
- if ((eventMask & PhoneStateListener.LISTEN_DATA_ACTIVATION_STATE) != 0) {
- eventList.add(PhoneStateListener.EVENT_DATA_ACTIVATION_STATE_CHANGED);
- }
-
- if ((eventMask & PhoneStateListener.LISTEN_USER_MOBILE_DATA_STATE) != 0) {
- eventList.add(PhoneStateListener.EVENT_USER_MOBILE_DATA_STATE_CHANGED);
- }
-
- if ((eventMask & PhoneStateListener.LISTEN_DISPLAY_INFO_CHANGED) != 0) {
- eventList.add(PhoneStateListener.EVENT_DISPLAY_INFO_CHANGED);
- }
-
- if ((eventMask & PhoneStateListener.LISTEN_PHONE_CAPABILITY_CHANGE) != 0) {
- eventList.add(PhoneStateListener.EVENT_PHONE_CAPABILITY_CHANGED);
- }
-
- if ((eventMask & PhoneStateListener.LISTEN_ACTIVE_DATA_SUBSCRIPTION_ID_CHANGE) != 0) {
- eventList.add(PhoneStateListener.EVENT_ACTIVE_DATA_SUBSCRIPTION_ID_CHANGED);
- }
-
- if ((eventMask & PhoneStateListener.LISTEN_RADIO_POWER_STATE_CHANGED) != 0) {
- eventList.add(PhoneStateListener.EVENT_RADIO_POWER_STATE_CHANGED);
- }
-
- if ((eventMask & PhoneStateListener.LISTEN_EMERGENCY_NUMBER_LIST) != 0) {
- eventList.add(PhoneStateListener.EVENT_EMERGENCY_NUMBER_LIST_CHANGED);
- }
-
- if ((eventMask & PhoneStateListener.LISTEN_CALL_DISCONNECT_CAUSES) != 0) {
- eventList.add(PhoneStateListener.EVENT_CALL_DISCONNECT_CAUSE_CHANGED);
- }
-
- if ((eventMask & PhoneStateListener.LISTEN_CALL_ATTRIBUTES_CHANGED) != 0) {
- eventList.add(PhoneStateListener.EVENT_CALL_ATTRIBUTES_CHANGED);
- }
-
- if ((eventMask & PhoneStateListener.LISTEN_IMS_CALL_DISCONNECT_CAUSES) != 0) {
- eventList.add(PhoneStateListener.EVENT_IMS_CALL_DISCONNECT_CAUSE_CHANGED);
- }
-
- if ((eventMask & PhoneStateListener.LISTEN_OUTGOING_EMERGENCY_CALL) != 0) {
- eventList.add(PhoneStateListener.EVENT_OUTGOING_EMERGENCY_CALL);
- }
-
- if ((eventMask & PhoneStateListener.LISTEN_OUTGOING_EMERGENCY_SMS) != 0) {
- eventList.add(PhoneStateListener.EVENT_OUTGOING_EMERGENCY_SMS);
- }
-
- if ((eventMask & PhoneStateListener.LISTEN_REGISTRATION_FAILURE) != 0) {
- eventList.add(PhoneStateListener.EVENT_REGISTRATION_FAILURE);
- }
-
- if ((eventMask & PhoneStateListener.LISTEN_BARRING_INFO) != 0) {
- eventList.add(PhoneStateListener.EVENT_BARRING_INFO_CHANGED);
- }
- return eventList;
-
- }
-
- /**
- * Registers a listener object to receive notification of changes
- * in specified telephony states.
- * <p>
- * To register a listener, pass a {@link PhoneStateListener} which implements
- * interfaces of events. For example,
- * FakeServiceStateChangedListener extends {@link PhoneStateListener} implements
- * {@link PhoneStateListener.ServiceStateChangedListener}.
- *
- * At registration, and when a specified telephony state changes, the telephony manager invokes
- * the appropriate callback method on the listener object and passes the current (updated)
- * values.
- * <p>
- *
- * If this TelephonyManager object has been created with
- * {@link TelephonyManager#createForSubscriptionId}, applies to the given subId.
- * Otherwise, applies to {@link SubscriptionManager#getDefaultSubscriptionId()}.
- * To listen events for multiple subIds, pass a separate listener object to
- * each TelephonyManager object created with {@link TelephonyManager#createForSubscriptionId}.
- *
- * Note: if you call this method while in the middle of a binder transaction, you <b>must</b>
- * call {@link android.os.Binder#clearCallingIdentity()} before calling this method. A
- * {@link SecurityException} will be thrown otherwise.
- *
- * This API should be used sparingly -- large numbers of listeners will cause system
- * instability. If a process has registered too many listeners without unregistering them, it
- * may encounter an {@link IllegalStateException} when trying to register more listeners.
- *
- * @param listener The {@link PhoneStateListener} object to register.
- */
- public void registerPhoneStateListener(@NonNull @CallbackExecutor Executor executor, int subId,
- String pkgName, String attributionTag, @NonNull PhoneStateListener listener,
- boolean notifyNow) {
- registerPhoneStateListener(executor, subId, pkgName, attributionTag, listener,
- getEventsFromListener(listener), notifyNow);
- }
-
- public void registerPhoneStateListenerWithEvents(int subId, String pkgName,
- String attributionTag, @NonNull PhoneStateListener listener, int events,
- boolean notifyNow) {
- if (Looper.myLooper() == null) {
- Looper.prepare();
- }
-
- registerPhoneStateListener(new HandlerExecutor(new Handler(Looper.myLooper())),
- subId, pkgName, attributionTag, listener, getEventsFromBitmask(events), notifyNow);
- }
-
- private void registerPhoneStateListener(@NonNull @CallbackExecutor Executor executor, int subId,
- String pkgName, String attributionTag, @NonNull PhoneStateListener listener,
- @NonNull Set<Integer> events, boolean notifyNow) {
- if (listener == null) {
- throw new IllegalStateException("telephony service is null.");
- }
-
- listener.setExecutor(executor);
- listenWithEventList(subId, pkgName, attributionTag, listener,
- events.stream().mapToInt(i -> i).toArray(), notifyNow);
- }
-
- /**
- * Unregister an existing {@link PhoneStateListener}.
- *
- * @param listener The {@link PhoneStateListener} object to unregister.
- */
- public void unregisterPhoneStateListener(int subId, String pkgName, String attributionTag,
- @NonNull PhoneStateListener listener,
- boolean notifyNow) {
- listenWithEventList(subId, pkgName, attributionTag, listener, new int[0], notifyNow);
- }
}
diff --git a/core/java/android/view/IWindowManager.aidl b/core/java/android/view/IWindowManager.aidl
index 924fc6d6dca0..053353330e4e 100644
--- a/core/java/android/view/IWindowManager.aidl
+++ b/core/java/android/view/IWindowManager.aidl
@@ -668,22 +668,24 @@ interface IWindowManager
void setShouldShowIme(int displayId, boolean shouldShow);
/**
- * Waits for transactions to get applied before injecting input.
- * This includes waiting for the input windows to get sent to InputManager.
+ * Waits for transactions to get applied before injecting input, optionally waiting for
+ * animations to complete. This includes waiting for the input windows to get sent to
+ * InputManager.
*
* This is needed for testing since the system add windows and injects input
* quick enough that the windows don't have time to get sent to InputManager.
*/
- boolean injectInputAfterTransactionsApplied(in InputEvent ev, int mode);
+ boolean injectInputAfterTransactionsApplied(in InputEvent ev, int mode,
+ boolean waitForAnimations);
/**
- * Waits until all animations have completed and input information has been sent from
- * WindowManager to native InputManager.
+ * Waits until input information has been sent from WindowManager to native InputManager,
+ * optionally waiting for animations to complete.
*
* This is needed for testing since we need to ensure input information has been propagated to
* native InputManager before proceeding with tests.
*/
- void syncInputTransactions();
+ void syncInputTransactions(boolean waitForAnimations);
/**
* Returns whether SurfaceFlinger layer tracing is enabled.
diff --git a/core/java/android/view/InputEventReceiver.java b/core/java/android/view/InputEventReceiver.java
index 038dff654ba6..7d1adc36964b 100644
--- a/core/java/android/view/InputEventReceiver.java
+++ b/core/java/android/view/InputEventReceiver.java
@@ -144,6 +144,20 @@ public abstract class InputEventReceiver {
}
/**
+ * Called when a Pointer Capture event is received.
+ *
+ * @param pointerCaptureEnabled if true, the window associated with this input channel has just
+ * received Pointer Capture
+ * if false, the window associated with this input channel has just
+ * lost Pointer Capture
+ * @see View#requestPointerCapture()
+ * @see View#releasePointerCapture()
+ */
+ // Called from native code.
+ public void onPointerCaptureEvent(boolean pointerCaptureEnabled) {
+ }
+
+ /**
* 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/NotificationHeaderView.java b/core/java/android/view/NotificationHeaderView.java
index f7fbb1ce0ab9..673ed0d8b95d 100644
--- a/core/java/android/view/NotificationHeaderView.java
+++ b/core/java/android/view/NotificationHeaderView.java
@@ -43,12 +43,13 @@ import java.util.ArrayList;
*/
@RemoteViews.RemoteView
public class NotificationHeaderView extends FrameLayout {
- private final int mContentEndMargin;
private final int mHeadingEndMargin;
+ private final int mTouchableHeight;
private OnClickListener mExpandClickListener;
private HeaderTouchListener mTouchListener = new HeaderTouchListener();
private NotificationTopLineView mTopLineView;
private NotificationExpandButton mExpandButton;
+ private View mAltExpandTarget;
private CachingIconView mIcon;
private Drawable mBackground;
private boolean mEntireHeaderClickable;
@@ -82,8 +83,8 @@ public class NotificationHeaderView extends FrameLayout {
int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
Resources res = getResources();
- mContentEndMargin = res.getDimensionPixelSize(R.dimen.notification_content_margin_end);
mHeadingEndMargin = res.getDimensionPixelSize(R.dimen.notification_heading_margin_end);
+ mTouchableHeight = res.getDimensionPixelSize(R.dimen.notification_header_touchable_height);
mEntireHeaderClickable = res.getBoolean(R.bool.config_notificationHeaderClickableForExpand);
}
@@ -93,6 +94,7 @@ public class NotificationHeaderView extends FrameLayout {
mIcon = findViewById(R.id.icon);
mTopLineView = findViewById(R.id.notification_top_line);
mExpandButton = findViewById(R.id.expand_button);
+ mAltExpandTarget = findViewById(R.id.alternate_expand_target);
setClipToPadding(false);
}
@@ -146,6 +148,7 @@ public class NotificationHeaderView extends FrameLayout {
public void setOnClickListener(@Nullable OnClickListener l) {
mExpandClickListener = l;
mExpandButton.setOnClickListener(mExpandClickListener);
+ mAltExpandTarget.setOnClickListener(mExpandClickListener);
updateTouchListener();
}
@@ -187,6 +190,7 @@ public class NotificationHeaderView extends FrameLayout {
private final ArrayList<Rect> mTouchRects = new ArrayList<>();
private Rect mExpandButtonRect;
+ private Rect mAltExpandTargetRect;
private int mTouchSlop;
private boolean mTrackGesture;
private float mDownX;
@@ -199,6 +203,7 @@ public class NotificationHeaderView extends FrameLayout {
mTouchRects.clear();
addRectAroundView(mIcon);
mExpandButtonRect = addRectAroundView(mExpandButton);
+ mAltExpandTargetRect = addRectAroundView(mAltExpandTarget);
addWidthRect();
mTouchSlop = ViewConfiguration.get(getContext()).getScaledTouchSlop();
}
@@ -206,7 +211,7 @@ public class NotificationHeaderView extends FrameLayout {
private void addWidthRect() {
Rect r = new Rect();
r.top = 0;
- r.bottom = (int) (32 * getResources().getDisplayMetrics().density);
+ r.bottom = mTouchableHeight;
r.left = 0;
r.right = getWidth();
mTouchRects.add(r);
@@ -277,7 +282,8 @@ public class NotificationHeaderView extends FrameLayout {
return true;
}
if (mExpandOnlyOnButton) {
- return mExpandButtonRect.contains((int) x, (int) y);
+ return mExpandButtonRect.contains((int) x, (int) y)
+ || mAltExpandTargetRect.contains((int) x, (int) y);
}
for (int i = 0; i < mTouchRects.size(); i++) {
Rect r = mTouchRects.get(i);
diff --git a/core/java/android/view/NotificationTopLineView.java b/core/java/android/view/NotificationTopLineView.java
index a8eabe5a7967..05636de8e8e4 100644
--- a/core/java/android/view/NotificationTopLineView.java
+++ b/core/java/android/view/NotificationTopLineView.java
@@ -97,10 +97,8 @@ public class NotificationTopLineView extends ViewGroup {
final int givenWidth = MeasureSpec.getSize(widthMeasureSpec);
final int givenHeight = MeasureSpec.getSize(heightMeasureSpec);
final boolean wrapHeight = MeasureSpec.getMode(heightMeasureSpec) == MeasureSpec.AT_MOST;
- int wrapContentWidthSpec = MeasureSpec.makeMeasureSpec(givenWidth,
- MeasureSpec.AT_MOST);
- int wrapContentHeightSpec = MeasureSpec.makeMeasureSpec(givenHeight,
- MeasureSpec.AT_MOST);
+ int wrapContentWidthSpec = MeasureSpec.makeMeasureSpec(givenWidth, MeasureSpec.AT_MOST);
+ int heightSpec = MeasureSpec.makeMeasureSpec(givenHeight, MeasureSpec.AT_MOST);
int totalWidth = getPaddingStart();
int maxChildHeight = -1;
mMaxAscent = -1;
@@ -114,7 +112,7 @@ public class NotificationTopLineView extends ViewGroup {
final MarginLayoutParams lp = (MarginLayoutParams) child.getLayoutParams();
int childWidthSpec = getChildMeasureSpec(wrapContentWidthSpec,
lp.leftMargin + lp.rightMargin, lp.width);
- int childHeightSpec = getChildMeasureSpec(wrapContentHeightSpec,
+ int childHeightSpec = getChildMeasureSpec(heightSpec,
lp.topMargin + lp.bottomMargin, lp.height);
child.measure(childWidthSpec, childHeightSpec);
totalWidth += lp.leftMargin + lp.rightMargin + child.getMeasuredWidth();
@@ -131,37 +129,37 @@ public class NotificationTopLineView extends ViewGroup {
int endMargin = Math.max(mHeaderTextMarginEnd, getPaddingEnd());
if (totalWidth > givenWidth - endMargin) {
int overFlow = totalWidth - givenWidth + endMargin;
- if (mAppName != null) {
- // We are overflowing, lets shrink the app name first
- overFlow = shrinkViewForOverflow(wrapContentHeightSpec, overFlow, mAppName,
- mChildMinWidth);
- }
- if (mTitle != null) {
- // still overflowing, we shrink the title text
- overFlow = shrinkViewForOverflow(wrapContentHeightSpec, overFlow, mTitle,
- mChildMinWidth);
- }
+ // First shrink the app name, down to a minimum size
+ overFlow = shrinkViewForOverflow(heightSpec, overFlow, mAppName, mChildMinWidth);
+
+ // Next, shrink the header text (this usually has subText)
+ // This shrinks the subtext first, but not all the way (yet!)
+ overFlow = shrinkViewForOverflow(heightSpec, overFlow, mHeaderText, mChildMinWidth);
- // still overflowing, we shrink the header text
- overFlow = shrinkViewForOverflow(wrapContentHeightSpec, overFlow, mHeaderText, 0);
+ // Next, shrink the secondary header text (this rarely has conversationTitle)
+ overFlow = shrinkViewForOverflow(heightSpec, overFlow, mSecondaryHeaderText, 0);
- // still overflowing, finally we shrink the secondary header text
- shrinkViewForOverflow(wrapContentHeightSpec, overFlow, mSecondaryHeaderText,
- 0);
+ // Next, shrink the title text (this has contentTitle; only in headerless views)
+ overFlow = shrinkViewForOverflow(heightSpec, overFlow, mTitle, mChildMinWidth);
+
+ // Finally, if there is still overflow, shrink the header down to 0 if still necessary.
+ shrinkViewForOverflow(heightSpec, overFlow, mHeaderText, 0);
}
setMeasuredDimension(givenWidth, wrapHeight ? maxChildHeight : givenHeight);
}
private int shrinkViewForOverflow(int heightSpec, int overFlow, View targetView,
int minimumWidth) {
- final int oldWidth = targetView.getMeasuredWidth();
- if (overFlow > 0 && targetView.getVisibility() != GONE && oldWidth > minimumWidth) {
- // we're still too big
- int newSize = Math.max(minimumWidth, oldWidth - overFlow);
- int childWidthSpec = MeasureSpec.makeMeasureSpec(newSize, MeasureSpec.AT_MOST);
- targetView.measure(childWidthSpec, heightSpec);
- overFlow -= oldWidth - newSize;
+ if (targetView != null) {
+ final int oldWidth = targetView.getMeasuredWidth();
+ if (overFlow > 0 && targetView.getVisibility() != GONE && oldWidth > minimumWidth) {
+ // we're still too big
+ int newSize = Math.max(minimumWidth, oldWidth - overFlow);
+ int childWidthSpec = MeasureSpec.makeMeasureSpec(newSize, MeasureSpec.AT_MOST);
+ targetView.measure(childWidthSpec, heightSpec);
+ overFlow -= oldWidth - newSize;
+ }
}
return overFlow;
}
diff --git a/core/java/android/view/inputmethod/BaseInputConnection.java b/core/java/android/view/inputmethod/BaseInputConnection.java
index 6a2a8d35a007..1ab9edf0caa2 100644
--- a/core/java/android/view/inputmethod/BaseInputConnection.java
+++ b/core/java/android/view/inputmethod/BaseInputConnection.java
@@ -43,6 +43,8 @@ import android.view.KeyEvent;
import android.view.OnReceiveContentListener;
import android.view.View;
+import com.android.internal.util.Preconditions;
+
class ComposingText implements NoCopySpan {
}
@@ -504,7 +506,7 @@ public class BaseInputConnection implements InputConnection {
*/
@Nullable
public CharSequence getTextBeforeCursor(@IntRange(from = 0) int length, int flags) {
- if (length < 0) return null;
+ Preconditions.checkArgumentNonnegative(length);
final Editable content = getEditable();
if (content == null) return null;
@@ -563,7 +565,7 @@ public class BaseInputConnection implements InputConnection {
*/
@Nullable
public CharSequence getTextAfterCursor(@IntRange(from = 0) int length, int flags) {
- if (length < 0) return null;
+ Preconditions.checkArgumentNonnegative(length);
final Editable content = getEditable();
if (content == null) return null;
@@ -600,7 +602,8 @@ public class BaseInputConnection implements InputConnection {
@Nullable
public SurroundingText getSurroundingText(
@IntRange(from = 0) int beforeLength, @IntRange(from = 0) int afterLength, int flags) {
- if (beforeLength < 0 || afterLength < 0) return null;
+ Preconditions.checkArgumentNonnegative(beforeLength);
+ Preconditions.checkArgumentNonnegative(afterLength);
final Editable content = getEditable();
if (content == null) return null;
diff --git a/core/java/com/android/internal/app/IBatteryStats.aidl b/core/java/com/android/internal/app/IBatteryStats.aidl
index e6a166140d89..6d98a5982c4f 100644
--- a/core/java/com/android/internal/app/IBatteryStats.aidl
+++ b/core/java/com/android/internal/app/IBatteryStats.aidl
@@ -52,7 +52,7 @@ interface IBatteryStats {
@UnsupportedAppUsage
byte[] getStatistics();
- ParcelFileDescriptor getStatisticsStream();
+ ParcelFileDescriptor getStatisticsStream(boolean updateAll);
// Return true if we see the battery as currently charging.
@UnsupportedAppUsage(maxTargetSdk = 30, trackingBug = 170729553)
diff --git a/core/java/com/android/internal/os/BatteryStatsHelper.java b/core/java/com/android/internal/os/BatteryStatsHelper.java
index 267674592b02..9e59e50cffd0 100644
--- a/core/java/com/android/internal/os/BatteryStatsHelper.java
+++ b/core/java/com/android/internal/os/BatteryStatsHelper.java
@@ -203,7 +203,7 @@ public class BatteryStatsHelper {
}
}
return getStats(IBatteryStats.Stub.asInterface(
- ServiceManager.getService(BatteryStats.SERVICE_NAME)));
+ ServiceManager.getService(BatteryStats.SERVICE_NAME)), true);
}
@UnsupportedAppUsage
@@ -223,8 +223,13 @@ public class BatteryStatsHelper {
@UnsupportedAppUsage
public BatteryStats getStats() {
+ return getStats(true /* updateAll */);
+ }
+
+ /** Retrieves stats from BatteryService, optionally getting updated numbers */
+ public BatteryStats getStats(boolean updateAll) {
if (mStats == null) {
- load();
+ load(updateAll);
}
return mStats;
}
@@ -720,19 +725,23 @@ public class BatteryStatsHelper {
@UnsupportedAppUsage
private void load() {
+ load(true);
+ }
+
+ private void load(boolean updateAll) {
if (mBatteryInfo == null) {
return;
}
- mStats = getStats(mBatteryInfo);
+ mStats = getStats(mBatteryInfo, updateAll);
if (mCollectBatteryBroadcast) {
mBatteryBroadcast = mContext.registerReceiver(null,
new IntentFilter(Intent.ACTION_BATTERY_CHANGED));
}
}
- private static BatteryStatsImpl getStats(IBatteryStats service) {
+ private static BatteryStatsImpl getStats(IBatteryStats service, boolean updateAll) {
try {
- ParcelFileDescriptor pfd = service.getStatisticsStream();
+ ParcelFileDescriptor pfd = service.getStatisticsStream(updateAll);
if (pfd != null) {
if (false) {
Log.d(TAG, "selinux context: "
diff --git a/core/java/com/android/internal/telephony/IPhoneStateListener.aidl b/core/java/com/android/internal/telephony/IPhoneStateListener.aidl
index 854fb17e692b..44dca9bae3da 100644
--- a/core/java/com/android/internal/telephony/IPhoneStateListener.aidl
+++ b/core/java/com/android/internal/telephony/IPhoneStateListener.aidl
@@ -69,6 +69,6 @@ oneway interface IPhoneStateListener {
void onRegistrationFailed(in CellIdentity cellIdentity,
String chosenPlmn, int domain, int causeCode, int additionalCauseCode);
void onBarringInfoChanged(in BarringInfo barringInfo);
- void onPhysicalChannelConfigChanged(in List<PhysicalChannelConfig> configs);
- void onDataEnabledChanged(boolean enabled, int reason);
+ void onPhysicalChannelConfigurationChanged(in List<PhysicalChannelConfig> configs);
+
}
diff --git a/core/java/com/android/internal/telephony/ITelephonyRegistry.aidl b/core/java/com/android/internal/telephony/ITelephonyRegistry.aidl
index ae1657b051e6..a28a66376497 100644
--- a/core/java/com/android/internal/telephony/ITelephonyRegistry.aidl
+++ b/core/java/com/android/internal/telephony/ITelephonyRegistry.aidl
@@ -41,10 +41,16 @@ interface ITelephonyRegistry {
IOnSubscriptionsChangedListener callback);
void removeOnSubscriptionsChangedListener(String pkg,
IOnSubscriptionsChangedListener callback);
-
- void listenWithEventList(in int subId, String pkg, String featureId,
- IPhoneStateListener callback, in int[] events, boolean notifyNow);
-
+ /**
+ * @deprecated Use {@link #listenWithFeature(String, String, IPhoneStateListener, int,
+ * boolean) instead
+ */
+ @UnsupportedAppUsage
+ void listen(String pkg, IPhoneStateListener callback, int events, boolean notifyNow);
+ void listenWithFeature(String pkg, String featureId, IPhoneStateListener callback, long events,
+ boolean notifyNow);
+ void listenForSubscriber(in int subId, String pkg, String featureId,
+ IPhoneStateListener callback, long events, boolean notifyNow);
@UnsupportedAppUsage(maxTargetSdk = 30, trackingBug = 170729553)
void notifyCallStateForAllSubs(int state, String incomingNumber);
void notifyCallState(in int phoneId, in int subId, int state, String incomingNumber);
@@ -93,6 +99,6 @@ interface ITelephonyRegistry {
void notifyRegistrationFailed(int slotIndex, int subId, in CellIdentity cellIdentity,
String chosenPlmn, int domain, int causeCode, int additionalCauseCode);
void notifyBarringInfoChanged(int slotIndex, int subId, in BarringInfo barringInfo);
- void notifyPhysicalChannelConfigForSubscriber(in int subId,
+ void notifyPhysicalChannelConfigurationForSubscriber(in int subId,
in List<PhysicalChannelConfig> configs);
}
diff --git a/core/jni/android_view_InputEventReceiver.cpp b/core/jni/android_view_InputEventReceiver.cpp
index 1ea918a900ad..1c78750f3610 100644
--- a/core/jni/android_view_InputEventReceiver.cpp
+++ b/core/jni/android_view_InputEventReceiver.cpp
@@ -50,6 +50,7 @@ static struct {
jmethodID dispatchInputEvent;
jmethodID onFocusEvent;
+ jmethodID onPointerCaptureEvent;
jmethodID onBatchedInputEventPending;
} gInputEventReceiverClassInfo;
@@ -345,6 +346,19 @@ status_t NativeInputEventReceiver::consumeEvents(JNIEnv* env,
finishInputEvent(seq, true /* handled */);
continue;
}
+ case AINPUT_EVENT_TYPE_CAPTURE: {
+ const CaptureEvent* captureEvent = static_cast<CaptureEvent*>(inputEvent);
+ if (kDebugDispatchCycle) {
+ ALOGD("channel '%s' ~ Received capture event: pointerCaptureEnabled=%s",
+ getInputChannelName().c_str(),
+ toString(captureEvent->getPointerCaptureEnabled()));
+ }
+ env->CallVoidMethod(receiverObj.get(),
+ gInputEventReceiverClassInfo.onPointerCaptureEvent,
+ jboolean(captureEvent->getPointerCaptureEnabled()));
+ finishInputEvent(seq, true /* handled */);
+ continue;
+ }
default:
assert(false); // InputConsumer should prevent this from ever happening
@@ -489,6 +503,9 @@ int register_android_view_InputEventReceiver(JNIEnv* env) {
"dispatchInputEvent", "(ILandroid/view/InputEvent;)V");
gInputEventReceiverClassInfo.onFocusEvent =
GetMethodIDOrDie(env, gInputEventReceiverClassInfo.clazz, "onFocusEvent", "(ZZ)V");
+ gInputEventReceiverClassInfo.onPointerCaptureEvent =
+ GetMethodIDOrDie(env, gInputEventReceiverClassInfo.clazz, "onPointerCaptureEvent",
+ "(Z)V");
gInputEventReceiverClassInfo.onBatchedInputEventPending =
GetMethodIDOrDie(env, gInputEventReceiverClassInfo.clazz, "onBatchedInputEventPending",
"(I)V");
diff --git a/core/proto/android/stats/camera/Android.bp b/core/proto/android/stats/camera/Android.bp
new file mode 100644
index 000000000000..cc75e57af87b
--- /dev/null
+++ b/core/proto/android/stats/camera/Android.bp
@@ -0,0 +1,33 @@
+// Copyright (C) 2020 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+java_library {
+ name: "cameraprotosnano",
+ proto: {
+ type: "nano",
+ },
+ srcs: [
+ "*.proto",
+ ],
+ java_version: "1.8",
+ target: {
+ android: {
+ jarjar_rules: "jarjar-rules.txt",
+ },
+ host: {
+ static_libs: ["libprotobuf-java-nano"],
+ }
+ },
+ sdk_version: "core_platform",
+}
diff --git a/core/proto/android/stats/camera/camera.proto b/core/proto/android/stats/camera/camera.proto
new file mode 100644
index 000000000000..406285551d98
--- /dev/null
+++ b/core/proto/android/stats/camera/camera.proto
@@ -0,0 +1,44 @@
+/*
+ * 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.
+ */
+
+syntax = "proto2";
+package android.stats.camera;
+option java_multiple_files = true;
+
+message CameraStreamProto {
+ // The stream width (in pixels)
+ optional int32 width = 1;
+ // The stream height (in pixels)
+ optional int32 height = 2;
+ // The format of the stream
+ optional int32 format = 3;
+ // The dataspace of the stream
+ optional int32 data_space = 4;
+ // The usage flag of the stream
+ optional int64 usage = 5;
+
+ // The number of requests for this stream
+ optional int64 request_count = 6;
+ // The number of buffer error for this stream
+ optional int64 error_count = 7;
+ // The capture latency of first request for this stream
+ optional int32 first_capture_latency_millis = 8;
+
+ // The maximum number of hal buffers
+ optional int32 max_hal_buffers = 9;
+ // The maximum number of app buffers
+ optional int32 max_app_buffers = 10;
+}
diff --git a/core/proto/android/stats/camera/jarjar-rules.txt b/core/proto/android/stats/camera/jarjar-rules.txt
new file mode 100644
index 000000000000..40043a861ceb
--- /dev/null
+++ b/core/proto/android/stats/camera/jarjar-rules.txt
@@ -0,0 +1 @@
+rule com.google.protobuf.nano.** com.android.framework.protobuf.nano.@1
diff --git a/core/proto/android/stats/mediametrics/mediametrics.proto b/core/proto/android/stats/mediametrics/mediametrics.proto
index 9d491263f8e0..eb8a3b19f263 100644
--- a/core/proto/android/stats/mediametrics/mediametrics.proto
+++ b/core/proto/android/stats/mediametrics/mediametrics.proto
@@ -166,12 +166,23 @@ message CodecData {
* Logged from:
* frameworks/av/media/libstagefright/RemoteMediaExtractor.cpp
* frameworks/av/services/mediaanalytics/statsd_extractor.cpp
- * Next Tag: 4
+ * Next Tag: 5
*/
message ExtractorData {
optional string format = 1;
optional string mime = 2;
optional int32 tracks = 3;
+
+ enum EntryPoint {
+ UNSET = 0; // For backwards compatibility with clients that don't
+ // collect the entry point.
+ SDK = 1;
+ NDK_WITH_JVM = 2;
+ NDK_NO_JVM = 3;
+ OTHER = 4; // For extractor users that don't make use of the APIs.
+ }
+
+ optional EntryPoint entry_point = 4 [default = UNSET];
}
/**
diff --git a/core/res/res/layout/notification_material_action_list.xml b/core/res/res/layout/notification_material_action_list.xml
index 552a1bd6aa2e..9662b8e35bf6 100644
--- a/core/res/res/layout/notification_material_action_list.xml
+++ b/core/res/res/layout/notification_material_action_list.xml
@@ -28,7 +28,6 @@
android:layout_height="wrap_content"
android:gravity="end"
android:orientation="horizontal"
- android:paddingEnd="@dimen/bubble_gone_padding_end"
android:background="@color/notification_action_list_background_color"
>
@@ -45,22 +44,34 @@
<!-- actions will be added here -->
</com.android.internal.widget.NotificationActionListLayout>
- <ImageView
- android:id="@+id/snooze_button"
- android:layout_width="@dimen/notification_actions_icon_size"
- android:layout_height="@dimen/notification_actions_icon_size"
- android:layout_gravity="center_vertical|end"
- android:visibility="gone"
- android:scaleType="centerInside"
- />
+ <!--
+ This nested linear layout exists to ensure that if the neither of the contained
+ actions is visible we have some minimum padding at the end of the actions is present,
+ then there will be 12dp of padding at the end of the actions list.
+ -->
+ <LinearLayout
+ android:layout_width="wrap_content"
+ android:layout_height="match_parent"
+ android:orientation="horizontal"
+ android:minWidth="@dimen/snooze_and_bubble_gone_padding_end"
+ >
+ <ImageView
+ android:id="@+id/snooze_button"
+ android:layout_width="@dimen/notification_actions_icon_size"
+ android:layout_height="@dimen/notification_actions_icon_size"
+ android:layout_gravity="center_vertical|end"
+ android:visibility="gone"
+ android:scaleType="centerInside"
+ />
- <ImageView
- android:id="@+id/bubble_button"
- android:layout_width="@dimen/notification_actions_icon_size"
- android:layout_height="@dimen/notification_actions_icon_size"
- android:layout_gravity="center_vertical|end"
- android:visibility="gone"
- android:scaleType="centerInside"
- />
+ <ImageView
+ android:id="@+id/bubble_button"
+ android:layout_width="@dimen/notification_actions_icon_size"
+ android:layout_height="@dimen/notification_actions_icon_size"
+ android:layout_gravity="center_vertical|end"
+ android:visibility="gone"
+ android:scaleType="centerInside"
+ />
+ </LinearLayout>
</LinearLayout>
</FrameLayout>
diff --git a/core/res/res/layout/notification_template_header.xml b/core/res/res/layout/notification_template_header.xml
index a26473ad6010..b0ee12a520d9 100644
--- a/core/res/res/layout/notification_template_header.xml
+++ b/core/res/res/layout/notification_template_header.xml
@@ -50,20 +50,18 @@
android:theme="@style/Theme.DeviceDefault.Notification"
>
- <TextView
- android:id="@+id/app_name_text"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginEnd="@dimen/notification_header_separating_margin"
- android:singleLine="true"
- android:textAppearance="?attr/notificationHeaderTextAppearance"
- android:visibility="?attr/notificationHeaderAppNameVisibility"
- />
-
<include layout="@layout/notification_top_line_views" />
</NotificationTopLineView>
+ <FrameLayout
+ android:id="@+id/alternate_expand_target"
+ android:layout_width="@dimen/notification_content_margin_start"
+ android:layout_height="match_parent"
+ android:layout_gravity="start"
+ android:importantForAccessibility="no"
+ />
+
<com.android.internal.widget.NotificationExpandButton
android:id="@+id/expand_button"
android:layout_width="@dimen/notification_header_expand_icon_size"
diff --git a/core/res/res/layout/notification_template_material_base.xml b/core/res/res/layout/notification_template_material_base.xml
index ded16b7edf87..69d4a12f4d69 100644
--- a/core/res/res/layout/notification_template_material_base.xml
+++ b/core/res/res/layout/notification_template_material_base.xml
@@ -68,6 +68,12 @@
android:theme="@style/Theme.DeviceDefault.Notification"
>
+ <!--
+ NOTE: The notification_top_line_views layout contains the app_name_text.
+ In order to include the title view at the beginning, the Notification.Builder
+ has logic to hide that view whenever this title view is to be visible.
+ -->
+
<TextView
android:id="@+id/title"
android:layout_width="wrap_content"
@@ -138,6 +144,14 @@
/>
<FrameLayout
+ android:id="@+id/alternate_expand_target"
+ android:layout_width="@dimen/notification_content_margin_start"
+ android:layout_height="match_parent"
+ android:layout_gravity="start"
+ android:importantForAccessibility="no"
+ />
+
+ <FrameLayout
android:id="@+id/expand_button_touch_container"
android:layout_width="wrap_content"
android:layout_height="match_parent"
diff --git a/core/res/res/layout/notification_template_material_big_media.xml b/core/res/res/layout/notification_template_material_big_media.xml
index 4cf323b24f0a..696cb6572e29 100644
--- a/core/res/res/layout/notification_template_material_big_media.xml
+++ b/core/res/res/layout/notification_template_material_big_media.xml
@@ -50,16 +50,56 @@
android:id="@+id/notification_main_column"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:layout_marginTop="@dimen/notification_content_margin_top"
+ android:layout_marginTop="46dp"
android:layout_marginStart="@dimen/notification_content_margin_start"
android:layout_marginBottom="@dimen/notification_content_margin"
android:layout_marginEnd="@dimen/notification_content_margin_end"
android:orientation="vertical"
>
+ <!-- TODO(b/172652345): fix the media style -->
+ <!--<include layout="@layout/notification_template_part_line1"/>-->
+ <!--<include layout="@layout/notification_template_text"/>-->
- <include layout="@layout/notification_template_part_line1" />
+ <LinearLayout
+ android:id="@+id/line1"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="horizontal"
+ >
+ <TextView android:id="@+id/title"
+ android:textAppearance="@style/TextAppearance.DeviceDefault.Notification.Title"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:singleLine="true"
+ android:ellipsize="marquee"
+ android:fadingEdge="horizontal"
+ android:textAlignment="viewStart"
+ />
+ <TextView android:id="@+id/text_line_1"
+ style="@style/Widget.DeviceDefault.Notification.Text"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:gravity="end|bottom"
+ android:layout_marginStart="16dp"
+ android:singleLine="true"
+ android:ellipsize="marquee"
+ android:fadingEdge="horizontal"
+ />
+ </LinearLayout>
- <include layout="@layout/notification_template_text" />
+ <com.android.internal.widget.ImageFloatingTextView
+ style="@style/Widget.DeviceDefault.Notification.Text"
+ android:id="@+id/text"
+ android:layout_width="match_parent"
+ android:layout_height="@dimen/notification_text_height"
+ android:layout_gravity="top"
+ android:layout_marginTop="0.5dp"
+ android:ellipsize="marquee"
+ android:fadingEdge="horizontal"
+ android:gravity="top"
+ android:singleLine="true"
+ android:textAlignment="viewStart"
+ />
</LinearLayout>
<LinearLayout
diff --git a/core/res/res/layout/notification_template_material_conversation.xml b/core/res/res/layout/notification_template_material_conversation.xml
index 520ae282b942..f9364d565f3b 100644
--- a/core/res/res/layout/notification_template_material_conversation.xml
+++ b/core/res/res/layout/notification_template_material_conversation.xml
@@ -327,10 +327,10 @@
android:id="@+id/expand_button_touch_container"
android:layout_width="wrap_content"
android:layout_height="@dimen/conversation_expand_button_size"
- android:paddingStart="16dp"
+ android:paddingStart="@dimen/conversation_expand_button_side_margin"
android:orientation="horizontal"
android:layout_gravity="end|top"
- android:paddingEnd="@dimen/notification_content_margin_end"
+ android:paddingEnd="@dimen/conversation_expand_button_side_margin"
android:clipToPadding="false"
android:clipChildren="false"
>
diff --git a/core/res/res/layout/notification_template_material_media.xml b/core/res/res/layout/notification_template_material_media.xml
index 52053dcdf800..7daccd2b8544 100644
--- a/core/res/res/layout/notification_template_material_media.xml
+++ b/core/res/res/layout/notification_template_material_media.xml
@@ -45,7 +45,7 @@
android:layout_height="wrap_content"
android:orientation="horizontal"
android:layout_marginStart="@dimen/notification_content_margin_start"
- android:layout_marginTop="@dimen/notification_content_margin_top"
+ android:layout_marginTop="46dp"
android:layout_alignParentTop="true"
android:tag="media"
>
@@ -58,8 +58,50 @@
android:paddingBottom="@dimen/notification_content_margin"
android:orientation="vertical"
>
- <include layout="@layout/notification_template_part_line1"/>
- <include layout="@layout/notification_template_text"/>
+ <!-- TODO(b/172652345): fix the media style -->
+ <!--<include layout="@layout/notification_template_part_line1"/>-->
+ <!--<include layout="@layout/notification_template_text"/>-->
+
+ <LinearLayout
+ android:id="@+id/line1"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="horizontal"
+ >
+ <TextView android:id="@+id/title"
+ android:textAppearance="@style/TextAppearance.DeviceDefault.Notification.Title"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:singleLine="true"
+ android:ellipsize="marquee"
+ android:fadingEdge="horizontal"
+ android:textAlignment="viewStart"
+ />
+ <TextView android:id="@+id/text_line_1"
+ style="@style/Widget.DeviceDefault.Notification.Text"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:gravity="end|bottom"
+ android:layout_marginStart="16dp"
+ android:singleLine="true"
+ android:ellipsize="marquee"
+ android:fadingEdge="horizontal"
+ />
+ </LinearLayout>
+
+ <com.android.internal.widget.ImageFloatingTextView
+ style="@style/Widget.DeviceDefault.Notification.Text"
+ android:id="@+id/text"
+ android:layout_width="match_parent"
+ android:layout_height="@dimen/notification_text_height"
+ android:layout_gravity="top"
+ android:layout_marginTop="0.5dp"
+ android:ellipsize="marquee"
+ android:fadingEdge="horizontal"
+ android:gravity="top"
+ android:singleLine="true"
+ android:textAlignment="viewStart"
+ />
</LinearLayout>
<LinearLayout
android:id="@+id/media_actions"
diff --git a/core/res/res/layout/notification_top_line_views.xml b/core/res/res/layout/notification_top_line_views.xml
index 51974ac7dcf3..c71e8863502c 100644
--- a/core/res/res/layout/notification_top_line_views.xml
+++ b/core/res/res/layout/notification_top_line_views.xml
@@ -14,13 +14,23 @@
~ limitations under the License
-->
<!--
- This layout file should be included inside a NotificationTopLineView, usually after either a
- <TextView android:id="@+id/app_name_text"/> or <TextView android:id="@+id/title"/>
+ This layout file should be included inside a NotificationTopLineView, sometimes after a
+ <TextView android:id="@+id/title"/>
-->
<merge
xmlns:android="http://schemas.android.com/apk/res/android">
<TextView
+ android:id="@+id/app_name_text"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginEnd="@dimen/notification_header_separating_margin"
+ android:singleLine="true"
+ android:textAppearance="?attr/notificationHeaderTextAppearance"
+ android:visibility="?attr/notificationHeaderAppNameVisibility"
+ />
+
+ <TextView
android:id="@+id/header_text_secondary_divider"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
diff --git a/core/res/res/values-af/strings.xml b/core/res/res/values-af/strings.xml
index 31993fb5860d..171d89628518 100644
--- a/core/res/res/values-af/strings.xml
+++ b/core/res/res/values-af/strings.xml
@@ -287,6 +287,8 @@
<string name="notification_channel_usb" msgid="1528280969406244896">"USB-verbinding"</string>
<string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"Program loop tans"</string>
<string name="notification_channel_foreground_service" msgid="7102189948158885178">"Programme wat batterykrag gebruik"</string>
+ <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) -->
+ <skip />
<string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> gebruik tans batterykrag"</string>
<string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> programme gebruik tans batterykrag"</string>
<string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Tik vir besonderhede oor battery- en datagebruik"</string>
@@ -2188,4 +2190,12 @@
<string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string>
<string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string>
<string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string>
+ <!-- no translation found for window_magnification_prompt_title (8197528399699536320) -->
+ <skip />
+ <!-- no translation found for window_magnification_prompt_content (4166711383253283838) -->
+ <skip />
+ <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) -->
+ <skip />
+ <!-- no translation found for dismiss_action (1728820550388704784) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-am/strings.xml b/core/res/res/values-am/strings.xml
index dee3521a1b2e..5871fe24920a 100644
--- a/core/res/res/values-am/strings.xml
+++ b/core/res/res/values-am/strings.xml
@@ -287,6 +287,8 @@
<string name="notification_channel_usb" msgid="1528280969406244896">"የዩኤስቢ ግንኙነት"</string>
<string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"APP እየሠራ ነው"</string>
<string name="notification_channel_foreground_service" msgid="7102189948158885178">"ባትሪ በመፍጀት ላይ ያሉ መተግበሪያዎች"</string>
+ <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) -->
+ <skip />
<string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> ባትሪ እየተጠቀመ ነው"</string>
<string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> መተግበሪያዎች ባትሪ እየተጠቀሙ ነው"</string>
<string name="foreground_service_tap_for_details" msgid="9078123626015586751">"በባትሪ እና ውሂብ አጠቃቀም ላይ ዝርዝሮችን ለማግኘት መታ ያድርጉ"</string>
@@ -2188,4 +2190,12 @@
<string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string>
<string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string>
<string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string>
+ <!-- no translation found for window_magnification_prompt_title (8197528399699536320) -->
+ <skip />
+ <!-- no translation found for window_magnification_prompt_content (4166711383253283838) -->
+ <skip />
+ <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) -->
+ <skip />
+ <!-- no translation found for dismiss_action (1728820550388704784) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-ar/strings.xml b/core/res/res/values-ar/strings.xml
index 905d2ddad1db..b57876906a94 100644
--- a/core/res/res/values-ar/strings.xml
+++ b/core/res/res/values-ar/strings.xml
@@ -299,6 +299,8 @@
<string name="notification_channel_usb" msgid="1528280969406244896">"‏اتصال USB"</string>
<string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"التطبيق قيد التشغيل"</string>
<string name="notification_channel_foreground_service" msgid="7102189948158885178">"التطبيقات التي تستهلك البطارية"</string>
+ <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) -->
+ <skip />
<string name="foreground_service_app_in_background" msgid="1439289699671273555">"يستخدم تطبيق <xliff:g id="APP_NAME">%1$s</xliff:g> البطارية"</string>
<string name="foreground_service_apps_in_background" msgid="7340037176412387863">"تستخدم <xliff:g id="NUMBER">%1$d</xliff:g> من التطبيقات البطارية"</string>
<string name="foreground_service_tap_for_details" msgid="9078123626015586751">"انقر للحصول على تفاصيل حول البطارية واستخدام البيانات"</string>
@@ -2324,4 +2326,12 @@
<string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string>
<string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string>
<string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string>
+ <!-- no translation found for window_magnification_prompt_title (8197528399699536320) -->
+ <skip />
+ <!-- no translation found for window_magnification_prompt_content (4166711383253283838) -->
+ <skip />
+ <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) -->
+ <skip />
+ <!-- no translation found for dismiss_action (1728820550388704784) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-as/strings.xml b/core/res/res/values-as/strings.xml
index e58274cedf89..f1b0d84883a0 100644
--- a/core/res/res/values-as/strings.xml
+++ b/core/res/res/values-as/strings.xml
@@ -287,6 +287,8 @@
<string name="notification_channel_usb" msgid="1528280969406244896">"ইউএছবি সংযোগ"</string>
<string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"এপ্ চলি আছে"</string>
<string name="notification_channel_foreground_service" msgid="7102189948158885178">"বেটাৰি খৰচ কৰা এপসমূহ"</string>
+ <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) -->
+ <skip />
<string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g>এ বেটাৰি ব্যৱহাৰ কৰি আছে"</string>
<string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g>টা এপে বেটাৰি ব্যৱহাৰ কৰি আছে"</string>
<string name="foreground_service_tap_for_details" msgid="9078123626015586751">"বেটাৰি আৰু ডেটাৰ ব্যৱহাৰৰ বিষয়ে বিশদভাৱে জানিবলৈ টিপক"</string>
@@ -2188,4 +2190,12 @@
<string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string>
<string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string>
<string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string>
+ <!-- no translation found for window_magnification_prompt_title (8197528399699536320) -->
+ <skip />
+ <!-- no translation found for window_magnification_prompt_content (4166711383253283838) -->
+ <skip />
+ <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) -->
+ <skip />
+ <!-- no translation found for dismiss_action (1728820550388704784) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-az/strings.xml b/core/res/res/values-az/strings.xml
index 499cd202b8ea..01fb48e18462 100644
--- a/core/res/res/values-az/strings.xml
+++ b/core/res/res/values-az/strings.xml
@@ -287,6 +287,8 @@
<string name="notification_channel_usb" msgid="1528280969406244896">"USB əlaqə"</string>
<string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"Tətbiq işləyir"</string>
<string name="notification_channel_foreground_service" msgid="7102189948158885178">"Batareyadan istifadə edən tətbiqlər"</string>
+ <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) -->
+ <skip />
<string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> batareyadan istifadə edir"</string>
<string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> tətbiq batareyadan istifadə edir"</string>
<string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Batareya və data istifadəsi haqqında ətraflı məlumat üçün klikləyin"</string>
@@ -2188,4 +2190,12 @@
<string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string>
<string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string>
<string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string>
+ <!-- no translation found for window_magnification_prompt_title (8197528399699536320) -->
+ <skip />
+ <!-- no translation found for window_magnification_prompt_content (4166711383253283838) -->
+ <skip />
+ <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) -->
+ <skip />
+ <!-- no translation found for dismiss_action (1728820550388704784) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-b+sr+Latn/strings.xml b/core/res/res/values-b+sr+Latn/strings.xml
index 5e264537c2b0..bfbd3e4586f2 100644
--- a/core/res/res/values-b+sr+Latn/strings.xml
+++ b/core/res/res/values-b+sr+Latn/strings.xml
@@ -123,28 +123,28 @@
<string name="roamingText11" msgid="5245687407203281407">"Baner rominga je uključen"</string>
<string name="roamingText12" msgid="673537506362152640">"Baner rominga je isključen"</string>
<string name="roamingTextSearching" msgid="5323235489657753486">"Pretraživanje usluge"</string>
- <string name="wfcRegErrorTitle" msgid="3193072971584858020">"Podešavanje pozivanja preko WiFi-ja nije uspelo"</string>
+ <string name="wfcRegErrorTitle" msgid="3193072971584858020">"Podešavanje pozivanja preko WiFi-a nije uspelo"</string>
<string-array name="wfcOperatorErrorAlertMessages">
- <item msgid="468830943567116703">"Da biste upućivali pozive i slali poruke preko WiFi-ja, prvo zatražite od mobilnog operatera da vam omogući ovu uslugu. Zatim u Podešavanjima ponovo uključite Pozivanje preko WiFi-ja. (kôd greške: <xliff:g id="CODE">%1$s</xliff:g>)"</item>
+ <item msgid="468830943567116703">"Da biste upućivali pozive i slali poruke preko WiFi-a, prvo zatražite od mobilnog operatera da vam omogući ovu uslugu. Zatim u Podešavanjima ponovo uključite Pozivanje preko WiFi-a. (kôd greške: <xliff:g id="CODE">%1$s</xliff:g>)"</item>
</string-array>
<string-array name="wfcOperatorErrorNotificationMessages">
<item msgid="4795145070505729156">"Problem u vezi sa registrovanjem pozivanja preko Wi‑Fi-ja kod mobilnog operatera: <xliff:g id="CODE">%1$s</xliff:g>"</item>
</string-array>
<!-- no translation found for wfcSpnFormat_spn (2982505428519096311) -->
<skip />
- <string name="wfcSpnFormat_spn_wifi_calling" msgid="3165949348000906194">"<xliff:g id="SPN">%s</xliff:g> pozivanje preko WiFi-ja"</string>
- <string name="wfcSpnFormat_spn_wifi_calling_vo_hyphen" msgid="3836827895369365298">"<xliff:g id="SPN">%s</xliff:g> – pozivanje preko WiFi-ja"</string>
+ <string name="wfcSpnFormat_spn_wifi_calling" msgid="3165949348000906194">"<xliff:g id="SPN">%s</xliff:g> pozivanje preko WiFi-a"</string>
+ <string name="wfcSpnFormat_spn_wifi_calling_vo_hyphen" msgid="3836827895369365298">"<xliff:g id="SPN">%s</xliff:g> – pozivanje preko WiFi-a"</string>
<string name="wfcSpnFormat_wlan_call" msgid="4895315549916165700">"WLAN poziv"</string>
<string name="wfcSpnFormat_spn_wlan_call" msgid="255919245825481510">"<xliff:g id="SPN">%s</xliff:g> WLAN poziv"</string>
<string name="wfcSpnFormat_spn_wifi" msgid="7232899594327126970">"<xliff:g id="SPN">%s</xliff:g> WiFi"</string>
- <string name="wfcSpnFormat_wifi_calling_bar_spn" msgid="8383917598312067365">"Pozivanje preko WiFi-ja | <xliff:g id="SPN">%s</xliff:g>"</string>
+ <string name="wfcSpnFormat_wifi_calling_bar_spn" msgid="8383917598312067365">"Pozivanje preko WiFi-a | <xliff:g id="SPN">%s</xliff:g>"</string>
<string name="wfcSpnFormat_spn_vowifi" msgid="6865214948822061486">"<xliff:g id="SPN">%s</xliff:g> VoWifi"</string>
- <string name="wfcSpnFormat_wifi_calling" msgid="6178935388378661755">"Pozivanje preko WiFi-ja"</string>
+ <string name="wfcSpnFormat_wifi_calling" msgid="6178935388378661755">"Pozivanje preko WiFi-a"</string>
<string name="wfcSpnFormat_wifi" msgid="1376356951297043426">"WiFi"</string>
- <string name="wfcSpnFormat_wifi_calling_wo_hyphen" msgid="7178561009225028264">"Pozivanje preko WiFi-ja"</string>
+ <string name="wfcSpnFormat_wifi_calling_wo_hyphen" msgid="7178561009225028264">"Pozivanje preko WiFi-a"</string>
<string name="wfcSpnFormat_vowifi" msgid="8371335230890725606">"VoWifi"</string>
<string name="wifi_calling_off_summary" msgid="5626710010766902560">"Isključeno"</string>
- <string name="wfc_mode_wifi_preferred_summary" msgid="1035175836270943089">"Pozivanje preko WiFi-ja"</string>
+ <string name="wfc_mode_wifi_preferred_summary" msgid="1035175836270943089">"Pozivanje preko WiFi-a"</string>
<string name="wfc_mode_cellular_preferred_summary" msgid="4958965609212575619">"Poziv preko mobilne mreže"</string>
<string name="wfc_mode_wifi_only_summary" msgid="104951993894678665">"Samo WiFi"</string>
<string name="cfTemplateNotForwarded" msgid="862202427794270501">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: Nije prosleđeno"</string>
@@ -290,6 +290,8 @@
<string name="notification_channel_usb" msgid="1528280969406244896">"USB veza"</string>
<string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"Aktivna aplikacija"</string>
<string name="notification_channel_foreground_service" msgid="7102189948158885178">"Aplikacije koje troše bateriju"</string>
+ <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) -->
+ <skip />
<string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> koristi bateriju"</string>
<string name="foreground_service_apps_in_background" msgid="7340037176412387863">"Aplikacije (<xliff:g id="NUMBER">%1$d</xliff:g>) koriste bateriju"</string>
<string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Dodirnite za detalje o bateriji i potrošnji podataka"</string>
@@ -2222,4 +2224,12 @@
<string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string>
<string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string>
<string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string>
+ <!-- no translation found for window_magnification_prompt_title (8197528399699536320) -->
+ <skip />
+ <!-- no translation found for window_magnification_prompt_content (4166711383253283838) -->
+ <skip />
+ <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) -->
+ <skip />
+ <!-- no translation found for dismiss_action (1728820550388704784) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-be/strings.xml b/core/res/res/values-be/strings.xml
index d6a725706433..c4a3a7e980c4 100644
--- a/core/res/res/values-be/strings.xml
+++ b/core/res/res/values-be/strings.xml
@@ -293,6 +293,8 @@
<string name="notification_channel_usb" msgid="1528280969406244896">"Падключэнне USB"</string>
<string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"Праграма працуе"</string>
<string name="notification_channel_foreground_service" msgid="7102189948158885178">"Праграмы, якія выкарыстоўваюць акумулятар"</string>
+ <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) -->
+ <skip />
<string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> выкарыстоўвае акумулятар"</string>
<string name="foreground_service_apps_in_background" msgid="7340037176412387863">"Наступная колькасць праграм выкарыстоўваюць акумулятар: <xliff:g id="NUMBER">%1$d</xliff:g>"</string>
<string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Дакраніцеся, каб даведацца пра выкарыстанне трафіка і акумулятара"</string>
@@ -2256,4 +2258,12 @@
<string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string>
<string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string>
<string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string>
+ <!-- no translation found for window_magnification_prompt_title (8197528399699536320) -->
+ <skip />
+ <!-- no translation found for window_magnification_prompt_content (4166711383253283838) -->
+ <skip />
+ <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) -->
+ <skip />
+ <!-- no translation found for dismiss_action (1728820550388704784) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-bg/strings.xml b/core/res/res/values-bg/strings.xml
index 376ef26412ff..07f1ce7b9bf9 100644
--- a/core/res/res/values-bg/strings.xml
+++ b/core/res/res/values-bg/strings.xml
@@ -287,6 +287,8 @@
<string name="notification_channel_usb" msgid="1528280969406244896">"USB връзка"</string>
<string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"Приложението работи"</string>
<string name="notification_channel_foreground_service" msgid="7102189948158885178">"Приложения, използващи батерията"</string>
+ <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) -->
+ <skip />
<string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> използва батерията"</string>
<string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> приложения използват батерията"</string>
<string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Докоснете за информация относно използването на батерията и преноса на данни"</string>
@@ -2188,4 +2190,12 @@
<string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string>
<string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string>
<string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string>
+ <!-- no translation found for window_magnification_prompt_title (8197528399699536320) -->
+ <skip />
+ <!-- no translation found for window_magnification_prompt_content (4166711383253283838) -->
+ <skip />
+ <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) -->
+ <skip />
+ <!-- no translation found for dismiss_action (1728820550388704784) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-bn/strings.xml b/core/res/res/values-bn/strings.xml
index 3b92f87cfc1c..9b85fc7a4d7d 100644
--- a/core/res/res/values-bn/strings.xml
+++ b/core/res/res/values-bn/strings.xml
@@ -287,6 +287,8 @@
<string name="notification_channel_usb" msgid="1528280969406244896">"USB সংযোগ"</string>
<string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"অ্যাপ চলছে"</string>
<string name="notification_channel_foreground_service" msgid="7102189948158885178">"কিছু অ্যাপ ব্যাটারি ব্যবহার করছে"</string>
+ <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) -->
+ <skip />
<string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> অ্যাপটি ব্যাটারি ব্যবহার করছে"</string>
<string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g>টি অ্যাপ ব্যাটারি ব্যবহার করছে"</string>
<string name="foreground_service_tap_for_details" msgid="9078123626015586751">"ব্যাটারি এবং ডেটার ব্যবহারের বিশদ বিবরণের জন্য ট্যাপ করুন"</string>
@@ -802,7 +804,7 @@
<string name="orgTypeOther" msgid="5450675258408005553">"অন্যান্য"</string>
<string name="orgTypeCustom" msgid="1126322047677329218">"কাস্টম"</string>
<string name="relationTypeCustom" msgid="282938315217441351">"কাস্টম"</string>
- <string name="relationTypeAssistant" msgid="4057605157116589315">"Assistant"</string>
+ <string name="relationTypeAssistant" msgid="4057605157116589315">"অ্যাসিস্ট্যান্ট"</string>
<string name="relationTypeBrother" msgid="7141662427379247820">"ভাই"</string>
<string name="relationTypeChild" msgid="9076258911292693601">"সন্তান"</string>
<string name="relationTypeDomesticPartner" msgid="7825306887697559238">"জীবনসাথি"</string>
@@ -2188,4 +2190,12 @@
<string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string>
<string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string>
<string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string>
+ <!-- no translation found for window_magnification_prompt_title (8197528399699536320) -->
+ <skip />
+ <!-- no translation found for window_magnification_prompt_content (4166711383253283838) -->
+ <skip />
+ <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) -->
+ <skip />
+ <!-- no translation found for dismiss_action (1728820550388704784) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-bs/strings.xml b/core/res/res/values-bs/strings.xml
index f180df6dbe71..3d2249b17122 100644
--- a/core/res/res/values-bs/strings.xml
+++ b/core/res/res/values-bs/strings.xml
@@ -290,6 +290,8 @@
<string name="notification_channel_usb" msgid="1528280969406244896">"USB veza"</string>
<string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"Pokrenuta aplikacija"</string>
<string name="notification_channel_foreground_service" msgid="7102189948158885178">"Aplikacije koje troše bateriju"</string>
+ <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) -->
+ <skip />
<string name="foreground_service_app_in_background" msgid="1439289699671273555">"Aplikacija <xliff:g id="APP_NAME">%1$s</xliff:g> troši bateriju"</string>
<string name="foreground_service_apps_in_background" msgid="7340037176412387863">"Broj aplikacija koje troše bateriju: <xliff:g id="NUMBER">%1$d</xliff:g>"</string>
<string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Dodirnite za detalje o potrošnji baterije i prijenosa podataka"</string>
@@ -2222,4 +2224,12 @@
<string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string>
<string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string>
<string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string>
+ <!-- no translation found for window_magnification_prompt_title (8197528399699536320) -->
+ <skip />
+ <!-- no translation found for window_magnification_prompt_content (4166711383253283838) -->
+ <skip />
+ <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) -->
+ <skip />
+ <!-- no translation found for dismiss_action (1728820550388704784) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-ca/strings.xml b/core/res/res/values-ca/strings.xml
index 4d45791c9bdc..f1845e340afa 100644
--- a/core/res/res/values-ca/strings.xml
+++ b/core/res/res/values-ca/strings.xml
@@ -287,6 +287,8 @@
<string name="notification_channel_usb" msgid="1528280969406244896">"Connexió USB"</string>
<string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"Aplicació en execució"</string>
<string name="notification_channel_foreground_service" msgid="7102189948158885178">"Aplicacions que consumeixen bateria"</string>
+ <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) -->
+ <skip />
<string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> està consumint bateria"</string>
<string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> aplicacions estan consumint bateria"</string>
<string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Toca per obtenir informació sobre l\'ús de dades i de bateria"</string>
@@ -2188,4 +2190,12 @@
<string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string>
<string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string>
<string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string>
+ <!-- no translation found for window_magnification_prompt_title (8197528399699536320) -->
+ <skip />
+ <!-- no translation found for window_magnification_prompt_content (4166711383253283838) -->
+ <skip />
+ <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) -->
+ <skip />
+ <!-- no translation found for dismiss_action (1728820550388704784) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-cs/strings.xml b/core/res/res/values-cs/strings.xml
index e9f1fad5e95d..42d56369c3af 100644
--- a/core/res/res/values-cs/strings.xml
+++ b/core/res/res/values-cs/strings.xml
@@ -293,6 +293,8 @@
<string name="notification_channel_usb" msgid="1528280969406244896">"Připojení USB"</string>
<string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"Aplikace je spuštěna"</string>
<string name="notification_channel_foreground_service" msgid="7102189948158885178">"Aplikace spotřebovávají baterii"</string>
+ <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) -->
+ <skip />
<string name="foreground_service_app_in_background" msgid="1439289699671273555">"Aplikace <xliff:g id="APP_NAME">%1$s</xliff:g> využívá baterii"</string>
<string name="foreground_service_apps_in_background" msgid="7340037176412387863">"Aplikace (<xliff:g id="NUMBER">%1$d</xliff:g>) využívají baterii"</string>
<string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Klepnutím zobrazíte podrobnosti o využití baterie a dat"</string>
@@ -2256,4 +2258,12 @@
<string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string>
<string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string>
<string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string>
+ <!-- no translation found for window_magnification_prompt_title (8197528399699536320) -->
+ <skip />
+ <!-- no translation found for window_magnification_prompt_content (4166711383253283838) -->
+ <skip />
+ <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) -->
+ <skip />
+ <!-- no translation found for dismiss_action (1728820550388704784) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-da/strings.xml b/core/res/res/values-da/strings.xml
index 75bdda0b590c..0487406d4e7c 100644
--- a/core/res/res/values-da/strings.xml
+++ b/core/res/res/values-da/strings.xml
@@ -287,6 +287,8 @@
<string name="notification_channel_usb" msgid="1528280969406244896">"USB-forbindelse"</string>
<string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"Appen kører"</string>
<string name="notification_channel_foreground_service" msgid="7102189948158885178">"Apps, der bruger batteri"</string>
+ <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) -->
+ <skip />
<string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> bruger batteri"</string>
<string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> apps bruger batteri"</string>
<string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Tryk for at se info om batteri- og dataforbrug"</string>
@@ -2188,4 +2190,12 @@
<string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string>
<string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string>
<string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string>
+ <!-- no translation found for window_magnification_prompt_title (8197528399699536320) -->
+ <skip />
+ <!-- no translation found for window_magnification_prompt_content (4166711383253283838) -->
+ <skip />
+ <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) -->
+ <skip />
+ <!-- no translation found for dismiss_action (1728820550388704784) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-de/strings.xml b/core/res/res/values-de/strings.xml
index 6d82b62daf2e..ebbde3c9afef 100644
--- a/core/res/res/values-de/strings.xml
+++ b/core/res/res/values-de/strings.xml
@@ -287,6 +287,8 @@
<string name="notification_channel_usb" msgid="1528280969406244896">"USB-Verbindung"</string>
<string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"App wird ausgeführt"</string>
<string name="notification_channel_foreground_service" msgid="7102189948158885178">"Strom verbrauchende Apps"</string>
+ <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) -->
+ <skip />
<string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> verbraucht Strom"</string>
<string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> Apps verbrauchen Strom"</string>
<string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Für Details zur Akku- und Datennutzung tippen"</string>
@@ -2188,4 +2190,12 @@
<string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string>
<string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string>
<string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string>
+ <!-- no translation found for window_magnification_prompt_title (8197528399699536320) -->
+ <skip />
+ <!-- no translation found for window_magnification_prompt_content (4166711383253283838) -->
+ <skip />
+ <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) -->
+ <skip />
+ <!-- no translation found for dismiss_action (1728820550388704784) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-el/strings.xml b/core/res/res/values-el/strings.xml
index 42513aa77300..306d36e0ae9f 100644
--- a/core/res/res/values-el/strings.xml
+++ b/core/res/res/values-el/strings.xml
@@ -287,6 +287,8 @@
<string name="notification_channel_usb" msgid="1528280969406244896">"Σύνδεση USB"</string>
<string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"Η εφαρμογή εκτελείται"</string>
<string name="notification_channel_foreground_service" msgid="7102189948158885178">"Εφαρμογές που καταναλώνουν μπαταρία"</string>
+ <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) -->
+ <skip />
<string name="foreground_service_app_in_background" msgid="1439289699671273555">"Η εφαρμογή <xliff:g id="APP_NAME">%1$s</xliff:g> χρησιμοποιεί μπαταρία"</string>
<string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> εφαρμογές χρησιμοποιούν μπαταρία"</string>
<string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Πατήστε για λεπτομέρειες σχετικά με τη χρήση μπαταρίας και δεδομένων"</string>
@@ -2188,4 +2190,12 @@
<string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string>
<string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string>
<string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string>
+ <!-- no translation found for window_magnification_prompt_title (8197528399699536320) -->
+ <skip />
+ <!-- no translation found for window_magnification_prompt_content (4166711383253283838) -->
+ <skip />
+ <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) -->
+ <skip />
+ <!-- no translation found for dismiss_action (1728820550388704784) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-en-rAU/strings.xml b/core/res/res/values-en-rAU/strings.xml
index ef5a92a6351c..a8706cbe32c2 100644
--- a/core/res/res/values-en-rAU/strings.xml
+++ b/core/res/res/values-en-rAU/strings.xml
@@ -287,6 +287,7 @@
<string name="notification_channel_usb" msgid="1528280969406244896">"USB connection"</string>
<string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"App running"</string>
<string name="notification_channel_foreground_service" msgid="7102189948158885178">"Apps consuming battery"</string>
+ <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Magnification"</string>
<string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> is using battery"</string>
<string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> apps are using battery"</string>
<string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Tap for details on battery and data usage"</string>
@@ -2188,4 +2189,8 @@
<string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string>
<string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string>
<string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string>
+ <string name="window_magnification_prompt_title" msgid="8197528399699536320">"New: Window magnifier"</string>
+ <string name="window_magnification_prompt_content" msgid="4166711383253283838">"You can now magnify some or all of your screen"</string>
+ <string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"Turn on in settings"</string>
+ <string name="dismiss_action" msgid="1728820550388704784">"Dismiss"</string>
</resources>
diff --git a/core/res/res/values-en-rCA/strings.xml b/core/res/res/values-en-rCA/strings.xml
index 6dae39bbc638..57e2eae62f9c 100644
--- a/core/res/res/values-en-rCA/strings.xml
+++ b/core/res/res/values-en-rCA/strings.xml
@@ -287,6 +287,7 @@
<string name="notification_channel_usb" msgid="1528280969406244896">"USB connection"</string>
<string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"App running"</string>
<string name="notification_channel_foreground_service" msgid="7102189948158885178">"Apps consuming battery"</string>
+ <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Magnification"</string>
<string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> is using battery"</string>
<string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> apps are using battery"</string>
<string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Tap for details on battery and data usage"</string>
@@ -2188,4 +2189,8 @@
<string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string>
<string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string>
<string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string>
+ <string name="window_magnification_prompt_title" msgid="8197528399699536320">"New: Window magnifier"</string>
+ <string name="window_magnification_prompt_content" msgid="4166711383253283838">"You can now magnify some or all of your screen"</string>
+ <string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"Turn on in settings"</string>
+ <string name="dismiss_action" msgid="1728820550388704784">"Dismiss"</string>
</resources>
diff --git a/core/res/res/values-en-rGB/strings.xml b/core/res/res/values-en-rGB/strings.xml
index 62e42b38abf5..33ffbe386fc4 100644
--- a/core/res/res/values-en-rGB/strings.xml
+++ b/core/res/res/values-en-rGB/strings.xml
@@ -287,6 +287,7 @@
<string name="notification_channel_usb" msgid="1528280969406244896">"USB connection"</string>
<string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"App running"</string>
<string name="notification_channel_foreground_service" msgid="7102189948158885178">"Apps consuming battery"</string>
+ <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Magnification"</string>
<string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> is using battery"</string>
<string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> apps are using battery"</string>
<string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Tap for details on battery and data usage"</string>
@@ -2188,4 +2189,8 @@
<string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string>
<string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string>
<string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string>
+ <string name="window_magnification_prompt_title" msgid="8197528399699536320">"New: Window magnifier"</string>
+ <string name="window_magnification_prompt_content" msgid="4166711383253283838">"You can now magnify some or all of your screen"</string>
+ <string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"Turn on in settings"</string>
+ <string name="dismiss_action" msgid="1728820550388704784">"Dismiss"</string>
</resources>
diff --git a/core/res/res/values-en-rIN/strings.xml b/core/res/res/values-en-rIN/strings.xml
index 85796287543d..f5be6fd8c337 100644
--- a/core/res/res/values-en-rIN/strings.xml
+++ b/core/res/res/values-en-rIN/strings.xml
@@ -287,6 +287,7 @@
<string name="notification_channel_usb" msgid="1528280969406244896">"USB connection"</string>
<string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"App running"</string>
<string name="notification_channel_foreground_service" msgid="7102189948158885178">"Apps consuming battery"</string>
+ <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Magnification"</string>
<string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> is using battery"</string>
<string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> apps are using battery"</string>
<string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Tap for details on battery and data usage"</string>
@@ -2188,4 +2189,8 @@
<string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string>
<string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string>
<string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string>
+ <string name="window_magnification_prompt_title" msgid="8197528399699536320">"New: Window magnifier"</string>
+ <string name="window_magnification_prompt_content" msgid="4166711383253283838">"You can now magnify some or all of your screen"</string>
+ <string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"Turn on in settings"</string>
+ <string name="dismiss_action" msgid="1728820550388704784">"Dismiss"</string>
</resources>
diff --git a/core/res/res/values-en-rXC/strings.xml b/core/res/res/values-en-rXC/strings.xml
index 6674ecd63906..cd3ff368c289 100644
--- a/core/res/res/values-en-rXC/strings.xml
+++ b/core/res/res/values-en-rXC/strings.xml
@@ -287,6 +287,7 @@
<string name="notification_channel_usb" msgid="1528280969406244896">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‎‏‎‏‎‎‏‏‎‏‎‏‏‎‎‎‏‎‏‏‎‏‏‏‎‎‎‏‏‏‎‎‏‎‏‎‎‏‏‏‎‎‏‎‏‏‏‎‏‎‎‎‎‎‏‎‎‎‎‎‎USB connection‎‏‎‎‏‎"</string>
<string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‎‏‏‎‏‏‏‏‏‎‎‎‎‎‎‎‏‏‏‏‏‎‏‎‏‏‎‎‎‎‎‏‎‏‏‎‎‎‎‏‎‎‎‏‏‏‏‏‏‏‏‎‎‎‏‎‏‏‎App running‎‏‎‎‏‎"</string>
<string name="notification_channel_foreground_service" msgid="7102189948158885178">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‎‎‏‎‏‎‎‏‎‎‎‎‎‎‎‎‏‏‎‎‎‎‏‎‎‎‎‎‏‏‏‏‏‎‏‏‎‏‎‏‏‏‎‎‎‎‏‏‏‏‎‏‎‎‏‏‏‎‏‎‎Apps consuming battery‎‏‎‎‏‎"</string>
+ <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‎‏‏‏‏‎‏‏‎‎‏‏‏‎‏‏‏‎‏‎‏‎‎‏‏‏‏‎‎‎‏‎‏‏‎‎‏‎‎‏‏‏‏‏‎‏‏‏‏‎‏‎‎‏‎‏‎‎‏‎‎Magnification‎‏‎‎‏‎"</string>
<string name="foreground_service_app_in_background" msgid="1439289699671273555">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‎‎‏‏‏‏‏‏‏‎‎‏‎‏‏‎‎‎‏‎‎‏‎‏‏‎‏‏‎‎‏‎‏‏‎‏‏‏‎‎‏‎‎‎‏‏‏‏‎‎‎‎‎‏‎‏‎‎‏‏‎‎‏‎‎‏‏‎<xliff:g id="APP_NAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎ is using battery‎‏‎‎‏‎"</string>
<string name="foreground_service_apps_in_background" msgid="7340037176412387863">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‎‏‎‏‏‏‎‏‏‏‎‏‎‎‎‎‏‏‎‎‏‏‏‎‏‏‎‎‎‎‏‏‏‎‏‎‎‎‏‏‏‎‎‎‏‎‏‏‏‎‏‎‎‎‎‏‎‏‏‏‎‎‏‎‎‏‏‎<xliff:g id="NUMBER">%1$d</xliff:g>‎‏‎‎‏‏‏‎ apps are using battery‎‏‎‎‏‎"</string>
<string name="foreground_service_tap_for_details" msgid="9078123626015586751">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‏‏‎‏‏‏‏‏‏‎‏‏‏‏‏‏‏‎‎‏‎‏‎‏‎‏‏‏‎‎‎‎‎‎‏‏‏‎‏‏‏‏‎‏‎‏‏‏‏‎‎‏‏‎‏‏‏‏‏‏‎Tap for details on battery and data usage‎‏‎‎‏‎"</string>
@@ -2188,4 +2189,8 @@
<string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string>
<string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string>
<string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string>
+ <string name="window_magnification_prompt_title" msgid="8197528399699536320">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‎‎‏‏‏‎‎‎‎‏‏‎‏‏‏‏‎‎‎‏‎‏‎‎‏‎‏‏‎‏‎‏‏‎‎‎‏‎‎‎‏‎‎‎‏‏‎‏‎‎‏‏‏‎‎‎‎‎‎‎New: Window Magnifier‎‏‎‎‏‎"</string>
+ <string name="window_magnification_prompt_content" msgid="4166711383253283838">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‎‎‏‏‏‎‏‎‎‏‏‎‎‏‎‎‎‎‏‏‏‏‎‏‏‎‏‎‏‎‎‏‎‎‎‎‏‏‎‎‎‏‏‎‏‏‏‎‎‏‏‏‏‏‏‏‏‏‎‎You can now magnify some or all of your screen‎‏‎‎‏‎"</string>
+ <string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‏‏‎‎‏‎‎‎‎‏‎‎‎‏‏‎‏‏‎‎‏‏‏‏‎‏‎‏‏‏‏‎‏‏‎‎‏‎‏‎‎‎‏‏‎‎‎‎‏‏‎‎‏‎‏‎‏‎‎‎Turn on in Settings‎‏‎‎‏‎"</string>
+ <string name="dismiss_action" msgid="1728820550388704784">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‎‏‏‏‏‏‏‏‏‏‏‎‎‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‎‎‎‎‎‏‎‎‏‎‏‎‎‎‎‎‏‏‎‎‏‏‎‎‎‎‏‎‎‎‎‎Dismiss‎‏‎‎‏‎"</string>
</resources>
diff --git a/core/res/res/values-es-rUS/strings.xml b/core/res/res/values-es-rUS/strings.xml
index a7e299456e95..2d521b3290c2 100644
--- a/core/res/res/values-es-rUS/strings.xml
+++ b/core/res/res/values-es-rUS/strings.xml
@@ -287,6 +287,8 @@
<string name="notification_channel_usb" msgid="1528280969406244896">"Conexión USB"</string>
<string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"App en ejecución"</string>
<string name="notification_channel_foreground_service" msgid="7102189948158885178">"Apps que consumen batería"</string>
+ <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) -->
+ <skip />
<string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> está consumiendo batería"</string>
<string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> apps están consumiendo batería"</string>
<string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Presiona para obtener información sobre el uso de datos y de la batería"</string>
@@ -2188,4 +2190,12 @@
<string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string>
<string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string>
<string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string>
+ <!-- no translation found for window_magnification_prompt_title (8197528399699536320) -->
+ <skip />
+ <!-- no translation found for window_magnification_prompt_content (4166711383253283838) -->
+ <skip />
+ <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) -->
+ <skip />
+ <!-- no translation found for dismiss_action (1728820550388704784) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-es/strings.xml b/core/res/res/values-es/strings.xml
index 0d8fc2b6ca69..abc694686bee 100644
--- a/core/res/res/values-es/strings.xml
+++ b/core/res/res/values-es/strings.xml
@@ -287,6 +287,8 @@
<string name="notification_channel_usb" msgid="1528280969406244896">"Conexión USB"</string>
<string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"Aplicación en ejecución"</string>
<string name="notification_channel_foreground_service" msgid="7102189948158885178">"Aplicaciones que consumen batería"</string>
+ <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) -->
+ <skip />
<string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> está usando la batería"</string>
<string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> aplicaciones están usando la batería"</string>
<string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Toca para ver información detallada sobre el uso de datos y de la batería"</string>
@@ -2188,4 +2190,12 @@
<string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string>
<string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string>
<string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string>
+ <!-- no translation found for window_magnification_prompt_title (8197528399699536320) -->
+ <skip />
+ <!-- no translation found for window_magnification_prompt_content (4166711383253283838) -->
+ <skip />
+ <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) -->
+ <skip />
+ <!-- no translation found for dismiss_action (1728820550388704784) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-et/strings.xml b/core/res/res/values-et/strings.xml
index 7a0a0ed005aa..130ef6e47b9f 100644
--- a/core/res/res/values-et/strings.xml
+++ b/core/res/res/values-et/strings.xml
@@ -287,6 +287,8 @@
<string name="notification_channel_usb" msgid="1528280969406244896">"USB-ühendus"</string>
<string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"Rakendus töötab"</string>
<string name="notification_channel_foreground_service" msgid="7102189948158885178">"Rakendused kasutavad akutoidet"</string>
+ <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) -->
+ <skip />
<string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> kasutab akutoidet"</string>
<string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> rakendust kasutab akutoidet"</string>
<string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Aku ja andmekasutuse üksikasjade nägemiseks puudutage"</string>
@@ -2188,4 +2190,12 @@
<string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string>
<string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string>
<string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string>
+ <!-- no translation found for window_magnification_prompt_title (8197528399699536320) -->
+ <skip />
+ <!-- no translation found for window_magnification_prompt_content (4166711383253283838) -->
+ <skip />
+ <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) -->
+ <skip />
+ <!-- no translation found for dismiss_action (1728820550388704784) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-eu/strings.xml b/core/res/res/values-eu/strings.xml
index a00282ff4292..5273a48fa3b5 100644
--- a/core/res/res/values-eu/strings.xml
+++ b/core/res/res/values-eu/strings.xml
@@ -287,6 +287,8 @@
<string name="notification_channel_usb" msgid="1528280969406244896">"USB konexioa"</string>
<string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"Aplikazio bat abian da"</string>
<string name="notification_channel_foreground_service" msgid="7102189948158885178">"Bateria kontsumitzen ari diren aplikazioak"</string>
+ <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) -->
+ <skip />
<string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> ari da bateria erabiltzen"</string>
<string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> aplikazio ari dira bateria erabiltzen"</string>
<string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Sakatu bateria eta datuen erabilerari buruzko xehetasunak ikusteko"</string>
@@ -2188,4 +2190,12 @@
<string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string>
<string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string>
<string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string>
+ <!-- no translation found for window_magnification_prompt_title (8197528399699536320) -->
+ <skip />
+ <!-- no translation found for window_magnification_prompt_content (4166711383253283838) -->
+ <skip />
+ <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) -->
+ <skip />
+ <!-- no translation found for dismiss_action (1728820550388704784) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-fa/strings.xml b/core/res/res/values-fa/strings.xml
index fb0ec661b2cb..7596bab30f16 100644
--- a/core/res/res/values-fa/strings.xml
+++ b/core/res/res/values-fa/strings.xml
@@ -287,6 +287,8 @@
<string name="notification_channel_usb" msgid="1528280969406244896">"‏اتصال USB"</string>
<string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"برنامه درحال اجرا"</string>
<string name="notification_channel_foreground_service" msgid="7102189948158885178">"برنامه‌های مصرف‌کننده باتری"</string>
+ <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) -->
+ <skip />
<string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> درحال استفاده کردن از باتری است"</string>
<string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> برنامه درحال استفاده کردن از باتری هستند"</string>
<string name="foreground_service_tap_for_details" msgid="9078123626015586751">"برای جزئیات مربوط به مصرف باتری و داده، ضربه بزنید"</string>
@@ -2188,4 +2190,12 @@
<string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string>
<string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string>
<string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string>
+ <!-- no translation found for window_magnification_prompt_title (8197528399699536320) -->
+ <skip />
+ <!-- no translation found for window_magnification_prompt_content (4166711383253283838) -->
+ <skip />
+ <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) -->
+ <skip />
+ <!-- no translation found for dismiss_action (1728820550388704784) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-fi/strings.xml b/core/res/res/values-fi/strings.xml
index 27abeea5dd86..d3373154196a 100644
--- a/core/res/res/values-fi/strings.xml
+++ b/core/res/res/values-fi/strings.xml
@@ -287,6 +287,8 @@
<string name="notification_channel_usb" msgid="1528280969406244896">"USB-yhteys"</string>
<string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"Sovellus käynnissä"</string>
<string name="notification_channel_foreground_service" msgid="7102189948158885178">"Akkua kuluttavat sovellukset"</string>
+ <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) -->
+ <skip />
<string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> käyttää akkua."</string>
<string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> sovellusta käyttää akkua."</string>
<string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Katso lisätietoja akun ja datan käytöstä napauttamalla."</string>
@@ -2188,4 +2190,12 @@
<string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string>
<string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string>
<string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string>
+ <!-- no translation found for window_magnification_prompt_title (8197528399699536320) -->
+ <skip />
+ <!-- no translation found for window_magnification_prompt_content (4166711383253283838) -->
+ <skip />
+ <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) -->
+ <skip />
+ <!-- no translation found for dismiss_action (1728820550388704784) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-fr-rCA/strings.xml b/core/res/res/values-fr-rCA/strings.xml
index c09c71e9244c..d2c89bc8d842 100644
--- a/core/res/res/values-fr-rCA/strings.xml
+++ b/core/res/res/values-fr-rCA/strings.xml
@@ -290,6 +290,8 @@
<string name="notification_channel_usb" msgid="1528280969406244896">"Connexion USB"</string>
<string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"Application en cours d\'exécution"</string>
<string name="notification_channel_foreground_service" msgid="7102189948158885178">"Applications qui sollicitent la pile"</string>
+ <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) -->
+ <skip />
<string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> sollicite la pile"</string>
<string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> applications sollicitent la pile"</string>
<string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Touchez pour afficher des détails sur l\'utilisation de la pile et des données"</string>
@@ -2222,4 +2224,12 @@
<string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string>
<string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string>
<string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string>
+ <!-- no translation found for window_magnification_prompt_title (8197528399699536320) -->
+ <skip />
+ <!-- no translation found for window_magnification_prompt_content (4166711383253283838) -->
+ <skip />
+ <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) -->
+ <skip />
+ <!-- no translation found for dismiss_action (1728820550388704784) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-fr/strings.xml b/core/res/res/values-fr/strings.xml
index 9c9cdd112bc6..1992068a4a85 100644
--- a/core/res/res/values-fr/strings.xml
+++ b/core/res/res/values-fr/strings.xml
@@ -290,6 +290,8 @@
<string name="notification_channel_usb" msgid="1528280969406244896">"Connexion USB"</string>
<string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"Application en cours d\'exécution"</string>
<string name="notification_channel_foreground_service" msgid="7102189948158885178">"Applications utilisant la batterie"</string>
+ <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) -->
+ <skip />
<string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> utilise la batterie"</string>
<string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> applications utilisent la batterie"</string>
<string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Appuyer pour obtenir des informations sur l\'utilisation de la batterie et des données"</string>
@@ -2222,4 +2224,12 @@
<string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string>
<string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string>
<string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string>
+ <!-- no translation found for window_magnification_prompt_title (8197528399699536320) -->
+ <skip />
+ <!-- no translation found for window_magnification_prompt_content (4166711383253283838) -->
+ <skip />
+ <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) -->
+ <skip />
+ <!-- no translation found for dismiss_action (1728820550388704784) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-gl/strings.xml b/core/res/res/values-gl/strings.xml
index 7dd89aa93702..7583502fb988 100644
--- a/core/res/res/values-gl/strings.xml
+++ b/core/res/res/values-gl/strings.xml
@@ -287,6 +287,8 @@
<string name="notification_channel_usb" msgid="1528280969406244896">"conexión USB"</string>
<string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"Estase executando a aplicación"</string>
<string name="notification_channel_foreground_service" msgid="7102189948158885178">"Aplicacións que consomen batería"</string>
+ <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) -->
+ <skip />
<string name="foreground_service_app_in_background" msgid="1439289699671273555">"A aplicación <xliff:g id="APP_NAME">%1$s</xliff:g> está consumindo batería"</string>
<string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> aplicacións están consumindo batería"</string>
<string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Toca para obter información sobre o uso de datos e a batería"</string>
@@ -2188,4 +2190,12 @@
<string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string>
<string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string>
<string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string>
+ <!-- no translation found for window_magnification_prompt_title (8197528399699536320) -->
+ <skip />
+ <!-- no translation found for window_magnification_prompt_content (4166711383253283838) -->
+ <skip />
+ <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) -->
+ <skip />
+ <!-- no translation found for dismiss_action (1728820550388704784) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-gu/strings.xml b/core/res/res/values-gu/strings.xml
index 6ace38db11ff..6f140c4b5d85 100644
--- a/core/res/res/values-gu/strings.xml
+++ b/core/res/res/values-gu/strings.xml
@@ -287,6 +287,8 @@
<string name="notification_channel_usb" msgid="1528280969406244896">"USB કનેક્શન"</string>
<string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"ઍપ ચાલી રહ્યું છે"</string>
<string name="notification_channel_foreground_service" msgid="7102189948158885178">"ઍપ બૅટરીનો વપરાશ કરી રહ્યાં છે"</string>
+ <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) -->
+ <skip />
<string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> બૅટરીનો ઉપયોગ કરી રહ્યું છે"</string>
<string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> ઍપ બૅટરીનો ઉપયોગ કરી રહ્યાં છે"</string>
<string name="foreground_service_tap_for_details" msgid="9078123626015586751">"બૅટરી અને ડેટા વપરાશ વિશેની વિગતો માટે ટૅપ કરો"</string>
@@ -2188,4 +2190,12 @@
<string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string>
<string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string>
<string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string>
+ <!-- no translation found for window_magnification_prompt_title (8197528399699536320) -->
+ <skip />
+ <!-- no translation found for window_magnification_prompt_content (4166711383253283838) -->
+ <skip />
+ <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) -->
+ <skip />
+ <!-- no translation found for dismiss_action (1728820550388704784) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-hi/strings.xml b/core/res/res/values-hi/strings.xml
index f1e57801d3ec..5892dab23628 100644
--- a/core/res/res/values-hi/strings.xml
+++ b/core/res/res/values-hi/strings.xml
@@ -287,6 +287,8 @@
<string name="notification_channel_usb" msgid="1528280969406244896">"USB कनेक्शन"</string>
<string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"ऐप अभी इस्तेमाल हो रहा है"</string>
<string name="notification_channel_foreground_service" msgid="7102189948158885178">"बैटरी की खपत करने वाले ऐप"</string>
+ <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) -->
+ <skip />
<string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> बैटरी का इस्तेमाल कर रहा है"</string>
<string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> ऐप बैटरी का इस्तेमाल कर रहे हैं"</string>
<string name="foreground_service_tap_for_details" msgid="9078123626015586751">"बैटरी और डेटा खर्च की जानकारी के लिए छूएं"</string>
@@ -2188,4 +2190,12 @@
<string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string>
<string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string>
<string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string>
+ <!-- no translation found for window_magnification_prompt_title (8197528399699536320) -->
+ <skip />
+ <!-- no translation found for window_magnification_prompt_content (4166711383253283838) -->
+ <skip />
+ <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) -->
+ <skip />
+ <!-- no translation found for dismiss_action (1728820550388704784) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-hr/strings.xml b/core/res/res/values-hr/strings.xml
index 4ff37c575a0f..f4d984275576 100644
--- a/core/res/res/values-hr/strings.xml
+++ b/core/res/res/values-hr/strings.xml
@@ -290,6 +290,8 @@
<string name="notification_channel_usb" msgid="1528280969406244896">"USB veza"</string>
<string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"Izvodi se aplikacija"</string>
<string name="notification_channel_foreground_service" msgid="7102189948158885178">"Aplikacije troše bateriju"</string>
+ <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) -->
+ <skip />
<string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> koristi bateriju"</string>
<string name="foreground_service_apps_in_background" msgid="7340037176412387863">"Broj aplikacija koje koriste bateriju: <xliff:g id="NUMBER">%1$d</xliff:g>"</string>
<string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Dodirnite da biste vidjeli pojedinosti o potrošnji baterije i podatkovnom prometu"</string>
@@ -2222,4 +2224,12 @@
<string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string>
<string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string>
<string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string>
+ <!-- no translation found for window_magnification_prompt_title (8197528399699536320) -->
+ <skip />
+ <!-- no translation found for window_magnification_prompt_content (4166711383253283838) -->
+ <skip />
+ <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) -->
+ <skip />
+ <!-- no translation found for dismiss_action (1728820550388704784) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-hu/strings.xml b/core/res/res/values-hu/strings.xml
index d01373f749f3..bff17731ac84 100644
--- a/core/res/res/values-hu/strings.xml
+++ b/core/res/res/values-hu/strings.xml
@@ -287,6 +287,8 @@
<string name="notification_channel_usb" msgid="1528280969406244896">"USB-kapcsolat"</string>
<string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"Jelenleg futó alkalmazás"</string>
<string name="notification_channel_foreground_service" msgid="7102189948158885178">"Akkumulátort használó alkalmazások"</string>
+ <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) -->
+ <skip />
<string name="foreground_service_app_in_background" msgid="1439289699671273555">"A(z) <xliff:g id="APP_NAME">%1$s</xliff:g> alkalmazás használja az akkumulátort"</string>
<string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> alkalmazás használja az akkumulátort"</string>
<string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Koppintson az akkumulátor- és adathasználat részleteinek megtekintéséhez"</string>
@@ -2188,4 +2190,12 @@
<string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string>
<string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string>
<string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string>
+ <!-- no translation found for window_magnification_prompt_title (8197528399699536320) -->
+ <skip />
+ <!-- no translation found for window_magnification_prompt_content (4166711383253283838) -->
+ <skip />
+ <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) -->
+ <skip />
+ <!-- no translation found for dismiss_action (1728820550388704784) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-hy/strings.xml b/core/res/res/values-hy/strings.xml
index a85ed708faba..1f2e642c74c6 100644
--- a/core/res/res/values-hy/strings.xml
+++ b/core/res/res/values-hy/strings.xml
@@ -287,6 +287,8 @@
<string name="notification_channel_usb" msgid="1528280969406244896">"USB կապակցում"</string>
<string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"Հավելվածն աշխատում է"</string>
<string name="notification_channel_foreground_service" msgid="7102189948158885178">"Մարտկոցի լիցքը ծախսող հավելվածներ"</string>
+ <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) -->
+ <skip />
<string name="foreground_service_app_in_background" msgid="1439289699671273555">"«<xliff:g id="APP_NAME">%1$s</xliff:g>» հավելվածը ծախսում է մարտկոցի լիցքը"</string>
<string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> հավելված ծախսում է մարտկոցի լիցքը"</string>
<string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Հպեք՝ մարտկոցի և թրաֆիկի մանրամասները տեսնելու համար"</string>
@@ -2188,4 +2190,12 @@
<string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string>
<string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string>
<string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string>
+ <!-- no translation found for window_magnification_prompt_title (8197528399699536320) -->
+ <skip />
+ <!-- no translation found for window_magnification_prompt_content (4166711383253283838) -->
+ <skip />
+ <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) -->
+ <skip />
+ <!-- no translation found for dismiss_action (1728820550388704784) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-in/strings.xml b/core/res/res/values-in/strings.xml
index cbcb131a64b0..4f26eb687082 100644
--- a/core/res/res/values-in/strings.xml
+++ b/core/res/res/values-in/strings.xml
@@ -287,6 +287,8 @@
<string name="notification_channel_usb" msgid="1528280969406244896">"Sambungan USB"</string>
<string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"Aplikasi berjalan"</string>
<string name="notification_channel_foreground_service" msgid="7102189948158885178">"Aplikasi yang menggunakan baterai"</string>
+ <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) -->
+ <skip />
<string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> sedang menggunakan baterai"</string>
<string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> aplikasi sedang meggunakan baterai"</string>
<string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Ketuk untuk melihat detail penggunaan baterai dan data"</string>
@@ -2188,4 +2190,12 @@
<string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string>
<string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string>
<string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string>
+ <!-- no translation found for window_magnification_prompt_title (8197528399699536320) -->
+ <skip />
+ <!-- no translation found for window_magnification_prompt_content (4166711383253283838) -->
+ <skip />
+ <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) -->
+ <skip />
+ <!-- no translation found for dismiss_action (1728820550388704784) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-is/strings.xml b/core/res/res/values-is/strings.xml
index 5d1912236a99..d5539a395206 100644
--- a/core/res/res/values-is/strings.xml
+++ b/core/res/res/values-is/strings.xml
@@ -287,6 +287,8 @@
<string name="notification_channel_usb" msgid="1528280969406244896">"USB-tenging"</string>
<string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"Forrit er í gangi"</string>
<string name="notification_channel_foreground_service" msgid="7102189948158885178">"Forrit sem nota rafhlöðuorku"</string>
+ <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) -->
+ <skip />
<string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> notar rafhlöðuorku"</string>
<string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> forrit nota rafhlöðuorku"</string>
<string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Ýttu til að fá upplýsingar um rafhlöðu- og gagnanotkun"</string>
@@ -2188,4 +2190,12 @@
<string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string>
<string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string>
<string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string>
+ <!-- no translation found for window_magnification_prompt_title (8197528399699536320) -->
+ <skip />
+ <!-- no translation found for window_magnification_prompt_content (4166711383253283838) -->
+ <skip />
+ <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) -->
+ <skip />
+ <!-- no translation found for dismiss_action (1728820550388704784) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-it/strings.xml b/core/res/res/values-it/strings.xml
index bf26d99b7e19..152cfee90863 100644
--- a/core/res/res/values-it/strings.xml
+++ b/core/res/res/values-it/strings.xml
@@ -287,6 +287,7 @@
<string name="notification_channel_usb" msgid="1528280969406244896">"Connessione USB"</string>
<string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"App in esecuzione"</string>
<string name="notification_channel_foreground_service" msgid="7102189948158885178">"App che consumano la batteria"</string>
+ <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Ingrandimento"</string>
<string name="foreground_service_app_in_background" msgid="1439289699671273555">"L\'app <xliff:g id="APP_NAME">%1$s</xliff:g> sta consumando la batteria"</string>
<string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> app stanno consumando la batteria"</string>
<string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Tocca per conoscere i dettagli sull\'utilizzo dei dati e della batteria"</string>
@@ -2188,4 +2189,8 @@
<string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string>
<string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string>
<string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string>
+ <string name="window_magnification_prompt_title" msgid="8197528399699536320">"Novità: Ingrandimento finestra"</string>
+ <string name="window_magnification_prompt_content" msgid="4166711383253283838">"Puoi ingrandire lo schermo in parte o per intero"</string>
+ <string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"Attiva nelle Impostazioni"</string>
+ <string name="dismiss_action" msgid="1728820550388704784">"Ignora"</string>
</resources>
diff --git a/core/res/res/values-iw/strings.xml b/core/res/res/values-iw/strings.xml
index 422d810d3c09..5ae9436dd1b3 100644
--- a/core/res/res/values-iw/strings.xml
+++ b/core/res/res/values-iw/strings.xml
@@ -293,6 +293,8 @@
<string name="notification_channel_usb" msgid="1528280969406244896">"‏חיבור USB"</string>
<string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"אפליקציה פועלת"</string>
<string name="notification_channel_foreground_service" msgid="7102189948158885178">"אפליקציות שמרוקנות את הסוללה"</string>
+ <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) -->
+ <skip />
<string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> משתמשת בסוללה"</string>
<string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> אפליקציות משתמשות בסוללה"</string>
<string name="foreground_service_tap_for_details" msgid="9078123626015586751">"הקש לקבלת פרטים על צריכה של נתונים וסוללה"</string>
@@ -2256,4 +2258,12 @@
<string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string>
<string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string>
<string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string>
+ <!-- no translation found for window_magnification_prompt_title (8197528399699536320) -->
+ <skip />
+ <!-- no translation found for window_magnification_prompt_content (4166711383253283838) -->
+ <skip />
+ <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) -->
+ <skip />
+ <!-- no translation found for dismiss_action (1728820550388704784) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-ja/strings.xml b/core/res/res/values-ja/strings.xml
index f5adb5962783..7a54a1594501 100644
--- a/core/res/res/values-ja/strings.xml
+++ b/core/res/res/values-ja/strings.xml
@@ -287,6 +287,8 @@
<string name="notification_channel_usb" msgid="1528280969406244896">"USB 接続"</string>
<string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"実行中のアプリ"</string>
<string name="notification_channel_foreground_service" msgid="7102189948158885178">"電池を消費しているアプリ"</string>
+ <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) -->
+ <skip />
<string name="foreground_service_app_in_background" msgid="1439289699671273555">"「<xliff:g id="APP_NAME">%1$s</xliff:g>」が電池を使用しています"</string>
<string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> 個のアプリが電池を使用しています"</string>
<string name="foreground_service_tap_for_details" msgid="9078123626015586751">"タップして電池やデータの使用量を確認"</string>
@@ -2188,4 +2190,12 @@
<string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string>
<string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string>
<string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string>
+ <!-- no translation found for window_magnification_prompt_title (8197528399699536320) -->
+ <skip />
+ <!-- no translation found for window_magnification_prompt_content (4166711383253283838) -->
+ <skip />
+ <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) -->
+ <skip />
+ <!-- no translation found for dismiss_action (1728820550388704784) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-ka/strings.xml b/core/res/res/values-ka/strings.xml
index 0c3e7b9f207c..1653cb91c3fb 100644
--- a/core/res/res/values-ka/strings.xml
+++ b/core/res/res/values-ka/strings.xml
@@ -287,6 +287,7 @@
<string name="notification_channel_usb" msgid="1528280969406244896">"USB კავშირი"</string>
<string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"აპი გაშვებულია"</string>
<string name="notification_channel_foreground_service" msgid="7102189948158885178">"ბატარეის მხარჯავი აპები"</string>
+ <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"გადიდება"</string>
<string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> იყენებს ბატარეას"</string>
<string name="foreground_service_apps_in_background" msgid="7340037176412387863">"ბატარეას <xliff:g id="NUMBER">%1$d</xliff:g> აპი იყენებს"</string>
<string name="foreground_service_tap_for_details" msgid="9078123626015586751">"შეეხეთ ბატარეისა და მონაცემების მოხმარების შესახებ დეტალური ინფორმაციისთვის"</string>
@@ -2188,4 +2189,8 @@
<string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string>
<string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string>
<string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string>
+ <string name="window_magnification_prompt_title" msgid="8197528399699536320">"სიახლე: ფანჯრის გამადიდებელი"</string>
+ <string name="window_magnification_prompt_content" msgid="4166711383253283838">"ახლა შეგიძლიათ, გაადიდოთ ეკრანი ან მისი ნაწილი"</string>
+ <string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"ჩართვა პარამეტრებში"</string>
+ <string name="dismiss_action" msgid="1728820550388704784">"უარყოფა"</string>
</resources>
diff --git a/core/res/res/values-kk/strings.xml b/core/res/res/values-kk/strings.xml
index 3139dcee7482..635fed7f6bf1 100644
--- a/core/res/res/values-kk/strings.xml
+++ b/core/res/res/values-kk/strings.xml
@@ -287,6 +287,8 @@
<string name="notification_channel_usb" msgid="1528280969406244896">"USB байланысы"</string>
<string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"Қолданба қосулы"</string>
<string name="notification_channel_foreground_service" msgid="7102189948158885178">"Батареяны пайдаланып жатқан қолданбалар"</string>
+ <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) -->
+ <skip />
<string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> батареяны пайдалануда"</string>
<string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> қолданба батареяны пайдалануда"</string>
<string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Батарея мен деректер трафигі туралы білу үшін түртіңіз"</string>
@@ -319,7 +321,7 @@
<string name="permgroupdesc_sensors" msgid="2610631290633747752">"ағза күйінің көрсеткіштері туралы сенсор деректеріне қатынасу"</string>
<string name="capability_title_canRetrieveWindowContent" msgid="7554282892101587296">"Терезе мазмұнын оқып отыру"</string>
<string name="capability_desc_canRetrieveWindowContent" msgid="6195610527625237661">"Ашық тұрған терезе мазмұнын тексеру."</string>
- <string name="capability_title_canRequestTouchExploration" msgid="327598364696316213">"Explore by Touch функциясын қосу"</string>
+ <string name="capability_title_canRequestTouchExploration" msgid="327598364696316213">"Түртілген элементтерді дыбыстау функциясын қосу"</string>
<string name="capability_desc_canRequestTouchExploration" msgid="4394677060796752976">"Түртілген элементтер дауыстап айтылады және экранды қимылдар арқылы зерттеуге болады."</string>
<string name="capability_title_canRequestFilterKeyEvents" msgid="2772371671541753254">"Терілген мәтінді тексеру"</string>
<string name="capability_desc_canRequestFilterKeyEvents" msgid="2381315802405773092">"Несиелік карта нөмірі және құпия сөздер сияқты жеке деректі қоса."</string>
@@ -994,9 +996,9 @@
<string name="searchview_description_clear" msgid="1989371719192982900">"Сұрақты өшіру"</string>
<string name="searchview_description_submit" msgid="6771060386117334686">"Сұрақ жіберу"</string>
<string name="searchview_description_voice" msgid="42360159504884679">"Дауыс арқылы іздеу"</string>
- <string name="enable_explore_by_touch_warning_title" msgid="5095399706284943314">"Explore by Touch функциясы қосылсын ба?"</string>
- <string name="enable_explore_by_touch_warning_message" product="tablet" msgid="1037295476738940824">"<xliff:g id="ACCESSIBILITY_SERVICE_NAME">%1$s</xliff:g> қызметі Explore by Touch мүмкіндігін қосқысы келеді. Explore by Touch мүмкіндігі қосылған кезде, саусағыңыздың астындағы нәрсенің сипаттамаларын естисіз не көресіз немесе планшетпен өзара байланысу үшін қимылдайсыз."</string>
- <string name="enable_explore_by_touch_warning_message" product="default" msgid="4312979647356179250">"<xliff:g id="ACCESSIBILITY_SERVICE_NAME">%1$s</xliff:g> қызметі Explore by Touch мүмкіндігін қосқысы келеді. Explore by Touch мүмкіндігі қосылған кезде, саусағыңыздың астындағы нәрсенің сипаттамаларын естисіз не көресіз немесе телефонмен өзара байланысу үшін қимылдайсыз."</string>
+ <string name="enable_explore_by_touch_warning_title" msgid="5095399706284943314">"Түртілген элементтерді дыбыстау функциясы қосылсын ба?"</string>
+ <string name="enable_explore_by_touch_warning_message" product="tablet" msgid="1037295476738940824">"<xliff:g id="ACCESSIBILITY_SERVICE_NAME">%1$s</xliff:g> қызметі Түртілген элементтерді дыбыстау функциясын қосуға рұқсат сұрап тұр. Ол қосылған кезде, саусағыңыздың астындағы элементтің сипаттамасын естіп не көріп тұрасыз немесе планшетті қимылмен басқарасыз."</string>
+ <string name="enable_explore_by_touch_warning_message" product="default" msgid="4312979647356179250">"<xliff:g id="ACCESSIBILITY_SERVICE_NAME">%1$s</xliff:g> қызметі Түртілген элементтерді дыбыстау функциясын қосуға рұқсат сұрап тұр. Ол қосылған кезде, саусағыңыздың астындағы элементтің сипаттамасын естіп не көріп тұрасыз немесе телефонды қимылмен басқарасыз."</string>
<string name="oneMonthDurationPast" msgid="4538030857114635777">"1 ай бұрын"</string>
<string name="beforeOneMonthDurationPast" msgid="8315149541372065392">"Осыған дейін 1 ай бұрын"</string>
<plurals name="last_num_days" formatted="false" msgid="687443109145393632">
@@ -1316,7 +1318,7 @@
<string name="usb_unsupported_audio_accessory_title" msgid="2335775548086533065">"Аналогтық аудиожабдық анықталды"</string>
<string name="usb_unsupported_audio_accessory_message" msgid="1300168007129796621">"Жалғанған құрылғы бұл телефонмен үйлесімсіз. Қосымша ақпарат алу үшін түртіңіз."</string>
<string name="adb_active_notification_title" msgid="408390247354560331">"USB арқылы түзету қосылған"</string>
- <string name="adb_active_notification_message" msgid="5617264033476778211">"USB арқылы түзетуді өшіру үшін түртіңіз"</string>
+ <string name="adb_active_notification_message" msgid="5617264033476778211">"USB арқылы түзетуді өшіру үшін түртіңіз."</string>
<string name="adb_active_notification_message" product="tv" msgid="6624498401272780855">"USB арқылы түзетуді өшіру үшін таңдаңыз."</string>
<string name="adbwifi_active_notification_title" msgid="6147343659168302473">"Сымсыз түзету байланыстырылды"</string>
<string name="adbwifi_active_notification_message" msgid="930987922852867972">"Сымсыз түзетуді өшіру үшін түртіңіз."</string>
@@ -2188,4 +2190,12 @@
<string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string>
<string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string>
<string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string>
+ <!-- no translation found for window_magnification_prompt_title (8197528399699536320) -->
+ <skip />
+ <!-- no translation found for window_magnification_prompt_content (4166711383253283838) -->
+ <skip />
+ <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) -->
+ <skip />
+ <!-- no translation found for dismiss_action (1728820550388704784) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-km/strings.xml b/core/res/res/values-km/strings.xml
index cc7c72abc180..1160a40bb899 100644
--- a/core/res/res/values-km/strings.xml
+++ b/core/res/res/values-km/strings.xml
@@ -287,6 +287,8 @@
<string name="notification_channel_usb" msgid="1528280969406244896">"ការ​តភ្ជាប់ USB"</string>
<string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"កម្មវិធី​ដែល​កំពុង​ដំណើរការ"</string>
<string name="notification_channel_foreground_service" msgid="7102189948158885178">"កម្មវិធីដែល​កំពុងប្រើថ្ម"</string>
+ <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) -->
+ <skip />
<string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> កំពុងប្រើថ្ម"</string>
<string name="foreground_service_apps_in_background" msgid="7340037176412387863">"កម្មវិធីចំនួន <xliff:g id="NUMBER">%1$d</xliff:g> កំពុងប្រើថ្ម"</string>
<string name="foreground_service_tap_for_details" msgid="9078123626015586751">"ចុចដើម្បីមើលព័ត៌មានលម្អិតអំពីការប្រើប្រាស់ទិន្នន័យ និងថ្ម"</string>
@@ -2188,4 +2190,12 @@
<string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string>
<string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string>
<string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string>
+ <!-- no translation found for window_magnification_prompt_title (8197528399699536320) -->
+ <skip />
+ <!-- no translation found for window_magnification_prompt_content (4166711383253283838) -->
+ <skip />
+ <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) -->
+ <skip />
+ <!-- no translation found for dismiss_action (1728820550388704784) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-kn/strings.xml b/core/res/res/values-kn/strings.xml
index d3a314859a88..8eb3467dd32e 100644
--- a/core/res/res/values-kn/strings.xml
+++ b/core/res/res/values-kn/strings.xml
@@ -287,6 +287,8 @@
<string name="notification_channel_usb" msgid="1528280969406244896">"USB ಸಂಪರ್ಕ"</string>
<string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"App ರನ್ ಆಗುತ್ತಿದೆ"</string>
<string name="notification_channel_foreground_service" msgid="7102189948158885178">"ಅಪ್ಲಿಕೇಶನ್‌ಗಳು ಬ್ಯಾಟರಿಯನ್ನು ಉಪಯೋಗಿಸುತ್ತಿವೆ"</string>
+ <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) -->
+ <skip />
<string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> ಆ್ಯಪ್, ಬ್ಯಾಟರಿಯನ್ನು ಬಳಸುತ್ತಿದೆ"</string>
<string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> ಅಪ್ಲಿಕೇಶನ್‌ಗಳು ಬ್ಯಾಟರಿ ಬಳಸುತ್ತಿವೆ"</string>
<string name="foreground_service_tap_for_details" msgid="9078123626015586751">"ಬ್ಯಾಟರಿ,ಡೇಟಾ ಬಳಕೆಯ ವಿವರಗಳಿಗಾಗಿ ಟ್ಯಾಪ್ ಮಾಡಿ"</string>
@@ -2188,4 +2190,12 @@
<string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string>
<string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string>
<string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string>
+ <!-- no translation found for window_magnification_prompt_title (8197528399699536320) -->
+ <skip />
+ <!-- no translation found for window_magnification_prompt_content (4166711383253283838) -->
+ <skip />
+ <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) -->
+ <skip />
+ <!-- no translation found for dismiss_action (1728820550388704784) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-ko/strings.xml b/core/res/res/values-ko/strings.xml
index f08ed6c253f1..46b4a1b3ed1c 100644
--- a/core/res/res/values-ko/strings.xml
+++ b/core/res/res/values-ko/strings.xml
@@ -287,6 +287,8 @@
<string name="notification_channel_usb" msgid="1528280969406244896">"USB 연결"</string>
<string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"실행 중인 앱"</string>
<string name="notification_channel_foreground_service" msgid="7102189948158885178">"배터리를 소모하는 앱"</string>
+ <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) -->
+ <skip />
<string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g>에서 배터리 사용 중"</string>
<string name="foreground_service_apps_in_background" msgid="7340037176412387863">"앱 <xliff:g id="NUMBER">%1$d</xliff:g>개에서 배터리 사용 중"</string>
<string name="foreground_service_tap_for_details" msgid="9078123626015586751">"탭하여 배터리 및 데이터 사용량 확인"</string>
@@ -2188,4 +2190,12 @@
<string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string>
<string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string>
<string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string>
+ <!-- no translation found for window_magnification_prompt_title (8197528399699536320) -->
+ <skip />
+ <!-- no translation found for window_magnification_prompt_content (4166711383253283838) -->
+ <skip />
+ <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) -->
+ <skip />
+ <!-- no translation found for dismiss_action (1728820550388704784) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-ky/strings.xml b/core/res/res/values-ky/strings.xml
index af980235650a..bb005f3281fc 100644
--- a/core/res/res/values-ky/strings.xml
+++ b/core/res/res/values-ky/strings.xml
@@ -287,6 +287,8 @@
<string name="notification_channel_usb" msgid="1528280969406244896">"USB аркылуу туташуу"</string>
<string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"Колдонмо иштеп жатат"</string>
<string name="notification_channel_foreground_service" msgid="7102189948158885178">"Колдонмолор батареяңызды коротууда"</string>
+ <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) -->
+ <skip />
<string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> колдонмосу батареяны пайдаланып жатат"</string>
<string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> колдонмо батареяны пайдаланып жатат"</string>
<string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Батареянын кубаты жана трафиктин көлөмү жөнүндө билүү үчүн таптап коюңуз"</string>
@@ -2188,4 +2190,12 @@
<string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string>
<string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string>
<string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string>
+ <!-- no translation found for window_magnification_prompt_title (8197528399699536320) -->
+ <skip />
+ <!-- no translation found for window_magnification_prompt_content (4166711383253283838) -->
+ <skip />
+ <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) -->
+ <skip />
+ <!-- no translation found for dismiss_action (1728820550388704784) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-lo/strings.xml b/core/res/res/values-lo/strings.xml
index 35d2e2d9857b..8e4e467fdd50 100644
--- a/core/res/res/values-lo/strings.xml
+++ b/core/res/res/values-lo/strings.xml
@@ -287,6 +287,8 @@
<string name="notification_channel_usb" msgid="1528280969406244896">"ການເຊື່ອມຕໍ່ USB"</string>
<string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"ແອັບກຳລັງເຮັດວຽກ"</string>
<string name="notification_channel_foreground_service" msgid="7102189948158885178">"ແອັບທີ່ກຳລັງໃຊ້ແບັດເຕີຣີ"</string>
+ <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) -->
+ <skip />
<string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> ກຳລັງໃຊ້ແບັດເຕີຣີຢູ່"</string>
<string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> ແອັບກຳລັງໃຊ້ແບັດເຕີຣີຢູ່"</string>
<string name="foreground_service_tap_for_details" msgid="9078123626015586751">"ແຕະເພື່ອເບິ່ງລາຍລະອຽດການນຳໃຊ້ແບັດເຕີຣີ ແລະ ອິນເຕີເນັດ"</string>
@@ -2188,4 +2190,12 @@
<string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string>
<string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string>
<string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string>
+ <!-- no translation found for window_magnification_prompt_title (8197528399699536320) -->
+ <skip />
+ <!-- no translation found for window_magnification_prompt_content (4166711383253283838) -->
+ <skip />
+ <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) -->
+ <skip />
+ <!-- no translation found for dismiss_action (1728820550388704784) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-lt/strings.xml b/core/res/res/values-lt/strings.xml
index 99e8b1f7277f..a9227163bf6b 100644
--- a/core/res/res/values-lt/strings.xml
+++ b/core/res/res/values-lt/strings.xml
@@ -293,6 +293,8 @@
<string name="notification_channel_usb" msgid="1528280969406244896">"USB jungtis"</string>
<string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"Programa paleista"</string>
<string name="notification_channel_foreground_service" msgid="7102189948158885178">"Programos, naudojančios akumuliatoriaus energiją"</string>
+ <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) -->
+ <skip />
<string name="foreground_service_app_in_background" msgid="1439289699671273555">"„<xliff:g id="APP_NAME">%1$s</xliff:g>“ naudoja akumuliatoriaus energiją"</string>
<string name="foreground_service_apps_in_background" msgid="7340037176412387863">"Programų, naudojančių akumuliatoriaus energiją: <xliff:g id="NUMBER">%1$d</xliff:g>"</string>
<string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Palieskite ir sužinokite išsamios informacijos apie akumuliatoriaus bei duomenų naudojimą"</string>
@@ -2256,4 +2258,12 @@
<string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string>
<string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string>
<string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string>
+ <!-- no translation found for window_magnification_prompt_title (8197528399699536320) -->
+ <skip />
+ <!-- no translation found for window_magnification_prompt_content (4166711383253283838) -->
+ <skip />
+ <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) -->
+ <skip />
+ <!-- no translation found for dismiss_action (1728820550388704784) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-lv/strings.xml b/core/res/res/values-lv/strings.xml
index 95752c336749..2fec712d0cd0 100644
--- a/core/res/res/values-lv/strings.xml
+++ b/core/res/res/values-lv/strings.xml
@@ -290,6 +290,8 @@
<string name="notification_channel_usb" msgid="1528280969406244896">"USB savienojums"</string>
<string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"Lietotne darbojas"</string>
<string name="notification_channel_foreground_service" msgid="7102189948158885178">"Lietotnes, kas patērē akumulatora jaudu"</string>
+ <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) -->
+ <skip />
<string name="foreground_service_app_in_background" msgid="1439289699671273555">"Lietotne <xliff:g id="APP_NAME">%1$s</xliff:g> izmanto akumulatoru"</string>
<string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> lietotne(-es) izmanto akumulatoru"</string>
<string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Pieskarieties, lai skatītu detalizētu informāciju par akumulatora un datu lietojumu"</string>
@@ -2222,4 +2224,12 @@
<string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string>
<string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string>
<string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string>
+ <!-- no translation found for window_magnification_prompt_title (8197528399699536320) -->
+ <skip />
+ <!-- no translation found for window_magnification_prompt_content (4166711383253283838) -->
+ <skip />
+ <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) -->
+ <skip />
+ <!-- no translation found for dismiss_action (1728820550388704784) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-mk/strings.xml b/core/res/res/values-mk/strings.xml
index 5e62762dc787..3d02757d8ed9 100644
--- a/core/res/res/values-mk/strings.xml
+++ b/core/res/res/values-mk/strings.xml
@@ -155,19 +155,19 @@
<string name="fcError" msgid="5325116502080221346">"Проблем со поврзувањето или неважечки код за карактеристиката."</string>
<string name="httpErrorOk" msgid="6206751415788256357">"Во ред"</string>
<string name="httpError" msgid="3406003584150566720">"Настана грешка на мрежа."</string>
- <string name="httpErrorLookup" msgid="3099834738227549349">"Не можеше да се најде URL."</string>
+ <string name="httpErrorLookup" msgid="3099834738227549349">"Не може да се најде URL."</string>
<string name="httpErrorUnsupportedAuthScheme" msgid="3976195595501606787">"Шемата за автентикација на локацијата не е поддржана."</string>
- <string name="httpErrorAuth" msgid="469553140922938968">"Не можеше да се автентицира."</string>
+ <string name="httpErrorAuth" msgid="469553140922938968">"Не може да се автентицира."</string>
<string name="httpErrorProxyAuth" msgid="7229662162030113406">"Автентикацијата преку прокси серверот беше неуспешна."</string>
- <string name="httpErrorConnect" msgid="3295081579893205617">"Не можеше да се поврзе со серверот."</string>
- <string name="httpErrorIO" msgid="3860318696166314490">"Не можеше да се комуницира со серверот. Обидете се повторно подоцна."</string>
+ <string name="httpErrorConnect" msgid="3295081579893205617">"Не може да се поврзе со серверот."</string>
+ <string name="httpErrorIO" msgid="3860318696166314490">"Не може да се комуницира со серверот. Обидете се повторно подоцна."</string>
<string name="httpErrorTimeout" msgid="7446272815190334204">"Времето за поврзување до серверот истече."</string>
<string name="httpErrorRedirectLoop" msgid="8455757777509512098">"Страницата содржи премногу пренасочувања од серверот."</string>
<string name="httpErrorUnsupportedScheme" msgid="2664108769858966374">"Протоколот не е поддржан."</string>
- <string name="httpErrorFailedSslHandshake" msgid="546319061228876290">"Не можеше да се воспостави безбедна врска."</string>
- <string name="httpErrorBadUrl" msgid="754447723314832538">"Страницата не можеше да се отвори, бидејќи URL е неважечки."</string>
- <string name="httpErrorFile" msgid="3400658466057744084">"Не можеше да се пристапи до датотеката."</string>
- <string name="httpErrorFileNotFound" msgid="5191433324871147386">"Не можеше да се најде бараната датотека."</string>
+ <string name="httpErrorFailedSslHandshake" msgid="546319061228876290">"Не може да се воспостави безбедна врска."</string>
+ <string name="httpErrorBadUrl" msgid="754447723314832538">"Страницата не може да се отвори, бидејќи URL е неважечки."</string>
+ <string name="httpErrorFile" msgid="3400658466057744084">"Не може да се пристапи до датотеката."</string>
+ <string name="httpErrorFileNotFound" msgid="5191433324871147386">"Не може да се најде бараната датотека."</string>
<string name="httpErrorTooManyRequests" msgid="2149677715552037198">"Се обработуваат премногу барања. Обидете се повторно подоцна."</string>
<string name="notification_title" msgid="5783748077084481121">"Грешка при пријавување за <xliff:g id="ACCOUNT">%1$s</xliff:g>"</string>
<string name="contentServiceSync" msgid="2341041749565687871">"Синхронизирај"</string>
@@ -287,6 +287,8 @@
<string name="notification_channel_usb" msgid="1528280969406244896">"USB-врска"</string>
<string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"Апликацијата работи"</string>
<string name="notification_channel_foreground_service" msgid="7102189948158885178">"Апликации што ја трошат батеријата"</string>
+ <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) -->
+ <skip />
<string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> користи батерија"</string>
<string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> апликации користат батерија"</string>
<string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Допрете за детали за батеријата и потрошениот сообраќај"</string>
@@ -550,7 +552,7 @@
<string name="biometric_error_device_not_secured" msgid="3129845065043995924">"Не е поставен PIN, шема или лозинка"</string>
<string name="biometric_error_generic" msgid="6784371929985434439">"Грешка при проверката"</string>
<string name="fingerprint_acquired_partial" msgid="8532380671091299342">"Откриен е делумен отпечаток. Обидете се повторно."</string>
- <string name="fingerprint_acquired_insufficient" msgid="2545149524031515411">"Отпечатокот не можеше да се обработи. Обидете се повторно."</string>
+ <string name="fingerprint_acquired_insufficient" msgid="2545149524031515411">"Отпечатокот не може да се обработи. Обидете се повторно."</string>
<string name="fingerprint_acquired_imager_dirty" msgid="4694800187151533990">"Сензорот за отпечатоци е валкан. Исчистете го и обидете се повторно."</string>
<string name="fingerprint_acquired_too_fast" msgid="5151661932298844352">"Прстот се движеше пребрзо. Обидете се повторно."</string>
<string name="fingerprint_acquired_too_slow" msgid="6683510291554497580">"Прстот се движеше премногу бавно. Обидете се повторно."</string>
@@ -1405,7 +1407,7 @@
<string name="permlab_requestIgnoreBatteryOptimizations" msgid="7646611326036631439">"прашај дали да се игнорираат оптимизациите на батеријата"</string>
<string name="permdesc_requestIgnoreBatteryOptimizations" msgid="634260656917874356">"Овозможува апликацијата да побара дозвола за игнорирање на оптимизациите на батеријата за таа апликација."</string>
<string name="tutorial_double_tap_to_zoom_message_short" msgid="1842872462124648678">"Допрете двапати за контрола на зумот"</string>
- <string name="gadget_host_error_inflating" msgid="2449961590495198720">"Не можеше да се додаде виџет."</string>
+ <string name="gadget_host_error_inflating" msgid="2449961590495198720">"Не може да се додаде виџет."</string>
<string name="ime_action_go" msgid="5536744546326495436">"Оди"</string>
<string name="ime_action_search" msgid="4501435960587287668">"Пребарај"</string>
<string name="ime_action_send" msgid="8456843745664334138">"Испрати"</string>
@@ -1440,7 +1442,7 @@
<string name="vpn_lockdown_connecting" msgid="6096725311950342607">"Поврзување со секогаш вклучена VPN..."</string>
<string name="vpn_lockdown_connected" msgid="2853127976590658469">"Поврзани со секогаш вклучена VPN"</string>
<string name="vpn_lockdown_disconnected" msgid="5573611651300764955">"Исклучено од секогаш вклучената VPN"</string>
- <string name="vpn_lockdown_error" msgid="4453048646854247947">"Не можеше да се поврзе на секогаш вклучената VPN"</string>
+ <string name="vpn_lockdown_error" msgid="4453048646854247947">"Не може да се поврзе на секогаш вклучената VPN"</string>
<string name="vpn_lockdown_config" msgid="8331697329868252169">"Променете ја мрежата или поставките за VPN"</string>
<string name="upload_file" msgid="8651942222301634271">"Избери датотека"</string>
<string name="no_file_chosen" msgid="4146295695162318057">"Не е избрана датотека"</string>
@@ -1982,9 +1984,9 @@
<string name="popup_window_default_title" msgid="6907717596694826919">"Појавен прозорец"</string>
<string name="slice_more_content" msgid="3377367737876888459">"+ <xliff:g id="NUMBER">%1$d</xliff:g>"</string>
<string name="shortcut_restored_on_lower_version" msgid="9206301954024286063">"Верзијата на апликацијата е постара или не е компатибилна со кратенкава"</string>
- <string name="shortcut_restore_not_supported" msgid="4763198938588468400">"Не можеше да се врати кратенката бидејќи апликацијата не поддржува бекап и враќање"</string>
- <string name="shortcut_restore_signature_mismatch" msgid="579345304221605479">"Не можеше да се врати кратенката бидејќи потписот на апликацијата не се совпаѓа"</string>
- <string name="shortcut_restore_unknown_issue" msgid="2478146134395982154">"Не можеше да се врати кратенката"</string>
+ <string name="shortcut_restore_not_supported" msgid="4763198938588468400">"Не може да се врати кратенката бидејќи апликацијата не поддржува бекап и враќање"</string>
+ <string name="shortcut_restore_signature_mismatch" msgid="579345304221605479">"Не може да се врати кратенката бидејќи потписот на апликацијата не се совпаѓа"</string>
+ <string name="shortcut_restore_unknown_issue" msgid="2478146134395982154">"Не може да се врати кратенката"</string>
<string name="shortcut_disabled_reason_unknown" msgid="753074793553599166">"Кратенката е оневозможена"</string>
<string name="harmful_app_warning_uninstall" msgid="6472912975664191772">"ДЕИНСТАЛИРАЈ"</string>
<string name="harmful_app_warning_open_anyway" msgid="5963657791740211807">"СЕПАК ОТВОРИ"</string>
@@ -2188,4 +2190,12 @@
<string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string>
<string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string>
<string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string>
+ <!-- no translation found for window_magnification_prompt_title (8197528399699536320) -->
+ <skip />
+ <!-- no translation found for window_magnification_prompt_content (4166711383253283838) -->
+ <skip />
+ <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) -->
+ <skip />
+ <!-- no translation found for dismiss_action (1728820550388704784) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-ml/strings.xml b/core/res/res/values-ml/strings.xml
index 85a797547475..583c46e325a3 100644
--- a/core/res/res/values-ml/strings.xml
+++ b/core/res/res/values-ml/strings.xml
@@ -287,6 +287,8 @@
<string name="notification_channel_usb" msgid="1528280969406244896">"USB കണക്ഷൻ"</string>
<string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"ആപ്പ് പ്രവർത്തിക്കുന്നു"</string>
<string name="notification_channel_foreground_service" msgid="7102189948158885178">"ആപ്പുകൾ ബാറ്ററി ഉപയോഗിക്കുന്നു"</string>
+ <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) -->
+ <skip />
<string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> ബാറ്ററി ഉപയോഗിക്കുന്നു"</string>
<string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> ആപ്പുകൾ ബാറ്ററി ഉപയോഗിക്കുന്നു"</string>
<string name="foreground_service_tap_for_details" msgid="9078123626015586751">"ബാറ്ററി, ഡാറ്റ ഉപയോഗം എന്നിവയുടെ വിശദാംശങ്ങളറിയാൻ ടാപ്പുചെയ്യുക"</string>
@@ -2188,4 +2190,12 @@
<string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string>
<string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string>
<string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string>
+ <!-- no translation found for window_magnification_prompt_title (8197528399699536320) -->
+ <skip />
+ <!-- no translation found for window_magnification_prompt_content (4166711383253283838) -->
+ <skip />
+ <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) -->
+ <skip />
+ <!-- no translation found for dismiss_action (1728820550388704784) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-mn/strings.xml b/core/res/res/values-mn/strings.xml
index 6523784a42e4..081e17065b56 100644
--- a/core/res/res/values-mn/strings.xml
+++ b/core/res/res/values-mn/strings.xml
@@ -287,6 +287,8 @@
<string name="notification_channel_usb" msgid="1528280969406244896">"USB холболт"</string>
<string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"Апп ажиллаж байна"</string>
<string name="notification_channel_foreground_service" msgid="7102189948158885178">"Апп батарей ашиглаж байна"</string>
+ <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) -->
+ <skip />
<string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> батерей ашиглаж байна"</string>
<string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> апп батерей ашиглаж байна"</string>
<string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Батерей, дата ашиглалтын талаар дэлгэрэнгүйг харахын тулд товшино уу"</string>
@@ -2188,4 +2190,12 @@
<string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string>
<string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string>
<string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string>
+ <!-- no translation found for window_magnification_prompt_title (8197528399699536320) -->
+ <skip />
+ <!-- no translation found for window_magnification_prompt_content (4166711383253283838) -->
+ <skip />
+ <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) -->
+ <skip />
+ <!-- no translation found for dismiss_action (1728820550388704784) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-mr/strings.xml b/core/res/res/values-mr/strings.xml
index e39d46dfb6f7..058863389c75 100644
--- a/core/res/res/values-mr/strings.xml
+++ b/core/res/res/values-mr/strings.xml
@@ -287,6 +287,8 @@
<string name="notification_channel_usb" msgid="1528280969406244896">"USB कनेक्‍शन"</string>
<string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"APP चालत आहे"</string>
<string name="notification_channel_foreground_service" msgid="7102189948158885178">"बॅटरी लवकर संपवणारी अ‍ॅप्स"</string>
+ <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) -->
+ <skip />
<string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> बॅटरी वापरत आहे"</string>
<string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> अ‍ॅप्स बॅटरी वापरत आहेत"</string>
<string name="foreground_service_tap_for_details" msgid="9078123626015586751">"बॅटरी आणि डेटा वापराच्‍या तपशीलांसाठी टॅप करा"</string>
@@ -2188,4 +2190,12 @@
<string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string>
<string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string>
<string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string>
+ <!-- no translation found for window_magnification_prompt_title (8197528399699536320) -->
+ <skip />
+ <!-- no translation found for window_magnification_prompt_content (4166711383253283838) -->
+ <skip />
+ <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) -->
+ <skip />
+ <!-- no translation found for dismiss_action (1728820550388704784) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-ms/strings.xml b/core/res/res/values-ms/strings.xml
index b38dec2c25ba..1d70f76f3cd7 100644
--- a/core/res/res/values-ms/strings.xml
+++ b/core/res/res/values-ms/strings.xml
@@ -287,6 +287,8 @@
<string name="notification_channel_usb" msgid="1528280969406244896">"Sambungan USB"</string>
<string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"Apl berjalan"</string>
<string name="notification_channel_foreground_service" msgid="7102189948158885178">"Apl yang menggunakan bateri"</string>
+ <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) -->
+ <skip />
<string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> sedang menggunakan bateri"</string>
<string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> apl sedang menggunakan bateri"</string>
<string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Ketik untuk mendapatkan butiran tentang penggunaan kuasa bateri dan data"</string>
@@ -2188,4 +2190,12 @@
<string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string>
<string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string>
<string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string>
+ <!-- no translation found for window_magnification_prompt_title (8197528399699536320) -->
+ <skip />
+ <!-- no translation found for window_magnification_prompt_content (4166711383253283838) -->
+ <skip />
+ <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) -->
+ <skip />
+ <!-- no translation found for dismiss_action (1728820550388704784) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-my/strings.xml b/core/res/res/values-my/strings.xml
index e1f3dcf31a49..097c6c599e2b 100644
--- a/core/res/res/values-my/strings.xml
+++ b/core/res/res/values-my/strings.xml
@@ -287,6 +287,8 @@
<string name="notification_channel_usb" msgid="1528280969406244896">"USB ချိတ်ဆက်မှု"</string>
<string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"APP လုပ်ဆောင်နေသည်"</string>
<string name="notification_channel_foreground_service" msgid="7102189948158885178">"အက်ပ်များက ဘက်ထရီကုန်စေသည်"</string>
+ <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) -->
+ <skip />
<string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> က ဘက်ထရီကို အသုံးပြုနေသည်"</string>
<string name="foreground_service_apps_in_background" msgid="7340037176412387863">"အက်ပ် <xliff:g id="NUMBER">%1$d</xliff:g> ခုက ဘက်ထရီကို အသုံးပြုနေသည်"</string>
<string name="foreground_service_tap_for_details" msgid="9078123626015586751">"ဘက်ထရီနှင့် ဒေတာအသုံးပြုမှု အသေးစိတ်ကို ကြည့်ရန် တို့ပါ"</string>
@@ -2188,4 +2190,12 @@
<string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string>
<string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string>
<string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string>
+ <!-- no translation found for window_magnification_prompt_title (8197528399699536320) -->
+ <skip />
+ <!-- no translation found for window_magnification_prompt_content (4166711383253283838) -->
+ <skip />
+ <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) -->
+ <skip />
+ <!-- no translation found for dismiss_action (1728820550388704784) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-nb/strings.xml b/core/res/res/values-nb/strings.xml
index 1c2e5c03d658..6fa80dd10722 100644
--- a/core/res/res/values-nb/strings.xml
+++ b/core/res/res/values-nb/strings.xml
@@ -287,6 +287,8 @@
<string name="notification_channel_usb" msgid="1528280969406244896">"USB-tilkobling"</string>
<string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"App kjører"</string>
<string name="notification_channel_foreground_service" msgid="7102189948158885178">"Apper bruker batteri"</string>
+ <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) -->
+ <skip />
<string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> bruker batteri"</string>
<string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> apper bruker batteri"</string>
<string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Trykk for detaljer om batteri- og databruk"</string>
@@ -2188,4 +2190,12 @@
<string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string>
<string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string>
<string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string>
+ <!-- no translation found for window_magnification_prompt_title (8197528399699536320) -->
+ <skip />
+ <!-- no translation found for window_magnification_prompt_content (4166711383253283838) -->
+ <skip />
+ <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) -->
+ <skip />
+ <!-- no translation found for dismiss_action (1728820550388704784) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-ne/strings.xml b/core/res/res/values-ne/strings.xml
index 915e158f3267..28c35254c5db 100644
--- a/core/res/res/values-ne/strings.xml
+++ b/core/res/res/values-ne/strings.xml
@@ -142,7 +142,7 @@
<string name="wfcSpnFormat_wifi" msgid="1376356951297043426">"Wi-Fi"</string>
<string name="wfcSpnFormat_wifi_calling_wo_hyphen" msgid="7178561009225028264">"WiFi कलिङ"</string>
<string name="wfcSpnFormat_vowifi" msgid="8371335230890725606">"VoWifi"</string>
- <string name="wifi_calling_off_summary" msgid="5626710010766902560">"निष्क्रिय"</string>
+ <string name="wifi_calling_off_summary" msgid="5626710010766902560">"अफ"</string>
<string name="wfc_mode_wifi_preferred_summary" msgid="1035175836270943089">"Wi-Fi मार्फत कल गर्नुहोस्"</string>
<string name="wfc_mode_cellular_preferred_summary" msgid="4958965609212575619">"मोबाइल नेटवर्कमार्फत कल गर्नुहोस्"</string>
<string name="wfc_mode_wifi_only_summary" msgid="104951993894678665">"Wi-Fi मात्र"</string>
@@ -203,7 +203,7 @@
<string name="factory_reset_message" msgid="2657049595153992213">"प्रशासकको एप प्रयोग गर्न मिल्दैन। तपाईंको यन्त्रको डेटा अब मेटाइने छ।\n\nतपाईंसँग प्रश्नहरू भएका खण्डमा आफ्नो संगठनका प्रशासकसँग सम्पर्क गर्नुहोस्।"</string>
<string name="printing_disabled_by" msgid="3517499806528864633">"<xliff:g id="OWNER_APP">%s</xliff:g> ले छाप्ने कार्यलाई असक्षम पार्यो।"</string>
<string name="personal_apps_suspension_title" msgid="7561416677884286600">"आफ्नो कार्य प्रोफाइल सक्रिय गर्नुहोस्"</string>
- <string name="personal_apps_suspension_text" msgid="6115455688932935597">"तपाईंले आफ्नो कार्य प्रोफाइल सक्रिय नगरुन्जेल तपाईंका व्यक्तिगत अनुप्रयोगहरूलाई रोक लगाइन्छ"</string>
+ <string name="personal_apps_suspension_text" msgid="6115455688932935597">"तपाईंले आफ्नो कार्य प्रोफाइल सक्रिय नगरुन्जेल तपाईंका व्यक्तिगत एपहरूलाई रोक लगाइन्छ"</string>
<string name="personal_apps_suspension_soon_text" msgid="8123898693479590">"मिति <xliff:g id="DATE">%1$s</xliff:g> <xliff:g id="TIME">%2$s</xliff:g> बजे व्यक्तिगत एपहरूलाई रोक लगाइने छ। तपाईंका IT एडमिन तपाईंलाई आफ्नो कार्य प्रोफाइल <xliff:g id="NUMBER">%3$d</xliff:g> भन्दा धेरै दिन निष्क्रिय राख्ने अनुमति दिनुहुन्न।"</string>
<string name="personal_apps_suspended_turn_profile_on" msgid="2758012869627513689">"सक्रिय गर्नुहोस्"</string>
<string name="me" msgid="6207584824693813140">"मलाई"</string>
@@ -231,7 +231,7 @@
<string name="shutdown_confirm" product="default" msgid="136816458966692315">"तपाईँको फोन बन्द हुने छ।"</string>
<string name="shutdown_confirm_question" msgid="796151167261608447">"के तपाईं बन्द गर्न चाहनुहुन्छ?"</string>
<string name="reboot_safemode_title" msgid="5853949122655346734">"सुरक्षित मोडमा पुनःबुट गर्नुहोस्"</string>
- <string name="reboot_safemode_confirm" msgid="1658357874737219624">"सुरक्षित मोडमा तपाईं पुनःबुट गर्न चाहनु हुन्छ? तपाईंले स्थापना गरेका सबै तेस्रो पक्षका अनुप्रयोगहरूलाई असक्षम गराउने छ।"</string>
+ <string name="reboot_safemode_confirm" msgid="1658357874737219624">"सुरक्षित मोडमा तपाईं पुनःबुट गर्न चाहनु हुन्छ? तपाईंले स्थापना गरेका सबै तेस्रो पक्षका एपहरूलाई असक्षम गराउने छ।"</string>
<string name="recent_tasks_title" msgid="8183172372995396653">"नयाँ"</string>
<string name="no_recent_tasks" msgid="9063946524312275906">"कुनै नयाँ एपहरू छैनन्।"</string>
<string name="global_actions" product="tablet" msgid="4412132498517933867">"ट्याब्लेट विकल्पहरू"</string>
@@ -287,6 +287,8 @@
<string name="notification_channel_usb" msgid="1528280969406244896">"USB जडान"</string>
<string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"एप चलिरहेको छ"</string>
<string name="notification_channel_foreground_service" msgid="7102189948158885178">"एपहरूले ब्याट्री खपत गर्दै छन्"</string>
+ <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) -->
+ <skip />
<string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> ले ब्याट्री प्रयोग गर्दै छ"</string>
<string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> एपहरूले ब्याट्री प्रयोग गर्दै छन्"</string>
<string name="foreground_service_tap_for_details" msgid="9078123626015586751">"ब्याट्री र डेटाका प्रयोग सम्बन्धी विवरणहरूका लागि ट्याप गर्नुहोस्"</string>
@@ -366,13 +368,13 @@
<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="permlab_reorderTasks" msgid="7598562301992923804">"चलिरहेका अनुप्रयोगहरूलाई पुनःक्रम गराउनुहोस्"</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="permdesc_killBackgroundProcesses" msgid="2357013583055434685">"एपलाई अन्य अनुप्रयोगहरूको पृष्ठभूमि प्रक्रियाहरू बन्द गर्न अनुमति दिन्छ। यसले अन्य अनुप्रयोगहरूलाई चल्नबाट रोक्न सक्दछ।"</string>
+ <string name="permdesc_killBackgroundProcesses" msgid="2357013583055434685">"एपलाई अन्य अनुप्रयोगहरूको पृष्ठभूमि प्रक्रियाहरू बन्द गर्न अनुमति दिन्छ। यसले अन्य एपहरूलाई चल्नबाट रोक्न सक्दछ।"</string>
<string name="permlab_systemAlertWindow" msgid="5757218350944719065">"यो एप अन्य एपहरूमाथि देखा पर्न सक्छ"</string>
<string name="permdesc_systemAlertWindow" msgid="1145660714855738308">"यो एप अन्य एपहरूमाथि वा स्क्रिनका अन्य भागहरूमा देखा पर्न सक्छ। यसले एपको सामान्य प्रयोगमा अवरोध पुर्याउन सक्छ र अन्य एपहरू देखा पर्ने तरिकालाई परिवर्तन गर्न सक्छ।"</string>
<string name="permlab_runInBackground" msgid="541863968571682785">"पृष्ठभूमिमा चलाउनुहोस्"</string>
@@ -380,7 +382,7 @@
<string name="permlab_useDataInBackground" msgid="783415807623038947">"पृष्ठभूमिमा डेटा प्रयोग गर्नुहोस्"</string>
<string name="permdesc_useDataInBackground" msgid="1230753883865891987">"यो अनुप्रयोगले पृष्ठभूमिमा डेटा प्रयोग गर्नसक्छ। यसले गर्दा धेरै डेटा प्रयोग हुनसक्छ।"</string>
<string name="permlab_persistentActivity" msgid="464970041740567970">"एपहरू जहिले पनि चल्ने बनाउनुहोस्"</string>
- <string name="permdesc_persistentActivity" product="tablet" msgid="6055271149187369916">"यसको आफ्नै मेमोरीमा दृढ भएकोको अंश बनाउनको लागि एपलाई अनुमति दिन्छ। ट्याब्लेटलाई ढिलो गराउँदै गरेका अन्य अनुप्रयोगहरूलाई सीमित मात्रामा यसले मेमोरी उपलब्ध गराउन सक्छ।"</string>
+ <string name="permdesc_persistentActivity" product="tablet" msgid="6055271149187369916">"यसको आफ्नै मेमोरीमा दृढ भएकोको अंश बनाउनको लागि एपलाई अनुमति दिन्छ। ट्याब्लेटलाई ढिलो गराउँदै गरेका अन्य एपहरूलाई सीमित मात्रामा यसले मेमोरी उपलब्ध गराउन सक्छ।"</string>
<string name="permdesc_persistentActivity" product="tv" msgid="6800526387664131321">"एपलाई आफ्ना केही अंशहरू मेमोरीमा स्थायी रूपमा राख्ने अनुमति दिन्छ। यसले गर्दा अन्य अनुप्रयोगहरूका लागि मेमोरीको अभाव हुन सक्ने भएकाले तपाईंको Android टिभी यन्त्र सुस्त हुन सक्छ।"</string>
<string name="permdesc_persistentActivity" product="default" msgid="1914841924366562051">"एपलाई मेमोरीमा आफैंको निरन्तरको अंश बनाउन अनुमति दिन्छ। यसले फोनलाई ढिला बनाएर अन्य एपहरूमा मेमोरी SIMित गर्न सक्दछन्।"</string>
<string name="permlab_foregroundService" msgid="1768855976818467491">"अग्रभूमिको सेवा सञ्चालन गर्नुहोस्"</string>
@@ -398,9 +400,9 @@
<string name="permdesc_broadcastSticky" product="tv" msgid="2338185920171000650">"एपलाई प्रसारण समाप्त भइसकेपछि पनि रहिरहने स्टिकी प्रसारणहरू पठाउने अनुमति दिन्छ। यो सुविधाको अत्यधिक प्रयोगले धेरै मेमोरी प्रयोग हुने भएकाले तपाईंको Android टिभी यन्त्र सुस्त वा अस्थिर हुन सक्छ।"</string>
<string name="permdesc_broadcastSticky" product="default" msgid="134529339678913453">"औपचारिक प्रसारणलाई पठाउनको लागि एक एपलाई अनुमति दिन्छ, जुन प्रसारण समाप्त भएपछि बाँकी रहन्छ। अत्यधिक प्रयोगले धेरै मेमोरी प्रयोग गरेको कारणले फोनलाई ढिलो र अस्थिर बनाउन सक्छ।"</string>
<string name="permlab_readContacts" msgid="8776395111787429099">"तपाईँका सम्पर्कहरू पढ्नुहोस्"</string>
- <string name="permdesc_readContacts" product="tablet" msgid="6430093481659992692">"एपलाई तपाईंको ट्याब्लेटमा भण्डार गरिएका सम्पर्क ठेगानाहरूसँग सम्बन्धित डेटा पढ्ने अनुमति दिन्छ। एपहरूले सम्पर्क ठेगानाहरू बनाउने तपाईंको ट्याब्लेटमा भण्डार गरिएका खाताहरूमाथि पनि पहुँच प्राप्त गर्ने छन्। यसमा तपाईंले स्थापना गरेका एपहरूले बनाएका खाताहरू पर्न सक्छन्। यस अनुमतिले अनुप्रयोगहरूलाई तपाईंको सम्पर्क ठेगानासम्बन्धी डेटा सुरक्षित गर्न दिने भएकाले हानिकारक एपहरूले तपाईंलाई थाहै नदिइकन सम्पर्क ठेगानासम्बन्धी डेटा आदान प्रदान गर्न सक्छन्।"</string>
- <string name="permdesc_readContacts" product="tv" msgid="8400138591135554789">"एपलाई तपाईंको Android टिभी यन्त्रमा भण्डारण गरिएका सम्पर्क ठेगानासम्बन्धी डेटा पढ्न अनुमति दिन्छ। एपहरूले सम्पर्क ठेगानाहरू बनाउने तपाईंको Android टिभी यन्त्रमा भण्डार गरिएका खाताहरूमाथि पनि पहुँच प्राप्त गर्ने छन्। यसमा तपाईंले स्थापना गरेका एपहरूले बनाएका खाताहरू पर्न सक्छन्। यस अनुमतिले अनुप्रयोगहरूलाई तपाईंको सम्पर्क ठेगानासम्बन्धी डेटा सुरक्षित गर्न दिने भएकाले हानिकारक एपहरूले तपाईंलाई थाहै नदिइकन सम्पर्क ठेगानासम्बन्धी डेटा आदान प्रदान गर्न सक्छन्।"</string>
- <string name="permdesc_readContacts" product="default" msgid="4911989776203207644">"एपलाई तपाईंको फोनमा भण्डार गरिएका सम्पर्क ठेगानाहरूसँग सम्बन्धित डेटा पढ्ने अनुमति दिन्छ। एपहरूले सम्पर्क ठेगानाहरू बनाउने तपाईंको फोनमा भण्डार गरिएका खाताहरूमाथि पनि पहुँच प्राप्त गर्ने छन्। यसमा तपाईंले स्थापना गरेका एपहरूले बनाएका खाताहरू पर्न सक्छन्। यस अनुमतिले अनुप्रयोगहरूलाई तपाईंको सम्पर्क ठेगानासम्बन्धी डेटा सुरक्षित गर्न दिने भएकाले हानिकारक एपहरूले तपाईंलाई थाहै नदिइकन सम्पर्क ठेगानासम्बन्धी डेटा आदान प्रदान गर्न सक्छन्।"</string>
+ <string name="permdesc_readContacts" product="tablet" msgid="6430093481659992692">"एपलाई तपाईंको ट्याब्लेटमा भण्डार गरिएका सम्पर्क ठेगानाहरूसँग सम्बन्धित डेटा पढ्ने अनुमति दिन्छ। एपहरूले सम्पर्क ठेगानाहरू बनाउने तपाईंको ट्याब्लेटमा भण्डार गरिएका खाताहरूमाथि पनि पहुँच प्राप्त गर्ने छन्। यसमा तपाईंले स्थापना गरेका एपहरूले बनाएका खाताहरू पर्न सक्छन्। यस अनुमतिले एपहरूलाई तपाईंको सम्पर्क ठेगानासम्बन्धी डेटा सुरक्षित गर्न दिने भएकाले हानिकारक एपहरूले तपाईंलाई थाहै नदिइकन सम्पर्क ठेगानासम्बन्धी डेटा आदान प्रदान गर्न सक्छन्।"</string>
+ <string name="permdesc_readContacts" product="tv" msgid="8400138591135554789">"एपलाई तपाईंको Android टिभी यन्त्रमा भण्डारण गरिएका सम्पर्क ठेगानासम्बन्धी डेटा पढ्न अनुमति दिन्छ। एपहरूले सम्पर्क ठेगानाहरू बनाउने तपाईंको Android टिभी यन्त्रमा भण्डार गरिएका खाताहरूमाथि पनि पहुँच प्राप्त गर्ने छन्। यसमा तपाईंले स्थापना गरेका एपहरूले बनाएका खाताहरू पर्न सक्छन्। यस अनुमतिले एपहरूलाई तपाईंको सम्पर्क ठेगानासम्बन्धी डेटा सुरक्षित गर्न दिने भएकाले हानिकारक एपहरूले तपाईंलाई थाहै नदिइकन सम्पर्क ठेगानासम्बन्धी डेटा आदान प्रदान गर्न सक्छन्।"</string>
+ <string name="permdesc_readContacts" product="default" msgid="4911989776203207644">"एपलाई तपाईंको फोनमा भण्डार गरिएका सम्पर्क ठेगानाहरूसँग सम्बन्धित डेटा पढ्ने अनुमति दिन्छ। एपहरूले सम्पर्क ठेगानाहरू बनाउने तपाईंको फोनमा भण्डार गरिएका खाताहरूमाथि पनि पहुँच प्राप्त गर्ने छन्। यसमा तपाईंले स्थापना गरेका एपहरूले बनाएका खाताहरू पर्न सक्छन्। यस अनुमतिले एपहरूलाई तपाईंको सम्पर्क ठेगानासम्बन्धी डेटा सुरक्षित गर्न दिने भएकाले हानिकारक एपहरूले तपाईंलाई थाहै नदिइकन सम्पर्क ठेगानासम्बन्धी डेटा आदान प्रदान गर्न सक्छन्।"</string>
<string name="permlab_writeContacts" msgid="8919430536404830430">"तपाईँका सम्पर्कहरू परिवर्तन गर्नुहोस्"</string>
<string name="permdesc_writeContacts" product="tablet" msgid="6422419281427826181">"एपलाई तपाईंको ट्याब्लेटमा भण्डारण गरिएका सम्पर्क ठेगानासम्बन्धी डेटा परिमार्जन गर्न अनुमति दिन्छ। यो अनुमतिले एपलाई सम्पर्क ठेगानासम्बन्धी डेटा मेटाउन अनुमति दिन्छ।"</string>
<string name="permdesc_writeContacts" product="tv" msgid="6488872735379978935">"एपलाई तपाईंको Android टिभी यन्त्रमा भण्डारण गरिएका सम्पर्क ठेगानासम्बन्धी डेटा परिमार्जन गर्न अनुमति दिन्छ। यो अनुमतिले एपलाई सम्पर्क ठेगानासम्बन्धी डेटा मेटाउन अनुमति दिन्छ।"</string>
@@ -621,7 +623,7 @@
<string name="permlab_readSyncSettings" msgid="6250532864893156277">"समीकरण सेटिङहरू पढ्नुहोस्"</string>
<string name="permdesc_readSyncSettings" msgid="1325658466358779298">"एपलाई खाताको लागि सिंक सेटिङहरू पढ्न अनुमति दिन्छ। उदाहरणको लागि यसले व्यक्तिहरको एप खातासँग सिंक भएको नभएको निर्धारण गर्न सक्दछ।"</string>
<string name="permlab_writeSyncSettings" msgid="6583154300780427399">"टगल सिंक खुला र बन्द"</string>
- <string name="permdesc_writeSyncSettings" msgid="6029151549667182687">"अनुप्रयोगहरूलाई खाताको लागि सिंक सेटिङहरू परिमार्जन गर्न अनुमति दिन्छ। उदाहरणको लागि, यो खातासँग व्यक्ति एपको सिंक सक्षम गर्न प्रयोग गर्न सकिन्छ।"</string>
+ <string name="permdesc_writeSyncSettings" msgid="6029151549667182687">"एपहरूलाई खाताको लागि सिंक सेटिङहरू परिमार्जन गर्न अनुमति दिन्छ। उदाहरणको लागि, यो खातासँग व्यक्ति एपको सिंक सक्षम गर्न प्रयोग गर्न सकिन्छ।"</string>
<string name="permlab_readSyncStats" msgid="3747407238320105332">"सिंक तथ्याङ्कहरू पढ्नुहोस्"</string>
<string name="permdesc_readSyncStats" msgid="3867809926567379434">"एपलाई खाताको लागि समीकरणको आँकडा समीकरण घटनाहरूको इतिहास र समीकरण गरिएको डेटाको मापन समेत, पढ्न अनुमति दिन्छ।"</string>
<string name="permlab_sdcardRead" msgid="5791467020950064920">"आफ्नो आदान प्रदान गरिएको भण्डारणको सामग्रीहरूहरू पढ्नुहोस्"</string>
@@ -649,9 +651,9 @@
<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="permlab_bindDreamService" msgid="4776175992848982706">"सपना सेवामा बाँध्नुहोस्"</string>
@@ -675,7 +677,7 @@
<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>
- <string name="permdesc_startViewPermissionUsage" msgid="2820325605959586538">"वाहकलाई कुनै अनुप्रयोगसम्बन्धी अनुमतिको प्रयोग सुरु गर्न दिन्छ। साधारण अनुप्रयोगहरूलाई कहिल्यै आवश्यक नपर्नु पर्ने हो।"</string>
+ <string name="permdesc_startViewPermissionUsage" msgid="2820325605959586538">"वाहकलाई कुनै एपसम्बन्धी अनुमतिको प्रयोग सुरु गर्न दिन्छ। साधारण एपहरूलाई कहिल्यै आवश्यक नपर्नु पर्ने हो।"</string>
<string name="policylab_limitPassword" msgid="4851829918814422199">"पासवर्ड नियमहरू मिलाउनुहोस्"</string>
<string name="policydesc_limitPassword" msgid="4105491021115793793">"स्क्रिन लक पासवर्ड र PIN हरूमा अनुमति दिइएको लम्बाइ र वर्णहरूको नियन्त्रण गर्नुहोस्।"</string>
<string name="policylab_watchLogin" msgid="7599669460083719504">"मनिटरको स्क्रिन अनलक गर्ने प्रयासहरू"</string>
@@ -1126,7 +1128,7 @@
<string name="dialog_alert_title" msgid="651856561974090712">"सावधानी"</string>
<string name="loading" msgid="3138021523725055037">"लोड हुँदै..."</string>
<string name="capital_on" msgid="2770685323900821829">"चालु"</string>
- <string name="capital_off" msgid="7443704171014626777">"बन्द"</string>
+ <string name="capital_off" msgid="7443704171014626777">"अफ"</string>
<string name="checked" msgid="9179896827054513119">"जाँच गरिएको"</string>
<string name="not_checked" msgid="7972320087569023342">"जाँच गरिएको छैन"</string>
<string name="selected" msgid="6614607926197755875">"चयन गरियो"</string>
@@ -1879,7 +1881,7 @@
<string name="default_notification_channel_label" msgid="3697928973567217330">"वर्गीकरण नगरिएको"</string>
<string name="importance_from_user" msgid="2782756722448800447">"तपाईंले यी सूचनाहरूको महत्त्व सेट गर्नुहोस् ।"</string>
<string name="importance_from_person" msgid="4235804979664465383">"यसमा सङ्लग्न भएका मानिसहरूको कारणले गर्दा यो महत्वपूर्ण छ।"</string>
- <string name="notification_history_title_placeholder" msgid="7748630986182249599">"अनुप्रयोगसम्बन्धी आफ्नो रोजाइअनुसारको सूचना"</string>
+ <string name="notification_history_title_placeholder" msgid="7748630986182249599">"एपसम्बन्धी आफ्नो रोजाइअनुसारको सूचना"</string>
<string name="user_creation_account_exists" msgid="2239146360099708035">"<xliff:g id="ACCOUNT">%2$s</xliff:g> (यस खाताको प्रयोगकर्ता पहिले नै अवस्थित छ) मा नयाँ प्रयोगकर्ता सिर्जना गर्न <xliff:g id="APP">%1$s</xliff:g> लाई अनुमति दिने हो?"</string>
<string name="user_creation_adding" msgid="7305185499667958364">"<xliff:g id="ACCOUNT">%2$s</xliff:g> मा नयाँ प्रयोगकर्ता सिर्जना गर्न <xliff:g id="APP">%1$s</xliff:g> लाई अनुमति दिने हो?"</string>
<string name="language_selection_title" msgid="52674936078683285">"भाषा थप्नुहोस्"</string>
@@ -1911,7 +1913,7 @@
<string name="pin_specific_target" msgid="7824671240625957415">"<xliff:g id="LABEL">%1$s</xliff:g> लाई पिन गर्नुहोस्"</string>
<string name="unpin_target" msgid="3963318576590204447">"अनपिन गर्नुहोस्"</string>
<string name="unpin_specific_target" msgid="3859828252160908146">"<xliff:g id="LABEL">%1$s</xliff:g> लाई अनपिन गर्नुहोस्"</string>
- <string name="app_info" msgid="6113278084877079851">"अनुप्रयोगका बारे जानकारी"</string>
+ <string name="app_info" msgid="6113278084877079851">"एपका बारे जानकारी"</string>
<string name="negative_duration" msgid="1938335096972945232">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="demo_starting_message" msgid="6577581216125805905">"डेमो सुरु गर्दै…"</string>
<string name="demo_restarting_message" msgid="1160053183701746766">"यन्त्रलाई रिसेट गर्दै…"</string>
@@ -2188,4 +2190,12 @@
<string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string>
<string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string>
<string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string>
+ <!-- no translation found for window_magnification_prompt_title (8197528399699536320) -->
+ <skip />
+ <!-- no translation found for window_magnification_prompt_content (4166711383253283838) -->
+ <skip />
+ <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) -->
+ <skip />
+ <!-- no translation found for dismiss_action (1728820550388704784) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-nl/strings.xml b/core/res/res/values-nl/strings.xml
index f768c833da66..8b571e82dea8 100644
--- a/core/res/res/values-nl/strings.xml
+++ b/core/res/res/values-nl/strings.xml
@@ -287,6 +287,8 @@
<string name="notification_channel_usb" msgid="1528280969406244896">"USB-verbinding"</string>
<string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"App actief"</string>
<string name="notification_channel_foreground_service" msgid="7102189948158885178">"Apps die de batterij gebruiken"</string>
+ <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) -->
+ <skip />
<string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> gebruikt de batterij"</string>
<string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> apps gebruiken de batterij"</string>
<string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Tik voor batterij- en datagebruik"</string>
@@ -2188,4 +2190,12 @@
<string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string>
<string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string>
<string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string>
+ <!-- no translation found for window_magnification_prompt_title (8197528399699536320) -->
+ <skip />
+ <!-- no translation found for window_magnification_prompt_content (4166711383253283838) -->
+ <skip />
+ <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) -->
+ <skip />
+ <!-- no translation found for dismiss_action (1728820550388704784) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-or/strings.xml b/core/res/res/values-or/strings.xml
index 520673279ce7..4b5c9b0be420 100644
--- a/core/res/res/values-or/strings.xml
+++ b/core/res/res/values-or/strings.xml
@@ -287,6 +287,8 @@
<string name="notification_channel_usb" msgid="1528280969406244896">"USB ସଂଯୋଗ"</string>
<string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"ଆପ୍‍ ଚାଲୁଛି"</string>
<string name="notification_channel_foreground_service" msgid="7102189948158885178">"ଆପ୍‍ଗୁଡ଼ିକ ବ୍ୟାଟେରୀ ଖର୍ଚ୍ଚ କରିଥା\'ନ୍ତି"</string>
+ <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) -->
+ <skip />
<string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> ବ୍ୟାଟେରୀ ବ୍ୟବହାର କରୁଛି"</string>
<string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g>ଟି ଆପ୍‍ ବ୍ୟାଟେରୀ ବ୍ୟବହାର କରୁଛନ୍ତି"</string>
<string name="foreground_service_tap_for_details" msgid="9078123626015586751">"ବ୍ୟାଟେରୀ ଏବଂ ଡାଟା ବ୍ୟବହାର ଉପରେ ବିବରଣୀ ପାଇଁ ଟାପ୍‍ କରନ୍ତୁ"</string>
@@ -2188,4 +2190,12 @@
<string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string>
<string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string>
<string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string>
+ <!-- no translation found for window_magnification_prompt_title (8197528399699536320) -->
+ <skip />
+ <!-- no translation found for window_magnification_prompt_content (4166711383253283838) -->
+ <skip />
+ <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) -->
+ <skip />
+ <!-- no translation found for dismiss_action (1728820550388704784) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-pa/strings.xml b/core/res/res/values-pa/strings.xml
index 11559f39565f..5de08850a3ee 100644
--- a/core/res/res/values-pa/strings.xml
+++ b/core/res/res/values-pa/strings.xml
@@ -287,6 +287,8 @@
<string name="notification_channel_usb" msgid="1528280969406244896">"USB ਕਨੈਕਸ਼ਨ"</string>
<string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"ਚੱਲ ਰਹੀ ਐਪ"</string>
<string name="notification_channel_foreground_service" msgid="7102189948158885178">"ਬੈਟਰੀ ਦੀ ਖਪਤ ਕਰਨ ਵਾਲੀਆਂ ਐਪਾਂ"</string>
+ <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) -->
+ <skip />
<string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> ਵੱਲੋਂ ਬੈਟਰੀ ਦੀ ਵਰਤੋਂ ਕੀਤੀ ਜਾ ਰਹੀ ਹੈ"</string>
<string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> ਐਪਾਂ ਬੈਟਰੀ ਦੀ ਵਰਤੋਂ ਕਰ ਰਹੀਆਂ ਹਨ"</string>
<string name="foreground_service_tap_for_details" msgid="9078123626015586751">"ਬੈਟਰੀ ਅਤੇ ਡਾਟਾ ਵਰਤੋਂ ਸਬੰਧੀ ਵੇਰਵਿਆਂ ਲਈ ਟੈਪ ਕਰੋ"</string>
@@ -2188,4 +2190,12 @@
<string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string>
<string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string>
<string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string>
+ <!-- no translation found for window_magnification_prompt_title (8197528399699536320) -->
+ <skip />
+ <!-- no translation found for window_magnification_prompt_content (4166711383253283838) -->
+ <skip />
+ <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) -->
+ <skip />
+ <!-- no translation found for dismiss_action (1728820550388704784) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-pl/strings.xml b/core/res/res/values-pl/strings.xml
index 07773da7f933..427beb508366 100644
--- a/core/res/res/values-pl/strings.xml
+++ b/core/res/res/values-pl/strings.xml
@@ -186,10 +186,10 @@
<item quantity="one">Urząd certyfikacji został zainstalowany</item>
</plurals>
<string name="ssl_ca_cert_noti_by_unknown" msgid="4961102218216815242">"Przez nieznany podmiot zewnętrzny"</string>
- <string name="ssl_ca_cert_noti_by_administrator" msgid="4564941950768783879">"Przez administratora Twojego profilu do pracy"</string>
+ <string name="ssl_ca_cert_noti_by_administrator" msgid="4564941950768783879">"Przez administratora Twojego profilu służbowego"</string>
<string name="ssl_ca_cert_noti_managed" msgid="217337232273211674">"Przez <xliff:g id="MANAGING_DOMAIN">%s</xliff:g>"</string>
<string name="work_profile_deleted" msgid="5891181538182009328">"Usunięto profil służbowy"</string>
- <string name="work_profile_deleted_details" msgid="3773706828364418016">"Brakuje aplikacji administratora profilu do pracy lub jest ona uszkodzona. Dlatego Twój profil służbowy i związane z nim dane zostały usunięte. Skontaktuj się ze swoim administratorem, by uzyskać pomoc."</string>
+ <string name="work_profile_deleted_details" msgid="3773706828364418016">"Brakuje aplikacji administratora profilu służbowego lub jest ona uszkodzona. Dlatego Twój profil służbowy i związane z nim dane zostały usunięte. Skontaktuj się ze swoim administratorem, by uzyskać pomoc."</string>
<string name="work_profile_deleted_description_dpm_wipe" msgid="2477244968924647232">"Twój profil służbowy nie jest już dostępny na tym urządzeniu"</string>
<string name="work_profile_deleted_reason_maximum_password_failure" msgid="1080323158315663167">"Zbyt wiele prób podania hasła"</string>
<string name="device_ownership_relinquished" msgid="4080886992183195724">"Administrator odstąpił urządzenie do użytku osobistego"</string>
@@ -206,8 +206,8 @@
<string name="factory_reset_warning" msgid="6858705527798047809">"Twoje urządzenie zostanie wyczyszczone"</string>
<string name="factory_reset_message" msgid="2657049595153992213">"Nie można użyć aplikacji administratora. Dane z urządzenia zostaną wykasowane.\n\nJeśli masz pytania, skontaktuj się z administratorem organizacji."</string>
<string name="printing_disabled_by" msgid="3517499806528864633">"Drukowanie wyłączone przez: <xliff:g id="OWNER_APP">%s</xliff:g>."</string>
- <string name="personal_apps_suspension_title" msgid="7561416677884286600">"Włącz profil do pracy"</string>
- <string name="personal_apps_suspension_text" msgid="6115455688932935597">"Zablokowano aplikacje osobiste do czasu włączenia profilu do pracy"</string>
+ <string name="personal_apps_suspension_title" msgid="7561416677884286600">"Włącz profil służbowy"</string>
+ <string name="personal_apps_suspension_text" msgid="6115455688932935597">"Zablokowano aplikacje osobiste do czasu włączenia profilu służbowego"</string>
<string name="personal_apps_suspension_soon_text" msgid="8123898693479590">"Aplikacje osobiste zostaną zablokowane <xliff:g id="DATE">%1$s</xliff:g> o <xliff:g id="TIME">%2$s</xliff:g>. Administrator IT nie pozwala na wyłączenie profilu służbowego na dłużej niż <xliff:g id="NUMBER">%3$d</xliff:g> dni."</string>
<string name="personal_apps_suspended_turn_profile_on" msgid="2758012869627513689">"Włącz"</string>
<string name="me" msgid="6207584824693813140">"Ja"</string>
@@ -293,6 +293,8 @@
<string name="notification_channel_usb" msgid="1528280969406244896">"Połączenie USB"</string>
<string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"Działa aplikacja"</string>
<string name="notification_channel_foreground_service" msgid="7102189948158885178">"Aplikacje zużywające baterię"</string>
+ <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) -->
+ <skip />
<string name="foreground_service_app_in_background" msgid="1439289699671273555">"Aplikacja <xliff:g id="APP_NAME">%1$s</xliff:g> zużywa baterię"</string>
<string name="foreground_service_apps_in_background" msgid="7340037176412387863">"Liczba aplikacji zużywających baterię: <xliff:g id="NUMBER">%1$d</xliff:g>"</string>
<string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Kliknij, by wyświetlić szczegóły wykorzystania baterii i użycia danych"</string>
@@ -716,7 +718,7 @@
<string-array name="phoneTypes">
<item msgid="8996339953292723951">"Dom"</item>
<item msgid="7740243458912727194">"Komórka"</item>
- <item msgid="8526146065496663766">"Praca"</item>
+ <item msgid="8526146065496663766">"Służbowy"</item>
<item msgid="8150904584178569699">"Faks w pracy"</item>
<item msgid="4537253139152229577">"Faks domowy"</item>
<item msgid="6751245029698664340">"Pager"</item>
@@ -725,24 +727,24 @@
</string-array>
<string-array name="emailAddressTypes">
<item msgid="7786349763648997741">"Dom"</item>
- <item msgid="435564470865989199">"Praca"</item>
+ <item msgid="435564470865989199">"Służbowy"</item>
<item msgid="4199433197875490373">"Inne"</item>
<item msgid="3233938986670468328">"Niestandardowy"</item>
</string-array>
<string-array name="postalAddressTypes">
<item msgid="3861463339764243038">"Dom"</item>
- <item msgid="5472578890164979109">"Praca"</item>
+ <item msgid="5472578890164979109">"Służbowy"</item>
<item msgid="5718921296646594739">"Inny"</item>
<item msgid="5523122236731783179">"Niestandardowy"</item>
</string-array>
<string-array name="imAddressTypes">
<item msgid="588088543406993772">"Dom"</item>
- <item msgid="5503060422020476757">"Praca"</item>
+ <item msgid="5503060422020476757">"Służbowy"</item>
<item msgid="2530391194653760297">"Inne"</item>
<item msgid="7640927178025203330">"Niestandardowy"</item>
</string-array>
<string-array name="organizationTypes">
- <item msgid="6144047813304847762">"Praca"</item>
+ <item msgid="6144047813304847762">"Służbowy"</item>
<item msgid="7402720230065674193">"Inne"</item>
<item msgid="808230403067569648">"Niestandardowy"</item>
</string-array>
@@ -1462,8 +1464,8 @@
<string name="deny" msgid="6632259981847676572">"Odmów"</string>
<string name="permission_request_notification_title" msgid="1810025922441048273">"Prośba o pozwolenie"</string>
<string name="permission_request_notification_with_subtitle" msgid="3743417870360129298">"Prośba o pozwolenie\ndotyczące konta <xliff:g id="ACCOUNT">%s</xliff:g>"</string>
- <string name="forward_intent_to_owner" msgid="4620359037192871015">"Używasz tej aplikacji poza profilem do pracy"</string>
- <string name="forward_intent_to_work" msgid="3620262405636021151">"Używasz tej aplikacji w swoim profilu do pracy"</string>
+ <string name="forward_intent_to_owner" msgid="4620359037192871015">"Używasz tej aplikacji poza profilem służbowym"</string>
+ <string name="forward_intent_to_work" msgid="3620262405636021151">"Używasz tej aplikacji w swoim profilu służbowym"</string>
<string name="input_method_binding_label" msgid="1166731601721983656">"Sposób wprowadzania tekstu"</string>
<string name="sync_binding_label" msgid="469249309424662147">"Synchronizacja"</string>
<string name="accessibility_binding_label" msgid="1974602776545801715">"Ułatwienia dostępu"</string>
@@ -1597,7 +1599,7 @@
<string name="SetupCallDefault" msgid="5581740063237175247">"Odebrać połączenie?"</string>
<string name="activity_resolver_use_always" msgid="5575222334666843269">"Zawsze"</string>
<string name="activity_resolver_use_once" msgid="948462794469672658">"Tylko raz"</string>
- <string name="activity_resolver_work_profiles_support" msgid="4071345609235361269">"%1$s nie obsługuje profilu do pracy"</string>
+ <string name="activity_resolver_work_profiles_support" msgid="4071345609235361269">"%1$s nie obsługuje profilu służbowego"</string>
<string name="default_audio_route_name" product="tablet" msgid="367936735632195517">"Tablet"</string>
<string name="default_audio_route_name" product="tv" msgid="4908971385068087367">"Telewizor"</string>
<string name="default_audio_route_name" product="default" msgid="9213546147739983977">"Telefon"</string>
@@ -1834,7 +1836,7 @@
<string name="select_day" msgid="2060371240117403147">"Wybierz miesiąc i dzień"</string>
<string name="select_year" msgid="1868350712095595393">"Wybierz rok"</string>
<string name="deleted_key" msgid="9130083334943364001">"<xliff:g id="KEY">%1$s</xliff:g> usunięte"</string>
- <string name="managed_profile_label_badge" msgid="6762559569999499495">"<xliff:g id="LABEL">%1$s</xliff:g> (praca)"</string>
+ <string name="managed_profile_label_badge" msgid="6762559569999499495">"<xliff:g id="LABEL">%1$s</xliff:g> (służbowy)"</string>
<string name="managed_profile_label_badge_2" msgid="5673187309555352550">"<xliff:g id="LABEL">%1$s</xliff:g> – praca 2"</string>
<string name="managed_profile_label_badge_3" msgid="6882151970556391957">"<xliff:g id="LABEL">%1$s</xliff:g> – praca 3"</string>
<string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"Podaj PIN, aby odpiąć"</string>
@@ -1957,8 +1959,8 @@
<string name="app_suspended_default_message" msgid="6451215678552004172">"Aplikacja <xliff:g id="APP_NAME_0">%1$s</xliff:g> nie jest teraz dostępna. Zarządza tym aplikacja <xliff:g id="APP_NAME_1">%2$s</xliff:g>."</string>
<string name="app_suspended_more_details" msgid="211260942831587014">"Więcej informacji"</string>
<string name="app_suspended_unsuspend_message" msgid="1665438589450555459">"Wznów działanie aplikacji"</string>
- <string name="work_mode_off_title" msgid="5503291976647976560">"Włączyć profil do pracy?"</string>
- <string name="work_mode_off_message" msgid="8417484421098563803">"Aplikacje do pracy, powiadomienia, dane i inne funkcje profilu do pracy zostaną włączone"</string>
+ <string name="work_mode_off_title" msgid="5503291976647976560">"Włączyć profil służbowy?"</string>
+ <string name="work_mode_off_message" msgid="8417484421098563803">"Aplikacje służbowe, powiadomienia, dane i inne funkcje profilu służbowego zostaną włączone"</string>
<string name="work_mode_turn_on" msgid="3662561662475962285">"Włącz"</string>
<string name="app_blocked_title" msgid="7353262160455028160">"Aplikacja jest niedostępna"</string>
<string name="app_blocked_message" msgid="542972921087873023">"Aplikacja <xliff:g id="APP_NAME">%1$s</xliff:g> jest obecnie niedostępna."</string>
@@ -2256,4 +2258,12 @@
<string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string>
<string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string>
<string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string>
+ <!-- no translation found for window_magnification_prompt_title (8197528399699536320) -->
+ <skip />
+ <!-- no translation found for window_magnification_prompt_content (4166711383253283838) -->
+ <skip />
+ <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) -->
+ <skip />
+ <!-- no translation found for dismiss_action (1728820550388704784) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-pt-rBR/strings.xml b/core/res/res/values-pt-rBR/strings.xml
index bfd32f35c993..3fed0287bc1e 100644
--- a/core/res/res/values-pt-rBR/strings.xml
+++ b/core/res/res/values-pt-rBR/strings.xml
@@ -287,6 +287,7 @@
<string name="notification_channel_usb" msgid="1528280969406244896">"Conexão USB"</string>
<string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"App em execução"</string>
<string name="notification_channel_foreground_service" msgid="7102189948158885178">"Apps que estão consumindo a bateria"</string>
+ <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Ampliação"</string>
<string name="foreground_service_app_in_background" msgid="1439289699671273555">"O app <xliff:g id="APP_NAME">%1$s</xliff:g> está consumindo a bateria"</string>
<string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> apps estão consumindo a bateria"</string>
<string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Tocar para ver detalhes sobre a bateria e o uso de dados"</string>
@@ -2188,4 +2189,8 @@
<string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string>
<string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string>
<string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string>
+ <string name="window_magnification_prompt_title" msgid="8197528399699536320">"Novo: Lupa de janela"</string>
+ <string name="window_magnification_prompt_content" msgid="4166711383253283838">"Agora você pode ampliar uma ou todas as suas telas"</string>
+ <string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"Ativar nas Configurações"</string>
+ <string name="dismiss_action" msgid="1728820550388704784">"Dispensar"</string>
</resources>
diff --git a/core/res/res/values-pt-rPT/strings.xml b/core/res/res/values-pt-rPT/strings.xml
index e83d5578cb32..1c890dd4b651 100644
--- a/core/res/res/values-pt-rPT/strings.xml
+++ b/core/res/res/values-pt-rPT/strings.xml
@@ -287,6 +287,7 @@
<string name="notification_channel_usb" msgid="1528280969406244896">"Ligação USB"</string>
<string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"Aplicação em execução"</string>
<string name="notification_channel_foreground_service" msgid="7102189948158885178">"Apps que estão a consumir bateria"</string>
+ <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Ampliação"</string>
<string name="foreground_service_app_in_background" msgid="1439289699671273555">"A app <xliff:g id="APP_NAME">%1$s</xliff:g> está a consumir bateria."</string>
<string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> aplicações estão a consumir bateria."</string>
<string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Toque para obter detalhes acerca da utilização da bateria e dos dados"</string>
@@ -2188,4 +2189,8 @@
<string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string>
<string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string>
<string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string>
+ <string name="window_magnification_prompt_title" msgid="8197528399699536320">"Novidade: ampliador da janela"</string>
+ <string name="window_magnification_prompt_content" msgid="4166711383253283838">"Já pode ampliar o ecrã parcial ou totalmente."</string>
+ <string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"Ativar nas Definições"</string>
+ <string name="dismiss_action" msgid="1728820550388704784">"Ignorar"</string>
</resources>
diff --git a/core/res/res/values-pt/strings.xml b/core/res/res/values-pt/strings.xml
index bfd32f35c993..3fed0287bc1e 100644
--- a/core/res/res/values-pt/strings.xml
+++ b/core/res/res/values-pt/strings.xml
@@ -287,6 +287,7 @@
<string name="notification_channel_usb" msgid="1528280969406244896">"Conexão USB"</string>
<string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"App em execução"</string>
<string name="notification_channel_foreground_service" msgid="7102189948158885178">"Apps que estão consumindo a bateria"</string>
+ <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Ampliação"</string>
<string name="foreground_service_app_in_background" msgid="1439289699671273555">"O app <xliff:g id="APP_NAME">%1$s</xliff:g> está consumindo a bateria"</string>
<string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> apps estão consumindo a bateria"</string>
<string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Tocar para ver detalhes sobre a bateria e o uso de dados"</string>
@@ -2188,4 +2189,8 @@
<string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string>
<string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string>
<string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string>
+ <string name="window_magnification_prompt_title" msgid="8197528399699536320">"Novo: Lupa de janela"</string>
+ <string name="window_magnification_prompt_content" msgid="4166711383253283838">"Agora você pode ampliar uma ou todas as suas telas"</string>
+ <string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"Ativar nas Configurações"</string>
+ <string name="dismiss_action" msgid="1728820550388704784">"Dispensar"</string>
</resources>
diff --git a/core/res/res/values-ro/strings.xml b/core/res/res/values-ro/strings.xml
index fcd70eb61a25..5cf30763d8f0 100644
--- a/core/res/res/values-ro/strings.xml
+++ b/core/res/res/values-ro/strings.xml
@@ -290,6 +290,8 @@
<string name="notification_channel_usb" msgid="1528280969406244896">"Conexiune USB"</string>
<string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"Aplicația rulează"</string>
<string name="notification_channel_foreground_service" msgid="7102189948158885178">"Aplicațiile consumă bateria"</string>
+ <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) -->
+ <skip />
<string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> folosește bateria"</string>
<string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> aplicații folosesc bateria"</string>
<string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Atingeți pentru mai multe detalii privind bateria și utilizarea datelor"</string>
@@ -2222,4 +2224,12 @@
<string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string>
<string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string>
<string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string>
+ <!-- no translation found for window_magnification_prompt_title (8197528399699536320) -->
+ <skip />
+ <!-- no translation found for window_magnification_prompt_content (4166711383253283838) -->
+ <skip />
+ <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) -->
+ <skip />
+ <!-- no translation found for dismiss_action (1728820550388704784) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-ru/strings.xml b/core/res/res/values-ru/strings.xml
index 35bf873dc5a6..efd3c6c5ad96 100644
--- a/core/res/res/values-ru/strings.xml
+++ b/core/res/res/values-ru/strings.xml
@@ -293,6 +293,8 @@
<string name="notification_channel_usb" msgid="1528280969406244896">"USB-подключение"</string>
<string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"Приложение активно"</string>
<string name="notification_channel_foreground_service" msgid="7102189948158885178">"Приложения, расходующие заряд"</string>
+ <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) -->
+ <skip />
<string name="foreground_service_app_in_background" msgid="1439289699671273555">"Приложение \"<xliff:g id="APP_NAME">%1$s</xliff:g>\" расходует заряд"</string>
<string name="foreground_service_apps_in_background" msgid="7340037176412387863">"Несколько приложений (<xliff:g id="NUMBER">%1$d</xliff:g>) расходуют заряд"</string>
<string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Нажмите, чтобы проверить энергопотребление и трафик"</string>
@@ -2256,4 +2258,12 @@
<string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string>
<string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string>
<string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string>
+ <!-- no translation found for window_magnification_prompt_title (8197528399699536320) -->
+ <skip />
+ <!-- no translation found for window_magnification_prompt_content (4166711383253283838) -->
+ <skip />
+ <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) -->
+ <skip />
+ <!-- no translation found for dismiss_action (1728820550388704784) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-si/strings.xml b/core/res/res/values-si/strings.xml
index 70cfaa7a741d..100aed1c3c66 100644
--- a/core/res/res/values-si/strings.xml
+++ b/core/res/res/values-si/strings.xml
@@ -287,6 +287,8 @@
<string name="notification_channel_usb" msgid="1528280969406244896">"USB සම්බන්ධතාවය"</string>
<string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"යෙදුම ධාවනය කරමින්"</string>
<string name="notification_channel_foreground_service" msgid="7102189948158885178">"බැටරිය භාවිත කරන යෙදුම්"</string>
+ <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) -->
+ <skip />
<string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> බැටරිය භාවිත කරයි"</string>
<string name="foreground_service_apps_in_background" msgid="7340037176412387863">"යෙදුම් <xliff:g id="NUMBER">%1$d</xliff:g>ක් බැටරිය භාවිත කරයි"</string>
<string name="foreground_service_tap_for_details" msgid="9078123626015586751">"බැටරි හා දත්ත භාවිතය පිළිබඳව විස්තර සඳහා තට්ටු කරන්න"</string>
@@ -2188,4 +2190,12 @@
<string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string>
<string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string>
<string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string>
+ <!-- no translation found for window_magnification_prompt_title (8197528399699536320) -->
+ <skip />
+ <!-- no translation found for window_magnification_prompt_content (4166711383253283838) -->
+ <skip />
+ <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) -->
+ <skip />
+ <!-- no translation found for dismiss_action (1728820550388704784) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-sk/strings.xml b/core/res/res/values-sk/strings.xml
index cef059d8cfde..f7756e5959ce 100644
--- a/core/res/res/values-sk/strings.xml
+++ b/core/res/res/values-sk/strings.xml
@@ -293,6 +293,8 @@
<string name="notification_channel_usb" msgid="1528280969406244896">"Pripojenie USB"</string>
<string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"Aplikácia je spustená"</string>
<string name="notification_channel_foreground_service" msgid="7102189948158885178">"Aplikácie spotrebúvajúce batériu"</string>
+ <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) -->
+ <skip />
<string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> používa batériu"</string>
<string name="foreground_service_apps_in_background" msgid="7340037176412387863">"Aplikácie (<xliff:g id="NUMBER">%1$d</xliff:g>) používajú batériu"</string>
<string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Klepnutím zobrazíte podrobnosti o batérii a spotrebe dát"</string>
@@ -2256,4 +2258,12 @@
<string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string>
<string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string>
<string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string>
+ <!-- no translation found for window_magnification_prompt_title (8197528399699536320) -->
+ <skip />
+ <!-- no translation found for window_magnification_prompt_content (4166711383253283838) -->
+ <skip />
+ <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) -->
+ <skip />
+ <!-- no translation found for dismiss_action (1728820550388704784) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-sl/strings.xml b/core/res/res/values-sl/strings.xml
index b29748c1360f..df7e0ee1a856 100644
--- a/core/res/res/values-sl/strings.xml
+++ b/core/res/res/values-sl/strings.xml
@@ -293,6 +293,8 @@
<string name="notification_channel_usb" msgid="1528280969406244896">"Povezava USB"</string>
<string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"Aplikacija se izvaja"</string>
<string name="notification_channel_foreground_service" msgid="7102189948158885178">"Aplikacije, ki porabljajo energijo baterije"</string>
+ <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) -->
+ <skip />
<string name="foreground_service_app_in_background" msgid="1439289699671273555">"Aplikacija <xliff:g id="APP_NAME">%1$s</xliff:g> porablja energijo baterije"</string>
<string name="foreground_service_apps_in_background" msgid="7340037176412387863">"Toliko aplikacij porablja energijo baterije: <xliff:g id="NUMBER">%1$d</xliff:g>"</string>
<string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Dotaknite se za prikaz podrobnosti porabe baterije in prenosa podatkov"</string>
@@ -2256,4 +2258,12 @@
<string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string>
<string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string>
<string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string>
+ <!-- no translation found for window_magnification_prompt_title (8197528399699536320) -->
+ <skip />
+ <!-- no translation found for window_magnification_prompt_content (4166711383253283838) -->
+ <skip />
+ <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) -->
+ <skip />
+ <!-- no translation found for dismiss_action (1728820550388704784) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-sq/strings.xml b/core/res/res/values-sq/strings.xml
index c852d277a92f..8de3f8ca4f80 100644
--- a/core/res/res/values-sq/strings.xml
+++ b/core/res/res/values-sq/strings.xml
@@ -287,6 +287,8 @@
<string name="notification_channel_usb" msgid="1528280969406244896">"Lidhja USB"</string>
<string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"Aplikacioni është në ekzekutim"</string>
<string name="notification_channel_foreground_service" msgid="7102189948158885178">"Aplikacionet që konsumojnë baterinë"</string>
+ <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) -->
+ <skip />
<string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> po përdor baterinë"</string>
<string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> aplikacione po përdorin baterinë"</string>
<string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Trokit për detaje mbi baterinë dhe përdorimin e të dhënave"</string>
@@ -2188,4 +2190,12 @@
<string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string>
<string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string>
<string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string>
+ <!-- no translation found for window_magnification_prompt_title (8197528399699536320) -->
+ <skip />
+ <!-- no translation found for window_magnification_prompt_content (4166711383253283838) -->
+ <skip />
+ <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) -->
+ <skip />
+ <!-- no translation found for dismiss_action (1728820550388704784) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-sr/strings.xml b/core/res/res/values-sr/strings.xml
index 6a66c1be3d07..e4031189f26e 100644
--- a/core/res/res/values-sr/strings.xml
+++ b/core/res/res/values-sr/strings.xml
@@ -123,28 +123,28 @@
<string name="roamingText11" msgid="5245687407203281407">"Банер роминга је укључен"</string>
<string name="roamingText12" msgid="673537506362152640">"Банер роминга је искључен"</string>
<string name="roamingTextSearching" msgid="5323235489657753486">"Претраживање услуге"</string>
- <string name="wfcRegErrorTitle" msgid="3193072971584858020">"Подешавање позивања преко WiFi-ја није успело"</string>
+ <string name="wfcRegErrorTitle" msgid="3193072971584858020">"Подешавање позивања преко WiFi-а није успело"</string>
<string-array name="wfcOperatorErrorAlertMessages">
- <item msgid="468830943567116703">"Да бисте упућивали позиве и слали поруке преко WiFi-ја, прво затражите од мобилног оператера да вам омогући ову услугу. Затим у Подешавањима поново укључите Позивање преко WiFi-ја. (кôд грешке: <xliff:g id="CODE">%1$s</xliff:g>)"</item>
+ <item msgid="468830943567116703">"Да бисте упућивали позиве и слали поруке преко WiFi-а, прво затражите од мобилног оператера да вам омогући ову услугу. Затим у Подешавањима поново укључите Позивање преко WiFi-а. (кôд грешке: <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>
</string-array>
<!-- no translation found for wfcSpnFormat_spn (2982505428519096311) -->
<skip />
- <string name="wfcSpnFormat_spn_wifi_calling" msgid="3165949348000906194">"<xliff:g id="SPN">%s</xliff:g> позивање преко WiFi-ја"</string>
- <string name="wfcSpnFormat_spn_wifi_calling_vo_hyphen" msgid="3836827895369365298">"<xliff:g id="SPN">%s</xliff:g> – позивање преко WiFi-ја"</string>
+ <string name="wfcSpnFormat_spn_wifi_calling" msgid="3165949348000906194">"<xliff:g id="SPN">%s</xliff:g> позивање преко WiFi-а"</string>
+ <string name="wfcSpnFormat_spn_wifi_calling_vo_hyphen" msgid="3836827895369365298">"<xliff:g id="SPN">%s</xliff:g> – позивање преко WiFi-а"</string>
<string name="wfcSpnFormat_wlan_call" msgid="4895315549916165700">"WLAN позив"</string>
<string name="wfcSpnFormat_spn_wlan_call" msgid="255919245825481510">"<xliff:g id="SPN">%s</xliff:g> WLAN позив"</string>
<string name="wfcSpnFormat_spn_wifi" msgid="7232899594327126970">"<xliff:g id="SPN">%s</xliff:g> WiFi"</string>
- <string name="wfcSpnFormat_wifi_calling_bar_spn" msgid="8383917598312067365">"Позивање преко WiFi-ја | <xliff:g id="SPN">%s</xliff:g>"</string>
+ <string name="wfcSpnFormat_wifi_calling_bar_spn" msgid="8383917598312067365">"Позивање преко WiFi-а | <xliff:g id="SPN">%s</xliff:g>"</string>
<string name="wfcSpnFormat_spn_vowifi" msgid="6865214948822061486">"<xliff:g id="SPN">%s</xliff:g> VoWifi"</string>
- <string name="wfcSpnFormat_wifi_calling" msgid="6178935388378661755">"Позивање преко WiFi-ја"</string>
+ <string name="wfcSpnFormat_wifi_calling" msgid="6178935388378661755">"Позивање преко WiFi-а"</string>
<string name="wfcSpnFormat_wifi" msgid="1376356951297043426">"WiFi"</string>
- <string name="wfcSpnFormat_wifi_calling_wo_hyphen" msgid="7178561009225028264">"Позивање преко WiFi-ја"</string>
+ <string name="wfcSpnFormat_wifi_calling_wo_hyphen" msgid="7178561009225028264">"Позивање преко WiFi-а"</string>
<string name="wfcSpnFormat_vowifi" msgid="8371335230890725606">"VoWifi"</string>
<string name="wifi_calling_off_summary" msgid="5626710010766902560">"Искључено"</string>
- <string name="wfc_mode_wifi_preferred_summary" msgid="1035175836270943089">"Позивање преко WiFi-ја"</string>
+ <string name="wfc_mode_wifi_preferred_summary" msgid="1035175836270943089">"Позивање преко WiFi-а"</string>
<string name="wfc_mode_cellular_preferred_summary" msgid="4958965609212575619">"Позив преко мобилне мреже"</string>
<string name="wfc_mode_wifi_only_summary" msgid="104951993894678665">"Само WiFi"</string>
<string name="cfTemplateNotForwarded" msgid="862202427794270501">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: Није прослеђено"</string>
@@ -290,6 +290,8 @@
<string name="notification_channel_usb" msgid="1528280969406244896">"USB веза"</string>
<string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"Активна апликација"</string>
<string name="notification_channel_foreground_service" msgid="7102189948158885178">"Апликације које троше батерију"</string>
+ <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) -->
+ <skip />
<string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> користи батерију"</string>
<string name="foreground_service_apps_in_background" msgid="7340037176412387863">"Апликације (<xliff:g id="NUMBER">%1$d</xliff:g>) користе батерију"</string>
<string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Додирните за детаље о батерији и потрошњи података"</string>
@@ -2222,4 +2224,12 @@
<string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string>
<string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string>
<string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string>
+ <!-- no translation found for window_magnification_prompt_title (8197528399699536320) -->
+ <skip />
+ <!-- no translation found for window_magnification_prompt_content (4166711383253283838) -->
+ <skip />
+ <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) -->
+ <skip />
+ <!-- no translation found for dismiss_action (1728820550388704784) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-sv/strings.xml b/core/res/res/values-sv/strings.xml
index 8c28252bdfd3..cc21f3929356 100644
--- a/core/res/res/values-sv/strings.xml
+++ b/core/res/res/values-sv/strings.xml
@@ -287,6 +287,8 @@
<string name="notification_channel_usb" msgid="1528280969406244896">"USB-anslutning"</string>
<string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"App körs"</string>
<string name="notification_channel_foreground_service" msgid="7102189948158885178">"Appar som drar batteri"</string>
+ <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) -->
+ <skip />
<string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> drar batteri"</string>
<string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> appar drar batteri"</string>
<string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Tryck för information om batteri- och dataanvändning"</string>
@@ -2188,4 +2190,12 @@
<string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string>
<string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string>
<string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string>
+ <!-- no translation found for window_magnification_prompt_title (8197528399699536320) -->
+ <skip />
+ <!-- no translation found for window_magnification_prompt_content (4166711383253283838) -->
+ <skip />
+ <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) -->
+ <skip />
+ <!-- no translation found for dismiss_action (1728820550388704784) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-sw/strings.xml b/core/res/res/values-sw/strings.xml
index 1ca8fb8bc482..9478b0b50832 100644
--- a/core/res/res/values-sw/strings.xml
+++ b/core/res/res/values-sw/strings.xml
@@ -287,6 +287,8 @@
<string name="notification_channel_usb" msgid="1528280969406244896">"Muunganisho wa USB"</string>
<string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"Programu inaendelea kutekelezwa"</string>
<string name="notification_channel_foreground_service" msgid="7102189948158885178">"Programu zinazotumia betri"</string>
+ <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) -->
+ <skip />
<string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> inatumia betri"</string>
<string name="foreground_service_apps_in_background" msgid="7340037176412387863">"Programu <xliff:g id="NUMBER">%1$d</xliff:g> zinatumia betri"</string>
<string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Gusa ili upate maelezo kuhusu betri na matumizi ya data"</string>
@@ -2188,4 +2190,12 @@
<string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string>
<string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string>
<string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string>
+ <!-- no translation found for window_magnification_prompt_title (8197528399699536320) -->
+ <skip />
+ <!-- no translation found for window_magnification_prompt_content (4166711383253283838) -->
+ <skip />
+ <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) -->
+ <skip />
+ <!-- no translation found for dismiss_action (1728820550388704784) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-ta/strings.xml b/core/res/res/values-ta/strings.xml
index c2972f13e372..ebaeaddfd86f 100644
--- a/core/res/res/values-ta/strings.xml
+++ b/core/res/res/values-ta/strings.xml
@@ -287,6 +287,8 @@
<string name="notification_channel_usb" msgid="1528280969406244896">"USB இணைப்பு"</string>
<string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"ஆப்ஸ் இயங்குகிறது"</string>
<string name="notification_channel_foreground_service" msgid="7102189948158885178">"பேட்டரியைப் பயன்படுத்தும் ஆப்ஸ்"</string>
+ <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) -->
+ <skip />
<string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> ஆப்ஸ் பேட்டரியைப் பயன்படுத்துகிறது"</string>
<string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> ஆப்ஸ் பேட்டரியைப் பயன்படுத்துகின்றன"</string>
<string name="foreground_service_tap_for_details" msgid="9078123626015586751">"பேட்டரி மற்றும் டேட்டா உபயோக விவரங்களைக் காண, தட்டவும்"</string>
@@ -2188,4 +2190,12 @@
<string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string>
<string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string>
<string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string>
+ <!-- no translation found for window_magnification_prompt_title (8197528399699536320) -->
+ <skip />
+ <!-- no translation found for window_magnification_prompt_content (4166711383253283838) -->
+ <skip />
+ <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) -->
+ <skip />
+ <!-- no translation found for dismiss_action (1728820550388704784) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-te/strings.xml b/core/res/res/values-te/strings.xml
index d959a37d8f3d..c63d175002ea 100644
--- a/core/res/res/values-te/strings.xml
+++ b/core/res/res/values-te/strings.xml
@@ -287,6 +287,8 @@
<string name="notification_channel_usb" msgid="1528280969406244896">"USB కనెక్షన్"</string>
<string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"యాప్ అమలవుతోంది"</string>
<string name="notification_channel_foreground_service" msgid="7102189948158885178">"బ్యాటరీని ఉపయోగిస్తున్న యాప్‌లు"</string>
+ <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) -->
+ <skip />
<string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> బ్యాటరీని ఉపయోగిస్తోంది"</string>
<string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> యాప్‌లు బ్యాటరీని ఉపయోగిస్తున్నాయి"</string>
<string name="foreground_service_tap_for_details" msgid="9078123626015586751">"బ్యాటరీ మరియు డేటా వినియోగ వివరాల కోసం నొక్కండి"</string>
@@ -2188,4 +2190,12 @@
<string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string>
<string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string>
<string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string>
+ <!-- no translation found for window_magnification_prompt_title (8197528399699536320) -->
+ <skip />
+ <!-- no translation found for window_magnification_prompt_content (4166711383253283838) -->
+ <skip />
+ <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) -->
+ <skip />
+ <!-- no translation found for dismiss_action (1728820550388704784) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-th/strings.xml b/core/res/res/values-th/strings.xml
index 5102f148bb7c..b0acb1217b8b 100644
--- a/core/res/res/values-th/strings.xml
+++ b/core/res/res/values-th/strings.xml
@@ -287,6 +287,8 @@
<string name="notification_channel_usb" msgid="1528280969406244896">"การเชื่อมต่อ USB"</string>
<string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"แอปที่ทำงานอยู่"</string>
<string name="notification_channel_foreground_service" msgid="7102189948158885178">"แอปหลายแอปกำลังใช้แบตเตอรี่"</string>
+ <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) -->
+ <skip />
<string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> กำลังใช้แบตเตอรี่"</string>
<string name="foreground_service_apps_in_background" msgid="7340037176412387863">"แอป <xliff:g id="NUMBER">%1$d</xliff:g> แอปกำลังใช้แบตเตอรี่"</string>
<string name="foreground_service_tap_for_details" msgid="9078123626015586751">"แตะเพื่อดูรายละเอียดเกี่ยวกับแบตเตอรี่และปริมาณการใช้อินเทอร์เน็ต"</string>
@@ -2188,4 +2190,12 @@
<string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string>
<string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string>
<string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string>
+ <!-- no translation found for window_magnification_prompt_title (8197528399699536320) -->
+ <skip />
+ <!-- no translation found for window_magnification_prompt_content (4166711383253283838) -->
+ <skip />
+ <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) -->
+ <skip />
+ <!-- no translation found for dismiss_action (1728820550388704784) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-tl/strings.xml b/core/res/res/values-tl/strings.xml
index 4112fa5c4ff1..f04e7e1f3d69 100644
--- a/core/res/res/values-tl/strings.xml
+++ b/core/res/res/values-tl/strings.xml
@@ -287,6 +287,8 @@
<string name="notification_channel_usb" msgid="1528280969406244896">"Koneksyon ng USB"</string>
<string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"Tumatakbo ang app"</string>
<string name="notification_channel_foreground_service" msgid="7102189948158885178">"Mga app na kumokonsumo ng baterya"</string>
+ <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) -->
+ <skip />
<string name="foreground_service_app_in_background" msgid="1439289699671273555">"Gumagamit ng baterya ang <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
<string name="foreground_service_apps_in_background" msgid="7340037176412387863">"Gumagamit ng baterya ang <xliff:g id="NUMBER">%1$d</xliff:g> (na) app"</string>
<string name="foreground_service_tap_for_details" msgid="9078123626015586751">"I-tap para sa mga detalye tungkol sa paggamit ng baterya at data"</string>
@@ -2188,4 +2190,12 @@
<string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string>
<string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string>
<string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string>
+ <!-- no translation found for window_magnification_prompt_title (8197528399699536320) -->
+ <skip />
+ <!-- no translation found for window_magnification_prompt_content (4166711383253283838) -->
+ <skip />
+ <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) -->
+ <skip />
+ <!-- no translation found for dismiss_action (1728820550388704784) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-tr/strings.xml b/core/res/res/values-tr/strings.xml
index 8ee1d30a11bc..79cfe191d35f 100644
--- a/core/res/res/values-tr/strings.xml
+++ b/core/res/res/values-tr/strings.xml
@@ -287,6 +287,8 @@
<string name="notification_channel_usb" msgid="1528280969406244896">"USB bağlantısı"</string>
<string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"Uygulama çalışıyor"</string>
<string name="notification_channel_foreground_service" msgid="7102189948158885178">"Pil kullanan uygulamalar"</string>
+ <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) -->
+ <skip />
<string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> pil kullanıyor"</string>
<string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> uygulama pil kullanıyor"</string>
<string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Pil ve veri kullanımı ile ilgili ayrıntılar için dokunun"</string>
@@ -2188,4 +2190,12 @@
<string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string>
<string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string>
<string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string>
+ <!-- no translation found for window_magnification_prompt_title (8197528399699536320) -->
+ <skip />
+ <!-- no translation found for window_magnification_prompt_content (4166711383253283838) -->
+ <skip />
+ <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) -->
+ <skip />
+ <!-- no translation found for dismiss_action (1728820550388704784) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-uk/strings.xml b/core/res/res/values-uk/strings.xml
index 778e4a5789fb..a752010655a9 100644
--- a/core/res/res/values-uk/strings.xml
+++ b/core/res/res/values-uk/strings.xml
@@ -293,6 +293,8 @@
<string name="notification_channel_usb" msgid="1528280969406244896">"З’єднання USB"</string>
<string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"Працює додаток"</string>
<string name="notification_channel_foreground_service" msgid="7102189948158885178">"Додатки, що використовують заряд акумулятора"</string>
+ <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) -->
+ <skip />
<string name="foreground_service_app_in_background" msgid="1439289699671273555">"Додаток <xliff:g id="APP_NAME">%1$s</xliff:g> використовує заряд акумулятора"</string>
<string name="foreground_service_apps_in_background" msgid="7340037176412387863">"Додатків, що використовують заряд акумулятора: <xliff:g id="NUMBER">%1$d</xliff:g>"</string>
<string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Торкніться, щоб перевірити використання акумулятора й трафік"</string>
@@ -2256,4 +2258,12 @@
<string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string>
<string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string>
<string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string>
+ <!-- no translation found for window_magnification_prompt_title (8197528399699536320) -->
+ <skip />
+ <!-- no translation found for window_magnification_prompt_content (4166711383253283838) -->
+ <skip />
+ <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) -->
+ <skip />
+ <!-- no translation found for dismiss_action (1728820550388704784) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-ur/strings.xml b/core/res/res/values-ur/strings.xml
index 78c9330a85e9..4324e36c62b9 100644
--- a/core/res/res/values-ur/strings.xml
+++ b/core/res/res/values-ur/strings.xml
@@ -287,6 +287,8 @@
<string name="notification_channel_usb" msgid="1528280969406244896">"‏USB کنکشن"</string>
<string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"ایپ چل رہی ہے"</string>
<string name="notification_channel_foreground_service" msgid="7102189948158885178">"ایپس بیٹری خرچ کر رہی ہیں"</string>
+ <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) -->
+ <skip />
<string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> بیٹری کا استعمال کر رہی ہے"</string>
<string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> ایپس بیٹری کا استعمال کر رہی ہیں"</string>
<string name="foreground_service_tap_for_details" msgid="9078123626015586751">"بیٹری اور ڈیٹا استعمال کے بارے میں تفصیلات کے لیے تھپتھپائیں"</string>
@@ -2188,4 +2190,12 @@
<string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string>
<string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string>
<string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string>
+ <!-- no translation found for window_magnification_prompt_title (8197528399699536320) -->
+ <skip />
+ <!-- no translation found for window_magnification_prompt_content (4166711383253283838) -->
+ <skip />
+ <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) -->
+ <skip />
+ <!-- no translation found for dismiss_action (1728820550388704784) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-uz/strings.xml b/core/res/res/values-uz/strings.xml
index 683a9115ce25..923831c00b88 100644
--- a/core/res/res/values-uz/strings.xml
+++ b/core/res/res/values-uz/strings.xml
@@ -287,6 +287,8 @@
<string name="notification_channel_usb" msgid="1528280969406244896">"USB orqali ulanish"</string>
<string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"Ilova faol"</string>
<string name="notification_channel_foreground_service" msgid="7102189948158885178">"Batareya quvvatini sarflayotgan ilovalar"</string>
+ <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) -->
+ <skip />
<string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> ilovasi batareya quvvatini sarflamoqda"</string>
<string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> ta ilova batareya quvvatini sarflamoqda"</string>
<string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Batareya va trafik sarfi tafsilotlari uchun ustiga bosing"</string>
@@ -2188,4 +2190,12 @@
<string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string>
<string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string>
<string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string>
+ <!-- no translation found for window_magnification_prompt_title (8197528399699536320) -->
+ <skip />
+ <!-- no translation found for window_magnification_prompt_content (4166711383253283838) -->
+ <skip />
+ <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) -->
+ <skip />
+ <!-- no translation found for dismiss_action (1728820550388704784) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-vi/strings.xml b/core/res/res/values-vi/strings.xml
index 050fa0b24cc4..296261f850e8 100644
--- a/core/res/res/values-vi/strings.xml
+++ b/core/res/res/values-vi/strings.xml
@@ -287,6 +287,8 @@
<string name="notification_channel_usb" msgid="1528280969406244896">"Kết nối USB"</string>
<string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"Ứng dụng đang chạy"</string>
<string name="notification_channel_foreground_service" msgid="7102189948158885178">"Các ứng dụng tiêu thụ pin"</string>
+ <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) -->
+ <skip />
<string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> đang sử dụng pin"</string>
<string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> ứng dụng đang sử dụng pin"</string>
<string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Nhấn để biết chi tiết về mức sử dụng dữ liệu và pin"</string>
@@ -2188,4 +2190,12 @@
<string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string>
<string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string>
<string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string>
+ <!-- no translation found for window_magnification_prompt_title (8197528399699536320) -->
+ <skip />
+ <!-- no translation found for window_magnification_prompt_content (4166711383253283838) -->
+ <skip />
+ <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) -->
+ <skip />
+ <!-- no translation found for dismiss_action (1728820550388704784) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-zh-rCN/strings.xml b/core/res/res/values-zh-rCN/strings.xml
index ec01ae3acbd7..a27e7b1ba94c 100644
--- a/core/res/res/values-zh-rCN/strings.xml
+++ b/core/res/res/values-zh-rCN/strings.xml
@@ -287,6 +287,8 @@
<string name="notification_channel_usb" msgid="1528280969406244896">"USB 连接"</string>
<string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"应用正在运行中"</string>
<string name="notification_channel_foreground_service" msgid="7102189948158885178">"消耗电量的应用"</string>
+ <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) -->
+ <skip />
<string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g>正在消耗电量"</string>
<string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> 个应用正在消耗电量"</string>
<string name="foreground_service_tap_for_details" msgid="9078123626015586751">"点按即可详细了解电量和流量消耗情况"</string>
@@ -2188,4 +2190,12 @@
<string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string>
<string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string>
<string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string>
+ <!-- no translation found for window_magnification_prompt_title (8197528399699536320) -->
+ <skip />
+ <!-- no translation found for window_magnification_prompt_content (4166711383253283838) -->
+ <skip />
+ <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) -->
+ <skip />
+ <!-- no translation found for dismiss_action (1728820550388704784) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-zh-rHK/strings.xml b/core/res/res/values-zh-rHK/strings.xml
index 58232b912b7f..5099ebfd463f 100644
--- a/core/res/res/values-zh-rHK/strings.xml
+++ b/core/res/res/values-zh-rHK/strings.xml
@@ -287,6 +287,8 @@
<string name="notification_channel_usb" msgid="1528280969406244896">"USB 連線"</string>
<string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"應用程式正在執行"</string>
<string name="notification_channel_foreground_service" msgid="7102189948158885178">"耗用電量的應用程式"</string>
+ <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) -->
+ <skip />
<string name="foreground_service_app_in_background" msgid="1439289699671273555">"「<xliff:g id="APP_NAME">%1$s</xliff:g>」正在使用電量"</string>
<string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> 個應用程式正在使用電量"</string>
<string name="foreground_service_tap_for_details" msgid="9078123626015586751">"輕按即可查看電池和數據用量詳情"</string>
@@ -2188,4 +2190,12 @@
<string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string>
<string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string>
<string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string>
+ <!-- no translation found for window_magnification_prompt_title (8197528399699536320) -->
+ <skip />
+ <!-- no translation found for window_magnification_prompt_content (4166711383253283838) -->
+ <skip />
+ <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) -->
+ <skip />
+ <!-- no translation found for dismiss_action (1728820550388704784) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-zh-rTW/strings.xml b/core/res/res/values-zh-rTW/strings.xml
index 617a671500ec..31bd99be57b1 100644
--- a/core/res/res/values-zh-rTW/strings.xml
+++ b/core/res/res/values-zh-rTW/strings.xml
@@ -287,6 +287,8 @@
<string name="notification_channel_usb" msgid="1528280969406244896">"USB 連線"</string>
<string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"應用程式執行中"</string>
<string name="notification_channel_foreground_service" msgid="7102189948158885178">"正在耗用電量的應用程式"</string>
+ <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) -->
+ <skip />
<string name="foreground_service_app_in_background" msgid="1439289699671273555">"「<xliff:g id="APP_NAME">%1$s</xliff:g>」正在耗用電量"</string>
<string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> 個應用程式正在耗用電量"</string>
<string name="foreground_service_tap_for_details" msgid="9078123626015586751">"輕觸即可查看電池和數據用量詳情"</string>
@@ -2188,4 +2190,12 @@
<string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string>
<string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string>
<string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string>
+ <!-- no translation found for window_magnification_prompt_title (8197528399699536320) -->
+ <skip />
+ <!-- no translation found for window_magnification_prompt_content (4166711383253283838) -->
+ <skip />
+ <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) -->
+ <skip />
+ <!-- no translation found for dismiss_action (1728820550388704784) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-zu/strings.xml b/core/res/res/values-zu/strings.xml
index fab89962ef69..28eed9b98efd 100644
--- a/core/res/res/values-zu/strings.xml
+++ b/core/res/res/values-zu/strings.xml
@@ -287,6 +287,8 @@
<string name="notification_channel_usb" msgid="1528280969406244896">"Ukuxhumeka kwe-USB"</string>
<string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"Uhlelo loksuebenza olusebenzayo"</string>
<string name="notification_channel_foreground_service" msgid="7102189948158885178">"Izinhlelo zokusebenza ezidla ibhethri"</string>
+ <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) -->
+ <skip />
<string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> isebenzisa ibhethri"</string>
<string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> izinhlelo zokusebenza zisebenzisa ibhethri"</string>
<string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Thepha ngemininingwane ekusetshenzisweni kwebhethri nedatha"</string>
@@ -2188,4 +2190,12 @@
<string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string>
<string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string>
<string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string>
+ <!-- no translation found for window_magnification_prompt_title (8197528399699536320) -->
+ <skip />
+ <!-- no translation found for window_magnification_prompt_content (4166711383253283838) -->
+ <skip />
+ <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) -->
+ <skip />
+ <!-- no translation found for dismiss_action (1728820550388704784) -->
+ <skip />
</resources>
diff --git a/core/res/res/values/attrs_manifest.xml b/core/res/res/values/attrs_manifest.xml
index fc9f670f31a7..85b19e7de04b 100644
--- a/core/res/res/values/attrs_manifest.xml
+++ b/core/res/res/values/attrs_manifest.xml
@@ -303,6 +303,9 @@
<!-- Additional flag from base permission type: this permission will be granted to the
retail demo app, as defined by the OEM. -->
<flag name="retailDemo" value="0x1000000" />
+ <!-- Additional flag from base permission type: this permission will be granted to the
+ recents app. -->
+ <flag name="recents" value="0x2000000" />
</attr>
<!-- Flags indicating more context for a permission group. -->
@@ -2834,6 +2837,38 @@
<attr name="resource" format="reference" />
</declare-styleable>
+ <!-- The <code>property</code> tag is used to attach additional data that can
+ be supplied to the parent component. A component element can contain any
+ number of <code>property</code> subelements. Valid names are any of the
+ <code>PROPERTY_</code> constants defined in the
+ {@link android.content.pm.PackageManager PackageManager} class. Values
+ are obtained using the appropriate method on the
+ {@link android.content.pm.PackageManager.Property PackageManager.Property} class.
+ <p>Ordinary values are specified through the value attribute. Resource IDs are
+ specified through the resource attribute.
+ <p>It is invalid to specify both a value and resource attributes. -->
+ <declare-styleable name="AndroidManifestProperty"
+ parent="AndroidManifestApplication
+ AndroidManifestActivity
+ AndroidManifestReceiver
+ AndroidManifestProvider
+ AndroidManifestService">
+ <attr name="name" />
+ <!-- Concrete value to assign to this property.
+ The data can later be retrieved from the property object
+ through
+ {@link android.content.pm.PackageManager.Property#getString Property.getString},
+ {@link android.content.pm.PackageManager.Property#getInteger Property.getInteger},
+ {@link android.content.pm.PackageManager.Property#getBoolean Property.getBoolean},
+ or {@link android.content.pm.PackageManager.Property#getFloat Property.getFloat}
+ depending on the type used here. -->
+ <attr name="value" />
+ <!-- The resource identifier to assign to this property.
+ The resource identifier can later be retrieved from the property object through
+ {@link android.content.pm.PackageManager.Property#getResourceId Property.getResourceId}. -->
+ <attr name="resource" />
+ </declare-styleable>
+
<!-- The <code>intent-filter</code> tag is used to construct an
{@link android.content.IntentFilter} object that will be used
to determine which component can handle a particular
diff --git a/core/res/res/values/dimens.xml b/core/res/res/values/dimens.xml
index 79eae67e5fba..19591f6a666f 100644
--- a/core/res/res/values/dimens.xml
+++ b/core/res/res/values/dimens.xml
@@ -259,6 +259,9 @@
<!-- The height of the background for a notification header on a group -->
<dimen name="notification_header_background_height">49.5dp</dimen>
+ <!-- The height of the full-width touch rectangle for the notification header -->
+ <dimen name="notification_header_touchable_height">36dp</dimen>
+
<!-- The top padding for the notification header -->
<dimen name="notification_header_padding_top">16dp</dimen>
@@ -340,11 +343,8 @@
<!-- The margin of the content to an image-->
<dimen name="notification_content_image_margin_end">8dp</dimen>
- <!-- The padding at the end of actions when the bubble button is visible-->
- <dimen name="bubble_visible_padding_end">3dp</dimen>
-
- <!-- The padding at the end of actions when the bubble button is gone-->
- <dimen name="bubble_gone_padding_end">12dp</dimen>
+ <!-- The padding at the end of actions when the snooze and bubble buttons are gone-->
+ <dimen name="snooze_and_bubble_gone_padding_end">12dp</dimen>
<!-- The spacing between messages in Notification.MessagingStyle -->
<dimen name="notification_messaging_spacing">6dp</dimen>
@@ -744,6 +744,9 @@
<dimen name="conversation_expand_button_size">80dp</dimen>
<!-- Top margin of the expand button for conversations when expanded -->
<dimen name="conversation_expand_button_top_margin_expanded">18dp</dimen>
+ <!-- Side margin of the expand button for conversations.
+ width of expand asset (22) + 2 * this (13) == notification_header_expand_icon_size (48) -->
+ <dimen name="conversation_expand_button_side_margin">13dp</dimen>
<!-- Side margins of the conversation badge in relation to the conversation icon -->
<dimen name="conversation_badge_side_margin">36dp</dimen>
<!-- size of the notification badge when applied to the conversation icon -->
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 752bb5b37a30..40aae9e4e085 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -2861,6 +2861,7 @@
<java-symbol type="id" name="header_text" />
<java-symbol type="id" name="header_text_secondary" />
<java-symbol type="id" name="expand_button" />
+ <java-symbol type="id" name="alternate_expand_target" />
<java-symbol type="id" name="notification_header" />
<java-symbol type="id" name="notification_top_line" />
<java-symbol type="id" name="time_divider" />
@@ -2878,6 +2879,7 @@
<java-symbol type="dimen" name="notification_content_margin_top" />
<java-symbol type="dimen" name="notification_content_margin" />
<java-symbol type="dimen" name="notification_header_background_height" />
+ <java-symbol type="dimen" name="notification_header_touchable_height" />
<java-symbol type="dimen" name="notification_header_expand_icon_size" />
<java-symbol type="dimen" name="notification_expand_button_padding_top" />
<java-symbol type="dimen" name="notification_header_icon_size" />
@@ -3560,8 +3562,6 @@
<java-symbol type="id" name="clip_children_tag" />
<java-symbol type="id" name="bubble_button" />
<java-symbol type="id" name="snooze_button" />
- <java-symbol type="dimen" name="bubble_visible_padding_end" />
- <java-symbol type="dimen" name="bubble_gone_padding_end" />
<java-symbol type="dimen" name="text_size_body_2_material" />
<java-symbol type="dimen" name="messaging_avatar_size" />
<java-symbol type="dimen" name="messaging_group_sending_progress_size" />
diff --git a/core/tests/coretests/src/android/app/appsearch/external/app/AppSearchEmailTest.java b/core/tests/coretests/src/android/app/appsearch/external/app/AppSearchEmailTest.java
index 2f2bef8bc5cc..119b70ab0439 100644
--- a/core/tests/coretests/src/android/app/appsearch/external/app/AppSearchEmailTest.java
+++ b/core/tests/coretests/src/android/app/appsearch/external/app/AppSearchEmailTest.java
@@ -24,16 +24,18 @@ public class AppSearchEmailTest {
@Test
public void testBuildEmailAndGetValue() {
- AppSearchEmail email = new AppSearchEmail.Builder("uri")
- .setFrom("FakeFromAddress")
- .setCc("CC1", "CC2")
- // Score and Property are mixed into the middle to make sure DocumentBuilder's
- // methods can be interleaved with EmailBuilder's methods.
- .setScore(1)
- .setPropertyString("propertyKey", "propertyValue1", "propertyValue2")
- .setSubject("subject")
- .setBody("EmailBody")
- .build();
+ AppSearchEmail email =
+ new AppSearchEmail.Builder("uri")
+ .setFrom("FakeFromAddress")
+ .setCc("CC1", "CC2")
+ // Score and Property are mixed into the middle to make sure
+ // DocumentBuilder's
+ // methods can be interleaved with EmailBuilder's methods.
+ .setScore(1)
+ .setPropertyString("propertyKey", "propertyValue1", "propertyValue2")
+ .setSubject("subject")
+ .setBody("EmailBody")
+ .build();
assertThat(email.getUri()).isEqualTo("uri");
assertThat(email.getFrom()).isEqualTo("FakeFromAddress");
@@ -42,8 +44,9 @@ public class AppSearchEmailTest {
assertThat(email.getBcc()).isNull();
assertThat(email.getScore()).isEqualTo(1);
assertThat(email.getPropertyString("propertyKey")).isEqualTo("propertyValue1");
- assertThat(email.getPropertyStringArray("propertyKey")).asList().containsExactly(
- "propertyValue1", "propertyValue2");
+ assertThat(email.getPropertyStringArray("propertyKey"))
+ .asList()
+ .containsExactly("propertyValue1", "propertyValue2");
assertThat(email.getSubject()).isEqualTo("subject");
assertThat(email.getBody()).isEqualTo("EmailBody");
}
diff --git a/core/tests/coretests/src/android/app/appsearch/external/app/GenericDocumentTest.java b/core/tests/coretests/src/android/app/appsearch/external/app/GenericDocumentTest.java
deleted file mode 100644
index 9c29943dbef4..000000000000
--- a/core/tests/coretests/src/android/app/appsearch/external/app/GenericDocumentTest.java
+++ /dev/null
@@ -1,252 +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.app.appsearch;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import static org.testng.Assert.expectThrows;
-
-import org.junit.Test;
-
-public class GenericDocumentTest {
- private static final byte[] sByteArray1 = new byte[]{(byte) 1, (byte) 2, (byte) 3};
- private static final byte[] sByteArray2 = new byte[]{(byte) 4, (byte) 5, (byte) 6, (byte) 7};
- private static final GenericDocument sDocumentProperties1 = new GenericDocument
- .Builder("sDocumentProperties1", "sDocumentPropertiesSchemaType1")
- .setCreationTimestampMillis(12345L)
- .build();
- private static final GenericDocument sDocumentProperties2 = new GenericDocument
- .Builder("sDocumentProperties2", "sDocumentPropertiesSchemaType2")
- .setCreationTimestampMillis(6789L)
- .build();
-
- @Test
- public void testDocumentEquals_Identical() {
- GenericDocument document1 = new GenericDocument.Builder("uri1", "schemaType1")
- .setCreationTimestampMillis(5L)
- .setTtlMillis(1L)
- .setPropertyLong("longKey1", 1L, 2L, 3L)
- .setPropertyDouble("doubleKey1", 1.0, 2.0, 3.0)
- .setPropertyBoolean("booleanKey1", true, false, true)
- .setPropertyString("stringKey1", "test-value1", "test-value2", "test-value3")
- .setPropertyBytes("byteKey1", sByteArray1, sByteArray2)
- .setPropertyDocument("documentKey1", sDocumentProperties1, sDocumentProperties2)
- .build();
- GenericDocument document2 = new GenericDocument.Builder("uri1", "schemaType1")
- .setCreationTimestampMillis(5L)
- .setTtlMillis(1L)
- .setPropertyLong("longKey1", 1L, 2L, 3L)
- .setPropertyDouble("doubleKey1", 1.0, 2.0, 3.0)
- .setPropertyBoolean("booleanKey1", true, false, true)
- .setPropertyString("stringKey1", "test-value1", "test-value2", "test-value3")
- .setPropertyBytes("byteKey1", sByteArray1, sByteArray2)
- .setPropertyDocument("documentKey1", sDocumentProperties1, sDocumentProperties2)
- .build();
- assertThat(document1).isEqualTo(document2);
- assertThat(document1.hashCode()).isEqualTo(document2.hashCode());
- }
-
- @Test
- public void testDocumentEquals_DifferentOrder() {
- GenericDocument document1 = new GenericDocument.Builder("uri1", "schemaType1")
- .setCreationTimestampMillis(5L)
- .setPropertyLong("longKey1", 1L, 2L, 3L)
- .setPropertyBytes("byteKey1", sByteArray1, sByteArray2)
- .setPropertyDouble("doubleKey1", 1.0, 2.0, 3.0)
- .setPropertyBoolean("booleanKey1", true, false, true)
- .setPropertyDocument("documentKey1", sDocumentProperties1, sDocumentProperties2)
- .setPropertyString("stringKey1", "test-value1", "test-value2", "test-value3")
- .build();
-
- // Create second document with same parameter but different order.
- GenericDocument document2 = new GenericDocument.Builder("uri1", "schemaType1")
- .setCreationTimestampMillis(5L)
- .setPropertyBoolean("booleanKey1", true, false, true)
- .setPropertyDocument("documentKey1", sDocumentProperties1, sDocumentProperties2)
- .setPropertyString("stringKey1", "test-value1", "test-value2", "test-value3")
- .setPropertyDouble("doubleKey1", 1.0, 2.0, 3.0)
- .setPropertyBytes("byteKey1", sByteArray1, sByteArray2)
- .setPropertyLong("longKey1", 1L, 2L, 3L)
- .build();
- assertThat(document1).isEqualTo(document2);
- assertThat(document1.hashCode()).isEqualTo(document2.hashCode());
- }
-
- @Test
- public void testDocumentEquals_Failure() {
- GenericDocument document1 = new GenericDocument.Builder("uri1", "schemaType1")
- .setCreationTimestampMillis(5L)
- .setPropertyLong("longKey1", 1L, 2L, 3L)
- .build();
-
- // Create second document with same order but different value.
- GenericDocument document2 = new GenericDocument.Builder("uri1", "schemaType1")
- .setCreationTimestampMillis(5L)
- .setPropertyLong("longKey1", 1L, 2L, 4L) // Different
- .build();
- assertThat(document1).isNotEqualTo(document2);
- assertThat(document1.hashCode()).isNotEqualTo(document2.hashCode());
- }
-
- @Test
- public void testDocumentEquals_Failure_RepeatedFieldOrder() {
- GenericDocument document1 = new GenericDocument.Builder("uri1", "schemaType1")
- .setCreationTimestampMillis(5L)
- .setPropertyBoolean("booleanKey1", true, false, true)
- .build();
-
- // Create second document with same order but different value.
- GenericDocument document2 = new GenericDocument.Builder("uri1", "schemaType1")
- .setCreationTimestampMillis(5L)
- .setPropertyBoolean("booleanKey1", true, true, false) // Different
- .build();
- assertThat(document1).isNotEqualTo(document2);
- assertThat(document1.hashCode()).isNotEqualTo(document2.hashCode());
- }
-
- @Test
- public void testDocumentGetSingleValue() {
- GenericDocument document = new GenericDocument.Builder("uri1", "schemaType1")
- .setCreationTimestampMillis(5L)
- .setScore(1)
- .setTtlMillis(1L)
- .setPropertyLong("longKey1", 1L)
- .setPropertyDouble("doubleKey1", 1.0)
- .setPropertyBoolean("booleanKey1", true)
- .setPropertyString("stringKey1", "test-value1")
- .setPropertyBytes("byteKey1", sByteArray1)
- .setPropertyDocument("documentKey1", sDocumentProperties1)
- .build();
- assertThat(document.getUri()).isEqualTo("uri1");
- assertThat(document.getTtlMillis()).isEqualTo(1L);
- assertThat(document.getSchemaType()).isEqualTo("schemaType1");
- assertThat(document.getCreationTimestampMillis()).isEqualTo(5);
- assertThat(document.getScore()).isEqualTo(1);
- assertThat(document.getPropertyLong("longKey1")).isEqualTo(1L);
- assertThat(document.getPropertyDouble("doubleKey1")).isEqualTo(1.0);
- assertThat(document.getPropertyBoolean("booleanKey1")).isTrue();
- assertThat(document.getPropertyString("stringKey1")).isEqualTo("test-value1");
- assertThat(document.getPropertyBytes("byteKey1"))
- .asList().containsExactly((byte) 1, (byte) 2, (byte) 3);
- assertThat(document.getPropertyDocument("documentKey1")).isEqualTo(sDocumentProperties1);
- }
-
- @Test
- public void testDocumentGetArrayValues() {
- GenericDocument document = new GenericDocument.Builder("uri1", "schemaType1")
- .setCreationTimestampMillis(5L)
- .setPropertyLong("longKey1", 1L, 2L, 3L)
- .setPropertyDouble("doubleKey1", 1.0, 2.0, 3.0)
- .setPropertyBoolean("booleanKey1", true, false, true)
- .setPropertyString("stringKey1", "test-value1", "test-value2", "test-value3")
- .setPropertyBytes("byteKey1", sByteArray1, sByteArray2)
- .setPropertyDocument("documentKey1", sDocumentProperties1, sDocumentProperties2)
- .build();
-
- assertThat(document.getUri()).isEqualTo("uri1");
- assertThat(document.getSchemaType()).isEqualTo("schemaType1");
- assertThat(document.getPropertyLongArray("longKey1")).asList().containsExactly(1L, 2L, 3L);
- assertThat(document.getPropertyDoubleArray("doubleKey1")).usingExactEquality()
- .containsExactly(1.0, 2.0, 3.0);
- assertThat(document.getPropertyBooleanArray("booleanKey1")).asList()
- .containsExactly(true, false, true);
- assertThat(document.getPropertyStringArray("stringKey1")).asList()
- .containsExactly("test-value1", "test-value2", "test-value3");
- assertThat(document.getPropertyBytesArray("byteKey1")).asList()
- .containsExactly(sByteArray1, sByteArray2);
- assertThat(document.getPropertyDocumentArray("documentKey1")).asList()
- .containsExactly(sDocumentProperties1, sDocumentProperties2);
- }
-
- @Test
- public void testDocument_ToString() throws Exception {
- GenericDocument document = new GenericDocument.Builder("uri1", "schemaType1")
- .setCreationTimestampMillis(5L)
- .setPropertyLong("longKey1", 1L, 2L, 3L)
- .setPropertyDouble("doubleKey1", 1.0, 2.0, 3.0)
- .setPropertyBoolean("booleanKey1", true, false, true)
- .setPropertyString("stringKey1", "String1", "String2", "String3")
- .setPropertyBytes("byteKey1", sByteArray1, sByteArray2)
- .setPropertyDocument("documentKey1", sDocumentProperties1, sDocumentProperties2)
- .build();
- String exceptedString = "{ key: 'creationTimestampMillis' value: 5 } "
- + "{ key: 'namespace' value: } "
- + "{ key: 'properties' value: "
- + "{ key: 'booleanKey1' value: [ 'true' 'false' 'true' ] } "
- + "{ key: 'byteKey1' value: "
- + "{ key: 'byteArray' value: [ '1' '2' '3' ] } "
- + "{ key: 'byteArray' value: [ '4' '5' '6' '7' ] } } "
- + "{ key: 'documentKey1' value: [ '"
- + "{ key: 'creationTimestampMillis' value: 12345 } "
- + "{ key: 'namespace' value: } "
- + "{ key: 'properties' value: } "
- + "{ key: 'schemaType' value: sDocumentPropertiesSchemaType1 } "
- + "{ key: 'score' value: 0 } "
- + "{ key: 'ttlMillis' value: 0 } "
- + "{ key: 'uri' value: sDocumentProperties1 } ' '"
- + "{ key: 'creationTimestampMillis' value: 6789 } "
- + "{ key: 'namespace' value: } "
- + "{ key: 'properties' value: } "
- + "{ key: 'schemaType' value: sDocumentPropertiesSchemaType2 } "
- + "{ key: 'score' value: 0 } "
- + "{ key: 'ttlMillis' value: 0 } "
- + "{ key: 'uri' value: sDocumentProperties2 } ' ] } "
- + "{ key: 'doubleKey1' value: [ '1.0' '2.0' '3.0' ] } "
- + "{ key: 'longKey1' value: [ '1' '2' '3' ] } "
- + "{ key: 'stringKey1' value: [ 'String1' 'String2' 'String3' ] } } "
- + "{ key: 'schemaType' value: schemaType1 } "
- + "{ key: 'score' value: 0 } "
- + "{ key: 'ttlMillis' value: 0 } "
- + "{ key: 'uri' value: uri1 } ";
- assertThat(document.toString()).isEqualTo(exceptedString);
- }
-
- @Test
- public void testDocumentGetValues_DifferentTypes() {
- GenericDocument document = new GenericDocument.Builder("uri1", "schemaType1")
- .setScore(1)
- .setPropertyLong("longKey1", 1L)
- .setPropertyBoolean("booleanKey1", true, false, true)
- .setPropertyString("stringKey1", "test-value1", "test-value2", "test-value3")
- .build();
-
- // Get a value for a key that doesn't exist
- assertThat(document.getPropertyDouble("doubleKey1")).isEqualTo(0.0);
- assertThat(document.getPropertyDoubleArray("doubleKey1")).isNull();
-
- // Get a value with a single element as an array and as a single value
- assertThat(document.getPropertyLong("longKey1")).isEqualTo(1L);
- assertThat(document.getPropertyLongArray("longKey1")).asList().containsExactly(1L);
-
- // Get a value with multiple elements as an array and as a single value
- assertThat(document.getPropertyString("stringKey1")).isEqualTo("test-value1");
- assertThat(document.getPropertyStringArray("stringKey1")).asList()
- .containsExactly("test-value1", "test-value2", "test-value3");
-
- // Get a value of the wrong type
- assertThat(document.getPropertyDouble("longKey1")).isEqualTo(0.0);
- assertThat(document.getPropertyDoubleArray("longKey1")).isNull();
- }
-
- @Test
- public void testDocumentInvalid() {
- GenericDocument.Builder builder = new GenericDocument.Builder("uri1", "schemaType1");
- expectThrows(
- IllegalArgumentException.class,
- () -> builder.setPropertyBoolean("test", new boolean[]{}));
- }
-}
diff --git a/core/tests/coretests/src/android/app/appsearch/external/app/SearchSpecTest.java b/core/tests/coretests/src/android/app/appsearch/external/app/SearchSpecTest.java
index d4635fdda052..9fd480d9e22a 100644
--- a/core/tests/coretests/src/android/app/appsearch/external/app/SearchSpecTest.java
+++ b/core/tests/coretests/src/android/app/appsearch/external/app/SearchSpecTest.java
@@ -18,69 +18,33 @@ package android.app.appsearch;
import static com.google.common.truth.Truth.assertThat;
-import static org.testng.Assert.expectThrows;
-
import android.os.Bundle;
import org.junit.Test;
public class SearchSpecTest {
@Test
- public void buildSearchSpecWithoutTermMatchType() {
- expectThrows(RuntimeException.class, () -> new SearchSpec.Builder()
- .addSchema("testSchemaType")
- .build());
- }
-
- @Test
- public void testBuildSearchSpec() {
- SearchSpec searchSpec = new SearchSpec.Builder()
- .setTermMatch(SearchSpec.TERM_MATCH_PREFIX)
- .addNamespace("namespace1", "namespace2")
- .addSchema("schemaTypes1", "schemaTypes2")
- .setSnippetCount(5)
- .setSnippetCountPerProperty(10)
- .setMaxSnippetSize(15)
- .setNumPerPage(42)
- .setOrder(SearchSpec.ORDER_ASCENDING)
- .setRankingStrategy(SearchSpec.RANKING_STRATEGY_DOCUMENT_SCORE)
- .build();
-
- assertThat(searchSpec.getTermMatch()).isEqualTo(SearchSpec.TERM_MATCH_PREFIX);
- assertThat(searchSpec.getNamespaces())
- .containsExactly("namespace1", "namespace2").inOrder();
- assertThat(searchSpec.getSchemas())
- .containsExactly("schemaTypes1", "schemaTypes2").inOrder();
- assertThat(searchSpec.getSnippetCount()).isEqualTo(5);
- assertThat(searchSpec.getSnippetCountPerProperty()).isEqualTo(10);
- assertThat(searchSpec.getMaxSnippetSize()).isEqualTo(15);
- assertThat(searchSpec.getNumPerPage()).isEqualTo(42);
- assertThat(searchSpec.getOrder()).isEqualTo(SearchSpec.ORDER_ASCENDING);
- assertThat(searchSpec.getRankingStrategy())
- .isEqualTo(SearchSpec.RANKING_STRATEGY_DOCUMENT_SCORE);
- }
-
- @Test
public void testGetBundle() {
- SearchSpec searchSpec = new SearchSpec.Builder()
- .setTermMatch(SearchSpec.TERM_MATCH_PREFIX)
- .addNamespace("namespace1", "namespace2")
- .addSchema("schemaTypes1", "schemaTypes2")
- .setSnippetCount(5)
- .setSnippetCountPerProperty(10)
- .setMaxSnippetSize(15)
- .setNumPerPage(42)
- .setOrder(SearchSpec.ORDER_ASCENDING)
- .setRankingStrategy(SearchSpec.RANKING_STRATEGY_DOCUMENT_SCORE)
- .build();
+ SearchSpec searchSpec =
+ new SearchSpec.Builder()
+ .setTermMatch(SearchSpec.TERM_MATCH_PREFIX)
+ .addNamespace("namespace1", "namespace2")
+ .addSchemaType("schemaTypes1", "schemaTypes2")
+ .setSnippetCount(5)
+ .setSnippetCountPerProperty(10)
+ .setMaxSnippetSize(15)
+ .setResultCountPerPage(42)
+ .setOrder(SearchSpec.ORDER_ASCENDING)
+ .setRankingStrategy(SearchSpec.RANKING_STRATEGY_DOCUMENT_SCORE)
+ .build();
Bundle bundle = searchSpec.getBundle();
assertThat(bundle.getInt(SearchSpec.TERM_MATCH_TYPE_FIELD))
.isEqualTo(SearchSpec.TERM_MATCH_PREFIX);
- assertThat(bundle.getStringArrayList(SearchSpec.NAMESPACE_FIELD)).containsExactly(
- "namespace1", "namespace2");
- assertThat(bundle.getStringArrayList(SearchSpec.SCHEMA_TYPE_FIELD)).containsExactly(
- "schemaTypes1", "schemaTypes2");
+ assertThat(bundle.getStringArrayList(SearchSpec.NAMESPACE_FIELD))
+ .containsExactly("namespace1", "namespace2");
+ assertThat(bundle.getStringArrayList(SearchSpec.SCHEMA_TYPE_FIELD))
+ .containsExactly("schemaTypes1", "schemaTypes2");
assertThat(bundle.getInt(SearchSpec.SNIPPET_COUNT_FIELD)).isEqualTo(5);
assertThat(bundle.getInt(SearchSpec.SNIPPET_COUNT_PER_PROPERTY_FIELD)).isEqualTo(10);
assertThat(bundle.getInt(SearchSpec.MAX_SNIPPET_FIELD)).isEqualTo(15);
diff --git a/core/tests/coretests/src/android/app/appsearch/external/app/cts/AppSearchResultCtsTest.java b/core/tests/coretests/src/android/app/appsearch/external/app/cts/AppSearchResultCtsTest.java
new file mode 100644
index 000000000000..9c34b172e1ff
--- /dev/null
+++ b/core/tests/coretests/src/android/app/appsearch/external/app/cts/AppSearchResultCtsTest.java
@@ -0,0 +1,79 @@
+/*
+ * 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.app.appsearch.cts;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.app.appsearch.AppSearchResult;
+
+import org.junit.Test;
+
+public class AppSearchResultCtsTest {
+
+ @Test
+ public void testResultEquals_identical() {
+ AppSearchResult<String> result1 = AppSearchResult.newSuccessfulResult("String");
+ AppSearchResult<String> result2 = AppSearchResult.newSuccessfulResult("String");
+
+ assertThat(result1).isEqualTo(result2);
+ assertThat(result1.hashCode()).isEqualTo(result2.hashCode());
+
+ AppSearchResult<String> result3 =
+ AppSearchResult.newFailedResult(
+ AppSearchResult.RESULT_INTERNAL_ERROR, "errorMessage");
+ AppSearchResult<String> result4 =
+ AppSearchResult.newFailedResult(
+ AppSearchResult.RESULT_INTERNAL_ERROR, "errorMessage");
+
+ assertThat(result3).isEqualTo(result4);
+ assertThat(result3.hashCode()).isEqualTo(result4.hashCode());
+ }
+
+ @Test
+ public void testResultEquals_failure() {
+ AppSearchResult<String> result1 = AppSearchResult.newSuccessfulResult("String");
+ AppSearchResult<String> result2 = AppSearchResult.newSuccessfulResult("Wrong");
+ AppSearchResult<String> resultNull = AppSearchResult.newSuccessfulResult(/*value=*/ null);
+
+ assertThat(result1).isNotEqualTo(result2);
+ assertThat(result1.hashCode()).isNotEqualTo(result2.hashCode());
+ assertThat(result1).isNotEqualTo(resultNull);
+ assertThat(result1.hashCode()).isNotEqualTo(resultNull.hashCode());
+
+ AppSearchResult<String> result3 =
+ AppSearchResult.newFailedResult(
+ AppSearchResult.RESULT_INTERNAL_ERROR, "errorMessage");
+ AppSearchResult<String> result4 =
+ AppSearchResult.newFailedResult(AppSearchResult.RESULT_IO_ERROR, "errorMessage");
+
+ assertThat(result3).isNotEqualTo(result4);
+ assertThat(result3.hashCode()).isNotEqualTo(result4.hashCode());
+
+ AppSearchResult<String> result5 =
+ AppSearchResult.newFailedResult(AppSearchResult.RESULT_INTERNAL_ERROR, "Wrong");
+
+ assertThat(result3).isNotEqualTo(result5);
+ assertThat(result3.hashCode()).isNotEqualTo(result5.hashCode());
+
+ AppSearchResult<String> result6 =
+ AppSearchResult.newFailedResult(
+ AppSearchResult.RESULT_INTERNAL_ERROR, /*errorMessage=*/ null);
+
+ assertThat(result3).isNotEqualTo(result6);
+ assertThat(result3.hashCode()).isNotEqualTo(result6.hashCode());
+ }
+}
diff --git a/core/tests/coretests/src/android/app/appsearch/external/app/AppSearchSchemaTest.java b/core/tests/coretests/src/android/app/appsearch/external/app/cts/AppSearchSchemaCtsTest.java
index c171270e23ea..2eaebd6e7b93 100644
--- a/core/tests/coretests/src/android/app/appsearch/external/app/AppSearchSchemaTest.java
+++ b/core/tests/coretests/src/android/app/appsearch/external/app/cts/AppSearchSchemaCtsTest.java
@@ -14,19 +14,19 @@
* limitations under the License.
*/
-package android.app.appsearch;
-
+package android.app.appsearch.cts;
import static com.google.common.truth.Truth.assertThat;
import static org.testng.Assert.expectThrows;
+import android.app.appsearch.AppSearchSchema;
import android.app.appsearch.AppSearchSchema.PropertyConfig;
import android.app.appsearch.exceptions.IllegalSchemaException;
import org.junit.Test;
-public class AppSearchSchemaTest {
+public class AppSearchSchemaCtsTest {
@Test
public void testInvalidEnums() {
PropertyConfig.Builder builder = new PropertyConfig.Builder("test");
@@ -54,21 +54,28 @@ public class AppSearchSchemaTest {
@Test
public void testDuplicateProperties() {
- AppSearchSchema.Builder builder = new AppSearchSchema.Builder("Email")
- .addProperty(new PropertyConfig.Builder("subject")
- .setDataType(PropertyConfig.DATA_TYPE_STRING)
- .setCardinality(PropertyConfig.CARDINALITY_OPTIONAL)
- .setIndexingType(PropertyConfig.INDEXING_TYPE_PREFIXES)
- .setTokenizerType(PropertyConfig.TOKENIZER_TYPE_PLAIN)
- .build()
- );
- IllegalSchemaException e = expectThrows(IllegalSchemaException.class,
- () -> builder.addProperty(new PropertyConfig.Builder("subject")
- .setDataType(PropertyConfig.DATA_TYPE_STRING)
- .setCardinality(PropertyConfig.CARDINALITY_OPTIONAL)
- .setIndexingType(PropertyConfig.INDEXING_TYPE_PREFIXES)
- .setTokenizerType(PropertyConfig.TOKENIZER_TYPE_PLAIN)
- .build()));
+ AppSearchSchema.Builder builder =
+ new AppSearchSchema.Builder("Email")
+ .addProperty(
+ new PropertyConfig.Builder("subject")
+ .setDataType(PropertyConfig.DATA_TYPE_STRING)
+ .setCardinality(PropertyConfig.CARDINALITY_OPTIONAL)
+ .setIndexingType(PropertyConfig.INDEXING_TYPE_PREFIXES)
+ .setTokenizerType(PropertyConfig.TOKENIZER_TYPE_PLAIN)
+ .build());
+ IllegalSchemaException e =
+ expectThrows(
+ IllegalSchemaException.class,
+ () ->
+ builder.addProperty(
+ new PropertyConfig.Builder("subject")
+ .setDataType(PropertyConfig.DATA_TYPE_STRING)
+ .setCardinality(PropertyConfig.CARDINALITY_OPTIONAL)
+ .setIndexingType(
+ PropertyConfig.INDEXING_TYPE_PREFIXES)
+ .setTokenizerType(
+ PropertyConfig.TOKENIZER_TYPE_PLAIN)
+ .build()));
assertThat(e).hasMessageThat().contains("Property defined more than once: subject");
}
}
diff --git a/core/tests/coretests/src/android/app/appsearch/external/app/cts/GenericDocumentCtsTest.java b/core/tests/coretests/src/android/app/appsearch/external/app/cts/GenericDocumentCtsTest.java
new file mode 100644
index 000000000000..657d55696f1f
--- /dev/null
+++ b/core/tests/coretests/src/android/app/appsearch/external/app/cts/GenericDocumentCtsTest.java
@@ -0,0 +1,286 @@
+/*
+ * 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.app.appsearch.cts;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.testng.Assert.expectThrows;
+
+import android.app.appsearch.GenericDocument;
+
+import org.junit.Test;
+
+public class GenericDocumentCtsTest {
+ private static final byte[] sByteArray1 = new byte[] {(byte) 1, (byte) 2, (byte) 3};
+ private static final byte[] sByteArray2 = new byte[] {(byte) 4, (byte) 5, (byte) 6, (byte) 7};
+ private static final GenericDocument sDocumentProperties1 =
+ new GenericDocument.Builder<>("sDocumentProperties1", "sDocumentPropertiesSchemaType1")
+ .setCreationTimestampMillis(12345L)
+ .build();
+ private static final GenericDocument sDocumentProperties2 =
+ new GenericDocument.Builder<>("sDocumentProperties2", "sDocumentPropertiesSchemaType2")
+ .setCreationTimestampMillis(6789L)
+ .build();
+
+ @Test
+ public void testDocumentEquals_identical() {
+ GenericDocument document1 =
+ new GenericDocument.Builder<>("uri1", "schemaType1")
+ .setCreationTimestampMillis(5L)
+ .setTtlMillis(1L)
+ .setPropertyLong("longKey1", 1L, 2L, 3L)
+ .setPropertyDouble("doubleKey1", 1.0, 2.0, 3.0)
+ .setPropertyBoolean("booleanKey1", true, false, true)
+ .setPropertyString(
+ "stringKey1", "test-value1", "test-value2", "test-value3")
+ .setPropertyBytes("byteKey1", sByteArray1, sByteArray2)
+ .setPropertyDocument(
+ "documentKey1", sDocumentProperties1, sDocumentProperties2)
+ .build();
+ GenericDocument document2 =
+ new GenericDocument.Builder<>("uri1", "schemaType1")
+ .setCreationTimestampMillis(5L)
+ .setTtlMillis(1L)
+ .setPropertyLong("longKey1", 1L, 2L, 3L)
+ .setPropertyDouble("doubleKey1", 1.0, 2.0, 3.0)
+ .setPropertyBoolean("booleanKey1", true, false, true)
+ .setPropertyString(
+ "stringKey1", "test-value1", "test-value2", "test-value3")
+ .setPropertyBytes("byteKey1", sByteArray1, sByteArray2)
+ .setPropertyDocument(
+ "documentKey1", sDocumentProperties1, sDocumentProperties2)
+ .build();
+ assertThat(document1).isEqualTo(document2);
+ assertThat(document1.hashCode()).isEqualTo(document2.hashCode());
+ }
+
+ @Test
+ public void testDocumentEquals_differentOrder() {
+ GenericDocument document1 =
+ new GenericDocument.Builder<>("uri1", "schemaType1")
+ .setCreationTimestampMillis(5L)
+ .setPropertyLong("longKey1", 1L, 2L, 3L)
+ .setPropertyBytes("byteKey1", sByteArray1, sByteArray2)
+ .setPropertyDouble("doubleKey1", 1.0, 2.0, 3.0)
+ .setPropertyBoolean("booleanKey1", true, false, true)
+ .setPropertyDocument(
+ "documentKey1", sDocumentProperties1, sDocumentProperties2)
+ .setPropertyString(
+ "stringKey1", "test-value1", "test-value2", "test-value3")
+ .build();
+
+ // Create second document with same parameter but different order.
+ GenericDocument document2 =
+ new GenericDocument.Builder<>("uri1", "schemaType1")
+ .setCreationTimestampMillis(5L)
+ .setPropertyBoolean("booleanKey1", true, false, true)
+ .setPropertyDocument(
+ "documentKey1", sDocumentProperties1, sDocumentProperties2)
+ .setPropertyString(
+ "stringKey1", "test-value1", "test-value2", "test-value3")
+ .setPropertyDouble("doubleKey1", 1.0, 2.0, 3.0)
+ .setPropertyBytes("byteKey1", sByteArray1, sByteArray2)
+ .setPropertyLong("longKey1", 1L, 2L, 3L)
+ .build();
+ assertThat(document1).isEqualTo(document2);
+ assertThat(document1.hashCode()).isEqualTo(document2.hashCode());
+ }
+
+ @Test
+ public void testDocumentEquals_failure() {
+ GenericDocument document1 =
+ new GenericDocument.Builder<>("uri1", "schemaType1")
+ .setCreationTimestampMillis(5L)
+ .setPropertyLong("longKey1", 1L, 2L, 3L)
+ .build();
+
+ // Create second document with same order but different value.
+ GenericDocument document2 =
+ new GenericDocument.Builder<>("uri1", "schemaType1")
+ .setCreationTimestampMillis(5L)
+ .setPropertyLong("longKey1", 1L, 2L, 4L) // Different
+ .build();
+ assertThat(document1).isNotEqualTo(document2);
+ assertThat(document1.hashCode()).isNotEqualTo(document2.hashCode());
+ }
+
+ @Test
+ public void testDocumentEquals_repeatedFieldOrder_failure() {
+ GenericDocument document1 =
+ new GenericDocument.Builder<>("uri1", "schemaType1")
+ .setCreationTimestampMillis(5L)
+ .setPropertyBoolean("booleanKey1", true, false, true)
+ .build();
+
+ // Create second document with same order but different value.
+ GenericDocument document2 =
+ new GenericDocument.Builder<>("uri1", "schemaType1")
+ .setCreationTimestampMillis(5L)
+ .setPropertyBoolean("booleanKey1", true, true, false) // Different
+ .build();
+ assertThat(document1).isNotEqualTo(document2);
+ assertThat(document1.hashCode()).isNotEqualTo(document2.hashCode());
+ }
+
+ @Test
+ public void testDocumentGetSingleValue() {
+ GenericDocument document =
+ new GenericDocument.Builder<>("uri1", "schemaType1")
+ .setCreationTimestampMillis(5L)
+ .setScore(1)
+ .setTtlMillis(1L)
+ .setPropertyLong("longKey1", 1L)
+ .setPropertyDouble("doubleKey1", 1.0)
+ .setPropertyBoolean("booleanKey1", true)
+ .setPropertyString("stringKey1", "test-value1")
+ .setPropertyBytes("byteKey1", sByteArray1)
+ .setPropertyDocument("documentKey1", sDocumentProperties1)
+ .build();
+ assertThat(document.getUri()).isEqualTo("uri1");
+ assertThat(document.getTtlMillis()).isEqualTo(1L);
+ assertThat(document.getSchemaType()).isEqualTo("schemaType1");
+ assertThat(document.getCreationTimestampMillis()).isEqualTo(5);
+ assertThat(document.getScore()).isEqualTo(1);
+ assertThat(document.getPropertyLong("longKey1")).isEqualTo(1L);
+ assertThat(document.getPropertyDouble("doubleKey1")).isEqualTo(1.0);
+ assertThat(document.getPropertyBoolean("booleanKey1")).isTrue();
+ assertThat(document.getPropertyString("stringKey1")).isEqualTo("test-value1");
+ assertThat(document.getPropertyBytes("byteKey1"))
+ .asList()
+ .containsExactly((byte) 1, (byte) 2, (byte) 3);
+ assertThat(document.getPropertyDocument("documentKey1")).isEqualTo(sDocumentProperties1);
+ }
+
+ @Test
+ public void testDocumentGetArrayValues() {
+ GenericDocument document =
+ new GenericDocument.Builder<>("uri1", "schemaType1")
+ .setCreationTimestampMillis(5L)
+ .setPropertyLong("longKey1", 1L, 2L, 3L)
+ .setPropertyDouble("doubleKey1", 1.0, 2.0, 3.0)
+ .setPropertyBoolean("booleanKey1", true, false, true)
+ .setPropertyString(
+ "stringKey1", "test-value1", "test-value2", "test-value3")
+ .setPropertyBytes("byteKey1", sByteArray1, sByteArray2)
+ .setPropertyDocument(
+ "documentKey1", sDocumentProperties1, sDocumentProperties2)
+ .build();
+
+ assertThat(document.getUri()).isEqualTo("uri1");
+ assertThat(document.getSchemaType()).isEqualTo("schemaType1");
+ assertThat(document.getPropertyLongArray("longKey1")).asList().containsExactly(1L, 2L, 3L);
+ assertThat(document.getPropertyDoubleArray("doubleKey1"))
+ .usingExactEquality()
+ .containsExactly(1.0, 2.0, 3.0);
+ assertThat(document.getPropertyBooleanArray("booleanKey1"))
+ .asList()
+ .containsExactly(true, false, true);
+ assertThat(document.getPropertyStringArray("stringKey1"))
+ .asList()
+ .containsExactly("test-value1", "test-value2", "test-value3");
+ assertThat(document.getPropertyBytesArray("byteKey1"))
+ .asList()
+ .containsExactly(sByteArray1, sByteArray2);
+ assertThat(document.getPropertyDocumentArray("documentKey1"))
+ .asList()
+ .containsExactly(sDocumentProperties1, sDocumentProperties2);
+ }
+
+ @Test
+ public void testDocument_toString() {
+ GenericDocument document =
+ new GenericDocument.Builder<>("uri1", "schemaType1")
+ .setCreationTimestampMillis(5L)
+ .setPropertyLong("longKey1", 1L, 2L, 3L)
+ .setPropertyDouble("doubleKey1", 1.0, 2.0, 3.0)
+ .setPropertyBoolean("booleanKey1", true, false, true)
+ .setPropertyString("stringKey1", "String1", "String2", "String3")
+ .setPropertyBytes("byteKey1", sByteArray1, sByteArray2)
+ .setPropertyDocument(
+ "documentKey1", sDocumentProperties1, sDocumentProperties2)
+ .build();
+ String exceptedString =
+ "{ key: 'creationTimestampMillis' value: 5 } "
+ + "{ key: 'namespace' value: } "
+ + "{ key: 'properties' value: "
+ + "{ key: 'booleanKey1' value: [ 'true' 'false' 'true' ] } "
+ + "{ key: 'byteKey1' value: "
+ + "{ key: 'byteArray' value: [ '1' '2' '3' ] } "
+ + "{ key: 'byteArray' value: [ '4' '5' '6' '7' ] } } "
+ + "{ key: 'documentKey1' value: [ '"
+ + "{ key: 'creationTimestampMillis' value: 12345 } "
+ + "{ key: 'namespace' value: } "
+ + "{ key: 'properties' value: } "
+ + "{ key: 'schemaType' value: sDocumentPropertiesSchemaType1 } "
+ + "{ key: 'score' value: 0 } "
+ + "{ key: 'ttlMillis' value: 0 } "
+ + "{ key: 'uri' value: sDocumentProperties1 } ' '"
+ + "{ key: 'creationTimestampMillis' value: 6789 } "
+ + "{ key: 'namespace' value: } "
+ + "{ key: 'properties' value: } "
+ + "{ key: 'schemaType' value: sDocumentPropertiesSchemaType2 } "
+ + "{ key: 'score' value: 0 } "
+ + "{ key: 'ttlMillis' value: 0 } "
+ + "{ key: 'uri' value: sDocumentProperties2 } ' ] } "
+ + "{ key: 'doubleKey1' value: [ '1.0' '2.0' '3.0' ] } "
+ + "{ key: 'longKey1' value: [ '1' '2' '3' ] } "
+ + "{ key: 'stringKey1' value: [ 'String1' 'String2' 'String3' ] } } "
+ + "{ key: 'schemaType' value: schemaType1 } "
+ + "{ key: 'score' value: 0 } "
+ + "{ key: 'ttlMillis' value: 0 } "
+ + "{ key: 'uri' value: uri1 } ";
+ assertThat(document.toString()).isEqualTo(exceptedString);
+ }
+
+ @Test
+ public void testDocumentGetValues_differentTypes() {
+ GenericDocument document =
+ new GenericDocument.Builder<>("uri1", "schemaType1")
+ .setScore(1)
+ .setPropertyLong("longKey1", 1L)
+ .setPropertyBoolean("booleanKey1", true, false, true)
+ .setPropertyString(
+ "stringKey1", "test-value1", "test-value2", "test-value3")
+ .build();
+
+ // Get a value for a key that doesn't exist
+ assertThat(document.getPropertyDouble("doubleKey1")).isEqualTo(0.0);
+ assertThat(document.getPropertyDoubleArray("doubleKey1")).isNull();
+
+ // Get a value with a single element as an array and as a single value
+ assertThat(document.getPropertyLong("longKey1")).isEqualTo(1L);
+ assertThat(document.getPropertyLongArray("longKey1")).asList().containsExactly(1L);
+
+ // Get a value with multiple elements as an array and as a single value
+ assertThat(document.getPropertyString("stringKey1")).isEqualTo("test-value1");
+ assertThat(document.getPropertyStringArray("stringKey1"))
+ .asList()
+ .containsExactly("test-value1", "test-value2", "test-value3");
+
+ // Get a value of the wrong type
+ assertThat(document.getPropertyDouble("longKey1")).isEqualTo(0.0);
+ assertThat(document.getPropertyDoubleArray("longKey1")).isNull();
+ }
+
+ @Test
+ public void testDocumentInvalid() {
+ GenericDocument.Builder<?> builder = new GenericDocument.Builder<>("uri1", "schemaType1");
+ expectThrows(
+ IllegalArgumentException.class,
+ () -> builder.setPropertyBoolean("test", new boolean[] {}));
+ }
+}
diff --git a/core/tests/coretests/src/android/app/appsearch/external/app/cts/SearchSpecCtsTest.java b/core/tests/coretests/src/android/app/appsearch/external/app/cts/SearchSpecCtsTest.java
new file mode 100644
index 000000000000..50bca278534e
--- /dev/null
+++ b/core/tests/coretests/src/android/app/appsearch/external/app/cts/SearchSpecCtsTest.java
@@ -0,0 +1,67 @@
+/*
+ * 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.app.appsearch.cts;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.testng.Assert.expectThrows;
+
+import android.app.appsearch.SearchSpec;
+
+import org.junit.Test;
+
+public class SearchSpecCtsTest {
+ @Test
+ public void buildSearchSpecWithoutTermMatchType() {
+ RuntimeException e =
+ expectThrows(
+ RuntimeException.class,
+ () -> new SearchSpec.Builder().addSchemaType("testSchemaType").build());
+ assertThat(e).hasMessageThat().contains("Missing termMatchType field");
+ }
+
+ @Test
+ public void testBuildSearchSpec() {
+ SearchSpec searchSpec =
+ new SearchSpec.Builder()
+ .setTermMatch(SearchSpec.TERM_MATCH_PREFIX)
+ .addNamespace("namespace1", "namespace2")
+ .addSchemaType("schemaTypes1", "schemaTypes2")
+ .setSnippetCount(5)
+ .setSnippetCountPerProperty(10)
+ .setMaxSnippetSize(15)
+ .setResultCountPerPage(42)
+ .setOrder(SearchSpec.ORDER_ASCENDING)
+ .setRankingStrategy(SearchSpec.RANKING_STRATEGY_DOCUMENT_SCORE)
+ .build();
+
+ assertThat(searchSpec.getTermMatch()).isEqualTo(SearchSpec.TERM_MATCH_PREFIX);
+ assertThat(searchSpec.getNamespaces())
+ .containsExactly("namespace1", "namespace2")
+ .inOrder();
+ assertThat(searchSpec.getSchemaTypes())
+ .containsExactly("schemaTypes1", "schemaTypes2")
+ .inOrder();
+ assertThat(searchSpec.getSnippetCount()).isEqualTo(5);
+ assertThat(searchSpec.getSnippetCountPerProperty()).isEqualTo(10);
+ assertThat(searchSpec.getMaxSnippetSize()).isEqualTo(15);
+ assertThat(searchSpec.getResultCountPerPage()).isEqualTo(42);
+ assertThat(searchSpec.getOrder()).isEqualTo(SearchSpec.ORDER_ASCENDING);
+ assertThat(searchSpec.getRankingStrategy())
+ .isEqualTo(SearchSpec.RANKING_STRATEGY_DOCUMENT_SCORE);
+ }
+}
diff --git a/core/tests/coretests/src/android/app/appsearch/external/app/customer/CustomerDocumentTest.java b/core/tests/coretests/src/android/app/appsearch/external/app/cts/customer/CustomerDocumentTest.java
index d56d0c3c5c8e..29b5754da520 100644
--- a/core/tests/coretests/src/android/app/appsearch/external/app/customer/CustomerDocumentTest.java
+++ b/core/tests/coretests/src/android/app/appsearch/external/app/cts/customer/CustomerDocumentTest.java
@@ -14,13 +14,13 @@
* limitations under the License.
*/
-package android.app.appsearch.customer;
+package android.app.appsearch.cts.customer;
+
+import static com.google.common.truth.Truth.assertThat;
import android.annotation.NonNull;
import android.app.appsearch.GenericDocument;
-import static com.google.common.truth.Truth.assertThat;
-
import org.junit.Test;
/**
@@ -32,50 +32,58 @@ import org.junit.Test;
*/
public class CustomerDocumentTest {
- private static byte[] sByteArray1 = new byte[]{(byte) 1, (byte) 2, (byte) 3};
- private static byte[] sByteArray2 = new byte[]{(byte) 4, (byte) 5, (byte) 6};
- private static GenericDocument sDocumentProperties1 = new GenericDocument
- .Builder("sDocumentProperties1", "sDocumentPropertiesSchemaType1")
- .build();
- private static GenericDocument sDocumentProperties2 = new GenericDocument
- .Builder("sDocumentProperties2", "sDocumentPropertiesSchemaType2")
- .build();
+ private static final byte[] BYTE_ARRAY1 = new byte[] {(byte) 1, (byte) 2, (byte) 3};
+ private static final byte[] BYTE_ARRAY2 = new byte[] {(byte) 4, (byte) 5, (byte) 6};
+ private static final GenericDocument DOCUMENT_PROPERTIES1 =
+ new GenericDocument.Builder<>("sDocumentProperties1", "sDocumentPropertiesSchemaType1")
+ .build();
+ private static final GenericDocument DOCUMENT_PROPERTIES2 =
+ new GenericDocument.Builder<>("sDocumentProperties2", "sDocumentPropertiesSchemaType2")
+ .build();
@Test
public void testBuildCustomerDocument() {
- CustomerDocument customerDocument = new CustomerDocument.Builder("uri1")
- .setScore(1)
- .setCreationTimestampMillis(0)
- .setPropertyLong("longKey1", 1L, 2L, 3L)
- .setPropertyDouble("doubleKey1", 1.0, 2.0, 3.0)
- .setPropertyBoolean("booleanKey1", true, false, true)
- .setPropertyString("stringKey1", "test-value1", "test-value2", "test-value3")
- .setPropertyBytes("byteKey1", sByteArray1, sByteArray2)
- .setPropertyDocument("documentKey1", sDocumentProperties1, sDocumentProperties2)
- .build();
+ CustomerDocument customerDocument =
+ new CustomerDocument.Builder("uri1")
+ .setScore(1)
+ .setCreationTimestampMillis(0)
+ .setPropertyLong("longKey1", 1L, 2L, 3L)
+ .setPropertyDouble("doubleKey1", 1.0, 2.0, 3.0)
+ .setPropertyBoolean("booleanKey1", true, false, true)
+ .setPropertyString(
+ "stringKey1", "test-value1", "test-value2", "test-value3")
+ .setPropertyBytes("byteKey1", BYTE_ARRAY1, BYTE_ARRAY2)
+ .setPropertyDocument(
+ "documentKey1", DOCUMENT_PROPERTIES1, DOCUMENT_PROPERTIES2)
+ .build();
assertThat(customerDocument.getUri()).isEqualTo("uri1");
assertThat(customerDocument.getSchemaType()).isEqualTo("customerDocument");
assertThat(customerDocument.getScore()).isEqualTo(1);
assertThat(customerDocument.getCreationTimestampMillis()).isEqualTo(0L);
- assertThat(customerDocument.getPropertyLongArray("longKey1")).asList()
+ assertThat(customerDocument.getPropertyLongArray("longKey1"))
+ .asList()
.containsExactly(1L, 2L, 3L);
- assertThat(customerDocument.getPropertyDoubleArray("doubleKey1")).usingExactEquality()
+ assertThat(customerDocument.getPropertyDoubleArray("doubleKey1"))
+ .usingExactEquality()
.containsExactly(1.0, 2.0, 3.0);
- assertThat(customerDocument.getPropertyBooleanArray("booleanKey1")).asList()
+ assertThat(customerDocument.getPropertyBooleanArray("booleanKey1"))
+ .asList()
.containsExactly(true, false, true);
- assertThat(customerDocument.getPropertyStringArray("stringKey1")).asList()
+ assertThat(customerDocument.getPropertyStringArray("stringKey1"))
+ .asList()
.containsExactly("test-value1", "test-value2", "test-value3");
- assertThat(customerDocument.getPropertyBytesArray("byteKey1")).asList()
- .containsExactly(sByteArray1, sByteArray2);
- assertThat(customerDocument.getPropertyDocumentArray("documentKey1")).asList()
- .containsExactly(sDocumentProperties1, sDocumentProperties2);
+ assertThat(customerDocument.getPropertyBytesArray("byteKey1"))
+ .asList()
+ .containsExactly(BYTE_ARRAY1, BYTE_ARRAY2);
+ assertThat(customerDocument.getPropertyDocumentArray("documentKey1"))
+ .asList()
+ .containsExactly(DOCUMENT_PROPERTIES1, DOCUMENT_PROPERTIES2);
}
/**
- * An example document type for test purposes, defined outside of
- * {@link GenericDocument} (the way an external developer would define
- * it).
+ * An example document type for test purposes, defined outside of {@link GenericDocument} (the
+ * way an external developer would define it).
*/
private static class CustomerDocument extends GenericDocument {
private CustomerDocument(GenericDocument document) {
diff --git a/core/tests/coretests/src/android/app/people/PeopleSpaceTileTest.java b/core/tests/coretests/src/android/app/people/PeopleSpaceTileTest.java
new file mode 100644
index 000000000000..27584a597cc8
--- /dev/null
+++ b/core/tests/coretests/src/android/app/people/PeopleSpaceTileTest.java
@@ -0,0 +1,191 @@
+/*
+ * 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.app.people;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static junit.framework.Assert.assertFalse;
+
+import static org.junit.Assert.assertTrue;
+
+import android.app.Notification;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.ShortcutInfo;
+import android.graphics.drawable.Icon;
+import android.net.Uri;
+import android.os.UserHandle;
+import android.service.notification.StatusBarNotification;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+public class PeopleSpaceTileTest {
+
+ private Context mContext;
+
+ @Before
+ public void setUp() {
+ mContext = InstrumentationRegistry.getContext();
+ }
+
+ @Test
+ public void testId() {
+ PeopleSpaceTile tile = new PeopleSpaceTile.Builder(
+ new ShortcutInfo.Builder(mContext, "123").build()).build();
+ assertThat(tile.getId()).isEqualTo("123");
+
+ tile = new PeopleSpaceTile.Builder(new ShortcutInfo.Builder(mContext, "123").build()).setId(
+ "5").build();
+ assertThat(tile.getId()).isEqualTo("5");
+
+ tile = new PeopleSpaceTile.Builder("12", null, null, null).build();
+ assertThat(tile.getId()).isEqualTo("12");
+ }
+
+ @Test
+ public void testUserName() {
+ PeopleSpaceTile tile = new PeopleSpaceTile.Builder(
+ new ShortcutInfo.Builder(mContext, "123").build()).build();
+ assertThat(tile.getUserName()).isNull();
+
+ tile = new PeopleSpaceTile.Builder(
+ new ShortcutInfo.Builder(mContext, "123").build()).setUserName("Name 1").build();
+ assertThat(tile.getUserName()).isEqualTo("Name 1");
+
+ tile = new PeopleSpaceTile.Builder(null, "Name 2", null, null).build();
+ assertThat(tile.getUserName()).isEqualTo("Name 2");
+ }
+
+ @Test
+ public void testUserIcon() {
+ PeopleSpaceTile tile = new PeopleSpaceTile.Builder(
+ new ShortcutInfo.Builder(mContext, "123").build()).setUserIcon(
+ Icon.createWithResource(mContext, 1)).build();
+ assertThat(tile.getUserIcon().toString()).isEqualTo(
+ Icon.createWithResource(mContext, 1).toString());
+
+ tile = new PeopleSpaceTile.Builder("12", null, Icon.createWithResource(mContext, 2),
+ null).build();
+ assertThat(tile.getUserIcon().toString()).isEqualTo(
+ Icon.createWithResource(mContext, 2).toString());
+ }
+
+ @Test
+ public void testContactUri() {
+ PeopleSpaceTile tile = new PeopleSpaceTile.Builder(
+ new ShortcutInfo.Builder(mContext, "123").build()).setContactUri(
+ Uri.parse("test")).build();
+
+ assertThat(tile.getContactUri()).isEqualTo(Uri.parse("test"));
+ }
+
+ @Test
+ public void testUid() {
+ PeopleSpaceTile tile = new PeopleSpaceTile.Builder(
+ new ShortcutInfo.Builder(mContext, "123").build()).setUid(42).build();
+
+ assertThat(tile.getUid()).isEqualTo(42);
+ }
+
+ @Test
+ public void testPackageName() {
+ PeopleSpaceTile tile = new PeopleSpaceTile.Builder(
+ new ShortcutInfo.Builder(mContext, "123").build()).build();
+ // Automatically added by creating a ShortcutInfo.
+ assertThat(tile.getPackageName()).isEqualTo("com.android.frameworks.coretests");
+
+ tile = new PeopleSpaceTile.Builder(
+ new ShortcutInfo.Builder(mContext, "123").build()).setPackageName(
+ "package.name").build();
+ assertThat(tile.getPackageName()).isEqualTo("package.name");
+
+ tile = new PeopleSpaceTile.Builder("12", null, null,
+ new Intent().setPackage("intent.package")).build();
+ assertThat(tile.getPackageName()).isEqualTo("intent.package");
+ }
+
+ @Test
+ public void testLastInteractionTimestamp() {
+ PeopleSpaceTile tile = new PeopleSpaceTile.Builder(
+ new ShortcutInfo.Builder(mContext, "123").build()).build();
+ assertThat(tile.getLastInteractionTimestamp()).isEqualTo(0L);
+
+ tile = new PeopleSpaceTile.Builder(
+ new ShortcutInfo.Builder(mContext, "123").build()).setLastInteractionTimestamp(
+ 7L).build();
+ assertThat(tile.getLastInteractionTimestamp()).isEqualTo(7L);
+ }
+
+ @Test
+ public void testImportantConversation() {
+ PeopleSpaceTile tile = new PeopleSpaceTile.Builder(
+ new ShortcutInfo.Builder(mContext, "123").build()).build();
+ assertFalse(tile.isImportantConversation());
+
+ tile = new PeopleSpaceTile.Builder(
+ new ShortcutInfo.Builder(mContext, "123").build()).setIsImportantConversation(
+ true).build();
+ assertTrue(tile.isImportantConversation());
+ }
+
+ @Test
+ public void testHiddenConversation() {
+ PeopleSpaceTile tile = new PeopleSpaceTile.Builder(
+ new ShortcutInfo.Builder(mContext, "123").build()).build();
+ assertFalse(tile.isHiddenConversation());
+
+ tile = new PeopleSpaceTile.Builder(
+ new ShortcutInfo.Builder(mContext, "123").build()).setIsHiddenConversation(
+ true).build();
+ assertTrue(tile.isHiddenConversation());
+ }
+
+ @Test
+ public void testNotification() {
+ Notification notification = new Notification.Builder(mContext, "test").build();
+ StatusBarNotification sbn = new StatusBarNotification("pkg" /* pkg */, "pkg" /* opPkg */,
+ 1 /* id */, "" /* tag */, 0 /* uid */, 0 /* initialPid */, 0 /* score */,
+ notification, UserHandle.CURRENT, 0 /* postTime */);
+ PeopleSpaceTile tile = new PeopleSpaceTile.Builder(
+ new ShortcutInfo.Builder(mContext, "123").build()).setNotification(sbn).build();
+
+ assertThat(tile.getNotification()).isEqualTo(sbn);
+ }
+
+ @Test
+ public void testIntent() {
+ PeopleSpaceTile tile = new PeopleSpaceTile.Builder(
+ new ShortcutInfo.Builder(mContext, "123").build()).build();
+ assertThat(tile.getIntent()).isNull();
+
+ tile = new PeopleSpaceTile.Builder(
+ new ShortcutInfo.Builder(mContext, "123").build()).setIntent(new Intent()).build();
+ assertThat(tile.getIntent().toString()).isEqualTo(new Intent().toString());
+
+ tile = new PeopleSpaceTile.Builder("12", null, null, new Intent()).build();
+ assertThat(tile.getIntent().toString()).isEqualTo(new Intent().toString());
+ }
+
+}
diff --git a/core/tests/coretests/src/android/content/pm/PackageManagerPropertyTests.java b/core/tests/coretests/src/android/content/pm/PackageManagerPropertyTests.java
new file mode 100644
index 000000000000..3757712010a2
--- /dev/null
+++ b/core/tests/coretests/src/android/content/pm/PackageManagerPropertyTests.java
@@ -0,0 +1,199 @@
+/*
+ * 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.content.pm;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import android.content.pm.PackageManager.Property;
+import android.os.Bundle;
+
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(AndroidJUnit4.class)
+public class PackageManagerPropertyTests {
+
+ @Test
+ public void testBooleanProperty() throws Exception {
+ final Property p =
+ new Property("booleanProperty", true, "android", null);
+ assertTrue(p.isBoolean());
+ assertFalse(p.isFloat());
+ assertFalse(p.isInteger());
+ assertFalse(p.isResourceId());
+ assertFalse(p.isString());
+ assertTrue(p.getBoolean());
+ assertEquals(0.0f, p.getFloat(), 0.0f);
+ assertEquals(0, p.getInteger());
+ assertEquals(0, p.getResourceId());
+ assertEquals(null, p.getString());
+ assertEquals("android", p.getPackageName());
+ assertNull(p.getClassName());
+ }
+
+ @Test
+ public void testBooleanPropertyToBundle() throws Exception {
+ final Bundle b =
+ new Property("booleanProperty", true, "android", null).toBundle(null);
+ assertTrue(b.getBoolean("booleanProperty"));
+ }
+
+ @Test
+ public void testFloatProperty() throws Exception {
+ final Property p =
+ new Property("floatProperty", 3.14f, "android", null);
+ assertFalse(p.isBoolean());
+ assertTrue(p.isFloat());
+ assertFalse(p.isInteger());
+ assertFalse(p.isResourceId());
+ assertFalse(p.isString());
+ assertFalse(p.getBoolean());
+ assertEquals(3.14f, p.getFloat(), 0.0f);
+ assertEquals(0, p.getInteger());
+ assertEquals(0, p.getResourceId());
+ assertEquals(null, p.getString());
+ assertEquals("android", p.getPackageName());
+ assertNull(p.getClassName());
+ }
+
+ @Test
+ public void testFloatPropertyToBundle() throws Exception {
+ final Bundle b =
+ new Property("floatProperty", 3.14f, "android", null).toBundle(null);
+ assertEquals(3.14f, b.getFloat("floatProperty"), 0.0f);
+ }
+
+ @Test
+ public void testIntegerProperty() throws Exception {
+ final Property p =
+ new Property("integerProperty", 42, false, "android", null);
+ assertFalse(p.isBoolean());
+ assertFalse(p.isFloat());
+ assertTrue(p.isInteger());
+ assertFalse(p.isResourceId());
+ assertFalse(p.isString());
+ assertFalse(p.getBoolean());
+ assertEquals(0.0f, p.getFloat(), 0.0f);
+ assertEquals(42, p.getInteger());
+ assertEquals(0, p.getResourceId());
+ assertEquals(null, p.getString());
+ assertEquals("android", p.getPackageName());
+ assertNull(p.getClassName());
+ }
+
+ @Test
+ public void testIntegerPropertyToBundle() throws Exception {
+ final Bundle b =
+ new Property("integerProperty", 42, false, "android", null).toBundle(null);
+ assertEquals(42, b.getInt("integerProperty"));
+ }
+
+ @Test
+ public void testResourceProperty() throws Exception {
+ final Property p =
+ new Property("resourceProperty", 0x7f010001, true, "android", null);
+ assertFalse(p.isBoolean());
+ assertFalse(p.isFloat());
+ assertFalse(p.isInteger());
+ assertTrue(p.isResourceId());
+ assertFalse(p.isString());
+ assertFalse(p.getBoolean());
+ assertEquals(0.0f, p.getFloat(), 0.0f);
+ assertEquals(0, p.getInteger());
+ assertEquals(0x7f010001, p.getResourceId());
+ assertEquals(null, p.getString());
+ assertEquals("android", p.getPackageName());
+ assertNull(p.getClassName());
+ }
+
+ @Test
+ public void testResourcePropertyToBundle() throws Exception {
+ final Bundle b =
+ new Property("resourceProperty", 0x7f010001, true, "android", null).toBundle(null);
+ assertEquals(0x7f010001, b.getInt("resourceProperty"));
+ }
+
+ @Test
+ public void testStringProperty() throws Exception {
+ final Property p =
+ new Property("stringProperty", "koala", "android", null);
+ assertFalse(p.isBoolean());
+ assertFalse(p.isFloat());
+ assertFalse(p.isInteger());
+ assertFalse(p.isResourceId());
+ assertTrue(p.isString());
+ assertFalse(p.getBoolean());
+ assertEquals(0.0f, p.getFloat(), 0.0f);
+ assertEquals(0, p.getInteger());
+ assertEquals(0, p.getResourceId());
+ assertEquals("koala", p.getString());
+ assertEquals("android", p.getPackageName());
+ assertNull(p.getClassName());
+ }
+
+ @Test
+ public void testStringPropertyToBundle() throws Exception {
+ final Bundle b =
+ new Property("stringProperty", "koala", "android", null).toBundle(null);
+ assertEquals("koala", b.getString("stringProperty"));
+ }
+
+ @Test
+ public void testProperty_invalidName() throws Exception {
+ try {
+ final Property p = new Property(null, 1, "android", null);
+ fail("expected assertion error");
+ } catch (AssertionError expected) {
+ }
+ }
+
+ @Test
+ public void testProperty_invalidType() throws Exception {
+ try {
+ final Property p = new Property("invalidTypeProperty", 0, "android", null);
+ fail("expected assertion error");
+ } catch (AssertionError expected) {
+ }
+
+ try {
+ final Property p = new Property("invalidTypeProperty", 6, "android", null);
+ fail("expected assertion error");
+ } catch (AssertionError expected) {
+ }
+
+ try {
+ final Property p = new Property("invalidTypeProperty", -1, "android", null);
+ fail("expected assertion error");
+ } catch (AssertionError expected) {
+ }
+ }
+
+ @Test
+ public void testProperty_noPackageName() throws Exception {
+ try {
+ final Property p = new Property(null, 1, null, null);
+ fail("expected assertion error");
+ } catch (AssertionError expected) {
+ }
+ }
+}
diff --git a/core/tests/coretests/src/com/android/internal/jank/FrameTrackerTest.java b/core/tests/coretests/src/com/android/internal/jank/FrameTrackerTest.java
index 2402420e1bc1..7f7bfa3c5e3d 100644
--- a/core/tests/coretests/src/com/android/internal/jank/FrameTrackerTest.java
+++ b/core/tests/coretests/src/com/android/internal/jank/FrameTrackerTest.java
@@ -77,7 +77,8 @@ public class FrameTrackerTest {
Session session = new Session(CUJ_NOTIFICATION_SHADE_EXPAND_COLLAPSE);
mTracker = Mockito.spy(
- new FrameTracker(session, handler, mRenderer, mWrapper, 1, -1));
+ new FrameTracker(session, handler, mRenderer, mWrapper,
+ /*traceThresholdMissedFrames=*/ 1, /*traceThresholdFrameTimeMillis=*/ -1));
doNothing().when(mTracker).triggerPerfetto();
}
diff --git a/core/tests/coretests/src/com/android/internal/jank/InteractionJankMonitorTest.java b/core/tests/coretests/src/com/android/internal/jank/InteractionJankMonitorTest.java
index 474cb1d7ed96..0ef5643b0905 100644
--- a/core/tests/coretests/src/com/android/internal/jank/InteractionJankMonitorTest.java
+++ b/core/tests/coretests/src/com/android/internal/jank/InteractionJankMonitorTest.java
@@ -94,7 +94,8 @@ public class InteractionJankMonitorTest {
Session session = new Session(CUJ_NOTIFICATION_SHADE_EXPAND_COLLAPSE);
FrameTracker tracker = spy(new FrameTracker(session, mWorker.getThreadHandler(),
new ThreadedRendererWrapper(mView.getThreadedRenderer()),
- new FrameMetricsWrapper(), 1, -1));
+ new FrameMetricsWrapper(), /*traceThresholdMissedFrames=*/ 1,
+ /*traceThresholdFrameTimeMillis=*/ -1));
doReturn(tracker).when(monitor).createFrameTracker(any());
// Simulate a trace session and see if begin / end are invoked.
@@ -150,7 +151,8 @@ public class InteractionJankMonitorTest {
Session session = new Session(CUJ_NOTIFICATION_SHADE_EXPAND_COLLAPSE);
FrameTracker tracker = spy(new FrameTracker(session, mWorker.getThreadHandler(),
new ThreadedRendererWrapper(mView.getThreadedRenderer()),
- new FrameMetricsWrapper(), 1, -1));
+ new FrameMetricsWrapper(), /*traceThresholdMissedFrames=*/ 1,
+ /*traceThresholdFrameTimeMillis=*/ -1));
doReturn(tracker).when(monitor).createFrameTracker(any());
assertThat(monitor.begin(session.getCuj())).isTrue();
diff --git a/core/tests/hdmitests/src/android/hardware/hdmi/HdmiAudioSystemClientTest.java b/core/tests/hdmitests/src/android/hardware/hdmi/HdmiAudioSystemClientTest.java
index 4094f836ff5a..306388f30e20 100644
--- a/core/tests/hdmitests/src/android/hardware/hdmi/HdmiAudioSystemClientTest.java
+++ b/core/tests/hdmitests/src/android/hardware/hdmi/HdmiAudioSystemClientTest.java
@@ -191,6 +191,10 @@ public class HdmiAudioSystemClientTest {
}
@Override
+ public void toggleAndFollowTvPower() {
+ }
+
+ @Override
public void queryDisplayStatus(final IHdmiControlCallback callback) {
}
diff --git a/data/etc/car/Android.bp b/data/etc/car/Android.bp
index 745de84a3f04..3e3aefc6f51d 100644
--- a/data/etc/car/Android.bp
+++ b/data/etc/car/Android.bp
@@ -156,4 +156,11 @@ prebuilt_etc {
sub_dir: "permissions",
src: "com.android.car.provision.xml",
filename_from_src: true,
-} \ No newline at end of file
+}
+
+prebuilt_etc {
+ name: "allowed_privapp_com.android.carshell",
+ sub_dir: "permissions",
+ src: "com.android.car.shell.xml",
+ filename_from_src: true,
+}
diff --git a/data/etc/car/com.android.car.shell.xml b/data/etc/car/com.android.car.shell.xml
new file mode 100644
index 000000000000..32666c8d9f68
--- /dev/null
+++ b/data/etc/car/com.android.car.shell.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2020 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License
+ -->
+<permissions>
+ <privapp-permissions package="com.android.car.shell">
+ <permission name="android.permission.INSTALL_PACKAGES" />
+ <permission name="android.permission.MEDIA_CONTENT_CONTROL"/>
+ </privapp-permissions>
+</permissions>
diff --git a/graphics/java/android/graphics/Typeface.java b/graphics/java/android/graphics/Typeface.java
index 5743df5216be..712349aaee57 100644
--- a/graphics/java/android/graphics/Typeface.java
+++ b/graphics/java/android/graphics/Typeface.java
@@ -169,6 +169,8 @@ public class Typeface {
@UnsupportedAppUsage
public long native_instance;
+ private Runnable mCleaner;
+
/** @hide */
@IntDef(value = {NORMAL, BOLD, ITALIC, BOLD_ITALIC})
@Retention(RetentionPolicy.SOURCE)
@@ -808,18 +810,16 @@ public class Typeface {
*/
public @NonNull Typeface build() {
final int userFallbackSize = mFamilies.size();
- final FontFamily[] fallback = SystemFonts.getSystemFallback(mFallbackName);
- final long[] ptrArray = new long[fallback.length + userFallbackSize];
+ final Typeface fallbackTypeface = getSystemDefaultTypeface(mFallbackName);
+ final long[] ptrArray = new long[userFallbackSize];
for (int i = 0; i < userFallbackSize; ++i) {
ptrArray[i] = mFamilies.get(i).getNativePtr();
}
- for (int i = 0; i < fallback.length; ++i) {
- ptrArray[i + userFallbackSize] = fallback[i].getNativePtr();
- }
final int weight = mStyle == null ? 400 : mStyle.getWeight();
final int italic =
(mStyle == null || mStyle.getSlant() == FontStyle.FONT_SLANT_UPRIGHT) ? 0 : 1;
- return new Typeface(nativeCreateFromArray(ptrArray, weight, italic));
+ return new Typeface(nativeCreateFromArray(
+ ptrArray, fallbackTypeface.native_instance, weight, italic));
}
}
@@ -1056,7 +1056,8 @@ public class Typeface {
ptrArray[i] = families[i].mNativePtr;
}
return new Typeface(nativeCreateFromArray(
- ptrArray, RESOLVE_BY_FONT_TABLE, RESOLVE_BY_FONT_TABLE));
+ ptrArray, 0, RESOLVE_BY_FONT_TABLE,
+ RESOLVE_BY_FONT_TABLE));
}
/**
@@ -1069,7 +1070,7 @@ public class Typeface {
for (int i = 0; i < families.length; ++i) {
ptrArray[i] = families[i].getNativePtr();
}
- return new Typeface(nativeCreateFromArray(ptrArray,
+ return new Typeface(nativeCreateFromArray(ptrArray, 0,
RESOLVE_BY_FONT_TABLE, RESOLVE_BY_FONT_TABLE));
}
@@ -1104,15 +1105,13 @@ public class Typeface {
@Deprecated
private static Typeface createFromFamiliesWithDefault(android.graphics.FontFamily[] families,
String fallbackName, int weight, int italic) {
- android.graphics.fonts.FontFamily[] fallback = SystemFonts.getSystemFallback(fallbackName);
- long[] ptrArray = new long[families.length + fallback.length];
+ final Typeface fallbackTypeface = getSystemDefaultTypeface(fallbackName);
+ long[] ptrArray = new long[families.length];
for (int i = 0; i < families.length; i++) {
ptrArray[i] = families[i].mNativePtr;
}
- for (int i = 0; i < fallback.length; i++) {
- ptrArray[i + families.length] = fallback[i].getNativePtr();
- }
- return new Typeface(nativeCreateFromArray(ptrArray, weight, italic));
+ return new Typeface(nativeCreateFromArray(
+ ptrArray, fallbackTypeface.native_instance, weight, italic));
}
// don't allow clients to call this directly
@@ -1123,7 +1122,7 @@ public class Typeface {
}
native_instance = ni;
- sRegistry.registerNativeAllocation(this, native_instance);
+ mCleaner = sRegistry.registerNativeAllocation(this, native_instance);
mStyle = nativeGetStyle(ni);
mWeight = nativeGetWeight(ni);
}
@@ -1237,6 +1236,13 @@ public class Typeface {
bos.write(value & 0xFF);
}
+ /** @hide */
+ public static Map<String, Typeface> getSystemFontMap() {
+ synchronized (SYSTEM_FONT_MAP_LOCK) {
+ return sSystemFontMap;
+ }
+ }
+
/**
* Deserialize font map and set it as system font map. This method should be called at most once
* per process.
@@ -1297,13 +1303,33 @@ public class Typeface {
}
}
- static {
+ /** @hide */
+ @VisibleForTesting
+ public static void destroySystemFontMap() {
+ synchronized (SYSTEM_FONT_MAP_LOCK) {
+ for (Typeface typeface : sSystemFontMap.values()) {
+ typeface.mCleaner.run();
+ }
+ sSystemFontMap.clear();
+ if (sSystemFontMapBuffer != null) {
+ SharedMemory.unmap(sSystemFontMapBuffer);
+ }
+ sSystemFontMapBuffer = null;
+ }
+ }
+
+ /** @hide */
+ public static void loadPreinstalledSystemFontMap() {
final HashMap<String, Typeface> systemFontMap = new HashMap<>();
initSystemDefaultTypefaces(systemFontMap, SystemFonts.getRawSystemFallbackMap(),
SystemFonts.getAliases());
setSystemFontMap(systemFontMap);
}
+ static {
+ loadPreinstalledSystemFontMap();
+ }
+
@Override
public boolean equals(Object o) {
if (this == o) return true;
@@ -1350,7 +1376,8 @@ public class Typeface {
@UnsupportedAppUsage
private static native long nativeCreateWeightAlias(long native_instance, int weight);
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
- private static native long nativeCreateFromArray(long[] familyArray, int weight, int italic);
+ private static native long nativeCreateFromArray(
+ long[] familyArray, long fallbackTypeface, int weight, int italic);
private static native int[] nativeGetSupportedAxes(long native_instance);
@CriticalNative
diff --git a/graphics/java/android/graphics/fonts/SystemFonts.java b/graphics/java/android/graphics/fonts/SystemFonts.java
index 95a8417b6f7f..95c470634518 100644
--- a/graphics/java/android/graphics/fonts/SystemFonts.java
+++ b/graphics/java/android/graphics/fonts/SystemFonts.java
@@ -67,19 +67,6 @@ public final class SystemFonts {
}
/**
- * Returns fallback list for the given family name.
- *
- * If no fallback found for the given family name, returns fallback for the default family.
- *
- * @param familyName family name, e.g. "serif"
- * @hide
- */
- public static @NonNull FontFamily[] getSystemFallback(@Nullable String familyName) {
- final FontFamily[] families = sSystemFallbackMap.get(familyName);
- return families == null ? sSystemFallbackMap.get(DEFAULT_FAMILY) : families;
- }
-
- /**
* Returns raw system fallback map.
*
* This method is intended to be used only by Typeface static initializer.
diff --git a/libs/WindowManager/Shell/res/values-ar/strings.xml b/libs/WindowManager/Shell/res/values-ar/strings.xml
index 6c7faded7dad..7b5bda72ccd4 100644
--- a/libs/WindowManager/Shell/res/values-ar/strings.xml
+++ b/libs/WindowManager/Shell/res/values-ar/strings.xml
@@ -28,7 +28,7 @@
<string name="pip_skip_to_next" msgid="8403429188794867653">"التخطي إلى التالي"</string>
<string name="pip_skip_to_prev" msgid="7172158111196394092">"التخطي إلى السابق"</string>
<string name="accessibility_action_pip_resize" msgid="4623966104749543182">"تغيير الحجم"</string>
- <string name="dock_forced_resizable" msgid="1749750436092293116">"يمكن ألا يعمل التطبيق مع وضع تقسيم الشاشة."</string>
+ <string name="dock_forced_resizable" msgid="1749750436092293116">"قد لا يعمل التطبيق بشكل سليم في وضع \"تقسيم الشاشة\"."</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>
@@ -45,7 +45,7 @@
<string name="accessibility_action_divider_bottom_full" msgid="2831868345092314060">"عرض النافذة السفلية بملء الشاشة"</string>
<string name="one_handed_tutorial_title" msgid="4583241688067426350">"استخدام وضع \"التصفح بيد واحدة\""</string>
<string name="one_handed_tutorial_description" msgid="3486582858591353067">"للخروج، مرِّر سريعًا من أسفل الشاشة إلى أعلاها أو انقر في أي مكان فوق التطبيق."</string>
- <string name="accessibility_action_start_one_handed" msgid="5070337354072861426">"تفعيل وضع \"التصفح بيد واحدة\""</string>
+ <string name="accessibility_action_start_one_handed" msgid="5070337354072861426">"بدء وضع \"التصفح بيد واحدة\""</string>
<string name="accessibility_action_stop_one_handed" msgid="1369940261782179442">"الخروج من وضع \"التصفح بيد واحدة\""</string>
<string name="bubbles_settings_button_description" msgid="1301286017420516912">"إعدادات فقاعات المحادثات على <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
<string name="bubble_overflow_button_content_description" msgid="8160974472718594382">"القائمة الكاملة"</string>
diff --git a/libs/WindowManager/Shell/res/values-be/strings_tv.xml b/libs/WindowManager/Shell/res/values-be/strings_tv.xml
index 973ae8ede5b3..d33bf99e2ebd 100644
--- a/libs/WindowManager/Shell/res/values-be/strings_tv.xml
+++ b/libs/WindowManager/Shell/res/values-be/strings_tv.xml
@@ -20,5 +20,5 @@
<string name="notification_channel_tv_pip" msgid="2576686079160402435">"Відарыс у відарысе"</string>
<string name="pip_notification_unknown_title" msgid="2729870284350772311">"(Праграма без назвы)"</string>
<string name="pip_close" msgid="9135220303720555525">"Закрыць PIP"</string>
- <string name="pip_fullscreen" msgid="7278047353591302554">"Ва ўвесь экран"</string>
+ <string name="pip_fullscreen" msgid="7278047353591302554">"Поўнаэкранны рэжым"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-de/strings.xml b/libs/WindowManager/Shell/res/values-de/strings.xml
index 4979a4015525..f04796aca753 100644
--- a/libs/WindowManager/Shell/res/values-de/strings.xml
+++ b/libs/WindowManager/Shell/res/values-de/strings.xml
@@ -28,8 +28,7 @@
<string name="pip_skip_to_next" msgid="8403429188794867653">"Vorwärts springen"</string>
<string name="pip_skip_to_prev" msgid="7172158111196394092">"Rückwärts springen"</string>
<string name="accessibility_action_pip_resize" msgid="4623966104749543182">"Größe anpassen"</string>
- <!-- no translation found for dock_forced_resizable (1749750436092293116) -->
- <skip />
+ <string name="dock_forced_resizable" msgid="1749750436092293116">"Die App funktioniert unter Umständen bei geteiltem Bildschirmmodus nicht."</string>
<string name="dock_non_resizeble_failed_to_dock_text" msgid="7408396418008948957">"Das Teilen des Bildschirms wird in dieser App nicht unterstützt."</string>
<string name="forced_resizable_secondary_display" msgid="1768046938673582671">"Die App funktioniert auf einem sekundären Display möglicherweise nicht."</string>
<string name="activity_launch_on_secondary_display_failed_text" msgid="4226485344988071769">"Die App unterstützt den Start auf sekundären Displays nicht."</string>
@@ -44,14 +43,10 @@
<string name="accessibility_action_divider_top_50" msgid="8649582798829048946">"50 % oben"</string>
<string name="accessibility_action_divider_top_30" msgid="3572788224908570257">"30 % oben"</string>
<string name="accessibility_action_divider_bottom_full" msgid="2831868345092314060">"Vollbild unten"</string>
- <!-- no translation found for one_handed_tutorial_title (4583241688067426350) -->
- <skip />
- <!-- no translation found for one_handed_tutorial_description (3486582858591353067) -->
- <skip />
- <!-- no translation found for accessibility_action_start_one_handed (5070337354072861426) -->
- <skip />
- <!-- no translation found for accessibility_action_stop_one_handed (1369940261782179442) -->
- <skip />
+ <string name="one_handed_tutorial_title" msgid="4583241688067426350">"Einhandmodus wird verwendet"</string>
+ <string name="one_handed_tutorial_description" msgid="3486582858591353067">"Wenn du die App schließen möchtest, wische vom unteren Rand des Displays nach oben oder tippe auf eine beliebige Stelle oberhalb der App"</string>
+ <string name="accessibility_action_start_one_handed" msgid="5070337354072861426">"Einhandmodus starten"</string>
+ <string name="accessibility_action_stop_one_handed" msgid="1369940261782179442">"Einhandmodus beenden"</string>
<string name="bubbles_settings_button_description" msgid="1301286017420516912">"Einstellungen für <xliff:g id="APP_NAME">%1$s</xliff:g>-Bubbles"</string>
<string name="bubble_overflow_button_content_description" msgid="8160974472718594382">"Mehr anzeigen"</string>
<string name="bubble_accessibility_action_add_back" msgid="1830101076853540953">"Wieder dem Stapel hinzufügen"</string>
@@ -68,8 +63,7 @@
<string name="bubbles_user_education_description" msgid="4215862563054175407">"Neue Unterhaltungen erscheinen als unverankerte Symbole, \"Bubbles\" genannt. Wenn du die Bubble öffnen möchtest, tippe sie an. Wenn du sie verschieben möchtest, zieh an ihr."</string>
<string name="bubbles_user_education_manage_title" msgid="7042699946735628035">"Bubble-Einstellungen festlegen"</string>
<string name="bubbles_user_education_manage" msgid="3460756219946517198">"Tippe auf \"Verwalten\", um Bubbles für diese App zu deaktivieren"</string>
- <!-- no translation found for bubbles_user_education_got_it (3382046149225428296) -->
- <skip />
+ <string name="bubbles_user_education_got_it" msgid="3382046149225428296">"OK"</string>
<string name="bubble_overflow_empty_title" msgid="2397251267073294968">"Keine kürzlich geschlossenen Bubbles"</string>
<string name="bubble_overflow_empty_subtitle" msgid="2627417924958633713">"Hier werden aktuelle und geschlossene Bubbles angezeigt"</string>
<string name="notification_bubble_title" msgid="6082910224488253378">"Bubble"</string>
diff --git a/libs/WindowManager/Shell/res/values-de/strings_tv.xml b/libs/WindowManager/Shell/res/values-de/strings_tv.xml
index 0432f1c353e4..02cce9d73647 100644
--- a/libs/WindowManager/Shell/res/values-de/strings_tv.xml
+++ b/libs/WindowManager/Shell/res/values-de/strings_tv.xml
@@ -17,8 +17,7 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <!-- no translation found for notification_channel_tv_pip (2576686079160402435) -->
- <skip />
+ <string name="notification_channel_tv_pip" msgid="2576686079160402435">"Bild im Bild"</string>
<string name="pip_notification_unknown_title" msgid="2729870284350772311">"(Kein Sendungsname gefunden)"</string>
<string name="pip_close" msgid="9135220303720555525">"PIP schließen"</string>
<string name="pip_fullscreen" msgid="7278047353591302554">"Vollbild"</string>
diff --git a/libs/WindowManager/Shell/res/values-ml/strings.xml b/libs/WindowManager/Shell/res/values-ml/strings.xml
index dfa4b2287b10..e675861166a3 100644
--- a/libs/WindowManager/Shell/res/values-ml/strings.xml
+++ b/libs/WindowManager/Shell/res/values-ml/strings.xml
@@ -28,8 +28,7 @@
<string name="pip_skip_to_next" msgid="8403429188794867653">"അടുത്തതിലേക്ക് പോകുക"</string>
<string name="pip_skip_to_prev" msgid="7172158111196394092">"മുമ്പത്തേതിലേക്ക് പോകുക"</string>
<string name="accessibility_action_pip_resize" msgid="4623966104749543182">"വലുപ്പം മാറ്റുക"</string>
- <!-- no translation found for dock_forced_resizable (1749750436092293116) -->
- <skip />
+ <string name="dock_forced_resizable" msgid="1749750436092293116">"സ്‌ക്രീൻ വിഭജന മോഡിൽ ആപ്പ് പ്രവർത്തിച്ചേക്കില്ല."</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>
@@ -44,14 +43,10 @@
<string name="accessibility_action_divider_top_50" msgid="8649582798829048946">"മുകളിൽ 50%"</string>
<string name="accessibility_action_divider_top_30" msgid="3572788224908570257">"മുകളിൽ 30%"</string>
<string name="accessibility_action_divider_bottom_full" msgid="2831868345092314060">"താഴെ പൂർണ്ണ സ്ക്രീൻ"</string>
- <!-- no translation found for one_handed_tutorial_title (4583241688067426350) -->
- <skip />
- <!-- no translation found for one_handed_tutorial_description (3486582858591353067) -->
- <skip />
- <!-- no translation found for accessibility_action_start_one_handed (5070337354072861426) -->
- <skip />
- <!-- no translation found for accessibility_action_stop_one_handed (1369940261782179442) -->
- <skip />
+ <string name="one_handed_tutorial_title" msgid="4583241688067426350">"ഒറ്റക്കൈ മോഡ് എങ്ങനെ ഉപയോഗിക്കാം"</string>
+ <string name="one_handed_tutorial_description" msgid="3486582858591353067">"പുറത്ത് കടക്കാൻ, സ്ക്രീനിന്റെ ചുവടെ നിന്ന് മുകളിലേക്ക് സ്വൈപ്പ് ചെയ്യുക അല്ലെങ്കിൽ ആപ്പിന് മുകളിലായി എവിടെയെങ്കിലും ടാപ്പ് ചെയ്യുക"</string>
+ <string name="accessibility_action_start_one_handed" msgid="5070337354072861426">"ഒറ്റക്കൈ മോഡ് ആരംഭിച്ചു"</string>
+ <string name="accessibility_action_stop_one_handed" msgid="1369940261782179442">"ഒറ്റക്കൈ മോഡിൽ നിന്ന് പുറത്തുകടക്കുക"</string>
<string name="bubbles_settings_button_description" msgid="1301286017420516912">"<xliff:g id="APP_NAME">%1$s</xliff:g> ബബിളുകളുടെ ക്രമീകരണം"</string>
<string name="bubble_overflow_button_content_description" msgid="8160974472718594382">"ഓവർഫ്ലോ"</string>
<string name="bubble_accessibility_action_add_back" msgid="1830101076853540953">"അടുക്കുകളിലേക്ക് തിരിച്ച് ചേർക്കുക"</string>
@@ -68,8 +63,7 @@
<string name="bubbles_user_education_description" msgid="4215862563054175407">"പുതിയ സംഭാഷണങ്ങൾ ഫ്ലോട്ടിംഗ് ഐക്കണുകളോ ബബിളുകളോ ആയി ദൃശ്യമാവുന്നു. ബബിൾ തുറക്കാൻ ടാപ്പ് ചെയ്യൂ. ഇത് നീക്കാൻ വലിച്ചിടുക."</string>
<string name="bubbles_user_education_manage_title" msgid="7042699946735628035">"ബബിളുകൾ ഏതുസമയത്തും നിയന്ത്രിക്കുക"</string>
<string name="bubbles_user_education_manage" msgid="3460756219946517198">"ഈ ആപ്പിൽ നിന്നുള്ള ബബിളുകൾ ഓഫാക്കാൻ മാനേജ് ചെയ്യുക ടാപ്പ് ചെയ്യുക"</string>
- <!-- no translation found for bubbles_user_education_got_it (3382046149225428296) -->
- <skip />
+ <string name="bubbles_user_education_got_it" msgid="3382046149225428296">"മനസ്സിലായി"</string>
<string name="bubble_overflow_empty_title" msgid="2397251267073294968">"അടുത്തിടെയുള്ള ബബിളുകൾ ഒന്നുമില്ല"</string>
<string name="bubble_overflow_empty_subtitle" msgid="2627417924958633713">"അടുത്തിടെയുള്ള ബബിളുകൾ, ഡിസ്മിസ് ചെയ്ത ബബിളുകൾ എന്നിവ ഇവിടെ ദൃശ്യമാവും"</string>
<string name="notification_bubble_title" msgid="6082910224488253378">"ബബ്ൾ"</string>
diff --git a/libs/WindowManager/Shell/res/values-ml/strings_tv.xml b/libs/WindowManager/Shell/res/values-ml/strings_tv.xml
index 7aaf79fb666e..c74e0bbfaa5b 100644
--- a/libs/WindowManager/Shell/res/values-ml/strings_tv.xml
+++ b/libs/WindowManager/Shell/res/values-ml/strings_tv.xml
@@ -17,8 +17,7 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <!-- no translation found for notification_channel_tv_pip (2576686079160402435) -->
- <skip />
+ <string name="notification_channel_tv_pip" msgid="2576686079160402435">"ചിത്രത്തിനുള്ളിൽ ചിത്രം"</string>
<string name="pip_notification_unknown_title" msgid="2729870284350772311">"(പേരില്ലാത്ത പ്രോഗ്രാം)"</string>
<string name="pip_close" msgid="9135220303720555525">"PIP അടയ്ക്കുക"</string>
<string name="pip_fullscreen" msgid="7278047353591302554">"പൂര്‍ണ്ണ സ്ക്രീന്‍"</string>
diff --git a/libs/WindowManager/Shell/res/values-ur/strings.xml b/libs/WindowManager/Shell/res/values-ur/strings.xml
index cd6529f0bf94..4b0adc640ddd 100644
--- a/libs/WindowManager/Shell/res/values-ur/strings.xml
+++ b/libs/WindowManager/Shell/res/values-ur/strings.xml
@@ -28,8 +28,7 @@
<string name="pip_skip_to_next" msgid="8403429188794867653">"نظرانداز کرکے اگلے پر جائیں"</string>
<string name="pip_skip_to_prev" msgid="7172158111196394092">"نظرانداز کرکے پچھلے پر جائیں"</string>
<string name="accessibility_action_pip_resize" msgid="4623966104749543182">"سائز تبدیل کریں"</string>
- <!-- no translation found for dock_forced_resizable (1749750436092293116) -->
- <skip />
+ <string name="dock_forced_resizable" msgid="1749750436092293116">"ممکن ہے کہ ایپ اسپلٹ اسکرین کے ساتھ کام نہ کرے۔"</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>
@@ -44,14 +43,10 @@
<string name="accessibility_action_divider_top_50" msgid="8649582798829048946">"اوپر %50"</string>
<string name="accessibility_action_divider_top_30" msgid="3572788224908570257">"اوپر %30"</string>
<string name="accessibility_action_divider_bottom_full" msgid="2831868345092314060">"نچلی فل اسکرین"</string>
- <!-- no translation found for one_handed_tutorial_title (4583241688067426350) -->
- <skip />
- <!-- no translation found for one_handed_tutorial_description (3486582858591353067) -->
- <skip />
- <!-- no translation found for accessibility_action_start_one_handed (5070337354072861426) -->
- <skip />
- <!-- no translation found for accessibility_action_stop_one_handed (1369940261782179442) -->
- <skip />
+ <string name="one_handed_tutorial_title" msgid="4583241688067426350">"ایک ہاتھ کی وضع کا استعمال کرنا"</string>
+ <string name="one_handed_tutorial_description" msgid="3486582858591353067">"باہر نکلنے کیلئے، اسکرین کے نیچے سے اوپر کی طرف سوائپ کریں یا ایپ کے اوپر کہیں بھی تھپتھپائیں"</string>
+ <string name="accessibility_action_start_one_handed" msgid="5070337354072861426">"ایک ہاتھ کی وضع شروع کریں"</string>
+ <string name="accessibility_action_stop_one_handed" msgid="1369940261782179442">"ایک ہاتھ کی وضع سے باہر نکلیں"</string>
<string name="bubbles_settings_button_description" msgid="1301286017420516912">"<xliff:g id="APP_NAME">%1$s</xliff:g> بلبلوں کے لیے ترتیبات"</string>
<string name="bubble_overflow_button_content_description" msgid="8160974472718594382">"اوورفلو"</string>
<string name="bubble_accessibility_action_add_back" msgid="1830101076853540953">"انبار میں واپس شامل کریں"</string>
@@ -68,8 +63,7 @@
<string name="bubbles_user_education_description" msgid="4215862563054175407">"نئی گفتگوئیں فلوٹنگ آئیکن یا بلبلے کے طور پر ظاہر ہوں گی۔ بلبلہ کھولنے کے لیے تھپتھپائیں۔ اسے منتقل کرنے کے لیے گھسیٹیں۔"</string>
<string name="bubbles_user_education_manage_title" msgid="7042699946735628035">"کسی بھی وقت بلبلے کو کنٹرول کریں"</string>
<string name="bubbles_user_education_manage" msgid="3460756219946517198">"اس ایپ سے بلبلوں کو آف کرنے کے لیے نظم کریں پر تھپتھپائیں"</string>
- <!-- no translation found for bubbles_user_education_got_it (3382046149225428296) -->
- <skip />
+ <string name="bubbles_user_education_got_it" msgid="3382046149225428296">"سمجھ آ گئی"</string>
<string name="bubble_overflow_empty_title" msgid="2397251267073294968">"کوئی حالیہ بلبلہ نہیں"</string>
<string name="bubble_overflow_empty_subtitle" msgid="2627417924958633713">"حالیہ بلبلے اور برخاست شدہ بلبلے یہاں ظاہر ہوں گے"</string>
<string name="notification_bubble_title" msgid="6082910224488253378">"بلبلہ"</string>
diff --git a/libs/WindowManager/Shell/res/values-ur/strings_tv.xml b/libs/WindowManager/Shell/res/values-ur/strings_tv.xml
index 64e5db5ae10a..317953309947 100644
--- a/libs/WindowManager/Shell/res/values-ur/strings_tv.xml
+++ b/libs/WindowManager/Shell/res/values-ur/strings_tv.xml
@@ -17,8 +17,7 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <!-- no translation found for notification_channel_tv_pip (2576686079160402435) -->
- <skip />
+ <string name="notification_channel_tv_pip" msgid="2576686079160402435">"تصویر میں تصویر"</string>
<string name="pip_notification_unknown_title" msgid="2729870284350772311">"(بلا عنوان پروگرام)"</string>
<string name="pip_close" msgid="9135220303720555525">"‏PIP بند کریں"</string>
<string name="pip_fullscreen" msgid="7278047353591302554">"فُل اسکرین"</string>
diff --git a/libs/WindowManager/Shell/res/values/config.xml b/libs/WindowManager/Shell/res/values/config.xml
index c913e0c441e5..f0eae97b107e 100644
--- a/libs/WindowManager/Shell/res/values/config.xml
+++ b/libs/WindowManager/Shell/res/values/config.xml
@@ -30,6 +30,12 @@
<!-- Animation duration when using long press on recents to dock -->
<integer name="long_press_dock_anim_duration">250</integer>
+ <!-- Animation duration for translating of one handed when trigger / dismiss. -->
+ <integer name="config_one_handed_translate_animation_duration">300</integer>
+
+ <!-- One handed mode default offset % of display size -->
+ <fraction name="config_one_handed_offset">40%</fraction>
+
<!-- Allow one handed to enable round corner -->
<bool name="config_one_handed_enable_round_corner">true</bool>
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedController.java
index f84936e5f386..e8c6cb74af0c 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedController.java
@@ -37,6 +37,7 @@ import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.VisibleForTesting;
+import com.android.wm.shell.R;
import com.android.wm.shell.common.DisplayChangeController;
import com.android.wm.shell.common.DisplayController;
import com.android.wm.shell.common.TaskStackListenerCallback;
@@ -205,8 +206,11 @@ public class OneHandedController implements OneHanded {
mGestureHandler = gestureHandler;
mOverlayManager = overlayManager;
- mOffSetFraction = SystemProperties.getInt(ONE_HANDED_MODE_OFFSET_PERCENTAGE, 50)
- / 100.0f;
+ final float offsetPercentageConfig = context.getResources().getFraction(
+ R.fraction.config_one_handed_offset, 1, 1);
+ final int sysPropPercentageConfig = SystemProperties.getInt(
+ ONE_HANDED_MODE_OFFSET_PERCENTAGE, Math.round(offsetPercentageConfig * 100.0f));
+ mOffSetFraction = sysPropPercentageConfig / 100.0f;
mIsOneHandedEnabled = OneHandedSettingsUtil.getSettingsOneHandedModeEnabled(
context.getContentResolver());
mIsSwipeToNotificationEnabled =
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedDisplayAreaOrganizer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedDisplayAreaOrganizer.java
index bd6c1e096d01..0311030890c4 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedDisplayAreaOrganizer.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedDisplayAreaOrganizer.java
@@ -40,6 +40,7 @@ import androidx.annotation.Nullable;
import androidx.annotation.VisibleForTesting;
import com.android.internal.os.SomeArgs;
+import com.android.wm.shell.R;
import com.android.wm.shell.common.DisplayController;
import java.io.PrintWriter;
@@ -156,8 +157,11 @@ public class OneHandedDisplayAreaOrganizer extends DisplayAreaOrganizer {
mDisplayController = displayController;
mDefaultDisplayBounds.set(getDisplayBounds());
mLastVisualDisplayBounds.set(getDisplayBounds());
+ final int animationDurationConfig = context.getResources().getInteger(
+ R.integer.config_one_handed_translate_animation_duration);
mEnterExitAnimationDurationMs =
- SystemProperties.getInt(ONE_HANDED_MODE_TRANSLATE_ANIMATION_DURATION, 300);
+ SystemProperties.getInt(ONE_HANDED_MODE_TRANSLATE_ANIMATION_DURATION,
+ animationDurationConfig);
mSurfaceControlTransactionFactory = SurfaceControl.Transaction::new;
mTutorialHandler = tutorialHandler;
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedTutorialHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedTutorialHandler.java
index b6b518d69c55..d65ad62cdbbb 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedTutorialHandler.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedTutorialHandler.java
@@ -86,8 +86,11 @@ public class OneHandedTutorialHandler implements OneHandedTransitionCallback {
context.getSystemService(Context.ACCESSIBILITY_SERVICE);
mTargetViewContainer = new FrameLayout(context);
mTargetViewContainer.setClipChildren(false);
- mTutorialAreaHeight = Math.round(mDisplaySize.y
- * (SystemProperties.getInt(ONE_HANDED_MODE_OFFSET_PERCENTAGE, 50) / 100.0f));
+ final float offsetPercentageConfig = context.getResources().getFraction(
+ R.fraction.config_one_handed_offset, 1, 1);
+ final int sysPropPercentageConfig = SystemProperties.getInt(
+ ONE_HANDED_MODE_OFFSET_PERCENTAGE, Math.round(offsetPercentageConfig * 100.0f));
+ mTutorialAreaHeight = Math.round(mDisplaySize.y * (sysPropPercentageConfig / 100.0f));
mTutorialView = LayoutInflater.from(context).inflate(R.layout.one_handed_tutorial, null);
mTargetViewContainer.addView(mTutorialView);
mCanShowTutorial = (Settings.Secure.getInt(mContentResolver,
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipBoundsState.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipBoundsState.java
index ce1139b4264d..53aa61477483 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipBoundsState.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipBoundsState.java
@@ -59,42 +59,39 @@ public final class PipBoundsState {
private final @NonNull Rect mExpandedBounds = new Rect();
private final @NonNull Rect mNormalMovementBounds = new Rect();
private final @NonNull Rect mExpandedMovementBounds = new Rect();
- private final Context mContext;
+ private final @NonNull Context mContext;
private float mAspectRatio;
private int mStashedState = STASH_TYPE_NONE;
private int mStashOffset;
- private PipReentryState mPipReentryState;
- private ComponentName mLastPipComponentName;
- private final DisplayInfo mDisplayInfo = new DisplayInfo();
- private final DisplayLayout mDisplayLayout = new DisplayLayout();
+ private @Nullable PipReentryState mPipReentryState;
+ private @Nullable ComponentName mLastPipComponentName;
+ private final @NonNull DisplayInfo mDisplayInfo = new DisplayInfo();
+ private final @NonNull DisplayLayout mDisplayLayout = new DisplayLayout();
/** The current minimum edge size of PIP. */
private int mMinEdgeSize;
/** The preferred minimum (and default) size specified by apps. */
- private Size mOverrideMinSize;
- private final @NonNull AnimatingBoundsState mAnimatingBoundsState = new AnimatingBoundsState();
+ private @Nullable Size mOverrideMinSize;
+ private final @NonNull MotionBoundsState mMotionBoundsState = new MotionBoundsState();
private boolean mIsImeShowing;
private int mImeHeight;
private boolean mIsShelfShowing;
private int mShelfHeight;
- private Runnable mOnMinimalSizeChangeCallback;
- private BiConsumer<Boolean, Integer> mOnShelfVisibilityChangeCallback;
+ private @Nullable Runnable mOnMinimalSizeChangeCallback;
+ private @Nullable BiConsumer<Boolean, Integer> mOnShelfVisibilityChangeCallback;
- public PipBoundsState(Context context) {
+ public PipBoundsState(@NonNull Context context) {
mContext = context;
reloadResources();
}
- /**
- * Reloads the resources.
- */
+ /** Reloads the resources. */
public void onConfigurationChanged() {
reloadResources();
}
private void reloadResources() {
- mStashOffset = mContext.getResources()
- .getDimensionPixelSize(R.dimen.pip_stash_offset);
+ mStashOffset = mContext.getResources().getDimensionPixelSize(R.dimen.pip_stash_offset);
}
/** Set the current PIP bounds. */
@@ -102,12 +99,14 @@ public final class PipBoundsState {
mBounds.set(bounds);
}
+ /** Get the current PIP bounds. */
@NonNull
public Rect getBounds() {
return new Rect(mBounds);
}
/** Returns the current movement bounds. */
+ @NonNull
public Rect getMovementBounds() {
return mMovementBounds;
}
@@ -135,28 +134,28 @@ public final class PipBoundsState {
}
/** Set the normal movement bounds. */
- public void setNormalMovementBounds(Rect bounds) {
+ public void setNormalMovementBounds(@NonNull Rect bounds) {
mNormalMovementBounds.set(bounds);
}
/** Returns the normal movement bounds. */
+ @NonNull
public Rect getNormalMovementBounds() {
return mNormalMovementBounds;
}
/** Set the expanded movement bounds. */
- public void setExpandedMovementBounds(Rect bounds) {
+ public void setExpandedMovementBounds(@NonNull Rect bounds) {
mExpandedMovementBounds.set(bounds);
}
/** Returns the expanded movement bounds. */
+ @NonNull
public Rect getExpandedMovementBounds() {
return mExpandedMovementBounds;
}
- /**
- * Dictate where PiP currently should be stashed, if at all.
- */
+ /** Dictate where PiP currently should be stashed, if at all. */
public void setStashed(@StashType int stashedState) {
mStashedState = stashedState;
}
@@ -169,50 +168,39 @@ public final class PipBoundsState {
return mStashedState;
}
- /**
- * Whether PiP is stashed or not.
- */
+ /** Whether PiP is stashed or not. */
public boolean isStashed() {
return mStashedState != STASH_TYPE_NONE;
}
- /**
- * Returns the offset from the edge of the screen for PiP stash.
- */
+ /** Returns the offset from the edge of the screen for PiP stash. */
public int getStashOffset() {
return mStashOffset;
}
+ /** Set the PIP aspect ratio. */
public void setAspectRatio(float aspectRatio) {
mAspectRatio = aspectRatio;
}
+ /** Get the PIP aspect ratio. */
public float getAspectRatio() {
return mAspectRatio;
}
- /**
- * Save the reentry state to restore to when re-entering PIP mode.
- *
- * TODO(b/169373982): consider refactoring this so that this class alone can use mBounds and
- * calculate the snap fraction to save for re-entry.
- */
+ /** Save the reentry state to restore to when re-entering PIP mode. */
public void saveReentryState(@NonNull Rect bounds, float fraction) {
mPipReentryState = new PipReentryState(new Size(bounds.width(), bounds.height()), fraction);
}
- /**
- * Returns the saved reentry state.
- */
+ /** Returns the saved reentry state. */
@Nullable
public PipReentryState getReentryState() {
return mPipReentryState;
}
- /**
- * Set the last {@link ComponentName} to enter PIP mode.
- */
- public void setLastPipComponentName(ComponentName lastPipComponentName) {
+ /** Set the last {@link ComponentName} to enter PIP mode. */
+ public void setLastPipComponentName(@Nullable ComponentName lastPipComponentName) {
final boolean changed = !Objects.equals(mLastPipComponentName, lastPipComponentName);
mLastPipComponentName = lastPipComponentName;
if (changed) {
@@ -220,41 +208,40 @@ public final class PipBoundsState {
}
}
+ /** Get the last PIP component name, if any. */
+ @Nullable
public ComponentName getLastPipComponentName() {
return mLastPipComponentName;
}
+ /** Get the current display info. */
@NonNull
public DisplayInfo getDisplayInfo() {
return mDisplayInfo;
}
- /**
- * Update the display info.
- */
+ /** Update the display info. */
public void setDisplayInfo(@NonNull DisplayInfo displayInfo) {
mDisplayInfo.copyFrom(displayInfo);
}
+ /** Set the rotation of the display. */
public void setDisplayRotation(int rotation) {
mDisplayInfo.rotation = rotation;
}
- /**
- * Returns the display's bound.
- */
+ /** Returns the display's bounds. */
@NonNull
public Rect getDisplayBounds() {
return new Rect(0, 0, mDisplayInfo.logicalWidth, mDisplayInfo.logicalHeight);
}
- /**
- * Update the display layout.
- */
+ /** Update the display layout. */
public void setDisplayLayout(@NonNull DisplayLayout displayLayout) {
mDisplayLayout.set(displayLayout);
}
+ /** Get the display layout. */
@NonNull
public DisplayLayout getDisplayLayout() {
return mDisplayLayout;
@@ -275,10 +262,8 @@ public final class PipBoundsState {
return mMinEdgeSize;
}
- /**
- * Sets the preferred size of PIP as specified by the activity in PIP mode.
- */
- public void setOverrideMinSize(Size overrideMinSize) {
+ /** Sets the preferred size of PIP as specified by the activity in PIP mode. */
+ public void setOverrideMinSize(@Nullable Size overrideMinSize) {
final boolean changed = !Objects.equals(overrideMinSize, mOverrideMinSize);
mOverrideMinSize = overrideMinSize;
if (changed && mOnMinimalSizeChangeCallback != null) {
@@ -287,6 +272,7 @@ public final class PipBoundsState {
}
/** Returns the preferred minimal size specified by the activity in PIP. */
+ @Nullable
public Size getOverrideMinSize() {
return mOverrideMinSize;
}
@@ -297,8 +283,10 @@ public final class PipBoundsState {
return Math.min(mOverrideMinSize.getWidth(), mOverrideMinSize.getHeight());
}
- public AnimatingBoundsState getAnimatingBoundsState() {
- return mAnimatingBoundsState;
+ /** Get the state of the bounds in motion. */
+ @NonNull
+ public MotionBoundsState getMotionBoundsState() {
+ return mMotionBoundsState;
}
/** Set whether the IME is currently showing and its height. */
@@ -344,41 +332,41 @@ public final class PipBoundsState {
/**
* Registers a callback when the minimal size of PIP that is set by the app changes.
*/
- public void setOnMinimalSizeChangeCallback(Runnable onMinimalSizeChangeCallback) {
+ public void setOnMinimalSizeChangeCallback(@Nullable Runnable onMinimalSizeChangeCallback) {
mOnMinimalSizeChangeCallback = onMinimalSizeChangeCallback;
}
/** Set a callback to be notified when the shelf visibility changes. */
public void setOnShelfVisibilityChangeCallback(
- BiConsumer<Boolean, Integer> onShelfVisibilityChangeCallback) {
+ @Nullable BiConsumer<Boolean, Integer> onShelfVisibilityChangeCallback) {
mOnShelfVisibilityChangeCallback = onShelfVisibilityChangeCallback;
}
- /** Source of truth for the current animation bounds of PIP. */
- public static class AnimatingBoundsState {
- /** The bounds used when PIP is being dragged or animated. */
- private final Rect mTemporaryBounds = new Rect();
+ /** Source of truth for the current bounds of PIP that may be in motion. */
+ public static class MotionBoundsState {
+ /** The bounds used when PIP is in motion (e.g. during a drag or animation) */
+ private final @NonNull Rect mBoundsInMotion = new Rect();
/** The destination bounds to which PIP is animating. */
- private final Rect mAnimatingToBounds = new Rect();
+ private final @NonNull Rect mAnimatingToBounds = new Rect();
/** Whether PIP is being dragged or animated (e.g. resizing, in fling, etc). */
- public boolean isAnimating() {
- return !mTemporaryBounds.isEmpty();
+ public boolean isInMotion() {
+ return !mBoundsInMotion.isEmpty();
}
/** Set the temporary bounds used to represent the drag or animation bounds of PIP. */
- public void setTemporaryBounds(Rect bounds) {
- mTemporaryBounds.set(bounds);
+ public void setBoundsInMotion(@NonNull Rect bounds) {
+ mBoundsInMotion.set(bounds);
}
/** Set the bounds to which PIP is animating. */
- public void setAnimatingToBounds(Rect bounds) {
+ public void setAnimatingToBounds(@NonNull Rect bounds) {
mAnimatingToBounds.set(bounds);
}
- /** Called when all ongoing dragging and animation operations have ended. */
+ /** Called when all ongoing motion operations have ended. */
public void onAllAnimationsEnded() {
- mTemporaryBounds.setEmpty();
+ mBoundsInMotion.setEmpty();
}
/** Called when an ongoing physics animation has ended. */
@@ -386,20 +374,22 @@ public final class PipBoundsState {
mAnimatingToBounds.setEmpty();
}
- /** Returns the temporary animation bounds. */
- public Rect getTemporaryBounds() {
- return mTemporaryBounds;
+ /** Returns the motion bounds. */
+ @NonNull
+ public Rect getBoundsInMotion() {
+ return mBoundsInMotion;
}
/** Returns the destination bounds to which PIP is currently animating. */
+ @NonNull
public Rect getAnimatingToBounds() {
return mAnimatingToBounds;
}
void dump(PrintWriter pw, String prefix) {
final String innerPrefix = prefix + " ";
- pw.println(prefix + AnimatingBoundsState.class.getSimpleName());
- pw.println(innerPrefix + "mTemporaryBounds=" + mTemporaryBounds);
+ pw.println(prefix + MotionBoundsState.class.getSimpleName());
+ pw.println(innerPrefix + "mBoundsInMotion=" + mBoundsInMotion);
pw.println(innerPrefix + "mAnimatingToBounds=" + mAnimatingToBounds);
}
}
@@ -432,9 +422,7 @@ public final class PipBoundsState {
}
}
- /**
- * Dumps internal state.
- */
+ /** Dumps internal state. */
public void dump(PrintWriter pw, String prefix) {
final String innerPrefix = prefix + " ";
pw.println(prefix + TAG);
@@ -461,6 +449,6 @@ public final class PipBoundsState {
} else {
mPipReentryState.dump(pw, innerPrefix);
}
- mAnimatingBoundsState.dump(pw, innerPrefix);
+ mMotionBoundsState.dump(pw, innerPrefix);
}
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipMotionHelper.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipMotionHelper.java
index 8fa944886905..903f7d773896 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipMotionHelper.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipMotionHelper.java
@@ -90,7 +90,7 @@ public class PipMotionHelper implements PipAppOpsListener.Callback,
});
/**
- * PhysicsAnimator instance for animating {@link PipBoundsState#getAnimatingBoundsState()}
+ * PhysicsAnimator instance for animating {@link PipBoundsState#getMotionBoundsState()}
* using physics animations.
*/
private final PhysicsAnimator<Rect> mTemporaryBoundsPhysicsAnimator;
@@ -98,7 +98,7 @@ public class PipMotionHelper implements PipAppOpsListener.Callback,
private MagnetizedObject<Rect> mMagnetizedPip;
/**
- * Update listener that resizes the PIP to {@link PipBoundsState#getAnimatingBoundsState()}.
+ * Update listener that resizes the PIP to {@link PipBoundsState#getMotionBoundsState()}.
*/
private final PhysicsAnimator.UpdateListener<Rect> mResizePipUpdateListener;
@@ -172,14 +172,14 @@ public class PipMotionHelper implements PipAppOpsListener.Callback,
mFloatingContentCoordinator = floatingContentCoordinator;
mPipTaskOrganizer.registerPipTransitionCallback(mPipTransitionCallback);
mTemporaryBoundsPhysicsAnimator = PhysicsAnimator.getInstance(
- mPipBoundsState.getAnimatingBoundsState().getTemporaryBounds());
+ mPipBoundsState.getMotionBoundsState().getBoundsInMotion());
mTemporaryBoundsPhysicsAnimator.setCustomAnimationHandler(
mSfAnimationHandlerThreadLocal.get());
mResizePipUpdateListener = (target, values) -> {
- if (mPipBoundsState.getAnimatingBoundsState().isAnimating()) {
+ if (mPipBoundsState.getMotionBoundsState().isInMotion()) {
mPipTaskOrganizer.scheduleUserResizePip(getBounds(),
- mPipBoundsState.getAnimatingBoundsState().getTemporaryBounds(), null);
+ mPipBoundsState.getMotionBoundsState().getBoundsInMotion(), null);
}
};
}
@@ -187,8 +187,8 @@ public class PipMotionHelper implements PipAppOpsListener.Callback,
@NonNull
@Override
public Rect getFloatingBoundsOnScreen() {
- return !mPipBoundsState.getAnimatingBoundsState().getAnimatingToBounds().isEmpty()
- ? mPipBoundsState.getAnimatingBoundsState().getAnimatingToBounds() : getBounds();
+ return !mPipBoundsState.getMotionBoundsState().getAnimatingToBounds().isEmpty()
+ ? mPipBoundsState.getMotionBoundsState().getAnimatingToBounds() : getBounds();
}
@NonNull
@@ -207,7 +207,7 @@ public class PipMotionHelper implements PipAppOpsListener.Callback,
*/
void synchronizePinnedStackBounds() {
cancelPhysicsAnimation();
- mPipBoundsState.getAnimatingBoundsState().onAllAnimationsEnded();
+ mPipBoundsState.getMotionBoundsState().onAllAnimationsEnded();
if (mPipTaskOrganizer.isInPip()) {
mFloatingContentCoordinator.onContentMoved(this);
@@ -242,7 +242,7 @@ public class PipMotionHelper implements PipAppOpsListener.Callback,
resizePipUnchecked(toBounds);
mPipBoundsState.setBounds(toBounds);
} else {
- mPipBoundsState.getAnimatingBoundsState().setTemporaryBounds(toBounds);
+ mPipBoundsState.getMotionBoundsState().setBoundsInMotion(toBounds);
mPipTaskOrganizer.scheduleUserResizePip(getBounds(), toBounds,
(Rect newBounds) -> {
mMainHandler.post(() -> {
@@ -278,8 +278,8 @@ public class PipMotionHelper implements PipAppOpsListener.Callback,
// If we're already in the dismiss target area, then there won't be a move to set the
// temporary bounds, so just initialize it to the current bounds.
- if (!mPipBoundsState.getAnimatingBoundsState().isAnimating()) {
- mPipBoundsState.getAnimatingBoundsState().setTemporaryBounds(getBounds());
+ if (!mPipBoundsState.getMotionBoundsState().isInMotion()) {
+ mPipBoundsState.getMotionBoundsState().setBoundsInMotion(getBounds());
}
mTemporaryBoundsPhysicsAnimator
.spring(FloatProperties.RECT_X, destinationX, velX, mSpringConfig)
@@ -396,7 +396,7 @@ public class PipMotionHelper implements PipAppOpsListener.Callback,
final float xEndValue = velocityX < 0 ? leftEdge : rightEdge;
- final int startValueY = mPipBoundsState.getAnimatingBoundsState().getTemporaryBounds().top;
+ final int startValueY = mPipBoundsState.getMotionBoundsState().getBoundsInMotion().top;
final float estimatedFlingYEndValue =
PhysicsAnimator.estimateFlingEndValue(startValueY, velocityY, mFlingConfigY);
@@ -411,7 +411,7 @@ public class PipMotionHelper implements PipAppOpsListener.Callback,
void animateToBounds(Rect bounds, PhysicsAnimator.SpringConfig springConfig) {
if (!mTemporaryBoundsPhysicsAnimator.isRunning()) {
// Animate from the current bounds if we're not already animating.
- mPipBoundsState.getAnimatingBoundsState().setTemporaryBounds(getBounds());
+ mPipBoundsState.getMotionBoundsState().setBoundsInMotion(getBounds());
}
mTemporaryBoundsPhysicsAnimator
@@ -492,7 +492,7 @@ public class PipMotionHelper implements PipAppOpsListener.Callback,
*/
private void cancelPhysicsAnimation() {
mTemporaryBoundsPhysicsAnimator.cancel();
- mPipBoundsState.getAnimatingBoundsState().onPhysicsAnimationEnded();
+ mPipBoundsState.getMotionBoundsState().onPhysicsAnimationEnded();
mSpringingToTouch = false;
}
@@ -565,17 +565,17 @@ public class PipMotionHelper implements PipAppOpsListener.Callback,
if (!mDismissalPending
&& !mSpringingToTouch
&& !mMagnetizedPip.getObjectStuckToTarget()) {
- // All animations (including dragging) have actually finished.
+ // All motion operations have actually finished.
mPipBoundsState.setBounds(
- mPipBoundsState.getAnimatingBoundsState().getTemporaryBounds());
- mPipBoundsState.getAnimatingBoundsState().onAllAnimationsEnded();
+ mPipBoundsState.getMotionBoundsState().getBoundsInMotion());
+ mPipBoundsState.getMotionBoundsState().onAllAnimationsEnded();
if (!mDismissalPending) {
// do not schedule resize if PiP is dismissing, which may cause app re-open to
// mBounds instead of it's normal bounds.
mPipTaskOrganizer.scheduleFinishResizePip(getBounds());
}
}
- mPipBoundsState.getAnimatingBoundsState().onPhysicsAnimationEnded();
+ mPipBoundsState.getMotionBoundsState().onPhysicsAnimationEnded();
mSpringingToTouch = false;
mDismissalPending = false;
}
@@ -586,7 +586,7 @@ public class PipMotionHelper implements PipAppOpsListener.Callback,
* {@link FloatingContentCoordinator.FloatingContent#getFloatingBoundsOnScreen()}.
*/
private void setAnimatingToBounds(Rect bounds) {
- mPipBoundsState.getAnimatingBoundsState().setAnimatingToBounds(bounds);
+ mPipBoundsState.getMotionBoundsState().setAnimatingToBounds(bounds);
mFloatingContentCoordinator.onContentMoved(this);
}
@@ -625,7 +625,7 @@ public class PipMotionHelper implements PipAppOpsListener.Callback,
MagnetizedObject<Rect> getMagnetizedPip() {
if (mMagnetizedPip == null) {
mMagnetizedPip = new MagnetizedObject<Rect>(
- mContext, mPipBoundsState.getAnimatingBoundsState().getTemporaryBounds(),
+ mContext, mPipBoundsState.getMotionBoundsState().getBoundsInMotion(),
FloatProperties.RECT_X, FloatProperties.RECT_Y) {
@Override
public float getWidth(@NonNull Rect animatedPipBounds) {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipTouchHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipTouchHandler.java
index 48fa2115305d..a78c4ecdb39f 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipTouchHandler.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipTouchHandler.java
@@ -706,7 +706,7 @@ public class PipTouchHandler {
return;
}
- Rect bounds = getPossiblyAnimatingBounds();
+ Rect bounds = getPossiblyMotionBounds();
mDelta.set(0f, 0f);
mStartPosition.set(bounds.left, bounds.top);
mMovementWithinDismiss = touchState.getDownTouchPosition().y
@@ -745,7 +745,7 @@ public class PipTouchHandler {
mDelta.x += left - lastX;
mDelta.y += top - lastY;
- mTmpBounds.set(getPossiblyAnimatingBounds());
+ mTmpBounds.set(getPossiblyMotionBounds());
mTmpBounds.offsetTo((int) left, (int) top);
mMotionHelper.movePip(mTmpBounds, true /* isDragging */);
@@ -895,12 +895,12 @@ public class PipTouchHandler {
}
/**
- * Returns the PIP bounds if we're not animating, or the current, temporary animating bounds
- * otherwise.
+ * Returns the PIP bounds if we're not in the middle of a motion operation, or the current,
+ * temporary motion bounds otherwise.
*/
- Rect getPossiblyAnimatingBounds() {
- return mPipBoundsState.getAnimatingBoundsState().isAnimating()
- ? mPipBoundsState.getAnimatingBoundsState().getTemporaryBounds()
+ Rect getPossiblyMotionBounds() {
+ return mPipBoundsState.getMotionBoundsState().isInMotion()
+ ? mPipBoundsState.getMotionBoundsState().getBoundsInMotion()
: mPipBoundsState.getBounds();
}
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/apppairs/AppPairsTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/apppairs/AppPairsTest.kt
index c33dbbc3f53a..2fc6944a3a5f 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/apppairs/AppPairsTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/apppairs/AppPairsTest.kt
@@ -70,8 +70,8 @@ class AppPairsTest(
eachRun {
executeShellCommand(composePairsCommand(
primaryTaskId, secondaryTaskId, false /* pair */))
- primaryApp.forceStop()
- secondaryApp.forceStop()
+ primaryApp.exit()
+ secondaryApp.exit()
}
}
assertions {
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/helpers/BaseAppHelper.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/helpers/BaseAppHelper.kt
index 6f008ce64fb4..22496a506e0d 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/helpers/BaseAppHelper.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/helpers/BaseAppHelper.kt
@@ -16,7 +16,6 @@
package com.android.wm.shell.flicker.helpers
-import android.app.ActivityManager
import android.app.Instrumentation
import android.content.ComponentName
import android.content.Context
@@ -46,9 +45,6 @@ abstract class BaseAppHelper(
protected val context: Context
get() = mInstrumentation.context
- private val activityManager: ActivityManager?
- get() = context.getSystemService(ActivityManager::class.java)
-
private val appSelector = By.pkg(packageName).depth(0)
protected val isTelevision: Boolean
@@ -77,10 +73,6 @@ abstract class BaseAppHelper(
return uiDevice.wait(Until.gone(appSelector), APP_CLOSE_WAIT_TIME_MS)
}
- fun forceStop() {
- activityManager?.forceStopPackage(packageName)
- }
-
override fun getOpenAppIntent(): Intent {
val intent = Intent()
intent.component = launcherActivityComponent
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipKeyboardTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipKeyboardTest.kt
index 3813d4dc3700..abb8fc52abbb 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipKeyboardTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipKeyboardTest.kt
@@ -76,12 +76,12 @@ class PipKeyboardTest(
}
teardown {
test {
- keyboardApp.forceStop()
+ keyboardApp.exit()
if (device.hasPipWindow()) {
device.closePipWindow()
}
- testApp.forceStop()
+ testApp.exit()
this.setRotation(Surface.ROTATION_0)
}
}
@@ -210,4 +210,4 @@ class PipKeyboardTest(
return supportedRotations.map { arrayOf(Surface.rotationToString(it), it) }
}
}
-} \ No newline at end of file
+}
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/tv/TvPipTestBase.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/tv/TvPipTestBase.kt
index d1906ba2e27e..251bc064352d 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/tv/TvPipTestBase.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/tv/TvPipTestBase.kt
@@ -53,7 +53,7 @@ abstract class TvPipTestBase : PipTestBase(rotationToString(ROTATION_0), ROTATIO
open fun tearDown() {
if (!isTelevision) return
- testApp.forceStop()
+ testApp.exit()
// Wait for 1 second, and check if the SystemUI has been alive and well since the start.
SystemClock.sleep(AFTER_TEXT_PROCESS_CHECK_DELAY)
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/EnterSplitScreenTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/EnterSplitScreenTest.kt
index 6e10f932c745..a0056dfc0948 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/EnterSplitScreenTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/EnterSplitScreenTest.kt
@@ -60,8 +60,8 @@ class EnterSplitScreenTest(
}
teardown {
eachRun {
- splitScreenApp.forceStop()
- secondaryApp.forceStop()
+ splitScreenApp.exit()
+ secondaryApp.exit()
}
}
assertions {
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/ExitSplitScreenTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/ExitSplitScreenTest.kt
index 17fc862fffec..32e112dbd598 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/ExitSplitScreenTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/ExitSplitScreenTest.kt
@@ -65,8 +65,8 @@ class ExitSplitScreenTest(
}
teardown {
eachRun {
- splitScreenApp.forceStop()!!
- secondaryApp.forceStop()!!
+ splitScreenApp.exit()
+ secondaryApp.exit()
}
}
}
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/PipBoundsStateTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/PipBoundsStateTest.java
index 59e10c189046..4bcca06b592f 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/PipBoundsStateTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/PipBoundsStateTest.java
@@ -135,4 +135,38 @@ public class PipBoundsStateTest extends ShellTestCase {
verify(callback, never()).accept(true, 100);
}
+
+ @Test
+ public void testSetOverrideMinSize_changed_callbackInvoked() {
+ final Runnable callback = mock(Runnable.class);
+ mPipBoundsState.setOverrideMinSize(new Size(5, 5));
+ mPipBoundsState.setOnMinimalSizeChangeCallback(callback);
+
+ mPipBoundsState.setOverrideMinSize(new Size(10, 10));
+
+ verify(callback).run();
+ }
+
+ @Test
+ public void testSetOverrideMinSize_notChanged_callbackNotInvoked() {
+ final Runnable callback = mock(Runnable.class);
+ mPipBoundsState.setOverrideMinSize(new Size(5, 5));
+ mPipBoundsState.setOnMinimalSizeChangeCallback(callback);
+
+ mPipBoundsState.setOverrideMinSize(new Size(5, 5));
+
+ verify(callback, never()).run();
+ }
+
+ @Test
+ public void testGetOverrideMinEdgeSize() {
+ mPipBoundsState.setOverrideMinSize(null);
+ assertEquals(0, mPipBoundsState.getOverrideMinEdgeSize());
+
+ mPipBoundsState.setOverrideMinSize(new Size(5, 10));
+ assertEquals(5, mPipBoundsState.getOverrideMinEdgeSize());
+
+ mPipBoundsState.setOverrideMinSize(new Size(15, 10));
+ assertEquals(10, mPipBoundsState.getOverrideMinEdgeSize());
+ }
}
diff --git a/libs/androidfw/AssetManager2.cpp b/libs/androidfw/AssetManager2.cpp
index 8c2a632b9fd7..a545b3d5e134 100644
--- a/libs/androidfw/AssetManager2.cpp
+++ b/libs/androidfw/AssetManager2.cpp
@@ -1041,7 +1041,9 @@ base::expected<const ResolvedBag*, NullOrIOError> AssetManager2::ResolveBag(
base::expected<const ResolvedBag*, NullOrIOError> AssetManager2::GetBag(uint32_t resid) const {
std::vector<uint32_t> found_resids;
- return GetBag(resid, found_resids);
+ const auto bag = GetBag(resid, found_resids);
+ cached_bag_resid_stacks_.emplace(resid, found_resids);
+ return bag;
}
base::expected<const ResolvedBag*, NullOrIOError> AssetManager2::GetBag(
diff --git a/libs/hwui/jni/Typeface.cpp b/libs/hwui/jni/Typeface.cpp
index b88ffa6e79b8..a2964d6627a1 100644
--- a/libs/hwui/jni/Typeface.cpp
+++ b/libs/hwui/jni/Typeface.cpp
@@ -94,13 +94,27 @@ static jint Typeface_getWeight(CRITICAL_JNI_PARAMS_COMMA jlong faceHandle) {
}
static jlong Typeface_createFromArray(JNIEnv *env, jobject, jlongArray familyArray,
- int weight, int italic) {
+ jlong fallbackPtr, int weight, int italic) {
ScopedLongArrayRO families(env, familyArray);
std::vector<std::shared_ptr<minikin::FontFamily>> familyVec;
- familyVec.reserve(families.size());
- for (size_t i = 0; i < families.size(); i++) {
- FontFamilyWrapper* family = reinterpret_cast<FontFamilyWrapper*>(families[i]);
- familyVec.emplace_back(family->family);
+ Typeface* typeface = (fallbackPtr == 0) ? nullptr : toTypeface(fallbackPtr);
+ if (typeface != nullptr) {
+ const std::vector<std::shared_ptr<minikin::FontFamily>>& fallbackFamilies =
+ toTypeface(fallbackPtr)->fFontCollection->getFamilies();
+ familyVec.reserve(families.size() + fallbackFamilies.size());
+ for (size_t i = 0; i < families.size(); i++) {
+ FontFamilyWrapper* family = reinterpret_cast<FontFamilyWrapper*>(families[i]);
+ familyVec.emplace_back(family->family);
+ }
+ for (size_t i = 0; i < fallbackFamilies.size(); i++) {
+ familyVec.emplace_back(fallbackFamilies[i]);
+ }
+ } else {
+ familyVec.reserve(families.size());
+ for (size_t i = 0; i < families.size(); i++) {
+ FontFamilyWrapper* family = reinterpret_cast<FontFamilyWrapper*>(families[i]);
+ familyVec.emplace_back(family->family);
+ }
}
return toJLong(Typeface::createFromFamilies(std::move(familyVec), weight, italic));
}
@@ -145,6 +159,13 @@ static std::function<std::shared_ptr<minikin::MinikinFont>()> readMinikinFontSki
return [fontPath, fontIndex, axesPtr, axesCount]() -> std::shared_ptr<minikin::MinikinFont> {
std::string path(fontPath.data(), fontPath.size());
sk_sp<SkData> data = SkData::MakeFromFileName(path.c_str());
+ if (data == nullptr) {
+ // This may happen if:
+ // 1. When the process failed to open the file (e.g. invalid path or permission).
+ // 2. When the process failed to map the file (e.g. hitting max_map_count limit).
+ ALOGE("Failed to make SkData from file name: %s", path.c_str());
+ return nullptr;
+ }
const void* fontPtr = data->data();
size_t fontSize = data->size();
std::vector<minikin::FontVariation> axes(axesPtr, axesPtr + axesCount);
@@ -243,7 +264,7 @@ static const JNINativeMethod gTypefaceMethods[] = {
{ "nativeGetReleaseFunc", "()J", (void*)Typeface_getReleaseFunc },
{ "nativeGetStyle", "(J)I", (void*)Typeface_getStyle },
{ "nativeGetWeight", "(J)I", (void*)Typeface_getWeight },
- { "nativeCreateFromArray", "([JII)J",
+ { "nativeCreateFromArray", "([JJII)J",
(void*)Typeface_createFromArray },
{ "nativeSetDefault", "(J)V", (void*)Typeface_setDefault },
{ "nativeGetSupportedAxes", "(J)[I", (void*)Typeface_getSupportedAxes },
diff --git a/location/java/android/location/util/identity/CallerIdentity.java b/location/java/android/location/util/identity/CallerIdentity.java
index e023aa1dcd22..9dbdedeb8a03 100644
--- a/location/java/android/location/util/identity/CallerIdentity.java
+++ b/location/java/android/location/util/identity/CallerIdentity.java
@@ -150,8 +150,8 @@ public final class CallerIdentity {
return mListenerId;
}
- /** Returns true if this represents a system identity. */
- public boolean isSystem() {
+ /** Returns true if this represents a system server identity. */
+ public boolean isSystemServer() {
return mUid == Process.SYSTEM_UID;
}
diff --git a/media/java/android/media/MediaPlayer.java b/media/java/android/media/MediaPlayer.java
index 973c2a82c549..4b11e3231aba 100644
--- a/media/java/android/media/MediaPlayer.java
+++ b/media/java/android/media/MediaPlayer.java
@@ -4237,14 +4237,14 @@ public class MediaPlayer extends PlayerBase
* @hide
*/
@SystemApi
- @RequiresPermission("android.permission.BIND_IMS_SERVICE")
+ @RequiresPermission(BIND_IMS_SERVICE)
public void setOnRtpRxNoticeListener(
@NonNull Context context,
@NonNull OnRtpRxNoticeListener listener, @Nullable Handler handler) {
Objects.requireNonNull(context);
Preconditions.checkArgument(
context.checkSelfPermission(BIND_IMS_SERVICE) == PERMISSION_GRANTED,
- "android.permission.BIND_IMS_SERVICE permission not granted.");
+ BIND_IMS_SERVICE + " permission not granted.");
mOnRtpRxNoticeListener = Objects.requireNonNull(listener);
mOnRtpRxNoticeHandler = handler;
}
diff --git a/media/java/android/media/Rating.java b/media/java/android/media/Rating.java
index be752583eae5..4da23a1319af 100644
--- a/media/java/android/media/Rating.java
+++ b/media/java/android/media/Rating.java
@@ -206,11 +206,12 @@ public final class Rating implements Parcelable {
Log.e(TAG, "Invalid rating style (" + starRatingStyle + ") for a star rating");
return null;
}
- if ((starRating < 0.0f) || (starRating > maxRating)) {
+ if (starRating >= 0.0f && starRating <= maxRating) {
+ return new Rating(starRatingStyle, starRating);
+ } else {
Log.e(TAG, "Trying to set out of range star-based rating");
return null;
}
- return new Rating(starRatingStyle, starRating);
}
/**
@@ -221,11 +222,11 @@ public final class Rating implements Parcelable {
* @return null if the rating is out of range, a new Rating instance otherwise.
*/
public static Rating newPercentageRating(float percent) {
- if ((percent < 0.0f) || (percent > 100.0f)) {
+ if (percent >= 0.0f && percent <= 100.0f) {
+ return new Rating(RATING_PERCENTAGE, percent);
+ } else {
Log.e(TAG, "Invalid percentage-based rating value");
return null;
- } else {
- return new Rating(RATING_PERCENTAGE, percent);
}
}
diff --git a/media/java/android/media/tv/tuner/Descrambler.java b/media/java/android/media/tv/tuner/Descrambler.java
index 5f79dc52a2f1..2217eb3a1dc1 100644
--- a/media/java/android/media/tv/tuner/Descrambler.java
+++ b/media/java/android/media/tv/tuner/Descrambler.java
@@ -22,6 +22,7 @@ import android.annotation.Nullable;
import android.annotation.SystemApi;
import android.media.tv.tuner.Tuner.Result;
import android.media.tv.tuner.filter.Filter;
+import android.util.Log;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -115,9 +116,9 @@ public class Descrambler implements AutoCloseable {
* keys for different purposes.
*
* @param keyToken the token to be used to link the key slot. Use {@link Tuner.INVALID_KEYTOKEN}
- * to remove the to remove the current key from descrambler. If the current keyToken
- * comes from MediaCas session, use {@link Tuner.INVALID_KEYTOKEN} to remove current key
- * before close MediaCas session.
+ * to remove the current key from descrambler. If the current keyToken comes from a
+ * MediaCas session, use {@link Tuner.INVALID_KEYTOKEN} to remove current key before
+ * closing the MediaCas session.
* @return result status of the operation.
*/
@Result
@@ -125,6 +126,9 @@ public class Descrambler implements AutoCloseable {
synchronized (mLock) {
TunerUtils.checkResourceState(TAG, mIsClosed);
Objects.requireNonNull(keyToken, "key token must not be null");
+ if (!isValidKeyToken(keyToken)) {
+ return Tuner.RESULT_INVALID_ARGUMENT;
+ }
return nativeSetKeyToken(keyToken);
}
}
@@ -147,4 +151,17 @@ public class Descrambler implements AutoCloseable {
}
}
+ private boolean isValidKeyToken(byte[] keyToken) {
+ if (keyToken.length == 0 || keyToken.length > 16) {
+ Log.d(TAG, "Invalid key token size: " + (keyToken.length * 8) + " bit.");
+ return false;
+ }
+ for (int i = 0; i < keyToken.length; i++) {
+ if (keyToken[i] < 0) {
+ Log.d(TAG, "Invalid key token.");
+ return false;
+ }
+ }
+ return true;
+ }
}
diff --git a/media/java/android/media/tv/tuner/filter/RecordSettings.java b/media/java/android/media/tv/tuner/filter/RecordSettings.java
index 52ce208f251e..91992afadb3e 100644
--- a/media/java/android/media/tv/tuner/filter/RecordSettings.java
+++ b/media/java/android/media/tv/tuner/filter/RecordSettings.java
@@ -51,7 +51,7 @@ public class RecordSettings extends Settings {
public @interface TsIndexMask {}
/**
- * Invalid TS index.
+ * Invalid Transport Stream (TS) index.
*/
public static final int TS_INDEX_INVALID = 0;
/**
diff --git a/packages/CompanionDeviceManager/res/layout/buttons.xml b/packages/CompanionDeviceManager/res/layout/buttons.xml
index b190a7f675ca..a80720c40737 100644
--- a/packages/CompanionDeviceManager/res/layout/buttons.xml
+++ b/packages/CompanionDeviceManager/res/layout/buttons.xml
@@ -29,14 +29,15 @@
android:id="@+id/button_cancel"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:text="@android:string/cancel"
+ android:text="@string/consent_no"
+ android:textColor="?android:attr/textColorSecondary"
style="@android:style/Widget.Material.Button.Borderless.Colored"
/>
<Button
android:id="@+id/button_pair"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:text="@android:string/ok"
+ android:text="@string/consent_yes"
style="@android:style/Widget.Material.Button.Borderless.Colored"
/>
</LinearLayout> \ No newline at end of file
diff --git a/packages/CompanionDeviceManager/res/layout/device_chooser.xml b/packages/CompanionDeviceManager/res/layout/device_chooser.xml
index db014aef6e8b..273347af6119 100644
--- a/packages/CompanionDeviceManager/res/layout/device_chooser.xml
+++ b/packages/CompanionDeviceManager/res/layout/device_chooser.xml
@@ -23,11 +23,13 @@
<include layout="@layout/title" />
+ <include layout="@layout/profile_summary" />
+
<ListView
android:id="@+id/device_list"
android:layout_width="match_parent"
android:layout_height="match_parent"
- android:layout_below="@+id/title"
+ android:layout_below="@+id/profile_summary"
android:layout_above="@+id/buttons"
style="@android:style/Widget.Material.ListView"
/>
diff --git a/packages/CompanionDeviceManager/res/layout/device_confirmation.xml b/packages/CompanionDeviceManager/res/layout/device_confirmation.xml
index 7cde41ac2894..1336e79a855b 100644
--- a/packages/CompanionDeviceManager/res/layout/device_confirmation.xml
+++ b/packages/CompanionDeviceManager/res/layout/device_confirmation.xml
@@ -23,6 +23,8 @@
<include layout="@layout/title" />
+ <include layout="@layout/profile_summary" />
+
<include layout="@layout/buttons" />
</LinearLayout> \ No newline at end of file
diff --git a/packages/CompanionDeviceManager/res/layout/profile_summary.xml b/packages/CompanionDeviceManager/res/layout/profile_summary.xml
new file mode 100644
index 000000000000..80fec59fbc45
--- /dev/null
+++ b/packages/CompanionDeviceManager/res/layout/profile_summary.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2020 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+
+<TextView
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/profile_summary"
+ android:layout_below="@+id/title"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginStart="16dp"
+ android:layout_marginEnd="16dp"
+ android:textColor="?android:attr/textColorSecondary"
+ android:textSize="14sp"
+ android:gravity="center"
+/> \ No newline at end of file
diff --git a/packages/CompanionDeviceManager/res/layout/title.xml b/packages/CompanionDeviceManager/res/layout/title.xml
index 0a44fbb34a9c..9a5036622468 100644
--- a/packages/CompanionDeviceManager/res/layout/title.xml
+++ b/packages/CompanionDeviceManager/res/layout/title.xml
@@ -20,5 +20,6 @@
android:id="@+id/title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
+ android:gravity="center"
style="@*android:style/TextAppearance.Widget.Toolbar.Title"
/> \ No newline at end of file
diff --git a/packages/CompanionDeviceManager/res/values/strings.xml b/packages/CompanionDeviceManager/res/values/strings.xml
index c4372ebef663..1b96b0045ef0 100644
--- a/packages/CompanionDeviceManager/res/values/strings.xml
+++ b/packages/CompanionDeviceManager/res/values/strings.xml
@@ -20,9 +20,21 @@
<string name="app_label">Companion Device Manager</string>
<!-- Title of the device selection dialog. -->
- <string name="chooser_title">Link with &lt;strong&gt;<xliff:g id="app_name" example="Android Wear">%1$s</xliff:g>&lt;/strong&gt;</string>
+ <string name="chooser_title">Choose a <xliff:g id="profile_name" example="watch">%1$s</xliff:g> to be managed by &lt;strong&gt;<xliff:g id="app_name" example="Android Wear">%2$s</xliff:g>&lt;/strong&gt;</string>
- <!-- Title of the device pairing confirmation dialog. -->
- <string name="confirmation_title">Link &lt;strong&gt;<xliff:g id="app_name" example="Android Wear">%1$s</xliff:g>&lt;/strong&gt; with &lt;strong&gt;<xliff:g id="device_name" example="ASUS ZenWatch 2">%2$s</xliff:g>&lt;/strong&gt;</string>
+ <!-- The generic placeholder for a device type when nothing specific is known about it [CHAR LIMIT=30] -->
+ <string name="profile_name_generic">device</string>
+
+ <!-- Title of the device association confirmation dialog. -->
+ <string name="confirmation_title">Set &lt;strong&gt;<xliff:g id="app_name" example="Android Wear">%1$s</xliff:g>&lt;/strong&gt; to manage your <xliff:g id="profile_name" example="watch">%2$s</xliff:g> - &lt;strong&gt;<xliff:g id="device_name" example="ASUS ZenWatch 2">%3$s</xliff:g>&lt;/strong&gt;</string>
+
+ <!-- Text of the device profile permissions explanation in the association dialog. -->
+ <string name="profile_summary"><xliff:g id="app_name" example="Android Wear">%1$s</xliff:g> is needed to manage your <xliff:g id="profile_name" example="watch">%2$s</xliff:g>. <xliff:g id="app_name2" example="Android Wear">%3$s</xliff:g> will get access to <xliff:g id="permissions" example="Notifications, Calendar and Phone">%4$s</xliff:g> while the <xliff:g id="profile_name2" example="watch">%5$s</xliff:g> is connected.</string>
+
+ <!-- Positive button for the device-app association consent dialog [CHAR LIMIT=30] -->
+ <string name="consent_yes">Yes</string>
+
+ <!-- Negative button for the device-app association consent dialog [CHAR LIMIT=30] -->
+ <string name="consent_no">No thanks</string>
</resources>
diff --git a/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/DeviceChooserActivity.java b/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/DeviceChooserActivity.java
index bdfbf82145c7..f42a51d6593a 100644
--- a/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/DeviceChooserActivity.java
+++ b/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/DeviceChooserActivity.java
@@ -17,11 +17,13 @@
package com.android.companiondevicemanager;
import static android.companion.BluetoothDeviceFilterUtils.getDeviceMacAddress;
+import static android.text.TextUtils.withoutPrefix;
import static android.view.WindowManager.LayoutParams.SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS;
import static java.util.Objects.requireNonNull;
import android.app.Activity;
+import android.companion.AssociationRequest;
import android.companion.CompanionDeviceManager;
import android.content.Intent;
import android.content.pm.PackageManager;
@@ -62,12 +64,19 @@ public class DeviceChooserActivity extends Activity {
getWindow().addSystemFlags(SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS);
- if (getService().mRequest.isSingleDevice()) {
+ String deviceProfile = getRequest().getDeviceProfile();
+ String profileName = deviceProfile == null
+ ? getString(R.string.profile_name_generic)
+ //TODO introduce PermissionController APIs to resolve UI values
+ : withoutPrefix("android.app.role.COMPANION_DEVICE_", deviceProfile).toLowerCase();
+
+ if (getRequest().isSingleDevice()) {
setContentView(R.layout.device_confirmation);
final DeviceFilterPair selectedDevice = getService().mDevicesFound.get(0);
setTitle(Html.fromHtml(getString(
R.string.confirmation_title,
getCallingAppName(),
+ profileName,
selectedDevice.getDisplayName()), 0));
mPairButton = findViewById(R.id.button_pair);
mPairButton.setOnClickListener(v -> onDeviceConfirmed(getService().mSelectedDevice));
@@ -77,7 +86,9 @@ public class DeviceChooserActivity extends Activity {
setContentView(R.layout.device_chooser);
mPairButton = findViewById(R.id.button_pair);
mPairButton.setVisibility(View.GONE);
- setTitle(Html.fromHtml(getString(R.string.chooser_title, getCallingAppName()), 0));
+ setTitle(Html.fromHtml(getString(R.string.chooser_title,
+ profileName,
+ getCallingAppName()), 0));
mDeviceListView = findViewById(R.id.device_list);
final DeviceDiscoveryService.DevicesAdapter adapter = getService().mDevicesAdapter;
mDeviceListView.setAdapter(adapter);
@@ -97,12 +108,33 @@ public class DeviceChooserActivity extends Activity {
});
mDeviceListView.addFooterView(mLoadingIndicator = getProgressBar(), null, false);
}
+
+ TextView profileSummary = findViewById(R.id.profile_summary);
+
+ if (deviceProfile != null) {
+ //TODO introduce PermissionController APIs to resolve UI values
+ String privileges = "Notifications, Phone, Contacts and Calendar";
+ profileSummary.setVisibility(View.VISIBLE);
+ profileSummary.setText(getString(R.string.profile_summary,
+ getCallingAppName(),
+ profileName,
+ getCallingAppName(),
+ privileges,
+ profileName));
+ } else {
+ profileSummary.setVisibility(View.GONE);
+ }
+
getService().mActivity = this;
mCancelButton = findViewById(R.id.button_cancel);
mCancelButton.setOnClickListener(v -> cancel());
}
+ private AssociationRequest getRequest() {
+ return getService().mRequest;
+ }
+
private void cancel() {
getService().onCancel();
setResult(RESULT_CANCELED);
@@ -132,7 +164,7 @@ public class DeviceChooserActivity extends Activity {
@Override
public String getCallingPackage() {
- return requireNonNull(getService().mRequest.getCallingPackage());
+ return requireNonNull(getRequest().getCallingPackage());
}
@Override
diff --git a/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/DeviceDiscoveryService.java b/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/DeviceDiscoveryService.java
index a7e397e9563c..2fe351edb080 100644
--- a/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/DeviceDiscoveryService.java
+++ b/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/DeviceDiscoveryService.java
@@ -64,7 +64,7 @@ import android.util.SparseArray;
import android.util.TypedValue;
import android.view.View;
import android.view.ViewGroup;
-import android.widget.ArrayAdapter;
+import android.widget.BaseAdapter;
import android.widget.TextView;
import com.android.internal.infra.AndroidFuture;
@@ -329,7 +329,7 @@ public class DeviceDiscoveryService extends Service {
mServiceCallback.cancel(true);
}
- class DevicesAdapter extends ArrayAdapter<DeviceFilterPair> {
+ class DevicesAdapter extends BaseAdapter {
private Drawable BLUETOOTH_ICON = icon(android.R.drawable.stat_sys_data_bluetooth);
private Drawable WIFI_ICON = icon(com.android.internal.R.drawable.ic_wifi_signal_3);
@@ -341,10 +341,6 @@ public class DeviceDiscoveryService extends Service {
return icon;
}
- public DevicesAdapter() {
- super(DeviceDiscoveryService.this, 0, mDevicesFound);
- }
-
@Override
public View getView(
int position,
@@ -391,6 +387,21 @@ public class DeviceDiscoveryService extends Service {
mColors.put(colorAttr, result);
return result;
}
+
+ @Override
+ public int getCount() {
+ return mDevicesFound.size();
+ }
+
+ @Override
+ public DeviceFilterPair getItem(int position) {
+ return mDevicesFound.get(position);
+ }
+
+ @Override
+ public long getItemId(int position) {
+ return position;
+ }
}
/**
diff --git a/packages/InputDevices/res/values-mn/strings.xml b/packages/InputDevices/res/values-mn/strings.xml
index fcaf321c6b6c..16970971243a 100644
--- a/packages/InputDevices/res/values-mn/strings.xml
+++ b/packages/InputDevices/res/values-mn/strings.xml
@@ -22,9 +22,9 @@
<string name="keyboard_layout_bulgarian_phonetic" msgid="7568914730360106653">"Болгар хэл, Авиа зүй"</string>
<string name="keyboard_layout_italian" msgid="6497079660449781213">"Итали"</string>
<string name="keyboard_layout_danish" msgid="8036432066627127851">"Дани"</string>
- <string name="keyboard_layout_norwegian" msgid="9090097917011040937">"Норвеги"</string>
+ <string name="keyboard_layout_norwegian" msgid="9090097917011040937">"Норвег"</string>
<string name="keyboard_layout_swedish" msgid="732959109088479351">"Швед"</string>
- <string name="keyboard_layout_finnish" msgid="5585659438924315466">"Финлянд"</string>
+ <string name="keyboard_layout_finnish" msgid="5585659438924315466">"Финланд"</string>
<string name="keyboard_layout_croatian" msgid="4172229471079281138">"Хорват"</string>
<string name="keyboard_layout_czech" msgid="1349256901452975343">"Чех"</string>
<string name="keyboard_layout_czech_qwerty" msgid="3331402534128515501">"Чех хэлний QWERTY загвар"</string>
diff --git a/packages/PackageInstaller/res/values-ne/strings.xml b/packages/PackageInstaller/res/values-ne/strings.xml
index 495a05b941d6..0b73271a0f34 100644
--- a/packages/PackageInstaller/res/values-ne/strings.xml
+++ b/packages/PackageInstaller/res/values-ne/strings.xml
@@ -37,7 +37,7 @@
<string name="install_failed_msg" product="tv" msgid="1920009940048975221">"तपाईंको टिभी मा <xliff:g id="APP_NAME">%1$s</xliff:g> स्थापना गर्न सकिएन।"</string>
<string name="install_failed_msg" product="default" msgid="6484461562647915707">"तपाईंको फोनमा <xliff:g id="APP_NAME">%1$s</xliff:g> स्थापना गर्न सकिएन।"</string>
<string name="launch" msgid="3952550563999890101">"खोल्नुहोस्"</string>
- <string name="unknown_apps_admin_dlg_text" msgid="4456572224020176095">"तपाईंका प्रशासकले अज्ञात स्रोतहरूबाट प्राप्त अनुप्रयोगहरूलाई स्थापना गर्ने अनुमति दिनुहुन्न"</string>
+ <string name="unknown_apps_admin_dlg_text" msgid="4456572224020176095">"तपाईंका प्रशासकले अज्ञात स्रोतहरूबाट प्राप्त एपहरूलाई स्थापना गर्ने अनुमति दिनुहुन्न"</string>
<string name="unknown_apps_user_restriction_dlg_text" msgid="151020786933988344">"यी प्रयोगकर्ता अज्ञात एपहरू स्थापना गर्न सक्नुहुन्न"</string>
<string name="install_apps_user_restriction_dlg_text" msgid="2154119597001074022">"यो प्रयोगकर्तालाई एपहरू स्थापना गर्ने अनुमति छैन"</string>
<string name="ok" msgid="7871959885003339302">"ठिक छ"</string>
diff --git a/packages/PackageInstaller/res/values-pl/strings.xml b/packages/PackageInstaller/res/values-pl/strings.xml
index 5ce30c29638f..f67cb0838358 100644
--- a/packages/PackageInstaller/res/values-pl/strings.xml
+++ b/packages/PackageInstaller/res/values-pl/strings.xml
@@ -57,7 +57,7 @@
<string name="uninstall_application_text_all_users" msgid="575491774380227119">"Chcesz odinstalować tę aplikację dla "<b>"wszystkich"</b>" użytkowników? Ta aplikacja i jej dane zostaną usunięte dla "<b>"wszystkich"</b>" użytkowników na urządzeniu."</string>
<string name="uninstall_application_text_user" msgid="498072714173920526">"Chcesz odinstalować tę aplikację dla użytkownika <xliff:g id="USERNAME">%1$s</xliff:g>?"</string>
<string name="uninstall_update_text" msgid="863648314632448705">"Przywrócić fabryczną wersję tej aplikacji? Wszystkie dane zostaną usunięte."</string>
- <string name="uninstall_update_text_multiuser" msgid="8992883151333057227">"Przywrócić fabryczną wersję tej aplikacji? Wszystkie dane zostaną usunięte. Dotyczy to wszystkich użytkowników tego urządzenia, również tych korzystających z profilu do pracy."</string>
+ <string name="uninstall_update_text_multiuser" msgid="8992883151333057227">"Przywrócić fabryczną wersję tej aplikacji? Wszystkie dane zostaną usunięte. Dotyczy to wszystkich użytkowników tego urządzenia, również tych korzystających z profilu służbowego."</string>
<string name="uninstall_keep_data" msgid="7002379587465487550">"Zachowaj <xliff:g id="SIZE">%1$s</xliff:g> danych aplikacji."</string>
<string name="uninstalling_notification_channel" msgid="840153394325714653">"Aktywne odinstalowania"</string>
<string name="uninstall_failure_notification_channel" msgid="1136405866767576588">"Nieudane odinstalowania"</string>
diff --git a/packages/SettingsLib/Android.bp b/packages/SettingsLib/Android.bp
index 3af4b25fb40c..64dc2afafd6a 100644
--- a/packages/SettingsLib/Android.bp
+++ b/packages/SettingsLib/Android.bp
@@ -51,6 +51,7 @@ java_defaults {
"SettingsLibRadioButtonPreference",
"SettingsLibDisplayDensityUtils",
"SettingsLibUtils",
+ "SettingsLibEmergencyNumber",
"SettingsLibTopIntroPreference",
],
}
diff --git a/packages/SettingsLib/EmergencyNumber/Android.bp b/packages/SettingsLib/EmergencyNumber/Android.bp
new file mode 100644
index 000000000000..3c41f7834d6c
--- /dev/null
+++ b/packages/SettingsLib/EmergencyNumber/Android.bp
@@ -0,0 +1,10 @@
+android_library {
+ name: "SettingsLibEmergencyNumber",
+
+ srcs: ["src/**/*.java"],
+ static_libs: [
+ "androidx.annotation_annotation",
+ ],
+ sdk_version: "system_current",
+ min_sdk_version: "21",
+}
diff --git a/packages/SettingsLib/EmergencyNumber/AndroidManifest.xml b/packages/SettingsLib/EmergencyNumber/AndroidManifest.xml
new file mode 100644
index 000000000000..b877fc4ba531
--- /dev/null
+++ b/packages/SettingsLib/EmergencyNumber/AndroidManifest.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2019 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License
+ -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.android.settingslib.emergencynumber">
+
+ <uses-sdk android:minSdkVersion="21" />
+
+</manifest>
diff --git a/packages/SettingsLib/EmergencyNumber/src/com/android/settingslib/emergencynumber/EmergencyNumberUtils.java b/packages/SettingsLib/EmergencyNumber/src/com/android/settingslib/emergencynumber/EmergencyNumberUtils.java
new file mode 100644
index 000000000000..12d21cae48d4
--- /dev/null
+++ b/packages/SettingsLib/EmergencyNumber/src/com/android/settingslib/emergencynumber/EmergencyNumberUtils.java
@@ -0,0 +1,133 @@
+/*
+ * 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.settingslib.emergencynumber;
+
+import static android.telephony.emergency.EmergencyNumber.EMERGENCY_NUMBER_SOURCE_DATABASE;
+import static android.telephony.emergency.EmergencyNumber.EMERGENCY_SERVICE_CATEGORY_POLICE;
+
+import android.content.Context;
+import android.content.pm.PackageManager;
+import android.provider.Settings;
+import android.telephony.SubscriptionManager;
+import android.telephony.TelephonyManager;
+import android.telephony.emergency.EmergencyNumber;
+import android.text.TextUtils;
+import android.util.ArrayMap;
+import android.util.Log;
+
+import androidx.annotation.VisibleForTesting;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Util class to help manage emergency numbers
+ */
+public class EmergencyNumberUtils {
+ private static final String TAG = "EmergencyNumberUtils";
+ private static final String EMERGENCY_GESTURE_CALL_NUMBER = "emergency_gesture_call_number";
+ @VisibleForTesting
+ static final String FALL_BACK_NUMBER = "112";
+
+ private final Context mContext;
+ private final TelephonyManager mTelephonyManager;
+
+
+ public EmergencyNumberUtils(Context context) {
+ mContext = context;
+ if (context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_TELEPHONY)) {
+ mTelephonyManager = context.getSystemService(TelephonyManager.class);
+ } else {
+ mTelephonyManager = null;
+ }
+ }
+
+ /**
+ * Returns the most appropriate number for police.
+ */
+ public String getDefaultPoliceNumber() {
+ if (mTelephonyManager == null) {
+ return FALL_BACK_NUMBER;
+ }
+ final List<EmergencyNumber> promotedPoliceNumber = getPromotedEmergencyNumbers(
+ EMERGENCY_SERVICE_CATEGORY_POLICE);
+ if (promotedPoliceNumber == null || promotedPoliceNumber.isEmpty()) {
+ return FALL_BACK_NUMBER;
+ }
+ return promotedPoliceNumber.get(0).getNumber();
+ }
+
+ /**
+ * Returns the number chosen by user. If user has not provided any number, use default ({@link
+ * #getDefaultPoliceNumber()}).
+ */
+ public String getPoliceNumber() {
+ final String userProvidedNumber = Settings.Secure.getString(mContext.getContentResolver(),
+ EMERGENCY_GESTURE_CALL_NUMBER);
+ return TextUtils.isEmpty(userProvidedNumber)
+ ? getDefaultPoliceNumber() : userProvidedNumber;
+ }
+
+ private List<EmergencyNumber> getPromotedEmergencyNumbers(int categories) {
+ Map<Integer, List<EmergencyNumber>> allLists = mTelephonyManager.getEmergencyNumberList(
+ categories);
+ if (allLists == null || allLists.isEmpty()) {
+ Log.w(TAG, "Unable to retrieve emergency number lists!");
+ return new ArrayList<>();
+ }
+ Map<Integer, List<EmergencyNumber>> promotedEmergencyNumberLists = new ArrayMap<>();
+ for (Map.Entry<Integer, List<EmergencyNumber>> entry : allLists.entrySet()) {
+ if (entry.getKey() == null || entry.getValue() == null) {
+ continue;
+ }
+ List<EmergencyNumber> emergencyNumberList = entry.getValue();
+ Log.d(TAG, "Emergency numbers for subscription id " + entry.getKey());
+
+ // The list of promoted emergency numbers which will be visible on shortcut view.
+ List<EmergencyNumber> promotedList = new ArrayList<>();
+ // A temporary list for non-prioritized emergency numbers.
+ List<EmergencyNumber> tempList = new ArrayList<>();
+
+ for (EmergencyNumber emergencyNumber : emergencyNumberList) {
+ // Emergency numbers in DATABASE are prioritized since they were well-categorized.
+ boolean isFromPrioritizedSource =
+ emergencyNumber.getEmergencyNumberSources().contains(
+ EMERGENCY_NUMBER_SOURCE_DATABASE);
+
+ Log.d(TAG, String.format("Number %s, isFromPrioritizedSource %b",
+ emergencyNumber, isFromPrioritizedSource));
+ if (isFromPrioritizedSource) {
+ promotedList.add(emergencyNumber);
+ } else {
+ tempList.add(emergencyNumber);
+ }
+ }
+ // Puts numbers in temp list after prioritized numbers.
+ promotedList.addAll(tempList);
+
+ if (!promotedList.isEmpty()) {
+ promotedEmergencyNumberLists.put(entry.getKey(), promotedList);
+ }
+ }
+
+ if (promotedEmergencyNumberLists.isEmpty()) {
+ Log.w(TAG, "No promoted emergency number found!");
+ }
+ return promotedEmergencyNumberLists.get(SubscriptionManager.getDefaultSubscriptionId());
+ }
+}
diff --git a/packages/SettingsLib/res/values-af/strings.xml b/packages/SettingsLib/res/values-af/strings.xml
index fa0fa5c93155..2b30e0a61863 100644
--- a/packages/SettingsLib/res/values-af/strings.xml
+++ b/packages/SettingsLib/res/values-af/strings.xml
@@ -399,9 +399,9 @@
<string name="inactive_app_inactive_summary" msgid="3161222402614236260">"Onaktief. Tik om te wissel."</string>
<string name="inactive_app_active_summary" msgid="8047630990208722344">"Aktief. Tik om te wissel."</string>
<string name="standby_bucket_summary" msgid="5128193447550429600">"Programbystandstatus:<xliff:g id="BUCKET"> %s</xliff:g>"</string>
- <string name="transcode_settings_title" msgid="6700974145733932357">"Mediakodewisselinginstellings"</string>
- <string name="transcode_enable_all" msgid="4719796495995795404">"Aktiveer kodewisseling vir alle programme"</string>
- <string name="transcode_skip_apps" msgid="5680997722349545778">"Deaktiveer kodewisseling vir programme"</string>
+ <string name="transcode_settings_title" msgid="2581975870429850549">"Mediakodewisselinginstellings"</string>
+ <string name="transcode_enable_all" msgid="9102460144086871903">"Deaktiveer kodewisseling"</string>
+ <string name="transcode_skip_apps" msgid="8249721984597390142">"Aktiveer kodewisseling vir programme"</string>
<string name="runningservices_settings_title" msgid="6460099290493086515">"Lopende dienste"</string>
<string name="runningservices_settings_summary" msgid="1046080643262665743">"Sien en beheer dienste wat tans aktief is"</string>
<string name="select_webview_provider_title" msgid="3917815648099445503">"WebView-implementering"</string>
@@ -449,6 +449,8 @@
<string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"<xliff:g id="TIME">%1$s</xliff:g> oor tot battery gelaai is"</string>
<string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> tot battery gelaai is"</string>
+ <!-- no translation found for power_charging_limited (5902301801611726210) -->
+ <skip />
<string name="battery_info_status_unknown" msgid="268625384868401114">"Onbekend"</string>
<string name="battery_info_status_charging" msgid="4279958015430387405">"Laai"</string>
<string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Laai tans vinnig"</string>
diff --git a/packages/SettingsLib/res/values-am/strings.xml b/packages/SettingsLib/res/values-am/strings.xml
index f98b80124c5e..0bebfabf2eb9 100644
--- a/packages/SettingsLib/res/values-am/strings.xml
+++ b/packages/SettingsLib/res/values-am/strings.xml
@@ -399,9 +399,9 @@
<string name="inactive_app_inactive_summary" msgid="3161222402614236260">"ቦዝኗል። ለመቀያየር ነካ ያድርጉ።"</string>
<string name="inactive_app_active_summary" msgid="8047630990208722344">"ገቢር። ለመቀያየር ነካ ያድርጉ።"</string>
<string name="standby_bucket_summary" msgid="5128193447550429600">"የመተግበሪያ ዝግጁ የመሆን ሁኔታ፦<xliff:g id="BUCKET"> %s</xliff:g>"</string>
- <string name="transcode_settings_title" msgid="6700974145733932357">"የሚዲያ ትራንስኮድ ቅንብሮች"</string>
- <string name="transcode_enable_all" msgid="4719796495995795404">"ለሁሉም መተግበሪያዎች ትራንስኮዲንግን ያንቁ"</string>
- <string name="transcode_skip_apps" msgid="5680997722349545778">"ለመተግበሪያዎች ትራንስኮዲንግን ያሰናክሉ"</string>
+ <string name="transcode_settings_title" msgid="2581975870429850549">"የሚዲያ ትራንስኮዲንግ ቅንብሮች"</string>
+ <string name="transcode_enable_all" msgid="9102460144086871903">"ትራንስኮንግን አሰናክል"</string>
+ <string name="transcode_skip_apps" msgid="8249721984597390142">"ለመተግበሪያዎች ትራንስኮዲንግን ያንቁ"</string>
<string name="runningservices_settings_title" msgid="6460099290493086515">"አሂድ አገልግሎቶች"</string>
<string name="runningservices_settings_summary" msgid="1046080643262665743">"በአሁኑጊዜ እየሄዱ ያሉ አገልግሎቶችን ተቆጣጠር እና እይ"</string>
<string name="select_webview_provider_title" msgid="3917815648099445503">"የWebView ትግበራ"</string>
@@ -449,6 +449,8 @@
<string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"<xliff:g id="TIME">%1$s</xliff:g> ኃይል እስከሚሞላ ድረስ ይቀራል"</string>
<string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> ኃይል እስከሚሞላ ድረስ"</string>
+ <!-- no translation found for power_charging_limited (5902301801611726210) -->
+ <skip />
<string name="battery_info_status_unknown" msgid="268625384868401114">"ያልታወቀ"</string>
<string name="battery_info_status_charging" msgid="4279958015430387405">"ኃይል በመሙላት ላይ"</string>
<string name="battery_info_status_charging_fast" msgid="8027559755902954885">"ኃይል በፍጥነት በመሙላት ላይ"</string>
diff --git a/packages/SettingsLib/res/values-ar/strings.xml b/packages/SettingsLib/res/values-ar/strings.xml
index a1432bf1e7f1..6eaf3a98da11 100644
--- a/packages/SettingsLib/res/values-ar/strings.xml
+++ b/packages/SettingsLib/res/values-ar/strings.xml
@@ -399,9 +399,9 @@
<string name="inactive_app_inactive_summary" msgid="3161222402614236260">"غير نشط، انقر للتبديل."</string>
<string name="inactive_app_active_summary" msgid="8047630990208722344">"نشط، انقر للتبديل."</string>
<string name="standby_bucket_summary" msgid="5128193447550429600">"حالة تطبيق وضع الاستعداد:<xliff:g id="BUCKET"> %s</xliff:g>"</string>
- <string name="transcode_settings_title" msgid="6700974145733932357">"إعدادات تحويل ترميز الوسائط"</string>
- <string name="transcode_enable_all" msgid="4719796495995795404">"تفعيل تحويل الترميز لكل التطبيقات"</string>
- <string name="transcode_skip_apps" msgid="5680997722349545778">"إيقاف تحويل الترميز للتطبيقات"</string>
+ <string name="transcode_settings_title" msgid="2581975870429850549">"إعدادات تحويل ترميز الوسائط"</string>
+ <string name="transcode_enable_all" msgid="9102460144086871903">"إيقاف تحويل الترميز"</string>
+ <string name="transcode_skip_apps" msgid="8249721984597390142">"تفعيل تحويل الترميز للتطبيقات"</string>
<string name="runningservices_settings_title" msgid="6460099290493086515">"الخدمات قيد التشغيل"</string>
<string name="runningservices_settings_summary" msgid="1046080643262665743">"عرض الخدمات قيد التشغيل في الوقت الحالي والتحكم فيها"</string>
<string name="select_webview_provider_title" msgid="3917815648099445503">"‏تطبيق WebView"</string>
@@ -449,6 +449,8 @@
<string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"<xliff:g id="TIME">%1$s</xliff:g> إلى أن يتم شحن الجهاز بالكامل"</string>
<string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> إلى أن يتم شحن الجهاز بالكامل"</string>
+ <!-- no translation found for power_charging_limited (5902301801611726210) -->
+ <skip />
<string name="battery_info_status_unknown" msgid="268625384868401114">"غير معروف"</string>
<string name="battery_info_status_charging" msgid="4279958015430387405">"جارٍ الشحن"</string>
<string name="battery_info_status_charging_fast" msgid="8027559755902954885">"جارٍ الشحن سريعًا"</string>
diff --git a/packages/SettingsLib/res/values-as/strings.xml b/packages/SettingsLib/res/values-as/strings.xml
index c7000dd8d23f..e207e1ce4c12 100644
--- a/packages/SettingsLib/res/values-as/strings.xml
+++ b/packages/SettingsLib/res/values-as/strings.xml
@@ -399,9 +399,9 @@
<string name="inactive_app_inactive_summary" msgid="3161222402614236260">"নিষ্ক্ৰিয়। ট\'গল কৰিবলৈ টিপক।"</string>
<string name="inactive_app_active_summary" msgid="8047630990208722344">"সক্ৰিয়। ট\'গল কৰিবলৈ টিপক।"</string>
<string name="standby_bucket_summary" msgid="5128193447550429600">"এপ্ ষ্টেণ্ডবাই অৱস্থাত আছে:<xliff:g id="BUCKET"> %s</xliff:g>"</string>
- <string name="transcode_settings_title" msgid="6700974145733932357">"মিডিয়া ট্ৰান্সক\'ডৰ ছেটিং"</string>
- <string name="transcode_enable_all" msgid="4719796495995795404">"আটাইবোৰ এপৰ বাবে ট্ৰান্সক\'ডিং সক্ষম কৰক"</string>
- <string name="transcode_skip_apps" msgid="5680997722349545778">"এপৰ বাবে ট্ৰান্সক\'ডিং অক্ষম কৰক"</string>
+ <string name="transcode_settings_title" msgid="2581975870429850549">"মিডিয়া ট্ৰান্সক\'ডিঙৰ ছেটিং"</string>
+ <string name="transcode_enable_all" msgid="9102460144086871903">"ট্ৰান্সক\'ডিং অক্ষম কৰক"</string>
+ <string name="transcode_skip_apps" msgid="8249721984597390142">"এপৰ বাবে ট্ৰান্সক\'ডিং সক্ষম কৰক"</string>
<string name="runningservices_settings_title" msgid="6460099290493086515">"চলিত সেৱা"</string>
<string name="runningservices_settings_summary" msgid="1046080643262665743">"বৰ্তমান চলি থকা সেৱাসমূহ চাওক আৰু নিয়ন্ত্ৰণ কৰক"</string>
<string name="select_webview_provider_title" msgid="3917815648099445503">"ৱেবভিউ প্ৰয়োগ"</string>
@@ -449,6 +449,8 @@
<string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"চাৰ্জ হ’বলৈ <xliff:g id="TIME">%1$s</xliff:g> বাকী আছে"</string>
<string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> চাৰ্জ হ\'বলৈ"</string>
+ <!-- no translation found for power_charging_limited (5902301801611726210) -->
+ <skip />
<string name="battery_info_status_unknown" msgid="268625384868401114">"অজ্ঞাত"</string>
<string name="battery_info_status_charging" msgid="4279958015430387405">"চাৰ্জ কৰি থকা হৈছে"</string>
<string name="battery_info_status_charging_fast" msgid="8027559755902954885">"দ্ৰুততাৰে চাৰ্জ হৈছে"</string>
diff --git a/packages/SettingsLib/res/values-az/strings.xml b/packages/SettingsLib/res/values-az/strings.xml
index c30b7b5a31a4..ff1209c754d1 100644
--- a/packages/SettingsLib/res/values-az/strings.xml
+++ b/packages/SettingsLib/res/values-az/strings.xml
@@ -399,9 +399,9 @@
<string name="inactive_app_inactive_summary" msgid="3161222402614236260">"Deaktivdir. Keçid etmək üçün basın."</string>
<string name="inactive_app_active_summary" msgid="8047630990208722344">"Aktivdir. Keçid etmək üçün basın."</string>
<string name="standby_bucket_summary" msgid="5128193447550429600">"Tətbiqin gözləmə rejimi:<xliff:g id="BUCKET"> %s</xliff:g>"</string>
- <string name="transcode_settings_title" msgid="6700974145733932357">"Media yenidən kodlaşdırma ayarları"</string>
- <string name="transcode_enable_all" msgid="4719796495995795404">"Bütün tətbiqlər üçün yenidən kodlaşdırmanı aktiv edin"</string>
- <string name="transcode_skip_apps" msgid="5680997722349545778">"Tətbiqlər üçün yenidən kodlaşdırmanı deaktiv edin"</string>
+ <string name="transcode_settings_title" msgid="2581975870429850549">"Media yenidən kodlaşdırma ayarları"</string>
+ <string name="transcode_enable_all" msgid="9102460144086871903">"Yenidən kodlaşdırmanı deaktiv edin"</string>
+ <string name="transcode_skip_apps" msgid="8249721984597390142">"Tətbiqlər üçün yenidən kodlaşdırmanı aktiv edin"</string>
<string name="runningservices_settings_title" msgid="6460099290493086515">"İşləyən xidmətlər"</string>
<string name="runningservices_settings_summary" msgid="1046080643262665743">"Hazırda prosesdə olan xidmətləri görüntüləyin və onlara nəzarət edin"</string>
<string name="select_webview_provider_title" msgid="3917815648099445503">"WebView icrası"</string>
@@ -449,6 +449,8 @@
<string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"Enerjinin dolmasına <xliff:g id="TIME">%1$s</xliff:g> qalıb"</string>
<string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - Enerjinin dolmasına <xliff:g id="TIME">%2$s</xliff:g> qalıb"</string>
+ <!-- no translation found for power_charging_limited (5902301801611726210) -->
+ <skip />
<string name="battery_info_status_unknown" msgid="268625384868401114">"Naməlum"</string>
<string name="battery_info_status_charging" msgid="4279958015430387405">"Enerji doldurma"</string>
<string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Sürətlə doldurulur"</string>
diff --git a/packages/SettingsLib/res/values-b+sr+Latn/strings.xml b/packages/SettingsLib/res/values-b+sr+Latn/strings.xml
index 5230a8019582..eb099c1926a7 100644
--- a/packages/SettingsLib/res/values-b+sr+Latn/strings.xml
+++ b/packages/SettingsLib/res/values-b+sr+Latn/strings.xml
@@ -399,9 +399,9 @@
<string name="inactive_app_inactive_summary" msgid="3161222402614236260">"Neaktivna. Dodirnite da biste je aktivirali."</string>
<string name="inactive_app_active_summary" msgid="8047630990208722344">"Aktivna. Dodirnite da biste je deaktivirali."</string>
<string name="standby_bucket_summary" msgid="5128193447550429600">"Stanje pripravnosti aplikacije: <xliff:g id="BUCKET"> %s</xliff:g>"</string>
- <string name="transcode_settings_title" msgid="6700974145733932357">"Podešavanja transkodiranja medija"</string>
- <string name="transcode_enable_all" msgid="4719796495995795404">"Omogući transkodiranje za sve aplikacije"</string>
- <string name="transcode_skip_apps" msgid="5680997722349545778">"Onemogućite transkodiranje za aplikacije"</string>
+ <string name="transcode_settings_title" msgid="2581975870429850549">"Podešavanja transkodiranja medija"</string>
+ <string name="transcode_enable_all" msgid="9102460144086871903">"Onemogući transkodiranje"</string>
+ <string name="transcode_skip_apps" msgid="8249721984597390142">"Omogućite transkodiranje za aplikacije"</string>
<string name="runningservices_settings_title" msgid="6460099290493086515">"Pokrenute usluge"</string>
<string name="runningservices_settings_summary" msgid="1046080643262665743">"Prikaz i kontrola trenutno pokrenutih usluga"</string>
<string name="select_webview_provider_title" msgid="3917815648099445503">"Primena WebView-a"</string>
@@ -449,6 +449,8 @@
<string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"Napuniće se za <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> – napuniće se za <xliff:g id="TIME">%2$s</xliff:g>"</string>
+ <!-- no translation found for power_charging_limited (5902301801611726210) -->
+ <skip />
<string name="battery_info_status_unknown" msgid="268625384868401114">"Nepoznato"</string>
<string name="battery_info_status_charging" msgid="4279958015430387405">"Puni se"</string>
<string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Brzo se puni"</string>
diff --git a/packages/SettingsLib/res/values-be/strings.xml b/packages/SettingsLib/res/values-be/strings.xml
index 04f6ef00a355..e6e49ab2063c 100644
--- a/packages/SettingsLib/res/values-be/strings.xml
+++ b/packages/SettingsLib/res/values-be/strings.xml
@@ -399,9 +399,9 @@
<string name="inactive_app_inactive_summary" msgid="3161222402614236260">"Неактыўная. Краніце, каб пераключыць."</string>
<string name="inactive_app_active_summary" msgid="8047630990208722344">"Актыўная. Краніце, каб пераключыць."</string>
<string name="standby_bucket_summary" msgid="5128193447550429600">"Стан праграмы ў рэжыме чакання: <xliff:g id="BUCKET"> %s</xliff:g>"</string>
- <string name="transcode_settings_title" msgid="6700974145733932357">"Налады перакадзіравання мультымедыя"</string>
- <string name="transcode_enable_all" msgid="4719796495995795404">"Дазволіць перакадзіраванне для ўсіх праграм"</string>
- <string name="transcode_skip_apps" msgid="5680997722349545778">"Адключыць перакадзіраванне для праграм"</string>
+ <string name="transcode_settings_title" msgid="2581975870429850549">"Налады перакадзіравання мультымедыя"</string>
+ <string name="transcode_enable_all" msgid="9102460144086871903">"Выключыць перакадзіраванне"</string>
+ <string name="transcode_skip_apps" msgid="8249721984597390142">"Уключыць перакадзіраванне для праграм"</string>
<string name="runningservices_settings_title" msgid="6460099290493086515">"Запушчаныя службы"</string>
<string name="runningservices_settings_summary" msgid="1046080643262665743">"Прагляд запушчаных службаў i кіраванне iмi"</string>
<string name="select_webview_provider_title" msgid="3917815648099445503">"Рэалізацыя WebView"</string>
@@ -449,6 +449,8 @@
<string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"Засталося <xliff:g id="TIME">%1$s</xliff:g> да поўнай зарадкі"</string>
<string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> да поўнай зарадкі"</string>
+ <!-- no translation found for power_charging_limited (5902301801611726210) -->
+ <skip />
<string name="battery_info_status_unknown" msgid="268625384868401114">"Невядома"</string>
<string name="battery_info_status_charging" msgid="4279958015430387405">"Зарадка"</string>
<string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Хуткая зарадка"</string>
diff --git a/packages/SettingsLib/res/values-bg/strings.xml b/packages/SettingsLib/res/values-bg/strings.xml
index e1f18a172194..251c4dd545c4 100644
--- a/packages/SettingsLib/res/values-bg/strings.xml
+++ b/packages/SettingsLib/res/values-bg/strings.xml
@@ -399,9 +399,9 @@
<string name="inactive_app_inactive_summary" msgid="3161222402614236260">"Неактивно. Докоснете, за да превключите."</string>
<string name="inactive_app_active_summary" msgid="8047630990208722344">"Активно. Докоснете, за да превключите."</string>
<string name="standby_bucket_summary" msgid="5128193447550429600">"Състояние на готовност на приложението: <xliff:g id="BUCKET"> %s</xliff:g>"</string>
- <string name="transcode_settings_title" msgid="6700974145733932357">"Настройки за прекодирането на мултимедийно съдържание"</string>
- <string name="transcode_enable_all" msgid="4719796495995795404">"Активиране на прекодирането за всички приложения"</string>
- <string name="transcode_skip_apps" msgid="5680997722349545778">"Деактивиране на прекодирането за приложения"</string>
+ <string name="transcode_settings_title" msgid="2581975870429850549">"Настройки за прекодирането на мултимедия"</string>
+ <string name="transcode_enable_all" msgid="9102460144086871903">"Деактивиране на прекодирането"</string>
+ <string name="transcode_skip_apps" msgid="8249721984597390142">"Активиране на прекодирането за приложения"</string>
<string name="runningservices_settings_title" msgid="6460099290493086515">"Изпълнявани услуги"</string>
<string name="runningservices_settings_summary" msgid="1046080643262665743">"Преглед и контрол върху изпълняващите се понастоящем услуги"</string>
<string name="select_webview_provider_title" msgid="3917815648099445503">"Внедряване на WebView"</string>
@@ -449,6 +449,8 @@
<string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"Оставащо време до пълно зареждане: <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> до пълно зареждане"</string>
+ <!-- no translation found for power_charging_limited (5902301801611726210) -->
+ <skip />
<string name="battery_info_status_unknown" msgid="268625384868401114">"Неизвестно"</string>
<string name="battery_info_status_charging" msgid="4279958015430387405">"Зарежда се"</string>
<string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Зарежда се бързо"</string>
diff --git a/packages/SettingsLib/res/values-bn/strings.xml b/packages/SettingsLib/res/values-bn/strings.xml
index b27d29c60d07..6a99a84358d4 100644
--- a/packages/SettingsLib/res/values-bn/strings.xml
+++ b/packages/SettingsLib/res/values-bn/strings.xml
@@ -399,9 +399,9 @@
<string name="inactive_app_inactive_summary" msgid="3161222402614236260">"নিষ্ক্রিয় রয়েছে৷ টগল করতে আলতো চাপুন৷"</string>
<string name="inactive_app_active_summary" msgid="8047630990208722344">"সক্রিয় রয়েছে৷ টগল করতে আলতো চাপুন৷"</string>
<string name="standby_bucket_summary" msgid="5128193447550429600">"অ্যাপ স্ট্যান্ডবাই-এর অবস্থা:<xliff:g id="BUCKET"> %s</xliff:g>"</string>
- <string name="transcode_settings_title" msgid="6700974145733932357">"মিডিয়া ট্রান্সকোড সেটিংস"</string>
- <string name="transcode_enable_all" msgid="4719796495995795404">"সব অ্যাপের জন্য ট্রান্সকোডিং চালু করুন"</string>
- <string name="transcode_skip_apps" msgid="5680997722349545778">"অ্যাপের ট্রান্সকোডিং বন্ধ করুন"</string>
+ <string name="transcode_settings_title" msgid="2581975870429850549">"মিডিয়া ট্রান্সকোডিং সেটিংস"</string>
+ <string name="transcode_enable_all" msgid="9102460144086871903">"ট্রান্সকোডিং বন্ধ করুন"</string>
+ <string name="transcode_skip_apps" msgid="8249721984597390142">"অ্যাপের জন্য ট্রান্সকোডিং চালু করুন"</string>
<string name="runningservices_settings_title" msgid="6460099290493086515">"এখন চলছে যে পরিষেবাগুলি"</string>
<string name="runningservices_settings_summary" msgid="1046080643262665743">"বর্তমান চলমান পরিষেবাগুলি দেখুন এবং নিয়ন্ত্রণ করুন"</string>
<string name="select_webview_provider_title" msgid="3917815648099445503">"ওয়েবভিউ প্রয়োগ"</string>
@@ -449,6 +449,8 @@
<string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"সম্পূর্ণ চার্জ হতে <xliff:g id="TIME">%1$s</xliff:g> বাকি আছে"</string>
<string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>-এ সম্পূর্ণ চার্জ হয়ে যাবে"</string>
+ <!-- no translation found for power_charging_limited (5902301801611726210) -->
+ <skip />
<string name="battery_info_status_unknown" msgid="268625384868401114">"অজানা"</string>
<string name="battery_info_status_charging" msgid="4279958015430387405">"চার্জ হচ্ছে"</string>
<string name="battery_info_status_charging_fast" msgid="8027559755902954885">"দ্রুত চার্জ হচ্ছে"</string>
diff --git a/packages/SettingsLib/res/values-bs/strings.xml b/packages/SettingsLib/res/values-bs/strings.xml
index 8d467587f3d6..aeb7f2ecc567 100644
--- a/packages/SettingsLib/res/values-bs/strings.xml
+++ b/packages/SettingsLib/res/values-bs/strings.xml
@@ -399,9 +399,9 @@
<string name="inactive_app_inactive_summary" msgid="3161222402614236260">"Neaktivno. Dodirnite za promjenu opcije."</string>
<string name="inactive_app_active_summary" msgid="8047630990208722344">"Aktivno. Dodirnite za promjenu opcije."</string>
<string name="standby_bucket_summary" msgid="5128193447550429600">"Stanje mirovanja aplikacije:<xliff:g id="BUCKET"> %s</xliff:g>"</string>
- <string name="transcode_settings_title" msgid="6700974145733932357">"Postavke transkodiranja medijskih fajlova"</string>
- <string name="transcode_enable_all" msgid="4719796495995795404">"Omogućite transkodiranje za sve aplikacije"</string>
- <string name="transcode_skip_apps" msgid="5680997722349545778">"Onemogućite transkodiranje za aplikacije"</string>
+ <string name="transcode_settings_title" msgid="2581975870429850549">"Postavke transkodiranja medija"</string>
+ <string name="transcode_enable_all" msgid="9102460144086871903">"Onemogućite transkodiranje"</string>
+ <string name="transcode_skip_apps" msgid="8249721984597390142">"Omogućite transkodiranje za aplikacije"</string>
<string name="runningservices_settings_title" msgid="6460099290493086515">"Pokrenute usluge"</string>
<string name="runningservices_settings_summary" msgid="1046080643262665743">"Prikaz i kontrola trenutno pokrenutih usluga"</string>
<string name="select_webview_provider_title" msgid="3917815648099445503">"Postavljanje WebViewa"</string>
@@ -449,6 +449,8 @@
<string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"Napunit će se za <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> – napunit će se za <xliff:g id="TIME">%2$s</xliff:g>"</string>
+ <!-- no translation found for power_charging_limited (5902301801611726210) -->
+ <skip />
<string name="battery_info_status_unknown" msgid="268625384868401114">"Nepoznato"</string>
<string name="battery_info_status_charging" msgid="4279958015430387405">"Punjenje"</string>
<string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Brzo punjenje"</string>
diff --git a/packages/SettingsLib/res/values-ca/strings.xml b/packages/SettingsLib/res/values-ca/strings.xml
index f4fc7d6d47d6..df4c99e20505 100644
--- a/packages/SettingsLib/res/values-ca/strings.xml
+++ b/packages/SettingsLib/res/values-ca/strings.xml
@@ -399,9 +399,9 @@
<string name="inactive_app_inactive_summary" msgid="3161222402614236260">"Aplicació inactiva. Toca per activar-la."</string>
<string name="inactive_app_active_summary" msgid="8047630990208722344">"Aplicació activa. Toca per desactivar-la."</string>
<string name="standby_bucket_summary" msgid="5128193447550429600">"Estat de les aplicacions inactives: <xliff:g id="BUCKET"> %s</xliff:g>"</string>
- <string name="transcode_settings_title" msgid="6700974145733932357">"Configuració de la transcodificació de contingut multimèdia"</string>
- <string name="transcode_enable_all" msgid="4719796495995795404">"Activa la transcodificació per a totes les aplicacions"</string>
- <string name="transcode_skip_apps" msgid="5680997722349545778">"Desactiva la transcodificació per a les aplicacions"</string>
+ <string name="transcode_settings_title" msgid="2581975870429850549">"Configuració de la transcodificació de contingut multimèdia"</string>
+ <string name="transcode_enable_all" msgid="9102460144086871903">"Desactiva la transcodificació"</string>
+ <string name="transcode_skip_apps" msgid="8249721984597390142">"Activa la transcodificació per a les aplicacions"</string>
<string name="runningservices_settings_title" msgid="6460099290493086515">"Serveis en execució"</string>
<string name="runningservices_settings_summary" msgid="1046080643262665743">"Visualitza i controla els serveis en execució"</string>
<string name="select_webview_provider_title" msgid="3917815648099445503">"Implementació de WebView"</string>
@@ -449,6 +449,8 @@
<string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g>: <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"<xliff:g id="TIME">%1$s</xliff:g> per completar la càrrega"</string>
<string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g>: <xliff:g id="TIME">%2$s</xliff:g> per completar la càrrega"</string>
+ <!-- no translation found for power_charging_limited (5902301801611726210) -->
+ <skip />
<string name="battery_info_status_unknown" msgid="268625384868401114">"Desconegut"</string>
<string name="battery_info_status_charging" msgid="4279958015430387405">"S\'està carregant"</string>
<string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Carregant ràpidament"</string>
diff --git a/packages/SettingsLib/res/values-cs/strings.xml b/packages/SettingsLib/res/values-cs/strings.xml
index be0bd47edb3e..e563ca5a03f8 100644
--- a/packages/SettingsLib/res/values-cs/strings.xml
+++ b/packages/SettingsLib/res/values-cs/strings.xml
@@ -399,9 +399,9 @@
<string name="inactive_app_inactive_summary" msgid="3161222402614236260">"Neaktivní. Klepnutím možnost přepnete."</string>
<string name="inactive_app_active_summary" msgid="8047630990208722344">"Aktivní. Klepnutím možnost přepnete."</string>
<string name="standby_bucket_summary" msgid="5128193447550429600">"Stav pohotovostního režimu aplikace: <xliff:g id="BUCKET"> %s</xliff:g>"</string>
- <string name="transcode_settings_title" msgid="6700974145733932357">"Nastavení překódování médií"</string>
- <string name="transcode_enable_all" msgid="4719796495995795404">"Povolit překódování u všech aplikací"</string>
- <string name="transcode_skip_apps" msgid="5680997722349545778">"Zakázat překódování aplikací"</string>
+ <string name="transcode_settings_title" msgid="2581975870429850549">"Nastavení překódování médií"</string>
+ <string name="transcode_enable_all" msgid="9102460144086871903">"Zakázat překódování"</string>
+ <string name="transcode_skip_apps" msgid="8249721984597390142">"Povolit překódování pro aplikace"</string>
<string name="runningservices_settings_title" msgid="6460099290493086515">"Spuštěné služby"</string>
<string name="runningservices_settings_summary" msgid="1046080643262665743">"Umožňuje zobrazit a ovládat aktuálně spuštěné služby"</string>
<string name="select_webview_provider_title" msgid="3917815648099445503">"Implementace WebView"</string>
@@ -449,6 +449,8 @@
<string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"Do nabití zbývá: <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> do nabití"</string>
+ <!-- no translation found for power_charging_limited (5902301801611726210) -->
+ <skip />
<string name="battery_info_status_unknown" msgid="268625384868401114">"Neznámé"</string>
<string name="battery_info_status_charging" msgid="4279958015430387405">"Nabíjí se"</string>
<string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Rychlé nabíjení"</string>
diff --git a/packages/SettingsLib/res/values-da/strings.xml b/packages/SettingsLib/res/values-da/strings.xml
index 2725598a0b57..8a3d054c3ae8 100644
--- a/packages/SettingsLib/res/values-da/strings.xml
+++ b/packages/SettingsLib/res/values-da/strings.xml
@@ -399,9 +399,9 @@
<string name="inactive_app_inactive_summary" msgid="3161222402614236260">"Inaktiv. Tryk for at skifte."</string>
<string name="inactive_app_active_summary" msgid="8047630990208722344">"Aktiv. Tryk for at skifte."</string>
<string name="standby_bucket_summary" msgid="5128193447550429600">"Standbystatus for appen:<xliff:g id="BUCKET"> %s</xliff:g>"</string>
- <string name="transcode_settings_title" msgid="6700974145733932357">"Indstillinger for omkodning af medier"</string>
- <string name="transcode_enable_all" msgid="4719796495995795404">"Aktivér omkodning for alle apps"</string>
- <string name="transcode_skip_apps" msgid="5680997722349545778">"Deaktiver omkodning for apps"</string>
+ <string name="transcode_settings_title" msgid="2581975870429850549">"Indstillinger for omkodning af medier"</string>
+ <string name="transcode_enable_all" msgid="9102460144086871903">"Deaktiver omkodning"</string>
+ <string name="transcode_skip_apps" msgid="8249721984597390142">"Aktivér omkodning for apps"</string>
<string name="runningservices_settings_title" msgid="6460099290493086515">"Kørende tjenester"</string>
<string name="runningservices_settings_summary" msgid="1046080643262665743">"Vis og administrer kørende tjenester"</string>
<string name="select_webview_provider_title" msgid="3917815648099445503">"WebView-implementering"</string>
@@ -449,6 +449,8 @@
<string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"Opladet om <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> – opladet om <xliff:g id="TIME">%2$s</xliff:g>"</string>
+ <!-- no translation found for power_charging_limited (5902301801611726210) -->
+ <skip />
<string name="battery_info_status_unknown" msgid="268625384868401114">"Ukendt"</string>
<string name="battery_info_status_charging" msgid="4279958015430387405">"Oplader"</string>
<string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Oplader hurtigt"</string>
diff --git a/packages/SettingsLib/res/values-de/strings.xml b/packages/SettingsLib/res/values-de/strings.xml
index fcd12227620f..624b299a96c3 100644
--- a/packages/SettingsLib/res/values-de/strings.xml
+++ b/packages/SettingsLib/res/values-de/strings.xml
@@ -399,11 +399,11 @@
<string name="inactive_app_inactive_summary" msgid="3161222402614236260">"Inaktiv. Zum Wechseln tippen."</string>
<string name="inactive_app_active_summary" msgid="8047630990208722344">"Aktiv. Zum Wechseln tippen."</string>
<string name="standby_bucket_summary" msgid="5128193447550429600">"Standby-Status der App:<xliff:g id="BUCKET"> %s</xliff:g>"</string>
- <!-- no translation found for transcode_settings_title (6700974145733932357) -->
+ <!-- no translation found for transcode_settings_title (2581975870429850549) -->
<skip />
- <!-- no translation found for transcode_enable_all (4719796495995795404) -->
+ <!-- no translation found for transcode_enable_all (9102460144086871903) -->
<skip />
- <!-- no translation found for transcode_skip_apps (5680997722349545778) -->
+ <!-- no translation found for transcode_skip_apps (8249721984597390142) -->
<skip />
<string name="runningservices_settings_title" msgid="6460099290493086515">"Aktive Dienste"</string>
<string name="runningservices_settings_summary" msgid="1046080643262665743">"Momentan ausgeführte Dienste anzeigen und steuern"</string>
@@ -452,6 +452,8 @@
<string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"Noch <xliff:g id="TIME">%1$s</xliff:g> bis zur Aufladung"</string>
<string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> bis zur Aufladung"</string>
+ <!-- no translation found for power_charging_limited (5902301801611726210) -->
+ <skip />
<string name="battery_info_status_unknown" msgid="268625384868401114">"Unbekannt"</string>
<string name="battery_info_status_charging" msgid="4279958015430387405">"Wird aufgeladen"</string>
<string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Schnelles Aufladen"</string>
diff --git a/packages/SettingsLib/res/values-el/strings.xml b/packages/SettingsLib/res/values-el/strings.xml
index 9e8845a584ac..7ea90506ac06 100644
--- a/packages/SettingsLib/res/values-el/strings.xml
+++ b/packages/SettingsLib/res/values-el/strings.xml
@@ -399,9 +399,9 @@
<string name="inactive_app_inactive_summary" msgid="3161222402614236260">"Ανενεργό. Πατήστε για εναλλαγή."</string>
<string name="inactive_app_active_summary" msgid="8047630990208722344">"Ενεργό. Πατήστε για εναλλαγή."</string>
<string name="standby_bucket_summary" msgid="5128193447550429600">"Κατάσταση αναμονής εφαρμογής:<xliff:g id="BUCKET"> %s</xliff:g>"</string>
- <string name="transcode_settings_title" msgid="6700974145733932357">"Ρυθμίσεις διακωδικοποίησης μέσων"</string>
- <string name="transcode_enable_all" msgid="4719796495995795404">"Ενεργοποίηση διακωδικοποίησης για όλες τις εφαρμογές"</string>
- <string name="transcode_skip_apps" msgid="5680997722349545778">"Απενεργοποίηση της διακωδικοποίησης για εφαρμογές"</string>
+ <string name="transcode_settings_title" msgid="2581975870429850549">"Ρυθμίσεις διακωδικοποίησης μέσων"</string>
+ <string name="transcode_enable_all" msgid="9102460144086871903">"Απενεργοποίηση διακωδικοποίησης"</string>
+ <string name="transcode_skip_apps" msgid="8249721984597390142">"Ενεργοποίηση διακωδικοποίησης για εφαρμογές"</string>
<string name="runningservices_settings_title" msgid="6460099290493086515">"Υπηρεσίες που εκτελούνται"</string>
<string name="runningservices_settings_summary" msgid="1046080643262665743">"Προβολή και έλεγχος των εφαρμογών που εκτελούνται αυτή τη στιγμή"</string>
<string name="select_webview_provider_title" msgid="3917815648099445503">"Υλοποίηση WebView"</string>
@@ -449,6 +449,8 @@
<string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"Απομένουν <xliff:g id="TIME">%1$s</xliff:g> για ολοκλήρωση της φόρτισης"</string>
<string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> για την ολοκλήρωση της φόρτισης"</string>
+ <!-- no translation found for power_charging_limited (5902301801611726210) -->
+ <skip />
<string name="battery_info_status_unknown" msgid="268625384868401114">"Άγνωστο"</string>
<string name="battery_info_status_charging" msgid="4279958015430387405">"Φόρτιση"</string>
<string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Ταχεία φόρτιση"</string>
diff --git a/packages/SettingsLib/res/values-en-rAU/strings.xml b/packages/SettingsLib/res/values-en-rAU/strings.xml
index 7729f8e2d834..f8019d21c65b 100644
--- a/packages/SettingsLib/res/values-en-rAU/strings.xml
+++ b/packages/SettingsLib/res/values-en-rAU/strings.xml
@@ -399,9 +399,9 @@
<string name="inactive_app_inactive_summary" msgid="3161222402614236260">"Inactive. Tap to toggle."</string>
<string name="inactive_app_active_summary" msgid="8047630990208722344">"Active. Tap to toggle."</string>
<string name="standby_bucket_summary" msgid="5128193447550429600">"App standby state:<xliff:g id="BUCKET"> %s</xliff:g>"</string>
- <string name="transcode_settings_title" msgid="6700974145733932357">"Media transcode settings"</string>
- <string name="transcode_enable_all" msgid="4719796495995795404">"Enable transcoding for all apps"</string>
- <string name="transcode_skip_apps" msgid="5680997722349545778">"Disable transcoding for apps"</string>
+ <string name="transcode_settings_title" msgid="2581975870429850549">"Media transcoding settings"</string>
+ <string name="transcode_enable_all" msgid="9102460144086871903">"Disable transcoding"</string>
+ <string name="transcode_skip_apps" msgid="8249721984597390142">"Enable transcoding for apps"</string>
<string name="runningservices_settings_title" msgid="6460099290493086515">"Running services"</string>
<string name="runningservices_settings_summary" msgid="1046080643262665743">"View and control currently running services"</string>
<string name="select_webview_provider_title" msgid="3917815648099445503">"WebView implementation"</string>
@@ -449,6 +449,7 @@
<string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"<xliff:g id="TIME">%1$s</xliff:g> left until charged"</string>
<string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> until charged"</string>
+ <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> – Battery limited temporarily"</string>
<string name="battery_info_status_unknown" msgid="268625384868401114">"Unknown"</string>
<string name="battery_info_status_charging" msgid="4279958015430387405">"Charging"</string>
<string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Charging rapidly"</string>
diff --git a/packages/SettingsLib/res/values-en-rCA/strings.xml b/packages/SettingsLib/res/values-en-rCA/strings.xml
index 00be3559a92f..7135de5676b2 100644
--- a/packages/SettingsLib/res/values-en-rCA/strings.xml
+++ b/packages/SettingsLib/res/values-en-rCA/strings.xml
@@ -399,9 +399,9 @@
<string name="inactive_app_inactive_summary" msgid="3161222402614236260">"Inactive. Tap to toggle."</string>
<string name="inactive_app_active_summary" msgid="8047630990208722344">"Active. Tap to toggle."</string>
<string name="standby_bucket_summary" msgid="5128193447550429600">"App standby state:<xliff:g id="BUCKET"> %s</xliff:g>"</string>
- <string name="transcode_settings_title" msgid="6700974145733932357">"Media transcode settings"</string>
- <string name="transcode_enable_all" msgid="4719796495995795404">"Enable transcoding for all apps"</string>
- <string name="transcode_skip_apps" msgid="5680997722349545778">"Disable transcoding for apps"</string>
+ <string name="transcode_settings_title" msgid="2581975870429850549">"Media transcoding settings"</string>
+ <string name="transcode_enable_all" msgid="9102460144086871903">"Disable transcoding"</string>
+ <string name="transcode_skip_apps" msgid="8249721984597390142">"Enable transcoding for apps"</string>
<string name="runningservices_settings_title" msgid="6460099290493086515">"Running services"</string>
<string name="runningservices_settings_summary" msgid="1046080643262665743">"View and control currently running services"</string>
<string name="select_webview_provider_title" msgid="3917815648099445503">"WebView implementation"</string>
@@ -449,6 +449,7 @@
<string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"<xliff:g id="TIME">%1$s</xliff:g> left until charged"</string>
<string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> until charged"</string>
+ <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> – Battery limited temporarily"</string>
<string name="battery_info_status_unknown" msgid="268625384868401114">"Unknown"</string>
<string name="battery_info_status_charging" msgid="4279958015430387405">"Charging"</string>
<string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Charging rapidly"</string>
diff --git a/packages/SettingsLib/res/values-en-rGB/strings.xml b/packages/SettingsLib/res/values-en-rGB/strings.xml
index 7729f8e2d834..f8019d21c65b 100644
--- a/packages/SettingsLib/res/values-en-rGB/strings.xml
+++ b/packages/SettingsLib/res/values-en-rGB/strings.xml
@@ -399,9 +399,9 @@
<string name="inactive_app_inactive_summary" msgid="3161222402614236260">"Inactive. Tap to toggle."</string>
<string name="inactive_app_active_summary" msgid="8047630990208722344">"Active. Tap to toggle."</string>
<string name="standby_bucket_summary" msgid="5128193447550429600">"App standby state:<xliff:g id="BUCKET"> %s</xliff:g>"</string>
- <string name="transcode_settings_title" msgid="6700974145733932357">"Media transcode settings"</string>
- <string name="transcode_enable_all" msgid="4719796495995795404">"Enable transcoding for all apps"</string>
- <string name="transcode_skip_apps" msgid="5680997722349545778">"Disable transcoding for apps"</string>
+ <string name="transcode_settings_title" msgid="2581975870429850549">"Media transcoding settings"</string>
+ <string name="transcode_enable_all" msgid="9102460144086871903">"Disable transcoding"</string>
+ <string name="transcode_skip_apps" msgid="8249721984597390142">"Enable transcoding for apps"</string>
<string name="runningservices_settings_title" msgid="6460099290493086515">"Running services"</string>
<string name="runningservices_settings_summary" msgid="1046080643262665743">"View and control currently running services"</string>
<string name="select_webview_provider_title" msgid="3917815648099445503">"WebView implementation"</string>
@@ -449,6 +449,7 @@
<string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"<xliff:g id="TIME">%1$s</xliff:g> left until charged"</string>
<string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> until charged"</string>
+ <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> – Battery limited temporarily"</string>
<string name="battery_info_status_unknown" msgid="268625384868401114">"Unknown"</string>
<string name="battery_info_status_charging" msgid="4279958015430387405">"Charging"</string>
<string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Charging rapidly"</string>
diff --git a/packages/SettingsLib/res/values-en-rIN/strings.xml b/packages/SettingsLib/res/values-en-rIN/strings.xml
index 7729f8e2d834..f8019d21c65b 100644
--- a/packages/SettingsLib/res/values-en-rIN/strings.xml
+++ b/packages/SettingsLib/res/values-en-rIN/strings.xml
@@ -399,9 +399,9 @@
<string name="inactive_app_inactive_summary" msgid="3161222402614236260">"Inactive. Tap to toggle."</string>
<string name="inactive_app_active_summary" msgid="8047630990208722344">"Active. Tap to toggle."</string>
<string name="standby_bucket_summary" msgid="5128193447550429600">"App standby state:<xliff:g id="BUCKET"> %s</xliff:g>"</string>
- <string name="transcode_settings_title" msgid="6700974145733932357">"Media transcode settings"</string>
- <string name="transcode_enable_all" msgid="4719796495995795404">"Enable transcoding for all apps"</string>
- <string name="transcode_skip_apps" msgid="5680997722349545778">"Disable transcoding for apps"</string>
+ <string name="transcode_settings_title" msgid="2581975870429850549">"Media transcoding settings"</string>
+ <string name="transcode_enable_all" msgid="9102460144086871903">"Disable transcoding"</string>
+ <string name="transcode_skip_apps" msgid="8249721984597390142">"Enable transcoding for apps"</string>
<string name="runningservices_settings_title" msgid="6460099290493086515">"Running services"</string>
<string name="runningservices_settings_summary" msgid="1046080643262665743">"View and control currently running services"</string>
<string name="select_webview_provider_title" msgid="3917815648099445503">"WebView implementation"</string>
@@ -449,6 +449,7 @@
<string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"<xliff:g id="TIME">%1$s</xliff:g> left until charged"</string>
<string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> until charged"</string>
+ <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> – Battery limited temporarily"</string>
<string name="battery_info_status_unknown" msgid="268625384868401114">"Unknown"</string>
<string name="battery_info_status_charging" msgid="4279958015430387405">"Charging"</string>
<string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Charging rapidly"</string>
diff --git a/packages/SettingsLib/res/values-en-rXC/strings.xml b/packages/SettingsLib/res/values-en-rXC/strings.xml
index dacc782bb030..54290d269f44 100644
--- a/packages/SettingsLib/res/values-en-rXC/strings.xml
+++ b/packages/SettingsLib/res/values-en-rXC/strings.xml
@@ -399,9 +399,9 @@
<string name="inactive_app_inactive_summary" msgid="3161222402614236260">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‎‏‎‏‎‏‏‏‏‎‏‏‏‏‎‏‏‏‎‏‎‏‏‎‎‎‎‎‏‏‎‏‎‏‏‏‎‏‏‏‏‎‏‎‏‎‎‎‎‎‏‎‏‎‎‎‏‏‎‎‏‎‎‎Inactive. Tap to toggle.‎‏‎‎‏‎"</string>
<string name="inactive_app_active_summary" msgid="8047630990208722344">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‏‎‏‏‏‏‏‎‏‎‏‏‏‎‏‏‏‎‏‏‎‏‏‎‏‏‏‏‏‏‎‏‎‏‎‏‏‎‏‏‎‏‎‎‎‎‏‏‏‎‎‏‎‏‏‎‏‎‏‎‎‎‎Active. Tap to toggle.‎‏‎‎‏‎"</string>
<string name="standby_bucket_summary" msgid="5128193447550429600">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‎‎‎‏‏‏‎‎‏‎‏‎‏‏‎‎‎‎‎‎‎‎‏‏‎‎‎‏‎‏‎‎‏‎‏‏‎‎‏‎‏‏‏‎‏‎‏‎‏‎‏‎‎‏‏‎‏‎‎‎‎‎‎App standby state:‎‏‎‎‏‏‎<xliff:g id="BUCKET"> %s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
- <string name="transcode_settings_title" msgid="6700974145733932357">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‎‏‏‏‎‎‏‏‏‏‏‏‏‎‏‎‏‎‎‏‎‎‎‏‏‏‏‎‏‏‎‏‏‏‎‏‎‏‏‎‎‎‏‏‎‎‎‎‏‏‎‏‎‏‎‏‎‎‎‏‎‏‎Media transcode settings‎‏‎‎‏‎"</string>
- <string name="transcode_enable_all" msgid="4719796495995795404">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‎‎‎‎‎‏‏‎‎‎‎‎‎‎‎‎‎‏‎‏‎‏‏‏‏‎‏‎‎‎‎‎‎‏‎‎‏‏‏‏‏‏‎‏‏‎‎‏‏‏‎‏‏‏‏‏‎‎‏‏‎‎‎Enable transcoding for all apps‎‏‎‎‏‎"</string>
- <string name="transcode_skip_apps" msgid="5680997722349545778">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‎‎‏‏‏‎‏‏‎‏‎‏‏‎‏‏‏‏‎‏‎‏‎‏‎‏‎‏‎‎‎‏‎‎‏‎‏‎‎‏‏‏‎‎‏‎‏‎‏‎‏‎‎‏‎‎‏‏‎‎‏‎‎Disable transcoding for apps‎‏‎‎‏‎"</string>
+ <string name="transcode_settings_title" msgid="2581975870429850549">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‎‏‎‎‎‏‏‏‏‎‏‎‏‎‏‎‎‎‎‎‏‎‏‎‏‎‏‏‏‏‏‏‏‎‎‏‏‏‏‏‎‎‏‏‎‎‏‏‏‏‎‏‎‏‏‏‎‏‏‎‏‎‏‎Media transcoding settings‎‏‎‎‏‎"</string>
+ <string name="transcode_enable_all" msgid="9102460144086871903">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‏‏‏‏‏‎‎‏‎‏‎‎‏‎‎‏‏‎‏‏‏‏‎‏‎‎‎‏‏‎‎‎‏‎‏‏‏‎‎‏‏‏‎‎‏‎‏‏‏‎‏‏‏‏‎‏‎‏‏‏‏‏‎Disable transcoding‎‏‎‎‏‎"</string>
+ <string name="transcode_skip_apps" msgid="8249721984597390142">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‏‏‎‎‏‎‎‏‏‏‏‏‎‎‏‏‏‎‎‏‏‎‎‏‏‎‏‏‏‏‏‎‏‎‎‎‏‏‏‎‏‎‏‎‎‎‎‏‏‏‎‎‏‏‎‎‏‏‏‏‏‎‎Enable transcoding for apps‎‏‎‎‏‎"</string>
<string name="runningservices_settings_title" msgid="6460099290493086515">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‎‏‏‎‎‏‏‎‏‎‎‏‏‎‏‏‏‎‎‎‏‎‎‎‎‏‎‎‏‏‏‏‎‏‏‏‏‏‏‎‎‏‎‏‏‏‏‏‏‎‏‎‏‏‎‎‏‏‎‎‏‏‎Running services‎‏‎‎‏‎"</string>
<string name="runningservices_settings_summary" msgid="1046080643262665743">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‎‎‏‏‏‎‏‎‎‎‎‏‎‎‎‏‏‎‏‏‎‎‏‏‎‎‏‏‎‏‎‏‏‏‏‏‎‎‎‎‎‏‎‏‎‏‎‏‎‏‎‏‎‎‎‎‎‎‏‏‏‏‎View and control currently running services‎‏‎‎‏‎"</string>
<string name="select_webview_provider_title" msgid="3917815648099445503">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‎‏‏‎‏‏‎‎‏‎‏‏‏‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‏‏‎‎‎‏‎‎‎‎‎‏‏‎‏‏‏‏‎‎‏‎‏‎‏‎‏‏‏‏‏‏‏‏‎WebView implementation‎‏‎‎‏‎"</string>
@@ -449,6 +449,7 @@
<string name="power_charging" msgid="6727132649743436802">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‎‏‏‏‎‏‎‏‎‏‏‎‏‏‏‎‎‏‎‎‏‏‏‎‎‎‎‎‎‎‏‏‎‎‏‎‎‎‏‏‏‎‎‎‏‏‏‏‎‎‏‏‎‎‎‎‎‎‎‎‏‎‎‎‏‎‎‏‏‎<xliff:g id="LEVEL">%1$s</xliff:g>‎‏‎‎‏‏‏‎ - ‎‏‎‎‏‏‎<xliff:g id="STATE">%2$s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
<string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‏‎‎‏‏‎‏‏‏‎‏‎‎‏‏‎‏‎‎‏‎‏‎‎‎‎‎‏‎‎‎‏‎‎‏‎‏‎‎‎‎‏‏‎‏‎‏‏‏‏‎‏‏‏‎‏‏‏‏‎‏‎‎‎‏‎‎‏‏‎<xliff:g id="TIME">%1$s</xliff:g>‎‏‎‎‏‏‏‎ left until charged‎‏‎‎‏‎"</string>
<string name="power_charging_duration" msgid="5005740040558984057">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‎‎‎‏‎‏‎‏‏‏‎‏‏‏‏‏‏‏‎‏‏‎‎‎‎‎‏‎‏‏‏‎‎‏‏‎‏‏‎‏‏‏‎‏‏‏‏‎‏‏‏‎‏‏‎‏‏‏‏‎‎‏‎‎‏‎‎‏‏‎<xliff:g id="LEVEL">%1$s</xliff:g>‎‏‎‎‏‏‏‎ - ‎‏‎‎‏‏‎<xliff:g id="TIME">%2$s</xliff:g>‎‏‎‎‏‏‏‎ until charged‎‏‎‎‏‎"</string>
+ <string name="power_charging_limited" msgid="5902301801611726210">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‎‏‎‎‎‏‏‏‏‎‏‎‎‏‎‎‏‏‎‎‎‎‎‎‏‏‎‏‏‏‏‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‎‎‎‎‏‏‎‏‏‎‎‎‎‎‏‎‎‎‏‎‎‏‏‎<xliff:g id="LEVEL">%1$s</xliff:g>‎‏‎‎‏‏‏‎ - Battery limited temporarily‎‏‎‎‏‎"</string>
<string name="battery_info_status_unknown" msgid="268625384868401114">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‎‏‎‏‏‏‎‏‏‏‎‏‎‎‏‎‏‏‎‎‏‎‏‎‏‏‏‎‏‎‏‎‎‎‎‏‎‏‎‏‏‏‎‏‏‏‏‎‎‏‏‏‏‏‏‎‏‏‎‏‎‎Unknown‎‏‎‎‏‎"</string>
<string name="battery_info_status_charging" msgid="4279958015430387405">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‎‏‏‏‎‏‏‎‏‏‎‎‏‎‏‎‏‏‏‎‏‏‏‎‎‏‎‎‎‏‏‏‎‎‎‏‎‏‏‎‏‎‏‎‎‎‎‎‏‏‎‎‏‏‎‏‏‎‎‏‏‎‏‎Charging‎‏‎‎‏‎"</string>
<string name="battery_info_status_charging_fast" msgid="8027559755902954885">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‏‎‏‏‏‏‎‏‏‎‎‏‏‏‏‎‎‏‏‏‏‏‎‎‎‏‎‎‎‎‏‏‏‎‏‏‏‏‏‏‎‏‎‎‎‏‎‎‏‎‏‏‎‏‏‎‎‎‎‏‎‏‎Charging rapidly‎‏‎‎‏‎"</string>
diff --git a/packages/SettingsLib/res/values-es-rUS/strings.xml b/packages/SettingsLib/res/values-es-rUS/strings.xml
index 40eb0c71bbb6..7affb5c89dfc 100644
--- a/packages/SettingsLib/res/values-es-rUS/strings.xml
+++ b/packages/SettingsLib/res/values-es-rUS/strings.xml
@@ -399,9 +399,9 @@
<string name="inactive_app_inactive_summary" msgid="3161222402614236260">"Inactiva. Presiona para activar o desactivar."</string>
<string name="inactive_app_active_summary" msgid="8047630990208722344">"Activa. Presiona para activar o desactivar."</string>
<string name="standby_bucket_summary" msgid="5128193447550429600">"Estado de la app en espera: <xliff:g id="BUCKET"> %s</xliff:g>"</string>
- <string name="transcode_settings_title" msgid="6700974145733932357">"Configuración de la transcodificación multimedia"</string>
- <string name="transcode_enable_all" msgid="4719796495995795404">"Habilitar la transcodificación para todas las apps"</string>
- <string name="transcode_skip_apps" msgid="5680997722349545778">"Inhabilitar la transcodificación para las apps"</string>
+ <string name="transcode_settings_title" msgid="2581975870429850549">"Configuración de transcodificación de contenido multimedia"</string>
+ <string name="transcode_enable_all" msgid="9102460144086871903">"Inhabilitar transcodificación"</string>
+ <string name="transcode_skip_apps" msgid="8249721984597390142">"Habilitar transcodificación en apps"</string>
<string name="runningservices_settings_title" msgid="6460099290493086515">"En ejecución"</string>
<string name="runningservices_settings_summary" msgid="1046080643262665743">"Ver y controlar servicios actuales en ejecución"</string>
<string name="select_webview_provider_title" msgid="3917815648099445503">"Implementación de WebView"</string>
@@ -449,6 +449,8 @@
<string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g>: <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"<xliff:g id="TIME">%1$s</xliff:g> para completar la carga"</string>
<string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> para completar la carga"</string>
+ <!-- no translation found for power_charging_limited (5902301801611726210) -->
+ <skip />
<string name="battery_info_status_unknown" msgid="268625384868401114">"Desconocido"</string>
<string name="battery_info_status_charging" msgid="4279958015430387405">"Cargando"</string>
<string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Cargando rápido"</string>
diff --git a/packages/SettingsLib/res/values-es/strings.xml b/packages/SettingsLib/res/values-es/strings.xml
index 83669172679c..ccdc1c443fbd 100644
--- a/packages/SettingsLib/res/values-es/strings.xml
+++ b/packages/SettingsLib/res/values-es/strings.xml
@@ -399,9 +399,9 @@
<string name="inactive_app_inactive_summary" msgid="3161222402614236260">"Inactiva. Toca para alternar."</string>
<string name="inactive_app_active_summary" msgid="8047630990208722344">"Activa. Toca para alternar."</string>
<string name="standby_bucket_summary" msgid="5128193447550429600">"Estado de la aplicación en espera: <xliff:g id="BUCKET"> %s</xliff:g>"</string>
- <string name="transcode_settings_title" msgid="6700974145733932357">"Configuración de la transcodificación multimedia"</string>
- <string name="transcode_enable_all" msgid="4719796495995795404">"Habilitar transcodificación en todas las aplicaciones"</string>
- <string name="transcode_skip_apps" msgid="5680997722349545778">"Inhabilitar transcodificación en las aplicaciones"</string>
+ <string name="transcode_settings_title" msgid="2581975870429850549">"Configuración de la transcodificación multimedia"</string>
+ <string name="transcode_enable_all" msgid="9102460144086871903">"Inhabilitar transcodificación"</string>
+ <string name="transcode_skip_apps" msgid="8249721984597390142">"Habilitar transcodificación en las aplicaciones"</string>
<string name="runningservices_settings_title" msgid="6460099290493086515">"Servicios en ejecución"</string>
<string name="runningservices_settings_summary" msgid="1046080643262665743">"Ver y controlar los servicios en ejecución"</string>
<string name="select_webview_provider_title" msgid="3917815648099445503">"Implementación de WebView"</string>
@@ -449,6 +449,8 @@
<string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"<xliff:g id="TIME">%1$s</xliff:g> hasta cargarse completamente"</string>
<string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> (<xliff:g id="TIME">%2$s</xliff:g> hasta cargarse completamente)"</string>
+ <!-- no translation found for power_charging_limited (5902301801611726210) -->
+ <skip />
<string name="battery_info_status_unknown" msgid="268625384868401114">"Desconocido"</string>
<string name="battery_info_status_charging" msgid="4279958015430387405">"Cargando"</string>
<string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Cargando rápidamente"</string>
diff --git a/packages/SettingsLib/res/values-et/strings.xml b/packages/SettingsLib/res/values-et/strings.xml
index f876b957b62d..852d6df7d31e 100644
--- a/packages/SettingsLib/res/values-et/strings.xml
+++ b/packages/SettingsLib/res/values-et/strings.xml
@@ -399,9 +399,9 @@
<string name="inactive_app_inactive_summary" msgid="3161222402614236260">"Passiivne. Puudutage vahetamiseks."</string>
<string name="inactive_app_active_summary" msgid="8047630990208722344">"Aktiivne. Puudutage vahetamiseks."</string>
<string name="standby_bucket_summary" msgid="5128193447550429600">"Rakenduse ootelolek:<xliff:g id="BUCKET"> %s</xliff:g>"</string>
- <string name="transcode_settings_title" msgid="6700974145733932357">"Meedia transkodeerimise seaded"</string>
- <string name="transcode_enable_all" msgid="4719796495995795404">"Luba transkodeerimine kõikide rakenduste puhul"</string>
- <string name="transcode_skip_apps" msgid="5680997722349545778">"Keela rakenduste puhul transkodeerimine"</string>
+ <string name="transcode_settings_title" msgid="2581975870429850549">"Meedia transkodeerimise seaded"</string>
+ <string name="transcode_enable_all" msgid="9102460144086871903">"Keela transkodeerimine"</string>
+ <string name="transcode_skip_apps" msgid="8249721984597390142">"Luba rakenduste puhul transkodeerimine"</string>
<string name="runningservices_settings_title" msgid="6460099290493086515">"Käitatud teenused"</string>
<string name="runningservices_settings_summary" msgid="1046080643262665743">"Praegu käitatud teenuste vaatamine ja juhtimine"</string>
<string name="select_webview_provider_title" msgid="3917815648099445503">"WebView\' rakendamine"</string>
@@ -449,6 +449,8 @@
<string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"Täislaadimiseni on jäänud <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> täislaadimiseni"</string>
+ <!-- no translation found for power_charging_limited (5902301801611726210) -->
+ <skip />
<string name="battery_info_status_unknown" msgid="268625384868401114">"Tundmatu"</string>
<string name="battery_info_status_charging" msgid="4279958015430387405">"Laadimine"</string>
<string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Kiirlaadimine"</string>
diff --git a/packages/SettingsLib/res/values-eu/strings.xml b/packages/SettingsLib/res/values-eu/strings.xml
index 0a7bc3eb8b06..6b6b9b63df65 100644
--- a/packages/SettingsLib/res/values-eu/strings.xml
+++ b/packages/SettingsLib/res/values-eu/strings.xml
@@ -399,9 +399,9 @@
<string name="inactive_app_inactive_summary" msgid="3161222402614236260">"Inaktibo. Aldatzeko, sakatu hau."</string>
<string name="inactive_app_active_summary" msgid="8047630990208722344">"Aktibo. Aldatzeko, sakatu hau."</string>
<string name="standby_bucket_summary" msgid="5128193447550429600">"Egonean moduko aplikazioaren egoera: <xliff:g id="BUCKET"> %s</xliff:g>"</string>
- <string name="transcode_settings_title" msgid="6700974145733932357">"Multimedia-edukia transkodetzeko ezarpenak"</string>
- <string name="transcode_enable_all" msgid="4719796495995795404">"Gaitu transkodetzeko aukera aplikazio guztietan"</string>
- <string name="transcode_skip_apps" msgid="5680997722349545778">"Desgaitu aplikazioak transkodetzeko aukera"</string>
+ <string name="transcode_settings_title" msgid="2581975870429850549">"Multimedia-edukia transkodetzeko ezarpenak"</string>
+ <string name="transcode_enable_all" msgid="9102460144086871903">"Desgaitu transkodetzeko aukera"</string>
+ <string name="transcode_skip_apps" msgid="8249721984597390142">"Gaitu aplikazioak transkodetzeko aukera"</string>
<string name="runningservices_settings_title" msgid="6460099290493086515">"Abian diren zerbitzuak"</string>
<string name="runningservices_settings_summary" msgid="1046080643262665743">"Ikusi eta kontrolatu une honetan abian diren zerbitzuak"</string>
<string name="select_webview_provider_title" msgid="3917815648099445503">"WebView inplementazioa"</string>
@@ -449,6 +449,8 @@
<string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"<xliff:g id="TIME">%1$s</xliff:g> guztiz kargatu arte"</string>
<string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> guztiz kargatu arte"</string>
+ <!-- no translation found for power_charging_limited (5902301801611726210) -->
+ <skip />
<string name="battery_info_status_unknown" msgid="268625384868401114">"Ezezaguna"</string>
<string name="battery_info_status_charging" msgid="4279958015430387405">"Kargatzen"</string>
<string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Bizkor kargatzen"</string>
diff --git a/packages/SettingsLib/res/values-fa/strings.xml b/packages/SettingsLib/res/values-fa/strings.xml
index e0f328065d99..af1e55be67c5 100644
--- a/packages/SettingsLib/res/values-fa/strings.xml
+++ b/packages/SettingsLib/res/values-fa/strings.xml
@@ -399,9 +399,9 @@
<string name="inactive_app_inactive_summary" msgid="3161222402614236260">"غیرفعال. برای تغییر حالت ضربه بزنید."</string>
<string name="inactive_app_active_summary" msgid="8047630990208722344">"فعال. برای تغییر حالت ضربه بزنید."</string>
<string name="standby_bucket_summary" msgid="5128193447550429600">"وضعیت حالت آماده به‌کار برنامه:<xliff:g id="BUCKET"> %s</xliff:g>"</string>
- <string name="transcode_settings_title" msgid="6700974145733932357">"تنظیمات تراتبدیل رسانه"</string>
- <string name="transcode_enable_all" msgid="4719796495995795404">"فعال کردن تراتبدیل برای همه برنامه‌ها"</string>
- <string name="transcode_skip_apps" msgid="5680997722349545778">"غیرفعال کردن تراتبدیل برای برنامه‌ها"</string>
+ <string name="transcode_settings_title" msgid="2581975870429850549">"تنظیمات تراتبدیل رسانه"</string>
+ <string name="transcode_enable_all" msgid="9102460144086871903">"غیرفعال کردن تراتبدیل"</string>
+ <string name="transcode_skip_apps" msgid="8249721984597390142">"فعال کردن تراتبدیل برای برنامه‌ها"</string>
<string name="runningservices_settings_title" msgid="6460099290493086515">"سرویس‌های در حال اجرا"</string>
<string name="runningservices_settings_summary" msgid="1046080643262665743">"مشاهده و کنترل سرویس‌های در حال اجرای فعلی"</string>
<string name="select_webview_provider_title" msgid="3917815648099445503">"اجرای وب‌نما"</string>
@@ -449,6 +449,8 @@
<string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - ‏<xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"<xliff:g id="TIME">%1$s</xliff:g> مانده تا شارژ کامل"</string>
<string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> تا شارژ کامل"</string>
+ <!-- no translation found for power_charging_limited (5902301801611726210) -->
+ <skip />
<string name="battery_info_status_unknown" msgid="268625384868401114">"ناشناس"</string>
<string name="battery_info_status_charging" msgid="4279958015430387405">"در حال شارژ شدن"</string>
<string name="battery_info_status_charging_fast" msgid="8027559755902954885">"درحال شارژ شدن سریع"</string>
diff --git a/packages/SettingsLib/res/values-fi/strings.xml b/packages/SettingsLib/res/values-fi/strings.xml
index 651faa54614c..8e819efe3557 100644
--- a/packages/SettingsLib/res/values-fi/strings.xml
+++ b/packages/SettingsLib/res/values-fi/strings.xml
@@ -399,9 +399,9 @@
<string name="inactive_app_inactive_summary" msgid="3161222402614236260">"Ei päällä. Ota käyttöön koskettamalla."</string>
<string name="inactive_app_active_summary" msgid="8047630990208722344">"Aktiivinen. Vaihda koskettamalla."</string>
<string name="standby_bucket_summary" msgid="5128193447550429600">"Sovelluksen valmiusluokka: <xliff:g id="BUCKET"> %s</xliff:g>"</string>
- <string name="transcode_settings_title" msgid="6700974145733932357">"Median transkoodausasetukset"</string>
- <string name="transcode_enable_all" msgid="4719796495995795404">"Ota transkoodaus käyttöön kaikissa sovelluksissa"</string>
- <string name="transcode_skip_apps" msgid="5680997722349545778">"Poista sovellusten transkoodaus käytöstä"</string>
+ <string name="transcode_settings_title" msgid="2581975870429850549">"Median transkoodausasetukset"</string>
+ <string name="transcode_enable_all" msgid="9102460144086871903">"Poista transkoodaus käytöstä"</string>
+ <string name="transcode_skip_apps" msgid="8249721984597390142">"Ota sovellusten transkoodaus käyttöön"</string>
<string name="runningservices_settings_title" msgid="6460099290493086515">"Käynnissä olevat palvelut"</string>
<string name="runningservices_settings_summary" msgid="1046080643262665743">"Tarkastele ja hallitse käynnissä olevia palveluita."</string>
<string name="select_webview_provider_title" msgid="3917815648099445503">"WebView-käyttöönotto"</string>
@@ -449,6 +449,8 @@
<string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"<xliff:g id="TIME">%1$s</xliff:g> jäljellä täyteen lataukseen"</string>
<string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> täyteen lataukseen"</string>
+ <!-- no translation found for power_charging_limited (5902301801611726210) -->
+ <skip />
<string name="battery_info_status_unknown" msgid="268625384868401114">"Tuntematon"</string>
<string name="battery_info_status_charging" msgid="4279958015430387405">"Ladataan"</string>
<string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Nopea lataus"</string>
diff --git a/packages/SettingsLib/res/values-fr-rCA/strings.xml b/packages/SettingsLib/res/values-fr-rCA/strings.xml
index c37d6cc59f1d..4754d15b5a52 100644
--- a/packages/SettingsLib/res/values-fr-rCA/strings.xml
+++ b/packages/SettingsLib/res/values-fr-rCA/strings.xml
@@ -142,7 +142,7 @@
<string name="process_kernel_label" msgid="950292573930336765">"Système d\'exploitation Android"</string>
<string name="data_usage_uninstalled_apps" msgid="1933665711856171491">"Applications supprimées"</string>
<string name="data_usage_uninstalled_apps_users" msgid="5533981546921913295">"Applications et utilisateurs supprimés"</string>
- <string name="data_usage_ota" msgid="7984667793701597001">"Mises à jour système"</string>
+ <string name="data_usage_ota" msgid="7984667793701597001">"Mises à jour du système"</string>
<string name="tether_settings_title_usb" msgid="3728686573430917722">"Partage de connexion par USB"</string>
<string name="tether_settings_title_wifi" msgid="4803402057533895526">"Point d\'accès Wi-Fi mobile"</string>
<string name="tether_settings_title_bluetooth" msgid="916519902721399656">"Partage connexion Bluetooth"</string>
@@ -399,9 +399,9 @@
<string name="inactive_app_inactive_summary" msgid="3161222402614236260">"Application inactive. Touchez ici pour l\'activer."</string>
<string name="inactive_app_active_summary" msgid="8047630990208722344">"Application active. Touchez ici pour la désactiver."</string>
<string name="standby_bucket_summary" msgid="5128193447550429600">"État de l\'application en veille :<xliff:g id="BUCKET"> %s</xliff:g>"</string>
- <string name="transcode_settings_title" msgid="6700974145733932357">"Paramètres de transcodage pour les éléments multimédias"</string>
- <string name="transcode_enable_all" msgid="4719796495995795404">"Activer le transcodage pour toutes les applications"</string>
- <string name="transcode_skip_apps" msgid="5680997722349545778">"Désactiver le transcodage pour toutes les applications"</string>
+ <string name="transcode_settings_title" msgid="2581975870429850549">"Paramètres de transcodage des éléments multimédias"</string>
+ <string name="transcode_enable_all" msgid="9102460144086871903">"Désactiver le transcodage"</string>
+ <string name="transcode_skip_apps" msgid="8249721984597390142">"Activer le transcodage pour les applications"</string>
<string name="runningservices_settings_title" msgid="6460099290493086515">"Services en cours d\'exécution"</string>
<string name="runningservices_settings_summary" msgid="1046080643262665743">"Afficher et contrôler les services en cours d\'exécution"</string>
<string name="select_webview_provider_title" msgid="3917815648099445503">"Mise en œuvre WebView"</string>
@@ -449,6 +449,8 @@
<string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"<xliff:g id="TIME">%1$s</xliff:g> jusqu\'à la charge complète"</string>
<string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> : <xliff:g id="TIME">%2$s</xliff:g> jusqu\'à la charge complète"</string>
+ <!-- no translation found for power_charging_limited (5902301801611726210) -->
+ <skip />
<string name="battery_info_status_unknown" msgid="268625384868401114">"Inconnu"</string>
<string name="battery_info_status_charging" msgid="4279958015430387405">"Charge en cours…"</string>
<string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Recharge rapide"</string>
@@ -501,7 +503,7 @@
<string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"Activer"</string>
<string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"Activer le mode Ne pas déranger"</string>
<string name="zen_mode_settings_summary_off" msgid="3832876036123504076">"Jamais"</string>
- <string name="zen_interruption_level_priority" msgid="5392140786447823299">"Priorités seulement"</string>
+ <string name="zen_interruption_level_priority" msgid="5392140786447823299">"Prioritaires seulement"</string>
<string name="zen_mode_and_condition" msgid="8877086090066332516">"<xliff:g id="ZEN_MODE">%1$s</xliff:g>. <xliff:g id="EXIT_CONDITION">%2$s</xliff:g>"</string>
<string name="zen_alarm_warning_indef" msgid="4146527909616457163">"Vous n\'entendrez pas votre prochaine alarme à <xliff:g id="WHEN">%1$s</xliff:g> sauf si vous désactivez préalablement cette option"</string>
<string name="zen_alarm_warning" msgid="245729928048586280">"Vous n\'entendrez pas votre prochaine alarme à <xliff:g id="WHEN">%1$s</xliff:g>"</string>
diff --git a/packages/SettingsLib/res/values-fr/strings.xml b/packages/SettingsLib/res/values-fr/strings.xml
index ef52ec562b89..a3863f596067 100644
--- a/packages/SettingsLib/res/values-fr/strings.xml
+++ b/packages/SettingsLib/res/values-fr/strings.xml
@@ -399,9 +399,9 @@
<string name="inactive_app_inactive_summary" msgid="3161222402614236260">"Application inactive. Appuyez ici pour l\'activer."</string>
<string name="inactive_app_active_summary" msgid="8047630990208722344">"Application active. Appuyez ici pour la désactiver."</string>
<string name="standby_bucket_summary" msgid="5128193447550429600">"État de mise en veille de l\'application : <xliff:g id="BUCKET"> %s</xliff:g>"</string>
- <string name="transcode_settings_title" msgid="6700974145733932357">"Paramètres de transcodage des contenus multimédias"</string>
- <string name="transcode_enable_all" msgid="4719796495995795404">"Activer le transcodage pour toutes les applications"</string>
- <string name="transcode_skip_apps" msgid="5680997722349545778">"Désactiver le transcodage pour les applications"</string>
+ <string name="transcode_settings_title" msgid="2581975870429850549">"Paramètres de transcodage des contenus multimédias"</string>
+ <string name="transcode_enable_all" msgid="9102460144086871903">"Désactiver le transcodage"</string>
+ <string name="transcode_skip_apps" msgid="8249721984597390142">"Activer le transcodage pour les applications"</string>
<string name="runningservices_settings_title" msgid="6460099290493086515">"Services en cours d\'exécution"</string>
<string name="runningservices_settings_summary" msgid="1046080643262665743">"Afficher et contrôler les services en cours d\'exécution"</string>
<string name="select_webview_provider_title" msgid="3917815648099445503">"Mise en œuvre WebView"</string>
@@ -449,6 +449,8 @@
<string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"<xliff:g id="TIME">%1$s</xliff:g> jusqu\'à ce que la batterie soit chargée"</string>
<string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> jusqu\'à la charge complète"</string>
+ <!-- no translation found for power_charging_limited (5902301801611726210) -->
+ <skip />
<string name="battery_info_status_unknown" msgid="268625384868401114">"Inconnu"</string>
<string name="battery_info_status_charging" msgid="4279958015430387405">"Batterie en charge"</string>
<string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Charge rapide"</string>
diff --git a/packages/SettingsLib/res/values-gl/strings.xml b/packages/SettingsLib/res/values-gl/strings.xml
index 16777aae2bb8..81e79e4a27a9 100644
--- a/packages/SettingsLib/res/values-gl/strings.xml
+++ b/packages/SettingsLib/res/values-gl/strings.xml
@@ -399,9 +399,9 @@
<string name="inactive_app_inactive_summary" msgid="3161222402614236260">"Aplicación inactiva. Toca para alternar a configuración."</string>
<string name="inactive_app_active_summary" msgid="8047630990208722344">"Aplicación activa. Toca para alternar a configuración."</string>
<string name="standby_bucket_summary" msgid="5128193447550429600">"Estado en espera da aplicación: <xliff:g id="BUCKET"> %s</xliff:g>"</string>
- <string name="transcode_settings_title" msgid="6700974145733932357">"Configuración de transcodificación de contido multimedia"</string>
- <string name="transcode_enable_all" msgid="4719796495995795404">"Activar transcodificación para todas as aplicacións"</string>
- <string name="transcode_skip_apps" msgid="5680997722349545778">"Desactivar transcodificación para determinadas aplicacións"</string>
+ <string name="transcode_settings_title" msgid="2581975870429850549">"Configuración de transcodificación de contido multimedia"</string>
+ <string name="transcode_enable_all" msgid="9102460144086871903">"Desactivar transcodificación"</string>
+ <string name="transcode_skip_apps" msgid="8249721984597390142">"Activar transcodificación para as aplicacións"</string>
<string name="runningservices_settings_title" msgid="6460099290493086515">"Servizos en uso"</string>
<string name="runningservices_settings_summary" msgid="1046080643262665743">"Comproba e controla os servizos actualmente en uso"</string>
<string name="select_webview_provider_title" msgid="3917815648099445503">"Implementación de WebView"</string>
@@ -449,6 +449,8 @@
<string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"<xliff:g id="TIME">%1$s</xliff:g> para completar a carga"</string>
<string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g>: <xliff:g id="TIME">%2$s</xliff:g> para completar a carga"</string>
+ <!-- no translation found for power_charging_limited (5902301801611726210) -->
+ <skip />
<string name="battery_info_status_unknown" msgid="268625384868401114">"Descoñecido"</string>
<string name="battery_info_status_charging" msgid="4279958015430387405">"Cargando"</string>
<string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Cargando rapidamente"</string>
diff --git a/packages/SettingsLib/res/values-gu/strings.xml b/packages/SettingsLib/res/values-gu/strings.xml
index ef88ab13c2f0..9bf09704a4f5 100644
--- a/packages/SettingsLib/res/values-gu/strings.xml
+++ b/packages/SettingsLib/res/values-gu/strings.xml
@@ -399,9 +399,12 @@
<string name="inactive_app_inactive_summary" msgid="3161222402614236260">"નિષ્ક્રિય. ટોગલ કરવા માટે ટૅપ કરો."</string>
<string name="inactive_app_active_summary" msgid="8047630990208722344">"સક્રિય. ટોગલ કરવા માટે ટૅપ કરો."</string>
<string name="standby_bucket_summary" msgid="5128193447550429600">"ઍપ સ્ટૅન્ડબાયની સ્થિતિ:<xliff:g id="BUCKET"> %s</xliff:g>"</string>
- <string name="transcode_settings_title" msgid="6700974145733932357">"મીડિયાનું ફૉર્મેટ બદલવાની પ્રક્રિયાના સેટિંગ"</string>
- <string name="transcode_enable_all" msgid="4719796495995795404">"બધી ઍપ માટે ફૉર્મેટ બદલવાની પ્રક્રિયા ચાલુ કરો"</string>
- <string name="transcode_skip_apps" msgid="5680997722349545778">"ઍપ માટે ફૉર્મેટ બદલવાની પ્રક્રિયા બંધ કરો"</string>
+ <!-- no translation found for transcode_settings_title (2581975870429850549) -->
+ <skip />
+ <!-- no translation found for transcode_enable_all (9102460144086871903) -->
+ <skip />
+ <!-- no translation found for transcode_skip_apps (8249721984597390142) -->
+ <skip />
<string name="runningservices_settings_title" msgid="6460099290493086515">"ચાલુ સેવાઓ"</string>
<string name="runningservices_settings_summary" msgid="1046080643262665743">"હાલમાં ચાલતી સેવાઓ જુઓ અને નિયંત્રિત કરો"</string>
<string name="select_webview_provider_title" msgid="3917815648099445503">"WebView અમલીકરણ"</string>
@@ -449,6 +452,8 @@
<string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"ચાર્જ થવામાં <xliff:g id="TIME">%1$s</xliff:g> બાકી છે"</string>
<string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - ચાર્જ થવા માટે <xliff:g id="TIME">%2$s</xliff:g>"</string>
+ <!-- no translation found for power_charging_limited (5902301801611726210) -->
+ <skip />
<string name="battery_info_status_unknown" msgid="268625384868401114">"અજાણ્યું"</string>
<string name="battery_info_status_charging" msgid="4279958015430387405">"ચાર્જ થઈ રહ્યું છે"</string>
<string name="battery_info_status_charging_fast" msgid="8027559755902954885">"ઝડપથી ચાર્જ થાય છે"</string>
diff --git a/packages/SettingsLib/res/values-hi/strings.xml b/packages/SettingsLib/res/values-hi/strings.xml
index 3aa413b3452a..151b861cbd3b 100644
--- a/packages/SettingsLib/res/values-hi/strings.xml
+++ b/packages/SettingsLib/res/values-hi/strings.xml
@@ -399,9 +399,9 @@
<string name="inactive_app_inactive_summary" msgid="3161222402614236260">"बंद है. टॉगल करने के लिए टैप करें."</string>
<string name="inactive_app_active_summary" msgid="8047630990208722344">"सक्रिय. टॉगल करने के लिए टैप करें."</string>
<string name="standby_bucket_summary" msgid="5128193447550429600">"ऐप्लिकेशन स्टैंडबाय की स्थिति:<xliff:g id="BUCKET"> %s</xliff:g>"</string>
- <string name="transcode_settings_title" msgid="6700974145733932357">"मीडिया ऐप्लिकेशन को ट्रांसकोड करने से जुड़ी सेटिंग"</string>
- <string name="transcode_enable_all" msgid="4719796495995795404">"सभी ऐप्लिकेशन के लिए ट्रांसकोडिंग चालू करें"</string>
- <string name="transcode_skip_apps" msgid="5680997722349545778">"ऐप्लिकेशन के लिए ट्रांसकोडिंग बंद करें"</string>
+ <string name="transcode_settings_title" msgid="2581975870429850549">"मीडिया ट्रांसकोडिंग सेटिंग"</string>
+ <string name="transcode_enable_all" msgid="9102460144086871903">"ट्रांसकोडिंग को बंद करें"</string>
+ <string name="transcode_skip_apps" msgid="8249721984597390142">"ऐप्लिकेशन के लिए ट्रांसकोडिंग चालू करें"</string>
<string name="runningservices_settings_title" msgid="6460099290493086515">"चल रही सेवाएं"</string>
<string name="runningservices_settings_summary" msgid="1046080643262665743">"इस समय चल रही सेवाओं को देखें और नियंत्रित करें"</string>
<string name="select_webview_provider_title" msgid="3917815648099445503">"वेबव्यू लागू करें"</string>
@@ -449,6 +449,8 @@
<string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"चार्ज पूरा होने में <xliff:g id="TIME">%1$s</xliff:g> बचा है"</string>
<string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> में पूरा चार्ज हो जाएगा"</string>
+ <!-- no translation found for power_charging_limited (5902301801611726210) -->
+ <skip />
<string name="battery_info_status_unknown" msgid="268625384868401114">"अज्ञात"</string>
<string name="battery_info_status_charging" msgid="4279958015430387405">"चार्ज हो रही है"</string>
<string name="battery_info_status_charging_fast" msgid="8027559755902954885">"तेज़ चार्ज हो रही है"</string>
diff --git a/packages/SettingsLib/res/values-hr/strings.xml b/packages/SettingsLib/res/values-hr/strings.xml
index bc0c2bc1b9a5..d37879f6e153 100644
--- a/packages/SettingsLib/res/values-hr/strings.xml
+++ b/packages/SettingsLib/res/values-hr/strings.xml
@@ -399,9 +399,9 @@
<string name="inactive_app_inactive_summary" msgid="3161222402614236260">"Nije aktivno. Dodirnite da biste to promijenili."</string>
<string name="inactive_app_active_summary" msgid="8047630990208722344">"Aktivno. Dodirnite da biste to promijenili."</string>
<string name="standby_bucket_summary" msgid="5128193447550429600">"Stanje aplikacije u mirovanju: <xliff:g id="BUCKET"> %s</xliff:g>"</string>
- <string name="transcode_settings_title" msgid="6700974145733932357">"Postavke konvertiranja medija"</string>
- <string name="transcode_enable_all" msgid="4719796495995795404">"Omogućavanje konvertiranja za sve aplikacije"</string>
- <string name="transcode_skip_apps" msgid="5680997722349545778">"Onemogućivanje konvertiranja za aplikacije"</string>
+ <string name="transcode_settings_title" msgid="2581975870429850549">"Postavke konvertiranja medija"</string>
+ <string name="transcode_enable_all" msgid="9102460144086871903">"Onemogućivanje konvertiranja"</string>
+ <string name="transcode_skip_apps" msgid="8249721984597390142">"Omogućivanje konvertiranja za aplikacije"</string>
<string name="runningservices_settings_title" msgid="6460099290493086515">"Pokrenute usluge"</string>
<string name="runningservices_settings_summary" msgid="1046080643262665743">"Pregledajte i kontrolirajte pokrenute usluge"</string>
<string name="select_webview_provider_title" msgid="3917815648099445503">"Implementacija WebViewa"</string>
@@ -449,6 +449,8 @@
<string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"Napunit će se za <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> – napunit će se za <xliff:g id="TIME">%2$s</xliff:g>"</string>
+ <!-- no translation found for power_charging_limited (5902301801611726210) -->
+ <skip />
<string name="battery_info_status_unknown" msgid="268625384868401114">"Nepoznato"</string>
<string name="battery_info_status_charging" msgid="4279958015430387405">"Punjenje"</string>
<string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Brzo punjenje"</string>
diff --git a/packages/SettingsLib/res/values-hu/strings.xml b/packages/SettingsLib/res/values-hu/strings.xml
index 37b5b50d2cb7..4ac5308474c5 100644
--- a/packages/SettingsLib/res/values-hu/strings.xml
+++ b/packages/SettingsLib/res/values-hu/strings.xml
@@ -399,9 +399,9 @@
<string name="inactive_app_inactive_summary" msgid="3161222402614236260">"Kikapcsolva. Koppintson ide a váltáshoz."</string>
<string name="inactive_app_active_summary" msgid="8047630990208722344">"Bekapcsolva. Koppintson ide a váltáshoz."</string>
<string name="standby_bucket_summary" msgid="5128193447550429600">"Alkalmazás készenléti állapota:<xliff:g id="BUCKET"> %s</xliff:g>"</string>
- <string name="transcode_settings_title" msgid="6700974145733932357">"Média átkódolásához tartozó beállítások"</string>
- <string name="transcode_enable_all" msgid="4719796495995795404">"Átkódolás engedélyezése minden alkalmazásnál"</string>
- <string name="transcode_skip_apps" msgid="5680997722349545778">"Átkódolás letiltása az alkalmazásoknál"</string>
+ <string name="transcode_settings_title" msgid="2581975870429850549">"Médiaátkódolási beállítások"</string>
+ <string name="transcode_enable_all" msgid="9102460144086871903">"Átkódolás letiltása"</string>
+ <string name="transcode_skip_apps" msgid="8249721984597390142">"Átkódolás engedélyezése az alkalmazásoknál"</string>
<string name="runningservices_settings_title" msgid="6460099290493086515">"Futó szolgáltatások"</string>
<string name="runningservices_settings_summary" msgid="1046080643262665743">"A jelenleg futó szolgáltatások megtekintése és vezérlése"</string>
<string name="select_webview_provider_title" msgid="3917815648099445503">"WebView-megvalósítás"</string>
@@ -449,6 +449,8 @@
<string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"<xliff:g id="TIME">%1$s</xliff:g> van hátra a feltöltésből"</string>
<string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> a feltöltésig"</string>
+ <!-- no translation found for power_charging_limited (5902301801611726210) -->
+ <skip />
<string name="battery_info_status_unknown" msgid="268625384868401114">"Ismeretlen"</string>
<string name="battery_info_status_charging" msgid="4279958015430387405">"Töltés"</string>
<string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Gyorstöltés"</string>
diff --git a/packages/SettingsLib/res/values-hy/strings.xml b/packages/SettingsLib/res/values-hy/strings.xml
index f2744b26a4ea..b0734fdee27e 100644
--- a/packages/SettingsLib/res/values-hy/strings.xml
+++ b/packages/SettingsLib/res/values-hy/strings.xml
@@ -399,9 +399,9 @@
<string name="inactive_app_inactive_summary" msgid="3161222402614236260">"Ակտիվ չէ: Հպեք՝ փոխելու համար:"</string>
<string name="inactive_app_active_summary" msgid="8047630990208722344">"Ակտիվ է: Հպեք՝ փոխելու համար:"</string>
<string name="standby_bucket_summary" msgid="5128193447550429600">"Հավելվածի սպասման կարգավիճակ՝ <xliff:g id="BUCKET"> %s</xliff:g>"</string>
- <string name="transcode_settings_title" msgid="6700974145733932357">"Մեդիա բովանդակության վերակոդավորման կարգավորումներ"</string>
- <string name="transcode_enable_all" msgid="4719796495995795404">"Միացնել վերակոդավորումը բոլոր հավելվածների համար"</string>
- <string name="transcode_skip_apps" msgid="5680997722349545778">"Անջատել վերակոդավորումը հավելվածների համար"</string>
+ <string name="transcode_settings_title" msgid="2581975870429850549">"Մեդիա ֆայլերի վերակոդավորման կարգավորումներ"</string>
+ <string name="transcode_enable_all" msgid="9102460144086871903">"Անջատել վերակոդավորումը"</string>
+ <string name="transcode_skip_apps" msgid="8249721984597390142">"Միացնել վերակոդավորումը հավելվածների համար"</string>
<string name="runningservices_settings_title" msgid="6460099290493086515">"Աշխատող ծառայություններ"</string>
<string name="runningservices_settings_summary" msgid="1046080643262665743">"Դիտել և վերահսկել ընթացիկ աշխատող ծառայությունները"</string>
<string name="select_webview_provider_title" msgid="3917815648099445503">"WebView ծառայություն"</string>
@@ -449,6 +449,8 @@
<string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"<xliff:g id="TIME">%1$s</xliff:g> մինչև լիցքավորումը"</string>
<string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> մինչև լիցքավորումը"</string>
+ <!-- no translation found for power_charging_limited (5902301801611726210) -->
+ <skip />
<string name="battery_info_status_unknown" msgid="268625384868401114">"Անհայտ"</string>
<string name="battery_info_status_charging" msgid="4279958015430387405">"Լիցքավորում"</string>
<string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Արագ լիցքավորում"</string>
diff --git a/packages/SettingsLib/res/values-in/strings.xml b/packages/SettingsLib/res/values-in/strings.xml
index e1298271d464..9db21c796bbf 100644
--- a/packages/SettingsLib/res/values-in/strings.xml
+++ b/packages/SettingsLib/res/values-in/strings.xml
@@ -399,9 +399,9 @@
<string name="inactive_app_inactive_summary" msgid="3161222402614236260">"Tidak aktif. Ketuk untuk beralih."</string>
<string name="inactive_app_active_summary" msgid="8047630990208722344">"Aktif. Ketuk untuk beralih."</string>
<string name="standby_bucket_summary" msgid="5128193447550429600">"Status standby aplikasi:<xliff:g id="BUCKET"> %s</xliff:g>"</string>
- <string name="transcode_settings_title" msgid="6700974145733932357">"Setelan transcoding media"</string>
- <string name="transcode_enable_all" msgid="4719796495995795404">"Mengaktifkan transcoding untuk semua aplikasi"</string>
- <string name="transcode_skip_apps" msgid="5680997722349545778">"Menonaktifkan transcoding untuk aplikasi"</string>
+ <string name="transcode_settings_title" msgid="2581975870429850549">"Setelan transcoding media"</string>
+ <string name="transcode_enable_all" msgid="9102460144086871903">"Menonaktifkan transcoding"</string>
+ <string name="transcode_skip_apps" msgid="8249721984597390142">"Mengaktifkan transcoding untuk aplikasi"</string>
<string name="runningservices_settings_title" msgid="6460099290493086515">"Layanan yang sedang berjalan"</string>
<string name="runningservices_settings_summary" msgid="1046080643262665743">"Melihat dan mengontrol layanan yang sedang berjalan"</string>
<string name="select_webview_provider_title" msgid="3917815648099445503">"Penerapan WebView"</string>
@@ -449,6 +449,8 @@
<string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"Sisa <xliff:g id="TIME">%1$s</xliff:g> hingga terisi penuh"</string>
<string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> lagi terisi penuh"</string>
+ <!-- no translation found for power_charging_limited (5902301801611726210) -->
+ <skip />
<string name="battery_info_status_unknown" msgid="268625384868401114">"Tidak diketahui"</string>
<string name="battery_info_status_charging" msgid="4279958015430387405">"Mengisi daya"</string>
<string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Mengisi daya cepat"</string>
diff --git a/packages/SettingsLib/res/values-is/strings.xml b/packages/SettingsLib/res/values-is/strings.xml
index 724cf638de6a..d9ee03adefa4 100644
--- a/packages/SettingsLib/res/values-is/strings.xml
+++ b/packages/SettingsLib/res/values-is/strings.xml
@@ -399,9 +399,9 @@
<string name="inactive_app_inactive_summary" msgid="3161222402614236260">"Óvirkt. Ýttu til að breyta."</string>
<string name="inactive_app_active_summary" msgid="8047630990208722344">"Virkt. Ýttu til að breyta."</string>
<string name="standby_bucket_summary" msgid="5128193447550429600">"Biðstaða forrits: <xliff:g id="BUCKET"> %s</xliff:g>"</string>
- <string name="transcode_settings_title" msgid="6700974145733932357">"Umkóðunarstillingar efnis"</string>
- <string name="transcode_enable_all" msgid="4719796495995795404">"Kveikja á umkóðun í öllum forritum"</string>
- <string name="transcode_skip_apps" msgid="5680997722349545778">"Slökkva á umkóðun í forritum"</string>
+ <string name="transcode_settings_title" msgid="2581975870429850549">"Stillingar efnisumkóðunar"</string>
+ <string name="transcode_enable_all" msgid="9102460144086871903">"Slökkva á umkóðun"</string>
+ <string name="transcode_skip_apps" msgid="8249721984597390142">"Kveikja á umkóðun í forritum"</string>
<string name="runningservices_settings_title" msgid="6460099290493086515">"Þjónustur í gangi"</string>
<string name="runningservices_settings_summary" msgid="1046080643262665743">"Skoða og stjórna þjónustum í gangi"</string>
<string name="select_webview_provider_title" msgid="3917815648099445503">"Innleiðing WebView"</string>
@@ -449,6 +449,8 @@
<string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"<xliff:g id="TIME">%1$s</xliff:g> að fullri hleðslu"</string>
<string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> að fullri hleðslu"</string>
+ <!-- no translation found for power_charging_limited (5902301801611726210) -->
+ <skip />
<string name="battery_info_status_unknown" msgid="268625384868401114">"Óþekkt"</string>
<string name="battery_info_status_charging" msgid="4279958015430387405">"Í hleðslu"</string>
<string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Hröð hleðsla"</string>
diff --git a/packages/SettingsLib/res/values-it/strings.xml b/packages/SettingsLib/res/values-it/strings.xml
index 4edb887d3db3..57378e78af65 100644
--- a/packages/SettingsLib/res/values-it/strings.xml
+++ b/packages/SettingsLib/res/values-it/strings.xml
@@ -399,9 +399,9 @@
<string name="inactive_app_inactive_summary" msgid="3161222402614236260">"Non attiva. Tocca per attivare/disattivare."</string>
<string name="inactive_app_active_summary" msgid="8047630990208722344">"Attiva. Tocca per attivare/disattivare."</string>
<string name="standby_bucket_summary" msgid="5128193447550429600">"Stato di standby dell\'app: <xliff:g id="BUCKET"> %s</xliff:g>"</string>
- <string name="transcode_settings_title" msgid="6700974145733932357">"Impostazioni transcodifica contenuti multimediali"</string>
- <string name="transcode_enable_all" msgid="4719796495995795404">"Attiva transcodifica per tutte le app"</string>
- <string name="transcode_skip_apps" msgid="5680997722349545778">"Disattiva transcodifica per le app"</string>
+ <string name="transcode_settings_title" msgid="2581975870429850549">"Impostazioni transcodifica contenuti multimediali"</string>
+ <string name="transcode_enable_all" msgid="9102460144086871903">"Disattiva transcodifica"</string>
+ <string name="transcode_skip_apps" msgid="8249721984597390142">"Attiva transcodifica per le app"</string>
<string name="runningservices_settings_title" msgid="6460099290493086515">"Servizi in esecuzione"</string>
<string name="runningservices_settings_summary" msgid="1046080643262665743">"Visualizza e controlla i servizi attualmente in esecuzione"</string>
<string name="select_webview_provider_title" msgid="3917815648099445503">"Implementazione di WebView"</string>
@@ -449,6 +449,7 @@
<string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"Tempo rimanente alla carica completa: <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> alla carica completa"</string>
+ <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> - Batteria momentaneamente limitata"</string>
<string name="battery_info_status_unknown" msgid="268625384868401114">"Sconosciuta"</string>
<string name="battery_info_status_charging" msgid="4279958015430387405">"In carica"</string>
<string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Ricarica veloce"</string>
diff --git a/packages/SettingsLib/res/values-iw/strings.xml b/packages/SettingsLib/res/values-iw/strings.xml
index 6c916d9ab399..fd53f14bd48f 100644
--- a/packages/SettingsLib/res/values-iw/strings.xml
+++ b/packages/SettingsLib/res/values-iw/strings.xml
@@ -399,9 +399,12 @@
<string name="inactive_app_inactive_summary" msgid="3161222402614236260">"אפליקציה לא פעילה. הקש כדי להחליף מצב."</string>
<string name="inactive_app_active_summary" msgid="8047630990208722344">"אפליקציה פעילה. הקש כדי להחליף מצב."</string>
<string name="standby_bucket_summary" msgid="5128193447550429600">"אפליקציה במצב המתנה:<xliff:g id="BUCKET"> %s</xliff:g>"</string>
- <string name="transcode_settings_title" msgid="6700974145733932357">"הגדרות המרת קידוד במדיה"</string>
- <string name="transcode_enable_all" msgid="4719796495995795404">"הפעלת המרת קידוד בכל האפליקציות"</string>
- <string name="transcode_skip_apps" msgid="5680997722349545778">"השבתת המרת קידוד באפליקציות"</string>
+ <!-- no translation found for transcode_settings_title (2581975870429850549) -->
+ <skip />
+ <!-- no translation found for transcode_enable_all (9102460144086871903) -->
+ <skip />
+ <!-- no translation found for transcode_skip_apps (8249721984597390142) -->
+ <skip />
<string name="runningservices_settings_title" msgid="6460099290493086515">"שירותים פועלים"</string>
<string name="runningservices_settings_summary" msgid="1046080643262665743">"הצגת השירותים הפועלים כעת ושליטה בהם"</string>
<string name="select_webview_provider_title" msgid="3917815648099445503">"‏יישום WebView"</string>
@@ -449,6 +452,8 @@
<string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g>‏ - <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"נשארו <xliff:g id="TIME">%1$s</xliff:g> עד הטעינה"</string>
<string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> עד הטעינה"</string>
+ <!-- no translation found for power_charging_limited (5902301801611726210) -->
+ <skip />
<string name="battery_info_status_unknown" msgid="268625384868401114">"לא ידוע"</string>
<string name="battery_info_status_charging" msgid="4279958015430387405">"בטעינה"</string>
<string name="battery_info_status_charging_fast" msgid="8027559755902954885">"הסוללה נטענת מהר"</string>
diff --git a/packages/SettingsLib/res/values-ja/strings.xml b/packages/SettingsLib/res/values-ja/strings.xml
index 69392ce1de7a..c0aa74bafc56 100644
--- a/packages/SettingsLib/res/values-ja/strings.xml
+++ b/packages/SettingsLib/res/values-ja/strings.xml
@@ -399,9 +399,9 @@
<string name="inactive_app_inactive_summary" msgid="3161222402614236260">"無効です。タップすると切り替わります。"</string>
<string name="inactive_app_active_summary" msgid="8047630990208722344">"有効です。タップすると切り替わります。"</string>
<string name="standby_bucket_summary" msgid="5128193447550429600">"アプリ スタンバイ状態: <xliff:g id="BUCKET"> %s</xliff:g>"</string>
- <string name="transcode_settings_title" msgid="6700974145733932357">"メディアのコード変換設定"</string>
- <string name="transcode_enable_all" msgid="4719796495995795404">"すべてのアプリに対しコード変換を有効にする"</string>
- <string name="transcode_skip_apps" msgid="5680997722349545778">"アプリに対しコード変換を無効にする"</string>
+ <string name="transcode_settings_title" msgid="2581975870429850549">"メディアのコード変換設定"</string>
+ <string name="transcode_enable_all" msgid="9102460144086871903">"コード変換を無効にする"</string>
+ <string name="transcode_skip_apps" msgid="8249721984597390142">"アプリに対しコード変換を有効にする"</string>
<string name="runningservices_settings_title" msgid="6460099290493086515">"実行中のサービス"</string>
<string name="runningservices_settings_summary" msgid="1046080643262665743">"現在実行中のサービスを表示して制御する"</string>
<string name="select_webview_provider_title" msgid="3917815648099445503">"WebView の実装"</string>
@@ -449,6 +449,8 @@
<string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"充電完了まであと <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - 充電完了まで <xliff:g id="TIME">%2$s</xliff:g>"</string>
+ <!-- no translation found for power_charging_limited (5902301801611726210) -->
+ <skip />
<string name="battery_info_status_unknown" msgid="268625384868401114">"不明"</string>
<string name="battery_info_status_charging" msgid="4279958015430387405">"充電中"</string>
<string name="battery_info_status_charging_fast" msgid="8027559755902954885">"急速充電中"</string>
diff --git a/packages/SettingsLib/res/values-ka/strings.xml b/packages/SettingsLib/res/values-ka/strings.xml
index e81562136a97..d1885789779a 100644
--- a/packages/SettingsLib/res/values-ka/strings.xml
+++ b/packages/SettingsLib/res/values-ka/strings.xml
@@ -399,9 +399,9 @@
<string name="inactive_app_inactive_summary" msgid="3161222402614236260">"უმოქმედო. შეეხეთ გადასართავად."</string>
<string name="inactive_app_active_summary" msgid="8047630990208722344">"აქტიური. შეეხეთ გადასართავად."</string>
<string name="standby_bucket_summary" msgid="5128193447550429600">"აპის მოლოდინის რეჟიმის მდგომარეობა:<xliff:g id="BUCKET"> %s</xliff:g>"</string>
- <string name="transcode_settings_title" msgid="6700974145733932357">"მედიის ტრანსკოდირების პარამეტრები"</string>
- <string name="transcode_enable_all" msgid="4719796495995795404">"ტრანსკოდირების ჩართვა ყველა აპისთვის"</string>
- <string name="transcode_skip_apps" msgid="5680997722349545778">"ტრანსკოდირების გამორთვა ყველა აპისთვის"</string>
+ <string name="transcode_settings_title" msgid="2581975870429850549">"მედიის ტრანსკოდირების პარამეტრები"</string>
+ <string name="transcode_enable_all" msgid="9102460144086871903">"ტრანსკოდირების გათიშვა"</string>
+ <string name="transcode_skip_apps" msgid="8249721984597390142">"ტრანსკოდირების ჩართვა აპებისთვის"</string>
<string name="runningservices_settings_title" msgid="6460099290493086515">"მიმდინარე სერვისები"</string>
<string name="runningservices_settings_summary" msgid="1046080643262665743">"ამჟამად მოქმედი სერვისების ნახვა და მართვა"</string>
<string name="select_webview_provider_title" msgid="3917815648099445503">"WebView რეალიზაცია"</string>
@@ -449,6 +449,7 @@
<string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"დატენვამდე დარჩა <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> დატენვამდე"</string>
+ <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> — ბატარეა დროებით შეზღუდულია"</string>
<string name="battery_info_status_unknown" msgid="268625384868401114">"უცნობი"</string>
<string name="battery_info_status_charging" msgid="4279958015430387405">"იტენება"</string>
<string name="battery_info_status_charging_fast" msgid="8027559755902954885">"სწრაფად იტენება"</string>
diff --git a/packages/SettingsLib/res/values-kk/strings.xml b/packages/SettingsLib/res/values-kk/strings.xml
index c75c722f5b1c..09f3ff5c957a 100644
--- a/packages/SettingsLib/res/values-kk/strings.xml
+++ b/packages/SettingsLib/res/values-kk/strings.xml
@@ -399,9 +399,9 @@
<string name="inactive_app_inactive_summary" msgid="3161222402614236260">"Белсенді емес. Ауыстырып қосу үшін түртіңіз."</string>
<string name="inactive_app_active_summary" msgid="8047630990208722344">"Белсенді. Ауыстырып қосу үшін түртіңіз."</string>
<string name="standby_bucket_summary" msgid="5128193447550429600">"Қолданбаның күту режимі: <xliff:g id="BUCKET"> %s</xliff:g>"</string>
- <string name="transcode_settings_title" msgid="6700974145733932357">"Медиамазмұнды қайта кодтау параметрлері"</string>
- <string name="transcode_enable_all" msgid="4719796495995795404">"Барлық қолданба үшін қайта кодтауға рұқсат ету"</string>
- <string name="transcode_skip_apps" msgid="5680997722349545778">"Қолданбалар үшін қайта кодтауды өшіру"</string>
+ <string name="transcode_settings_title" msgid="2581975870429850549">"Медиамазмұнды қайта кодтау параметрлері"</string>
+ <string name="transcode_enable_all" msgid="9102460144086871903">"Қайта кодтауды өшіру"</string>
+ <string name="transcode_skip_apps" msgid="8249721984597390142">"Қолданбалар үшін қайта кодтауға рұқсат ету"</string>
<string name="runningservices_settings_title" msgid="6460099290493086515">"Қосылып тұрған қызметтер"</string>
<string name="runningservices_settings_summary" msgid="1046080643262665743">"Қазір істеп тұрған қызметтерді көру және басқару"</string>
<string name="select_webview_provider_title" msgid="3917815648099445503">"WebView қызметі"</string>
@@ -449,6 +449,8 @@
<string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"Зарядталғанға дейін <xliff:g id="TIME">%1$s</xliff:g> қалды"</string>
<string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> – зарядталғанға дейін <xliff:g id="TIME">%2$s</xliff:g>"</string>
+ <!-- no translation found for power_charging_limited (5902301801611726210) -->
+ <skip />
<string name="battery_info_status_unknown" msgid="268625384868401114">"Белгісіз"</string>
<string name="battery_info_status_charging" msgid="4279958015430387405">"Зарядталуда"</string>
<string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Жылдам зарядталуда"</string>
diff --git a/packages/SettingsLib/res/values-km/strings.xml b/packages/SettingsLib/res/values-km/strings.xml
index 2590a9fe46d7..42e6a53a0078 100644
--- a/packages/SettingsLib/res/values-km/strings.xml
+++ b/packages/SettingsLib/res/values-km/strings.xml
@@ -399,9 +399,9 @@
<string name="inactive_app_inactive_summary" msgid="3161222402614236260">"សកម្ម។ ប៉ះដើម្បីបិទ/បើក។"</string>
<string name="inactive_app_active_summary" msgid="8047630990208722344">"សកម្ម។ ប៉ះដើម្បីបិទ/បើក។"</string>
<string name="standby_bucket_summary" msgid="5128193447550429600">"ស្ថាន​ភាព​មុខងារ​ផ្អាក​ដំណើរការ​កម្មវិធី៖<xliff:g id="BUCKET"> %s</xliff:g>"</string>
- <string name="transcode_settings_title" msgid="6700974145733932357">"ការកំណត់​ការបំប្លែង​កូដមេឌៀ"</string>
- <string name="transcode_enable_all" msgid="4719796495995795404">"បើក​ការបំប្លែងកូដ​សម្រាប់​កម្មវិធីទាំងអស់"</string>
- <string name="transcode_skip_apps" msgid="5680997722349545778">"បិទ​ការបំប្លែងកូដ​សម្រាប់​កម្មវិធី"</string>
+ <string name="transcode_settings_title" msgid="2581975870429850549">"ការកំណត់​ការបំប្លែង​កូដមេឌៀ"</string>
+ <string name="transcode_enable_all" msgid="9102460144086871903">"បិទ​ការបំប្លែងកូដ"</string>
+ <string name="transcode_skip_apps" msgid="8249721984597390142">"បើក​ការបំប្លែងកូដ​សម្រាប់​កម្មវិធី"</string>
<string name="runningservices_settings_title" msgid="6460099290493086515">"សេវាកម្ម​កំពុង​ដំណើរការ"</string>
<string name="runningservices_settings_summary" msgid="1046080643262665743">"មើល និង​គ្រប់គ្រង​សេវាកម្ម​កំពុង​ដំណើរការ​បច្ចុប្បន្ន"</string>
<string name="select_webview_provider_title" msgid="3917815648099445503">"ការអនុវត្ត WebView"</string>
@@ -449,6 +449,8 @@
<string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"<xliff:g id="TIME">%1$s</xliff:g> ទៀតទើបសាកថ្មពេញ"</string>
<string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> ទៀតទើប​សាកថ្មពេញ"</string>
+ <!-- no translation found for power_charging_limited (5902301801611726210) -->
+ <skip />
<string name="battery_info_status_unknown" msgid="268625384868401114">"មិន​ស្គាល់"</string>
<string name="battery_info_status_charging" msgid="4279958015430387405">"កំពុងបញ្ចូល​ថ្ម"</string>
<string name="battery_info_status_charging_fast" msgid="8027559755902954885">"កំពុងសាកថ្មយ៉ាងឆាប់រហ័ស"</string>
diff --git a/packages/SettingsLib/res/values-kn/strings.xml b/packages/SettingsLib/res/values-kn/strings.xml
index dad3e03e94c7..658b987dd833 100644
--- a/packages/SettingsLib/res/values-kn/strings.xml
+++ b/packages/SettingsLib/res/values-kn/strings.xml
@@ -399,9 +399,9 @@
<string name="inactive_app_inactive_summary" msgid="3161222402614236260">"ನಿಷ್ಕ್ರಿಯ. ಟಾಗಲ್ ಮಾಡಲು ಟ್ಯಾಪ್ ಮಾಡಿ."</string>
<string name="inactive_app_active_summary" msgid="8047630990208722344">"ಸಕ್ರಿಯ. ಟಾಗಲ್ ಮಾಡಲು ಟ್ಯಾಪ್ ಮಾಡಿ."</string>
<string name="standby_bucket_summary" msgid="5128193447550429600">"ಅಪ್ಲಿಕೇಶನ್ ಸ್ಟ್ಯಾಂಡ್‌ಬೈ ಸ್ಥಿತಿ:<xliff:g id="BUCKET"> %s</xliff:g>"</string>
- <string name="transcode_settings_title" msgid="6700974145733932357">"ಮಾಧ್ಯಮ ಟ್ರಾನ್ಸ್‌ಕೋಡ್ ಸೆಟ್ಟಿಂಗ್‌ಗಳು"</string>
- <string name="transcode_enable_all" msgid="4719796495995795404">"ಎಲ್ಲಾ ಆ್ಯಪ್‌ಗಳಿಗಾಗಿ ಟ್ರಾನ್ಸ್‌ಕೋಡಿಂಗ್ ಅನ್ನು ಸಕ್ರಿಯಗೊಳಿಸಿ"</string>
- <string name="transcode_skip_apps" msgid="5680997722349545778">"ಆ್ಯಪ್‌ಗಳಿಗಾಗಿ ಟ್ರಾನ್ಸ್‌ಕೋಡಿಂಗ್ ಅನ್ನು ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಿ"</string>
+ <string name="transcode_settings_title" msgid="2581975870429850549">"ಮೀಡಿಯಾ ಟ್ರಾನ್ಸ್‌ಕೋಡಿಂಗ್ ಸೆಟ್ಟಿಂಗ್‌ಗಳು"</string>
+ <string name="transcode_enable_all" msgid="9102460144086871903">"ಟ್ರಾನ್ಸ್‌ಕೋಡಿಂಗ್ ಅನ್ನು ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಿ"</string>
+ <string name="transcode_skip_apps" msgid="8249721984597390142">"ಆ್ಯಪ್‌ಗಳಿಗಾಗಿ ಟ್ರಾನ್ಸ್‌ಕೋಡಿಂಗ್ ಅನ್ನು ಸಕ್ರಿಯಗೊಳಿಸಿ"</string>
<string name="runningservices_settings_title" msgid="6460099290493086515">"ರನ್‌ ಆಗುತ್ತಿರುವ ಸೇವೆಗಳು"</string>
<string name="runningservices_settings_summary" msgid="1046080643262665743">"ಈಗ ರನ್‌ ಆಗುತ್ತಿರುವ ಸೇವೆಗಳನ್ನು ವೀಕ್ಷಿಸಿ ಮತ್ತು ನಿಯಂತ್ರಿಸಿ"</string>
<string name="select_webview_provider_title" msgid="3917815648099445503">"WebView ಹೊಂದಿಸಿ"</string>
@@ -449,6 +449,8 @@
<string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"ಚಾರ್ಜ್ ಆಗಲು <xliff:g id="TIME">%1$s</xliff:g> ಸಮಯ ಬಾಕಿ ಇದೆ"</string>
<string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - ಚಾರ್ಜ್ ಆಗಲು <xliff:g id="TIME">%2$s</xliff:g> ಸಮಯ ಬೇಕು"</string>
+ <!-- no translation found for power_charging_limited (5902301801611726210) -->
+ <skip />
<string name="battery_info_status_unknown" msgid="268625384868401114">"ಅಪರಿಚಿತ"</string>
<string name="battery_info_status_charging" msgid="4279958015430387405">"ಚಾರ್ಜ್ ಆಗುತ್ತಿದೆ"</string>
<string name="battery_info_status_charging_fast" msgid="8027559755902954885">"ವೇಗದ ಚಾರ್ಜಿಂಗ್"</string>
diff --git a/packages/SettingsLib/res/values-ko/strings.xml b/packages/SettingsLib/res/values-ko/strings.xml
index d41e7dbc1e5d..2b0843dcef39 100644
--- a/packages/SettingsLib/res/values-ko/strings.xml
+++ b/packages/SettingsLib/res/values-ko/strings.xml
@@ -399,9 +399,9 @@
<string name="inactive_app_inactive_summary" msgid="3161222402614236260">"비활성화 상태입니다. 전환하려면 탭하세요."</string>
<string name="inactive_app_active_summary" msgid="8047630990208722344">"활성화되었습니다. 전환하려면 탭하세요."</string>
<string name="standby_bucket_summary" msgid="5128193447550429600">"앱 대기 상태:<xliff:g id="BUCKET"> %s</xliff:g>"</string>
- <string name="transcode_settings_title" msgid="6700974145733932357">"미디어 트랜스코딩 설정"</string>
- <string name="transcode_enable_all" msgid="4719796495995795404">"모든 앱에서 트랜스코딩 사용 설정"</string>
- <string name="transcode_skip_apps" msgid="5680997722349545778">"모든 앱에서 트랜스코딩 사용 중지"</string>
+ <string name="transcode_settings_title" msgid="2581975870429850549">"미디어 트랜스코딩 설정"</string>
+ <string name="transcode_enable_all" msgid="9102460144086871903">"트랜스코딩 사용 중지"</string>
+ <string name="transcode_skip_apps" msgid="8249721984597390142">"앱 트랜스코딩 사용 설정"</string>
<string name="runningservices_settings_title" msgid="6460099290493086515">"실행 중인 서비스"</string>
<string name="runningservices_settings_summary" msgid="1046080643262665743">"현재 실행 중인 서비스 보기 및 제어"</string>
<string name="select_webview_provider_title" msgid="3917815648099445503">"WebView 구현"</string>
@@ -449,6 +449,8 @@
<string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"충전 완료까지 <xliff:g id="TIME">%1$s</xliff:g> 남음"</string>
<string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - 충전 완료까지 <xliff:g id="TIME">%2$s</xliff:g> 남음"</string>
+ <!-- no translation found for power_charging_limited (5902301801611726210) -->
+ <skip />
<string name="battery_info_status_unknown" msgid="268625384868401114">"알 수 없음"</string>
<string name="battery_info_status_charging" msgid="4279958015430387405">"충전 중"</string>
<string name="battery_info_status_charging_fast" msgid="8027559755902954885">"고속 충전 중"</string>
diff --git a/packages/SettingsLib/res/values-ky/strings.xml b/packages/SettingsLib/res/values-ky/strings.xml
index c07f334abdf2..499fd88f5a4f 100644
--- a/packages/SettingsLib/res/values-ky/strings.xml
+++ b/packages/SettingsLib/res/values-ky/strings.xml
@@ -399,9 +399,9 @@
<string name="inactive_app_inactive_summary" msgid="3161222402614236260">"Иштеген жок. Күйгүзүү үчүн басып коюңуз."</string>
<string name="inactive_app_active_summary" msgid="8047630990208722344">"Иштеп турат. Өчүрүү үчүн басып коюңуз."</string>
<string name="standby_bucket_summary" msgid="5128193447550429600">"Көшүү режиминдеги колдонмонун абалы:<xliff:g id="BUCKET"> %s</xliff:g>"</string>
- <string name="transcode_settings_title" msgid="6700974145733932357">"Медианы транскоддоо жөндөөлөрү"</string>
- <string name="transcode_enable_all" msgid="4719796495995795404">"Бардык колдонмолор үчүн транскоддоону иштетүү"</string>
- <string name="transcode_skip_apps" msgid="5680997722349545778">"Бардык колдонмолор үчүн транскоддоону өчүрүү"</string>
+ <string name="transcode_settings_title" msgid="2581975870429850549">"Медиа файлдарды транскоддоо жөндөөлөрү"</string>
+ <string name="transcode_enable_all" msgid="9102460144086871903">"Транскоддоону өчүрүү"</string>
+ <string name="transcode_skip_apps" msgid="8249721984597390142">"Колдонмолорду транскоддоону күйгүзүү"</string>
<string name="runningservices_settings_title" msgid="6460099290493086515">"Иштеп жаткан кызматтар"</string>
<string name="runningservices_settings_summary" msgid="1046080643262665743">"Учурда иштеп жаткан кызматтарды көрүп, көзөмөлдөп турасыз"</string>
<string name="select_webview_provider_title" msgid="3917815648099445503">"WebView кызматы"</string>
@@ -449,6 +449,8 @@
<string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"<xliff:g id="TIME">%1$s</xliff:g> кийин толук кубатталып бүтөт"</string>
<string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> кийин толук кубатталып бүтөт"</string>
+ <!-- no translation found for power_charging_limited (5902301801611726210) -->
+ <skip />
<string name="battery_info_status_unknown" msgid="268625384868401114">"Белгисиз"</string>
<string name="battery_info_status_charging" msgid="4279958015430387405">"Кубатталууда"</string>
<string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Ыкчам кубатталууда"</string>
diff --git a/packages/SettingsLib/res/values-lo/strings.xml b/packages/SettingsLib/res/values-lo/strings.xml
index 5aa27bf2a67a..a5be6017ca62 100644
--- a/packages/SettingsLib/res/values-lo/strings.xml
+++ b/packages/SettingsLib/res/values-lo/strings.xml
@@ -399,9 +399,9 @@
<string name="inactive_app_inactive_summary" msgid="3161222402614236260">"ບໍ່ໄດ້ນຳໃຊ້. ແຕະບໍ່ສັບປ່ຽນ."</string>
<string name="inactive_app_active_summary" msgid="8047630990208722344">"ນຳໃຊ້ຢູ່. ແຕະເພື່ອສັບປ່ຽນ."</string>
<string name="standby_bucket_summary" msgid="5128193447550429600">"ສະຖານະສະແຕນບາຍແອັບ:<xliff:g id="BUCKET"> %s</xliff:g>"</string>
- <string name="transcode_settings_title" msgid="6700974145733932357">"ການຕັ້ງຄ່າການ​ປ່ຽນ​ຮູບ​ແບບ​ລະ​ຫັດມີເດຍ"</string>
- <string name="transcode_enable_all" msgid="4719796495995795404">"ເປີດການນຳໃຊ້ການ​ປ່ຽນ​ຮູບ​ແບບ​ລະ​ຫັດສຳລັບທຸກແອັບ"</string>
- <string name="transcode_skip_apps" msgid="5680997722349545778">"ປິດການນຳໃຊ້ການ​ປ່ຽນ​ຮູບ​ແບບ​ລະ​ຫັດສຳລັບແອັບ"</string>
+ <string name="transcode_settings_title" msgid="2581975870429850549">"ການຕັ້ງຄ່າການ​ປ່ຽນ​ຮູບ​ແບບ​ລະ​ຫັດມີເດຍ"</string>
+ <string name="transcode_enable_all" msgid="9102460144086871903">"ປິດການນຳໃຊ້ການ​ປ່ຽນ​ຮູບ​ແບບ​ລະ​ຫັດ"</string>
+ <string name="transcode_skip_apps" msgid="8249721984597390142">"ເປີດການນຳໃຊ້ການ​ປ່ຽນ​ຮູບ​ແບບ​ລະ​ຫັດສຳລັບແອັບ"</string>
<string name="runningservices_settings_title" msgid="6460099290493086515">"ບໍລິການທີ່ເຮັດວຽກຢູ່"</string>
<string name="runningservices_settings_summary" msgid="1046080643262665743">"ເບິ່ງ ແລະຈັດການບໍລິການທີ່ກຳລັງເຮັດວຽກຢູ່ໃນປັດຈຸບັນ"</string>
<string name="select_webview_provider_title" msgid="3917815648099445503">"ການຈັດຕັ້ງປະຕິບັດ WebView"</string>
@@ -449,6 +449,8 @@
<string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"<xliff:g id="TIME">%1$s</xliff:g> ຈົນກວ່າຈະສາກເຕັມ"</string>
<string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> ຈົນກວ່າຈະສາກເຕັມ"</string>
+ <!-- no translation found for power_charging_limited (5902301801611726210) -->
+ <skip />
<string name="battery_info_status_unknown" msgid="268625384868401114">"ບໍ່ຮູ້ຈັກ"</string>
<string name="battery_info_status_charging" msgid="4279958015430387405">"ກຳລັງສາກໄຟ"</string>
<string name="battery_info_status_charging_fast" msgid="8027559755902954885">"ກຳລັງສາກໄຟດ່ວນ"</string>
diff --git a/packages/SettingsLib/res/values-lt/strings.xml b/packages/SettingsLib/res/values-lt/strings.xml
index ff4d336440eb..181fb10dd845 100644
--- a/packages/SettingsLib/res/values-lt/strings.xml
+++ b/packages/SettingsLib/res/values-lt/strings.xml
@@ -399,9 +399,9 @@
<string name="inactive_app_inactive_summary" msgid="3161222402614236260">"Neaktyvi. Palieskite, kad perjungtumėte."</string>
<string name="inactive_app_active_summary" msgid="8047630990208722344">"Aktyvi. Palieskite, kad perjungtumėte."</string>
<string name="standby_bucket_summary" msgid="5128193447550429600">"Programų budėjimo režimo būsena: <xliff:g id="BUCKET"> %s</xliff:g>"</string>
- <string name="transcode_settings_title" msgid="6700974145733932357">"Medijos perkodavimo nustatymai"</string>
- <string name="transcode_enable_all" msgid="4719796495995795404">"Įjungti visų programų perkodavimą"</string>
- <string name="transcode_skip_apps" msgid="5680997722349545778">"Išjungti programų perkodavimą"</string>
+ <string name="transcode_settings_title" msgid="2581975870429850549">"Medijos perkodavimo nustatymai"</string>
+ <string name="transcode_enable_all" msgid="9102460144086871903">"Išjungti perkodavimą"</string>
+ <string name="transcode_skip_apps" msgid="8249721984597390142">"Įjungti programų perkodavimą"</string>
<string name="runningservices_settings_title" msgid="6460099290493086515">"Vykdomos paslaugos"</string>
<string name="runningservices_settings_summary" msgid="1046080643262665743">"Žiūrėti ir valdyti dabar vykdomas paslaugas"</string>
<string name="select_webview_provider_title" msgid="3917815648099445503">"„WebView“ diegimas"</string>
@@ -449,6 +449,8 @@
<string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"Iki visiškos įkrovos liko <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> – iki visiškos įkrovos liko <xliff:g id="TIME">%2$s</xliff:g>"</string>
+ <!-- no translation found for power_charging_limited (5902301801611726210) -->
+ <skip />
<string name="battery_info_status_unknown" msgid="268625384868401114">"Nežinomas"</string>
<string name="battery_info_status_charging" msgid="4279958015430387405">"Kraunasi..."</string>
<string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Greitai įkraunama"</string>
diff --git a/packages/SettingsLib/res/values-lv/strings.xml b/packages/SettingsLib/res/values-lv/strings.xml
index e876cef9a98a..717e2b0c89d8 100644
--- a/packages/SettingsLib/res/values-lv/strings.xml
+++ b/packages/SettingsLib/res/values-lv/strings.xml
@@ -399,9 +399,9 @@
<string name="inactive_app_inactive_summary" msgid="3161222402614236260">"Neaktīva. Pieskarieties, lai pārslēgtu."</string>
<string name="inactive_app_active_summary" msgid="8047630990208722344">"Aktīva. Pieskarieties, lai pārslēgtu."</string>
<string name="standby_bucket_summary" msgid="5128193447550429600">"Lietotnes gaidstāves stāvoklis: <xliff:g id="BUCKET"> %s</xliff:g>"</string>
- <string name="transcode_settings_title" msgid="6700974145733932357">"Multivides failu pārkodēšanas iestatījumi"</string>
- <string name="transcode_enable_all" msgid="4719796495995795404">"Iespējot pārkodēšanu visām lietotnēm"</string>
- <string name="transcode_skip_apps" msgid="5680997722349545778">"Atspējot pārkodēšanu noteiktām lietotnēm"</string>
+ <string name="transcode_settings_title" msgid="2581975870429850549">"Multivides failu pārkodēšanas iestatījumi"</string>
+ <string name="transcode_enable_all" msgid="9102460144086871903">"Atspējot pārkodēšanu"</string>
+ <string name="transcode_skip_apps" msgid="8249721984597390142">"Iespējot pārkodēšanu noteiktām lietotnēm"</string>
<string name="runningservices_settings_title" msgid="6460099290493086515">"Aktīvie pakalpojumi"</string>
<string name="runningservices_settings_summary" msgid="1046080643262665743">"Pašreiz darbojošos pakalpojumu skatīšana un vadība"</string>
<string name="select_webview_provider_title" msgid="3917815648099445503">"WebView ieviešana"</string>
@@ -449,6 +449,8 @@
<string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> — <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"Vēl <xliff:g id="TIME">%1$s</xliff:g> līdz pilnai uzlādei"</string>
<string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> — <xliff:g id="TIME">%2$s</xliff:g> līdz pilnai uzlādei"</string>
+ <!-- no translation found for power_charging_limited (5902301801611726210) -->
+ <skip />
<string name="battery_info_status_unknown" msgid="268625384868401114">"Nezināms"</string>
<string name="battery_info_status_charging" msgid="4279958015430387405">"Uzlāde"</string>
<string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Notiek ātrā uzlāde"</string>
diff --git a/packages/SettingsLib/res/values-mk/strings.xml b/packages/SettingsLib/res/values-mk/strings.xml
index 3507ae723f2a..2ccb150b8ca3 100644
--- a/packages/SettingsLib/res/values-mk/strings.xml
+++ b/packages/SettingsLib/res/values-mk/strings.xml
@@ -51,9 +51,9 @@
<string name="connected_via_carrier" msgid="1968057009076191514">"Поврзано преку %1$s"</string>
<string name="available_via_carrier" msgid="465598683092718294">"Достапно преку %1$s"</string>
<string name="osu_opening_provider" msgid="4318105381295178285">"Се отвора <xliff:g id="PASSPOINTPROVIDER">%1$s</xliff:g>"</string>
- <string name="osu_connect_failed" msgid="9107873364807159193">"Не можеше да се поврзе"</string>
+ <string name="osu_connect_failed" msgid="9107873364807159193">"Не може да се поврзе"</string>
<string name="osu_completing_sign_up" msgid="8412636665040390901">"Се завршува регистрацијата…"</string>
- <string name="osu_sign_up_failed" msgid="5605453599586001793">"Не можеше да се заврши регистрацијата. Допрете за да се обидете повторно."</string>
+ <string name="osu_sign_up_failed" msgid="5605453599586001793">"Не може да се заврши регистрацијата. Допрете за да се обидете повторно."</string>
<string name="osu_sign_up_complete" msgid="7640183358878916847">"Регистрацијата е завршена. Се поврзува…"</string>
<string name="speed_label_very_slow" msgid="8526005255731597666">"Многу бавна"</string>
<string name="speed_label_slow" msgid="6069917670665664161">"Бавна"</string>
@@ -116,8 +116,8 @@
<string name="bluetooth_pairing_accept_all_caps" msgid="2734383073450506220">"СПАРИ"</string>
<string name="bluetooth_pairing_decline" msgid="6483118841204885890">"Откажи"</string>
<string name="bluetooth_pairing_will_share_phonebook" msgid="3064334458659165176">"Кога е поврзано, спарувањето одобрува пристап до контактите и историјата на повиците."</string>
- <string name="bluetooth_pairing_error_message" msgid="6626399020672335565">"Не можеше да се спари со <xliff:g id="DEVICE_NAME">%1$s</xliff:g>."</string>
- <string name="bluetooth_pairing_pin_error_message" msgid="264422127613704940">"Не можеше да се спари со <xliff:g id="DEVICE_NAME">%1$s</xliff:g> поради погрешен PIN или лозинка."</string>
+ <string name="bluetooth_pairing_error_message" msgid="6626399020672335565">"Не може да се спари со <xliff:g id="DEVICE_NAME">%1$s</xliff:g>."</string>
+ <string name="bluetooth_pairing_pin_error_message" msgid="264422127613704940">"Не може да се спари со <xliff:g id="DEVICE_NAME">%1$s</xliff:g> поради погрешен PIN или лозинка."</string>
<string name="bluetooth_pairing_device_down_error_message" msgid="2554424863101358857">"Не може да комуницира со <xliff:g id="DEVICE_NAME">%1$s</xliff:g>."</string>
<string name="bluetooth_pairing_rejected_error_message" msgid="5943444352777314442">"Спарувањето е одбиено од <xliff:g id="DEVICE_NAME">%1$s</xliff:g>."</string>
<string name="bluetooth_talkback_computer" msgid="3736623135703893773">"Компјутер"</string>
@@ -399,9 +399,9 @@
<string name="inactive_app_inactive_summary" msgid="3161222402614236260">"Неактивно. Допрете за да смените."</string>
<string name="inactive_app_active_summary" msgid="8047630990208722344">"Активно. Допрете за да смените."</string>
<string name="standby_bucket_summary" msgid="5128193447550429600">"Состојба на мирување на апликацијата: <xliff:g id="BUCKET"> %s</xliff:g>"</string>
- <string name="transcode_settings_title" msgid="6700974145733932357">"Поставки за транскодирање на аудиовизуелни содржини"</string>
- <string name="transcode_enable_all" msgid="4719796495995795404">"Овозможи транскодирање за сите апликации"</string>
- <string name="transcode_skip_apps" msgid="5680997722349545778">"Оневозможи транскодирање за сите апликации"</string>
+ <string name="transcode_settings_title" msgid="2581975870429850549">"Поставки за транскодирање аудиовизуелни содржини"</string>
+ <string name="transcode_enable_all" msgid="9102460144086871903">"Оневозможи транскодирање"</string>
+ <string name="transcode_skip_apps" msgid="8249721984597390142">"Овозможете транскодирање за апликациите"</string>
<string name="runningservices_settings_title" msgid="6460099290493086515">"Активни услуги"</string>
<string name="runningservices_settings_summary" msgid="1046080643262665743">"Погледнете и контролирајте услуги што се моментално активни"</string>
<string name="select_webview_provider_title" msgid="3917815648099445503">"Воведување WebView"</string>
@@ -449,6 +449,8 @@
<string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"Уште <xliff:g id="TIME">%1$s</xliff:g> до целосно полнење"</string>
<string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> до целосно полнење"</string>
+ <!-- no translation found for power_charging_limited (5902301801611726210) -->
+ <skip />
<string name="battery_info_status_unknown" msgid="268625384868401114">"Непознато"</string>
<string name="battery_info_status_charging" msgid="4279958015430387405">"Се полни"</string>
<string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Брзо полнење"</string>
diff --git a/packages/SettingsLib/res/values-ml/strings.xml b/packages/SettingsLib/res/values-ml/strings.xml
index 4aae6ee47930..768ad5e70698 100644
--- a/packages/SettingsLib/res/values-ml/strings.xml
+++ b/packages/SettingsLib/res/values-ml/strings.xml
@@ -399,11 +399,11 @@
<string name="inactive_app_inactive_summary" msgid="3161222402614236260">"നിഷ്‌ക്രിയം. മാറ്റുന്നതിനു ടാപ്പുചെയ്യുക."</string>
<string name="inactive_app_active_summary" msgid="8047630990208722344">"സജീവം. മാറ്റുന്നതിന് ടാപ്പുചെയ്യുക."</string>
<string name="standby_bucket_summary" msgid="5128193447550429600">"ആപ്പ് സ്‌റ്റാൻഡ്‌ബൈ നില:<xliff:g id="BUCKET"> %s</xliff:g>"</string>
- <!-- no translation found for transcode_settings_title (6700974145733932357) -->
+ <!-- no translation found for transcode_settings_title (2581975870429850549) -->
<skip />
- <!-- no translation found for transcode_enable_all (4719796495995795404) -->
+ <!-- no translation found for transcode_enable_all (9102460144086871903) -->
<skip />
- <!-- no translation found for transcode_skip_apps (5680997722349545778) -->
+ <!-- no translation found for transcode_skip_apps (8249721984597390142) -->
<skip />
<string name="runningservices_settings_title" msgid="6460099290493086515">"പ്രവർത്തിക്കുന്ന സേവനങ്ങൾ"</string>
<string name="runningservices_settings_summary" msgid="1046080643262665743">"നിലവിൽ പ്രവർത്തിക്കുന്ന സേവനങ്ങൾ കാണുക, നിയന്ത്രിക്കുക"</string>
@@ -452,6 +452,8 @@
<string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"പൂർണ്ണമായി ചാർജാവാൻ <xliff:g id="TIME">%1$s</xliff:g> ശേഷിക്കുന്നു"</string>
<string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - പൂർണ്ണമായി ചാർജാവാൻ <xliff:g id="TIME">%2$s</xliff:g>"</string>
+ <!-- no translation found for power_charging_limited (5902301801611726210) -->
+ <skip />
<string name="battery_info_status_unknown" msgid="268625384868401114">"അജ്ഞാതം"</string>
<string name="battery_info_status_charging" msgid="4279958015430387405">"ചാർജ് ചെയ്യുന്നു"</string>
<string name="battery_info_status_charging_fast" msgid="8027559755902954885">"അതിവേഗ ചാർജിംഗ്"</string>
diff --git a/packages/SettingsLib/res/values-mn/strings.xml b/packages/SettingsLib/res/values-mn/strings.xml
index 9cdf5bf98ede..61ebca5992b8 100644
--- a/packages/SettingsLib/res/values-mn/strings.xml
+++ b/packages/SettingsLib/res/values-mn/strings.xml
@@ -399,9 +399,9 @@
<string name="inactive_app_inactive_summary" msgid="3161222402614236260">"Идэвхгүй байна. Унтраах/асаахын тулд дарна уу."</string>
<string name="inactive_app_active_summary" msgid="8047630990208722344">"Идэвхтэй байна. Унтраах/асаахын тулд дарна уу."</string>
<string name="standby_bucket_summary" msgid="5128193447550429600">"Апп зогсолтын горимын төлөв:<xliff:g id="BUCKET"> %s</xliff:g>"</string>
- <string name="transcode_settings_title" msgid="6700974145733932357">"Медиагийн хөрвүүлгийн тохиргоо"</string>
- <string name="transcode_enable_all" msgid="4719796495995795404">"Бүх аппад хөрвүүлгийг идэвхжүүлэх"</string>
- <string name="transcode_skip_apps" msgid="5680997722349545778">"Аппуудад хөрвүүлгийг идэвхгүй болгох"</string>
+ <string name="transcode_settings_title" msgid="2581975870429850549">"Медиа хөрвүүлгийн тохиргоо"</string>
+ <string name="transcode_enable_all" msgid="9102460144086871903">"Хөрвүүлгийг идэвхгүй болгох"</string>
+ <string name="transcode_skip_apps" msgid="8249721984597390142">"Аппуудад хөрвүүлгийг идэвхжүүлэх"</string>
<string name="runningservices_settings_title" msgid="6460099290493086515">"Ажиллаж байгаа үйлчилгээнүүд"</string>
<string name="runningservices_settings_summary" msgid="1046080643262665743">"Одоо ажиллаж байгаа үйлчилгээнүүдийг харах болон хянах"</string>
<string name="select_webview_provider_title" msgid="3917815648099445503">"WebView хэрэгжилт"</string>
@@ -449,6 +449,8 @@
<string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"Цэнэглэх хүртэл үлдсэн <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - цэнэглэх хүртэл <xliff:g id="TIME">%2$s</xliff:g>"</string>
+ <!-- no translation found for power_charging_limited (5902301801611726210) -->
+ <skip />
<string name="battery_info_status_unknown" msgid="268625384868401114">"Тодорхойгүй"</string>
<string name="battery_info_status_charging" msgid="4279958015430387405">"Цэнэглэж байна"</string>
<string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Хурдан цэнэглэж байна"</string>
diff --git a/packages/SettingsLib/res/values-mr/strings.xml b/packages/SettingsLib/res/values-mr/strings.xml
index d6563ae41832..ef319c3a4fc1 100644
--- a/packages/SettingsLib/res/values-mr/strings.xml
+++ b/packages/SettingsLib/res/values-mr/strings.xml
@@ -399,11 +399,11 @@
<string name="inactive_app_inactive_summary" msgid="3161222402614236260">"निष्क्रिय. टॉगल करण्यासाठी टॅप करा."</string>
<string name="inactive_app_active_summary" msgid="8047630990208722344">"सक्रिय. टॉगल करण्यासाठी टॅप करा."</string>
<string name="standby_bucket_summary" msgid="5128193447550429600">"अ‍ॅप स्टँडबाय स्थिती: <xliff:g id="BUCKET"> %s</xliff:g>"</string>
- <!-- no translation found for transcode_settings_title (6700974145733932357) -->
+ <!-- no translation found for transcode_settings_title (2581975870429850549) -->
<skip />
- <!-- no translation found for transcode_enable_all (4719796495995795404) -->
+ <!-- no translation found for transcode_enable_all (9102460144086871903) -->
<skip />
- <!-- no translation found for transcode_skip_apps (5680997722349545778) -->
+ <!-- no translation found for transcode_skip_apps (8249721984597390142) -->
<skip />
<string name="runningservices_settings_title" msgid="6460099290493086515">"सुरू सेवा"</string>
<string name="runningservices_settings_summary" msgid="1046080643262665743">"सध्या सुरू असलेल्या सेवा पहा आणि नियंत्रित करा"</string>
@@ -452,6 +452,8 @@
<string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"<xliff:g id="TIME">%1$s</xliff:g> पर्यंत पूर्ण चार्ज होईल"</string>
<string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> पर्यंत पूर्ण चार्ज होईल"</string>
+ <!-- no translation found for power_charging_limited (5902301801611726210) -->
+ <skip />
<string name="battery_info_status_unknown" msgid="268625384868401114">"अज्ञात"</string>
<string name="battery_info_status_charging" msgid="4279958015430387405">"चार्ज होत आहे"</string>
<string name="battery_info_status_charging_fast" msgid="8027559755902954885">"वेगाने चार्ज होत आहे"</string>
diff --git a/packages/SettingsLib/res/values-ms/strings.xml b/packages/SettingsLib/res/values-ms/strings.xml
index 6bcc5d2fa3e8..83c038453265 100644
--- a/packages/SettingsLib/res/values-ms/strings.xml
+++ b/packages/SettingsLib/res/values-ms/strings.xml
@@ -399,9 +399,9 @@
<string name="inactive_app_inactive_summary" msgid="3161222402614236260">"Tidak aktif. Ketik untuk menogol."</string>
<string name="inactive_app_active_summary" msgid="8047630990208722344">"Aktif. Ketik untuk menogol."</string>
<string name="standby_bucket_summary" msgid="5128193447550429600">"Keadaan tunggu sedia apl:<xliff:g id="BUCKET"> %s</xliff:g>"</string>
- <string name="transcode_settings_title" msgid="6700974145733932357">"Tetapan transpengekodan media"</string>
- <string name="transcode_enable_all" msgid="4719796495995795404">"Dayakan transpengekodan untuk semua apl"</string>
- <string name="transcode_skip_apps" msgid="5680997722349545778">"Lumpuhkan transpengekodan untuk apl"</string>
+ <string name="transcode_settings_title" msgid="2581975870429850549">"Tetapan transpengekodan media"</string>
+ <string name="transcode_enable_all" msgid="9102460144086871903">"Lumpuhkan transpengekodan"</string>
+ <string name="transcode_skip_apps" msgid="8249721984597390142">"Dayakan transpengekodan untuk apl"</string>
<string name="runningservices_settings_title" msgid="6460099290493086515">"Perkhidmatan dijalankan"</string>
<string name="runningservices_settings_summary" msgid="1046080643262665743">"Lihat dan kawal perkhidmatan yang sedang dijalankan"</string>
<string name="select_webview_provider_title" msgid="3917815648099445503">"Pelaksanaan WebView"</string>
@@ -449,6 +449,8 @@
<string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"<xliff:g id="TIME">%1$s</xliff:g> lagi sehingga dicas penuh"</string>
<string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> sehingga dicas"</string>
+ <!-- no translation found for power_charging_limited (5902301801611726210) -->
+ <skip />
<string name="battery_info_status_unknown" msgid="268625384868401114">"Tidak diketahui"</string>
<string name="battery_info_status_charging" msgid="4279958015430387405">"Mengecas"</string>
<string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Mengecas dgn cepat"</string>
diff --git a/packages/SettingsLib/res/values-my/strings.xml b/packages/SettingsLib/res/values-my/strings.xml
index 8bb717a57789..f398487856bf 100644
--- a/packages/SettingsLib/res/values-my/strings.xml
+++ b/packages/SettingsLib/res/values-my/strings.xml
@@ -399,9 +399,9 @@
<string name="inactive_app_inactive_summary" msgid="3161222402614236260">"ပွင့်မနေပါ။ ပြောင်းရန်တို့ပါ။"</string>
<string name="inactive_app_active_summary" msgid="8047630990208722344">"ပွင့်နေသည်။ ပြောင်းရန်တို့ပါ။"</string>
<string name="standby_bucket_summary" msgid="5128193447550429600">"အက်ပ်ကို အရန်သင့်ထားရှိခြင်း အခြေအနေ-<xliff:g id="BUCKET"> %s</xliff:g>"</string>
- <string name="transcode_settings_title" msgid="6700974145733932357">"မီဒီယာအမျိုးအစားပြောင်းခြင်း ဆက်တင်များ"</string>
- <string name="transcode_enable_all" msgid="4719796495995795404">"အက်ပ်အားလုံးအတွက် အမျိုးအစားပြောင်းခြင်းကို ဖွင့်ရန်"</string>
- <string name="transcode_skip_apps" msgid="5680997722349545778">"အက်ပ်များအတွက် အမျိုးအစားပြောင်းခြင်းကို ပိတ်ရန်"</string>
+ <string name="transcode_settings_title" msgid="2581975870429850549">"မီဒီယာအမျိုးအစားပြောင်းခြင်း ဆက်တင်များ"</string>
+ <string name="transcode_enable_all" msgid="9102460144086871903">"အမျိုးအစားပြောင်းခြင်းကို ပိတ်ရန်"</string>
+ <string name="transcode_skip_apps" msgid="8249721984597390142">"အက်ပ်များအတွက် အမျိုးအစားပြောင်းခြင်းကို ဖွင့်ရန်"</string>
<string name="runningservices_settings_title" msgid="6460099290493086515">"အလုပ်လုပ်နေသောဝန်ဆောင်မှုများ"</string>
<string name="runningservices_settings_summary" msgid="1046080643262665743">"လက်ရှိ ဝန်ဆောင်မှုများကို ကြည့်ရှု ထိန်းသိမ်းသည်"</string>
<string name="select_webview_provider_title" msgid="3917815648099445503">"WebView အကောင်အထည်ဖော်မှု"</string>
@@ -449,6 +449,8 @@
<string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"အားပြည့်ရန် <xliff:g id="TIME">%1$s</xliff:g> ကျန်သည်"</string>
<string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - အားပြည့်ရန် <xliff:g id="TIME">%2$s</xliff:g> ကျန်သည်"</string>
+ <!-- no translation found for power_charging_limited (5902301801611726210) -->
+ <skip />
<string name="battery_info_status_unknown" msgid="268625384868401114">"မသိ"</string>
<string name="battery_info_status_charging" msgid="4279958015430387405">"အားသွင်းနေပါသည်"</string>
<string name="battery_info_status_charging_fast" msgid="8027559755902954885">"အမြန် အားသွင်းနေသည်"</string>
diff --git a/packages/SettingsLib/res/values-nb/strings.xml b/packages/SettingsLib/res/values-nb/strings.xml
index 6a3aa29e0561..0ef5809e2a6d 100644
--- a/packages/SettingsLib/res/values-nb/strings.xml
+++ b/packages/SettingsLib/res/values-nb/strings.xml
@@ -399,9 +399,9 @@
<string name="inactive_app_inactive_summary" msgid="3161222402614236260">"Ikke aktiv. Trykk for å slå av/på."</string>
<string name="inactive_app_active_summary" msgid="8047630990208722344">"Aktiv. Trykk for å slå av/på."</string>
<string name="standby_bucket_summary" msgid="5128193447550429600">"Hvilemodus:<xliff:g id="BUCKET"> %s</xliff:g>"</string>
- <string name="transcode_settings_title" msgid="6700974145733932357">"Innstillinger for omkoding av medier"</string>
- <string name="transcode_enable_all" msgid="4719796495995795404">"Aktiver omkoding for alle apper"</string>
- <string name="transcode_skip_apps" msgid="5680997722349545778">"Deaktiver omkoding for apper"</string>
+ <string name="transcode_settings_title" msgid="2581975870429850549">"Innstillinger for omkoding av medier"</string>
+ <string name="transcode_enable_all" msgid="9102460144086871903">"Deaktiver omkoding"</string>
+ <string name="transcode_skip_apps" msgid="8249721984597390142">"Aktiver omkoding for apper"</string>
<string name="runningservices_settings_title" msgid="6460099290493086515">"Aktive tjenester"</string>
<string name="runningservices_settings_summary" msgid="1046080643262665743">"Se og kontrollér tjenester som kjører"</string>
<string name="select_webview_provider_title" msgid="3917815648099445503">"WebView-implementering"</string>
@@ -449,6 +449,8 @@
<string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"<xliff:g id="TIME">%1$s</xliff:g> til batteriet er fulladet"</string>
<string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> til batteriet er fulladet"</string>
+ <!-- no translation found for power_charging_limited (5902301801611726210) -->
+ <skip />
<string name="battery_info_status_unknown" msgid="268625384868401114">"Ukjent"</string>
<string name="battery_info_status_charging" msgid="4279958015430387405">"Lader"</string>
<string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Lader raskt"</string>
diff --git a/packages/SettingsLib/res/values-ne/strings.xml b/packages/SettingsLib/res/values-ne/strings.xml
index 5bc98c1b26cf..b956e2104c82 100644
--- a/packages/SettingsLib/res/values-ne/strings.xml
+++ b/packages/SettingsLib/res/values-ne/strings.xml
@@ -305,7 +305,7 @@
<string name="adbwifi_warning_message" msgid="8005936574322702388">"वायरलेस डिबगिङ डिभलपमेन्ट प्रयोजनका लागि मात्रै हो। यसलाई आफ्ना कम्प्युटर र उपकरणका बिच डेटा प्रतिलिपि गर्न, सूचना नदिई आफ्नो उपकरणमा एपहरू स्थापना गर्न र लग डेटा पढ्न प्रयोग गर्नुहोस्।"</string>
<string name="adb_keys_warning_message" msgid="2968555274488101220">"तपाईं पहिले नै अधिकृत गर्नुभएका सबै कम्प्यूटरबाट USB डिबग गर्नको लागि पहुँच रद्द गर्ने हो?"</string>
<string name="dev_settings_warning_title" msgid="8251234890169074553">"विकास सेटिङहरू अनुमति दिने हो?"</string>
- <string name="dev_settings_warning_message" msgid="37741686486073668">"यी सेटिङहरू केवल विकास प्रयोगको लागि विचार गरिएको हो। तिनीहरूले तपाईंको उपकरण र अनुप्रयोगहरूलाई विच्छेदन गर्न वा दुर्व्यवहार गर्न सक्दछ।"</string>
+ <string name="dev_settings_warning_message" msgid="37741686486073668">"यी सेटिङहरू केवल विकास प्रयोगको लागि विचार गरिएको हो। तिनीहरूले तपाईंको उपकरण र एपहरूलाई विच्छेदन गर्न वा दुर्व्यवहार गर्न सक्दछ।"</string>
<string name="verify_apps_over_usb_title" msgid="6031809675604442636">"USB मा एपहरू रुजु गर्नुहोस्"</string>
<string name="verify_apps_over_usb_summary" msgid="1317933737581167839">"हानिकारक व्यवहारको लागि ADB/ADT को माध्यमबाट स्थापित अनुप्रयोगहरूको जाँच गर्नुहोस्।"</string>
<string name="bluetooth_show_devices_without_names_summary" msgid="780964354377854507">"नामकरण नगरिएका ब्लुटुथ यन्त्रहरू (MAC ठेगाना भएका मात्र) देखाइनेछ"</string>
@@ -399,9 +399,12 @@
<string name="inactive_app_inactive_summary" msgid="3161222402614236260">"निष्क्रिय। टगल गर्न ट्याप गर्नुहोस्।"</string>
<string name="inactive_app_active_summary" msgid="8047630990208722344">"सक्रिय। टगल गर्न ट्याप गर्नुहोस्।"</string>
<string name="standby_bucket_summary" msgid="5128193447550429600">"एपको स्ट्यान्डबाई अवस्था:<xliff:g id="BUCKET"> %s</xliff:g>"</string>
- <string name="transcode_settings_title" msgid="6700974145733932357">"मिडिया फाइल ट्रान्सकोड गर्नेसम्बन्धी सेटिङ"</string>
- <string name="transcode_enable_all" msgid="4719796495995795404">"सबै एपमा ट्रान्सकोडिङ अन गर्नुहोस्"</string>
- <string name="transcode_skip_apps" msgid="5680997722349545778">"एपमा ट्रान्सकोडिङ अफ गर्नुहोस्"</string>
+ <!-- no translation found for transcode_settings_title (2581975870429850549) -->
+ <skip />
+ <!-- no translation found for transcode_enable_all (9102460144086871903) -->
+ <skip />
+ <!-- no translation found for transcode_skip_apps (8249721984597390142) -->
+ <skip />
<string name="runningservices_settings_title" msgid="6460099290493086515">"चलिरहेका सेवाहरू"</string>
<string name="runningservices_settings_summary" msgid="1046080643262665743">"हाल चालु भइरहेका सेवाहरू हेर्नुहोस् र नियन्त्रण गर्नुहोस्"</string>
<string name="select_webview_provider_title" msgid="3917815648099445503">"WebView कार्यान्वयन"</string>
@@ -449,6 +452,8 @@
<string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"पूर्ण चार्ज हुन <xliff:g id="TIME">%1$s</xliff:g> बाँकी"</string>
<string name="power_charging_duration" msgid="5005740040558984057">"पूर्ण चार्ज हुन <xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> लाग्छ"</string>
+ <!-- no translation found for power_charging_limited (5902301801611726210) -->
+ <skip />
<string name="battery_info_status_unknown" msgid="268625384868401114">"अज्ञात"</string>
<string name="battery_info_status_charging" msgid="4279958015430387405">"चार्ज हुँदै"</string>
<string name="battery_info_status_charging_fast" msgid="8027559755902954885">"द्रुत गतिमा चार्ज गरिँदै"</string>
diff --git a/packages/SettingsLib/res/values-nl/strings.xml b/packages/SettingsLib/res/values-nl/strings.xml
index bf40f40f1b21..3223857a0949 100644
--- a/packages/SettingsLib/res/values-nl/strings.xml
+++ b/packages/SettingsLib/res/values-nl/strings.xml
@@ -399,9 +399,9 @@
<string name="inactive_app_inactive_summary" msgid="3161222402614236260">"Inactief. Tik om te schakelen."</string>
<string name="inactive_app_active_summary" msgid="8047630990208722344">"Actief. Tik om te schakelen."</string>
<string name="standby_bucket_summary" msgid="5128193447550429600">"Stand-bystatus app: <xliff:g id="BUCKET"> %s</xliff:g>"</string>
- <string name="transcode_settings_title" msgid="6700974145733932357">"Instellingen voor mediatranscodering"</string>
- <string name="transcode_enable_all" msgid="4719796495995795404">"Transcodering inschakelen voor alle apps"</string>
- <string name="transcode_skip_apps" msgid="5680997722349545778">"Transcodering uitschakelen voor alle apps"</string>
+ <string name="transcode_settings_title" msgid="2581975870429850549">"Instellingen voor mediatranscodering"</string>
+ <string name="transcode_enable_all" msgid="9102460144086871903">"Transcodering uitschakelen"</string>
+ <string name="transcode_skip_apps" msgid="8249721984597390142">"Transcodering inschakelen voor apps"</string>
<string name="runningservices_settings_title" msgid="6460099290493086515">"Actieve services"</string>
<string name="runningservices_settings_summary" msgid="1046080643262665743">"Services die momenteel actief zijn, weergeven en beheren"</string>
<string name="select_webview_provider_title" msgid="3917815648099445503">"WebView-implementatie"</string>
@@ -449,6 +449,8 @@
<string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"Nog <xliff:g id="TIME">%1$s</xliff:g> tot opgeladen"</string>
<string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> tot opgeladen"</string>
+ <!-- no translation found for power_charging_limited (5902301801611726210) -->
+ <skip />
<string name="battery_info_status_unknown" msgid="268625384868401114">"Onbekend"</string>
<string name="battery_info_status_charging" msgid="4279958015430387405">"Opladen"</string>
<string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Snel opladen"</string>
diff --git a/packages/SettingsLib/res/values-or/strings.xml b/packages/SettingsLib/res/values-or/strings.xml
index a65a7d80eb7b..11bb550caa49 100644
--- a/packages/SettingsLib/res/values-or/strings.xml
+++ b/packages/SettingsLib/res/values-or/strings.xml
@@ -399,9 +399,12 @@
<string name="inactive_app_inactive_summary" msgid="3161222402614236260">"ନିଷ୍କ୍ରିୟ। ଟୋଗଲ୍‌ କରିବାକୁ ଟାପ୍‌ କରନ୍ତୁ।"</string>
<string name="inactive_app_active_summary" msgid="8047630990208722344">"ସକ୍ରିୟ। ବଦଳାଇବା ପାଇଁ ଟାପ୍‌ କରନ୍ତୁ"</string>
<string name="standby_bucket_summary" msgid="5128193447550429600">"ଆପ୍ ଷ୍ଟାଣ୍ଡବାଏ ଅବସ୍ଥା:<xliff:g id="BUCKET"> %s</xliff:g>"</string>
- <string name="transcode_settings_title" msgid="6700974145733932357">"ମିଡିଆ ଟ୍ରାନ୍ସକୋଡିଂ ସେଟିଂସ୍"</string>
- <string name="transcode_enable_all" msgid="4719796495995795404">"ସମସ୍ତ ଆପ୍ ପାଇଁ ଟ୍ରାନ୍ସକୋଡିଂ ସକ୍ଷମ କରନ୍ତୁ"</string>
- <string name="transcode_skip_apps" msgid="5680997722349545778">"ଆପଗୁଡ଼ିକ ପାଇଁ ଟ୍ରାନ୍ସକୋଡିଂ ଅକ୍ଷମ କରନ୍ତୁ"</string>
+ <!-- no translation found for transcode_settings_title (2581975870429850549) -->
+ <skip />
+ <!-- no translation found for transcode_enable_all (9102460144086871903) -->
+ <skip />
+ <!-- no translation found for transcode_skip_apps (8249721984597390142) -->
+ <skip />
<string name="runningservices_settings_title" msgid="6460099290493086515">"ଚାଲୁଥିବା ସେବାଗୁଡ଼ିକ"</string>
<string name="runningservices_settings_summary" msgid="1046080643262665743">"ଏବେ ଚାଲୁଥିବା ସେବାଗୁଡ଼ିକୁ ଦେଖନ୍ତୁ ଓ ନିୟନ୍ତ୍ରଣ କରନ୍ତୁ"</string>
<string name="select_webview_provider_title" msgid="3917815648099445503">"ୱେବ୍‌ଭ୍ୟୁ ପ୍ରୟୋଗ"</string>
@@ -449,6 +452,8 @@
<string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"ଚାର୍ଜ ହେବା ପାଇଁ <xliff:g id="TIME">%1$s</xliff:g> ବାକି ଅଛି"</string>
<string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> ଚାର୍ଜ ହେବା ପର୍ଯ୍ୟନ୍ତ"</string>
+ <!-- no translation found for power_charging_limited (5902301801611726210) -->
+ <skip />
<string name="battery_info_status_unknown" msgid="268625384868401114">"ଅଜ୍ଞାତ"</string>
<string name="battery_info_status_charging" msgid="4279958015430387405">"ଚାର୍ଜ ହେଉଛି"</string>
<string name="battery_info_status_charging_fast" msgid="8027559755902954885">"ଶୀଘ୍ର ଚାର୍ଜ ହେଉଛି"</string>
diff --git a/packages/SettingsLib/res/values-pa/strings.xml b/packages/SettingsLib/res/values-pa/strings.xml
index 5a009bea08af..8d66f3ca4adc 100644
--- a/packages/SettingsLib/res/values-pa/strings.xml
+++ b/packages/SettingsLib/res/values-pa/strings.xml
@@ -399,9 +399,12 @@
<string name="inactive_app_inactive_summary" msgid="3161222402614236260">"ਅਕਿਰਿਆਸ਼ੀਲ। ਟੌਗਲ ਕਰਨ ਲਈ ਟੈਪ ਕਰੋ।"</string>
<string name="inactive_app_active_summary" msgid="8047630990208722344">"ਕਿਰਿਆਸ਼ੀਲ। ਟੌਗਲ ਕਰਨ ਲਈ ਟੈਪ ਕਰੋ।"</string>
<string name="standby_bucket_summary" msgid="5128193447550429600">"ਐਪ ਸਟੈਂਡਬਾਈ ਸਥਿਤੀ:<xliff:g id="BUCKET"> %s</xliff:g>"</string>
- <string name="transcode_settings_title" msgid="6700974145733932357">"ਮੀਡੀਆ ਦੀਆਂ ਟ੍ਰਾਂਸਕੋਡ ਸੈਟਿੰਗਾਂ"</string>
- <string name="transcode_enable_all" msgid="4719796495995795404">"ਸਾਰੀਆਂ ਐਪਾਂ ਲਈ ਟ੍ਰਾਂਸਕੋਡਿੰਗ ਚਾਲੂ ਕਰੋ"</string>
- <string name="transcode_skip_apps" msgid="5680997722349545778">"ਸਾਰੀਆਂ ਐਪਾਂ ਲਈ ਟ੍ਰਾਂਸਕੋਡਿੰਗ ਬੰਦ ਕਰੋ"</string>
+ <!-- no translation found for transcode_settings_title (2581975870429850549) -->
+ <skip />
+ <!-- no translation found for transcode_enable_all (9102460144086871903) -->
+ <skip />
+ <!-- no translation found for transcode_skip_apps (8249721984597390142) -->
+ <skip />
<string name="runningservices_settings_title" msgid="6460099290493086515">"ਚੱਲ ਰਹੀਆਂ ਸੇਵਾਵਾਂ"</string>
<string name="runningservices_settings_summary" msgid="1046080643262665743">"ਇਸ ਵੇਲੇ ਚੱਲ ਰਹੀਆਂ ਸੇਵਾਵਾਂ ਦੇਖੋ ਅਤੇ ਇਹਨਾਂ ਨੂੰ ਕੰਟਰੋਲ ਕਰੋ"</string>
<string name="select_webview_provider_title" msgid="3917815648099445503">"WebView ਅਮਲ"</string>
@@ -449,6 +452,8 @@
<string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"ਚਾਰਜ ਹੋਣ ਵਿੱਚ <xliff:g id="TIME">%1$s</xliff:g> ਬਾਕੀ"</string>
<string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> ਤੱਕ ਚਾਰਜ ਹੋ ਜਾਵੇਗੀ"</string>
+ <!-- no translation found for power_charging_limited (5902301801611726210) -->
+ <skip />
<string name="battery_info_status_unknown" msgid="268625384868401114">"ਅਗਿਆਤ"</string>
<string name="battery_info_status_charging" msgid="4279958015430387405">"ਚਾਰਜ ਹੋ ਰਿਹਾ ਹੈ"</string>
<string name="battery_info_status_charging_fast" msgid="8027559755902954885">"ਤੇਜ਼ ਚਾਰਜ ਹੋ ਰਹੀ ਹੈ"</string>
diff --git a/packages/SettingsLib/res/values-pl/strings.xml b/packages/SettingsLib/res/values-pl/strings.xml
index 294e628ef567..ed96c46848d9 100644
--- a/packages/SettingsLib/res/values-pl/strings.xml
+++ b/packages/SettingsLib/res/values-pl/strings.xml
@@ -148,7 +148,7 @@
<string name="tether_settings_title_bluetooth" msgid="916519902721399656">"Tethering przez Bluetooth"</string>
<string name="tether_settings_title_usb_bluetooth" msgid="1727111807207577322">"Tethering"</string>
<string name="tether_settings_title_all" msgid="8910259483383010470">"Tethering i punkt dostępu"</string>
- <string name="managed_user_title" msgid="449081789742645723">"Wszystkie aplikacje do pracy"</string>
+ <string name="managed_user_title" msgid="449081789742645723">"Wszystkie aplikacje służbowe"</string>
<string name="user_guest" msgid="6939192779649870792">"Gość"</string>
<string name="unknown" msgid="3544487229740637809">"Nieznana"</string>
<string name="running_process_item_user_label" msgid="3988506293099805796">"Użytkownik: <xliff:g id="USER_NAME">%1$s</xliff:g>"</string>
@@ -399,9 +399,9 @@
<string name="inactive_app_inactive_summary" msgid="3161222402614236260">"Nieaktywna. Dotknij, by zmienić."</string>
<string name="inactive_app_active_summary" msgid="8047630990208722344">"Aktywna. Dotknij, by zmienić."</string>
<string name="standby_bucket_summary" msgid="5128193447550429600">"Stan aplikacji w trybie czuwania: <xliff:g id="BUCKET"> %s</xliff:g>"</string>
- <string name="transcode_settings_title" msgid="6700974145733932357">"Ustawienia transkodowania multimediów"</string>
- <string name="transcode_enable_all" msgid="4719796495995795404">"Włącz transkodowanie dla wszystkich aplikacji"</string>
- <string name="transcode_skip_apps" msgid="5680997722349545778">"Wyłącz transkodowanie dla aplikacji"</string>
+ <string name="transcode_settings_title" msgid="2581975870429850549">"Ustawienia transkodowania multimediów"</string>
+ <string name="transcode_enable_all" msgid="9102460144086871903">"Wyłącz transkodowanie"</string>
+ <string name="transcode_skip_apps" msgid="8249721984597390142">"Włącz transkodowanie dla aplikacji"</string>
<string name="runningservices_settings_title" msgid="6460099290493086515">"Uruchomione usługi"</string>
<string name="runningservices_settings_summary" msgid="1046080643262665743">"Wyświetl obecnie uruchomione usługi i nimi zarządzaj"</string>
<string name="select_webview_provider_title" msgid="3917815648099445503">"Implementacja WebView"</string>
@@ -449,6 +449,8 @@
<string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"Do naładowania <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> – do naładowania <xliff:g id="TIME">%2$s</xliff:g>"</string>
+ <!-- no translation found for power_charging_limited (5902301801611726210) -->
+ <skip />
<string name="battery_info_status_unknown" msgid="268625384868401114">"Nieznane"</string>
<string name="battery_info_status_charging" msgid="4279958015430387405">"Ładowanie"</string>
<string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Szybkie ładowanie"</string>
diff --git a/packages/SettingsLib/res/values-pt-rBR/strings.xml b/packages/SettingsLib/res/values-pt-rBR/strings.xml
index d9d1973a4457..acaabc793970 100644
--- a/packages/SettingsLib/res/values-pt-rBR/strings.xml
+++ b/packages/SettingsLib/res/values-pt-rBR/strings.xml
@@ -399,9 +399,9 @@
<string name="inactive_app_inactive_summary" msgid="3161222402614236260">"Inativo. Tocar para alternar."</string>
<string name="inactive_app_active_summary" msgid="8047630990208722344">"Ativo. Tocar para alternar."</string>
<string name="standby_bucket_summary" msgid="5128193447550429600">"Estado em espera do app:<xliff:g id="BUCKET"> %s</xliff:g>"</string>
- <string name="transcode_settings_title" msgid="6700974145733932357">"Configurações de transcodificação de mídia"</string>
- <string name="transcode_enable_all" msgid="4719796495995795404">"Ativar a transcodificação para todos os apps"</string>
- <string name="transcode_skip_apps" msgid="5680997722349545778">"Desativar a transcodificação para apps"</string>
+ <string name="transcode_settings_title" msgid="2581975870429850549">"Configurações de transcodificação de mídia"</string>
+ <string name="transcode_enable_all" msgid="9102460144086871903">"Desativar transcodificação"</string>
+ <string name="transcode_skip_apps" msgid="8249721984597390142">"Ativar transcodificação para apps"</string>
<string name="runningservices_settings_title" msgid="6460099290493086515">"Serviços em execução"</string>
<string name="runningservices_settings_summary" msgid="1046080643262665743">"Visualizar e controlar os serviços em execução no momento"</string>
<string name="select_webview_provider_title" msgid="3917815648099445503">"Implementação do WebView"</string>
@@ -449,6 +449,7 @@
<string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"Tempo restante até a carga completa: <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g>: <xliff:g id="TIME">%2$s</xliff:g> até a carga completa"</string>
+ <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g>: bateria limitada temporariamente"</string>
<string name="battery_info_status_unknown" msgid="268625384868401114">"Desconhecido"</string>
<string name="battery_info_status_charging" msgid="4279958015430387405">"Carregando"</string>
<string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Carregando rápido"</string>
diff --git a/packages/SettingsLib/res/values-pt-rPT/strings.xml b/packages/SettingsLib/res/values-pt-rPT/strings.xml
index ee6e5fec7eae..2c1a9678f158 100644
--- a/packages/SettingsLib/res/values-pt-rPT/strings.xml
+++ b/packages/SettingsLib/res/values-pt-rPT/strings.xml
@@ -399,9 +399,9 @@
<string name="inactive_app_inactive_summary" msgid="3161222402614236260">"Inativo. Toque para ativar/desativar."</string>
<string name="inactive_app_active_summary" msgid="8047630990208722344">"Ativo. Toque para ativar/desativar."</string>
<string name="standby_bucket_summary" msgid="5128193447550429600">"Estado do Modo de espera das apps:<xliff:g id="BUCKET"> %s</xliff:g>"</string>
- <string name="transcode_settings_title" msgid="6700974145733932357">"Definições da transcodificação multimédia"</string>
- <string name="transcode_enable_all" msgid="4719796495995795404">"Ativar transcodificação para todas as apps"</string>
- <string name="transcode_skip_apps" msgid="5680997722349545778">"Desative a transcodificação para apps"</string>
+ <string name="transcode_settings_title" msgid="2581975870429850549">"Definições da transcodificação de multimédia"</string>
+ <string name="transcode_enable_all" msgid="9102460144086871903">"Desativar a transcodificação"</string>
+ <string name="transcode_skip_apps" msgid="8249721984597390142">"Ative a transcodificação para apps"</string>
<string name="runningservices_settings_title" msgid="6460099290493086515">"Serviços em execução"</string>
<string name="runningservices_settings_summary" msgid="1046080643262665743">"Ver e controlar os serviços actualmente em execução"</string>
<string name="select_webview_provider_title" msgid="3917815648099445503">"Implementação WebView"</string>
@@ -449,6 +449,7 @@
<string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"Falta(m) <xliff:g id="TIME">%1$s</xliff:g> até ficar carregada"</string>
<string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> até ficar carregada"</string>
+ <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> – Bateria limitada temporariamente."</string>
<string name="battery_info_status_unknown" msgid="268625384868401114">"Desconhecido"</string>
<string name="battery_info_status_charging" msgid="4279958015430387405">"A carregar"</string>
<string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Carregamento rápido"</string>
diff --git a/packages/SettingsLib/res/values-pt/strings.xml b/packages/SettingsLib/res/values-pt/strings.xml
index d9d1973a4457..acaabc793970 100644
--- a/packages/SettingsLib/res/values-pt/strings.xml
+++ b/packages/SettingsLib/res/values-pt/strings.xml
@@ -399,9 +399,9 @@
<string name="inactive_app_inactive_summary" msgid="3161222402614236260">"Inativo. Tocar para alternar."</string>
<string name="inactive_app_active_summary" msgid="8047630990208722344">"Ativo. Tocar para alternar."</string>
<string name="standby_bucket_summary" msgid="5128193447550429600">"Estado em espera do app:<xliff:g id="BUCKET"> %s</xliff:g>"</string>
- <string name="transcode_settings_title" msgid="6700974145733932357">"Configurações de transcodificação de mídia"</string>
- <string name="transcode_enable_all" msgid="4719796495995795404">"Ativar a transcodificação para todos os apps"</string>
- <string name="transcode_skip_apps" msgid="5680997722349545778">"Desativar a transcodificação para apps"</string>
+ <string name="transcode_settings_title" msgid="2581975870429850549">"Configurações de transcodificação de mídia"</string>
+ <string name="transcode_enable_all" msgid="9102460144086871903">"Desativar transcodificação"</string>
+ <string name="transcode_skip_apps" msgid="8249721984597390142">"Ativar transcodificação para apps"</string>
<string name="runningservices_settings_title" msgid="6460099290493086515">"Serviços em execução"</string>
<string name="runningservices_settings_summary" msgid="1046080643262665743">"Visualizar e controlar os serviços em execução no momento"</string>
<string name="select_webview_provider_title" msgid="3917815648099445503">"Implementação do WebView"</string>
@@ -449,6 +449,7 @@
<string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"Tempo restante até a carga completa: <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g>: <xliff:g id="TIME">%2$s</xliff:g> até a carga completa"</string>
+ <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g>: bateria limitada temporariamente"</string>
<string name="battery_info_status_unknown" msgid="268625384868401114">"Desconhecido"</string>
<string name="battery_info_status_charging" msgid="4279958015430387405">"Carregando"</string>
<string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Carregando rápido"</string>
diff --git a/packages/SettingsLib/res/values-ro/strings.xml b/packages/SettingsLib/res/values-ro/strings.xml
index 8f6ddeb11fe3..46d6d0a89f5e 100644
--- a/packages/SettingsLib/res/values-ro/strings.xml
+++ b/packages/SettingsLib/res/values-ro/strings.xml
@@ -399,9 +399,9 @@
<string name="inactive_app_inactive_summary" msgid="3161222402614236260">"Inactivă. Atingeți pentru a comuta."</string>
<string name="inactive_app_active_summary" msgid="8047630990208722344">"Activă. Atingeți pentru a comuta."</string>
<string name="standby_bucket_summary" msgid="5128193447550429600">"Stare Standby aplicații: <xliff:g id="BUCKET"> %s</xliff:g>"</string>
- <string name="transcode_settings_title" msgid="6700974145733932357">"Setări pentru transcodarea conținutului media"</string>
- <string name="transcode_enable_all" msgid="4719796495995795404">"Activați transcodarea pentru toate aplicațiile"</string>
- <string name="transcode_skip_apps" msgid="5680997722349545778">"Dezactivați transcodarea pentru aplicații"</string>
+ <string name="transcode_settings_title" msgid="2581975870429850549">"Setări pentru transcodarea conținutului media"</string>
+ <string name="transcode_enable_all" msgid="9102460144086871903">"Dezactivați transcodarea"</string>
+ <string name="transcode_skip_apps" msgid="8249721984597390142">"Activați transcodarea pentru aplicații"</string>
<string name="runningservices_settings_title" msgid="6460099290493086515">"Servicii în curs de funcționare"</string>
<string name="runningservices_settings_summary" msgid="1046080643262665743">"Vedeți și controlați serviciile care funcționează în prezent"</string>
<string name="select_webview_provider_title" msgid="3917815648099445503">"Implementare WebView"</string>
@@ -449,6 +449,8 @@
<string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"Au mai rămas <xliff:g id="TIME">%1$s</xliff:g> până la încărcare"</string>
<string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> până la încărcare"</string>
+ <!-- no translation found for power_charging_limited (5902301801611726210) -->
+ <skip />
<string name="battery_info_status_unknown" msgid="268625384868401114">"Necunoscut"</string>
<string name="battery_info_status_charging" msgid="4279958015430387405">"Se încarcă"</string>
<string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Se încarcă rapid"</string>
diff --git a/packages/SettingsLib/res/values-ru/strings.xml b/packages/SettingsLib/res/values-ru/strings.xml
index e61eb29db2f5..2a79ad3005ff 100644
--- a/packages/SettingsLib/res/values-ru/strings.xml
+++ b/packages/SettingsLib/res/values-ru/strings.xml
@@ -399,9 +399,9 @@
<string name="inactive_app_inactive_summary" msgid="3161222402614236260">"Выключено. Нажмите, чтобы включить."</string>
<string name="inactive_app_active_summary" msgid="8047630990208722344">"Включено. Нажмите, чтобы отключить."</string>
<string name="standby_bucket_summary" msgid="5128193447550429600">"Статус приложения в режиме ожидания:<xliff:g id="BUCKET"> %s</xliff:g>"</string>
- <string name="transcode_settings_title" msgid="6700974145733932357">"Настройки перекодирования медиаконтента"</string>
- <string name="transcode_enable_all" msgid="4719796495995795404">"Разрешить перекодирование для всех приложений"</string>
- <string name="transcode_skip_apps" msgid="5680997722349545778">"Приложения, для которых нужно запретить перекодирование"</string>
+ <string name="transcode_settings_title" msgid="2581975870429850549">"Настройки перекодирования медиафайлов"</string>
+ <string name="transcode_enable_all" msgid="9102460144086871903">"Отключить перекодирование"</string>
+ <string name="transcode_skip_apps" msgid="8249721984597390142">"Включить перекодирование для приложений"</string>
<string name="runningservices_settings_title" msgid="6460099290493086515">"Работающие службы"</string>
<string name="runningservices_settings_summary" msgid="1046080643262665743">"Просмотр и управление работающими службами"</string>
<string name="select_webview_provider_title" msgid="3917815648099445503">"Сервис WebView"</string>
@@ -449,6 +449,8 @@
<string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"<xliff:g id="TIME">%1$s</xliff:g> до полной зарядки"</string>
<string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> до полной зарядки"</string>
+ <!-- no translation found for power_charging_limited (5902301801611726210) -->
+ <skip />
<string name="battery_info_status_unknown" msgid="268625384868401114">"Неизвестно"</string>
<string name="battery_info_status_charging" msgid="4279958015430387405">"Идет зарядка"</string>
<string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Быстрая зарядка"</string>
diff --git a/packages/SettingsLib/res/values-si/strings.xml b/packages/SettingsLib/res/values-si/strings.xml
index cfea2aac17cb..78f355865ced 100644
--- a/packages/SettingsLib/res/values-si/strings.xml
+++ b/packages/SettingsLib/res/values-si/strings.xml
@@ -399,9 +399,9 @@
<string name="inactive_app_inactive_summary" msgid="3161222402614236260">"අක්‍රියයි. ටොගල කිරීමට තට්ටු කරන්න."</string>
<string name="inactive_app_active_summary" msgid="8047630990208722344">"සක්‍රියයි. ටොගල කිරීමට තට්ටු කරන්න."</string>
<string name="standby_bucket_summary" msgid="5128193447550429600">"යෙදුම් පොරොත්තු තත්ත්වය:<xliff:g id="BUCKET"> %s</xliff:g>"</string>
- <string name="transcode_settings_title" msgid="6700974145733932357">"මාධ්‍ය ට්‍රාන්ස්කෝඩ් සැකසීම්"</string>
- <string name="transcode_enable_all" msgid="4719796495995795404">"සියලු යෙදුම් සඳහා ට්‍රාන්ස්කෝඩින් සබල කරන්න"</string>
- <string name="transcode_skip_apps" msgid="5680997722349545778">"සියලු යෙදුම් සඳහා ට්‍රාන්ස්කෝඩින් අබල කරන්න"</string>
+ <string name="transcode_settings_title" msgid="2581975870429850549">"මාධ්‍ය ට්‍රාන්ස්කෝඩින් සැකසීම්"</string>
+ <string name="transcode_enable_all" msgid="9102460144086871903">"ට්‍රාන්ස්කෝඩින් අබල කරන්න"</string>
+ <string name="transcode_skip_apps" msgid="8249721984597390142">"යෙදුම් සඳහා ට්‍රාන්ස්කෝඩින් සබල කරන්න"</string>
<string name="runningservices_settings_title" msgid="6460099290493086515">"ධාවනය වන සේවා"</string>
<string name="runningservices_settings_summary" msgid="1046080643262665743">"දැනට ධාවනය වන සේවා බලන්න සහ පාලනය කරන්න"</string>
<string name="select_webview_provider_title" msgid="3917815648099445503">"WebView ක්‍රියාත්මක කිරීම"</string>
@@ -449,6 +449,8 @@
<string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"ආරෝපණය වන තෙක් <xliff:g id="TIME">%1$s</xliff:g> ඇත"</string>
<string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - ආරෝපණය වන තෙක් <xliff:g id="TIME">%2$s</xliff:g>"</string>
+ <!-- no translation found for power_charging_limited (5902301801611726210) -->
+ <skip />
<string name="battery_info_status_unknown" msgid="268625384868401114">"නොදනී"</string>
<string name="battery_info_status_charging" msgid="4279958015430387405">"ආරෝපණය වෙමින්"</string>
<string name="battery_info_status_charging_fast" msgid="8027559755902954885">"ශීඝ්‍ර ආරෝපණය"</string>
diff --git a/packages/SettingsLib/res/values-sk/strings.xml b/packages/SettingsLib/res/values-sk/strings.xml
index 56fc8116ad8a..152c7a885457 100644
--- a/packages/SettingsLib/res/values-sk/strings.xml
+++ b/packages/SettingsLib/res/values-sk/strings.xml
@@ -399,9 +399,9 @@
<string name="inactive_app_inactive_summary" msgid="3161222402614236260">"Neaktívne. Prepnite klepnutím."</string>
<string name="inactive_app_active_summary" msgid="8047630990208722344">"Aktívne. Prepnite klepnutím."</string>
<string name="standby_bucket_summary" msgid="5128193447550429600">"Stav pohotovostného režimu aplikácie: <xliff:g id="BUCKET"> %s</xliff:g>"</string>
- <string name="transcode_settings_title" msgid="6700974145733932357">"Nastavenie prekódovania médií"</string>
- <string name="transcode_enable_all" msgid="4719796495995795404">"Povoliť prekódovanie všetkých aplikácií"</string>
- <string name="transcode_skip_apps" msgid="5680997722349545778">"Zakázať prekódovanie všetkých aplikácií"</string>
+ <string name="transcode_settings_title" msgid="2581975870429850549">"Nastavenia prekódovania médií"</string>
+ <string name="transcode_enable_all" msgid="9102460144086871903">"Vypnúť prekódovanie"</string>
+ <string name="transcode_skip_apps" msgid="8249721984597390142">"Zapnúť prekódovanie aplikácií"</string>
<string name="runningservices_settings_title" msgid="6460099290493086515">"Spustené služby"</string>
<string name="runningservices_settings_summary" msgid="1046080643262665743">"Zobrazovať a riadiť aktuálne spustené služby"</string>
<string name="select_webview_provider_title" msgid="3917815648099445503">"Implementácia WebView"</string>
@@ -449,6 +449,8 @@
<string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"Zostávajúci čas do úplného nabitia: <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> do úplného nabitia"</string>
+ <!-- no translation found for power_charging_limited (5902301801611726210) -->
+ <skip />
<string name="battery_info_status_unknown" msgid="268625384868401114">"Neznáme"</string>
<string name="battery_info_status_charging" msgid="4279958015430387405">"Nabíja sa"</string>
<string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Rýchle nabíjanie"</string>
diff --git a/packages/SettingsLib/res/values-sl/strings.xml b/packages/SettingsLib/res/values-sl/strings.xml
index 22a65702b3c2..a2f093e89ad8 100644
--- a/packages/SettingsLib/res/values-sl/strings.xml
+++ b/packages/SettingsLib/res/values-sl/strings.xml
@@ -399,9 +399,9 @@
<string name="inactive_app_inactive_summary" msgid="3161222402614236260">"Neaktivno. Dotaknite se za preklop."</string>
<string name="inactive_app_active_summary" msgid="8047630990208722344">"Aktivno. Dotaknite se za preklop."</string>
<string name="standby_bucket_summary" msgid="5128193447550429600">"Stanje pripravljenosti aplikacije: <xliff:g id="BUCKET"> %s</xliff:g>"</string>
- <string name="transcode_settings_title" msgid="6700974145733932357">"Nastavitve prekodiranja predstavnosti"</string>
- <string name="transcode_enable_all" msgid="4719796495995795404">"Omogočanje prekodiranja za vse aplikacije"</string>
- <string name="transcode_skip_apps" msgid="5680997722349545778">"Onemogočanje prekodiranja za aplikacije"</string>
+ <string name="transcode_settings_title" msgid="2581975870429850549">"Nastavitve prekodiranja predstavnosti"</string>
+ <string name="transcode_enable_all" msgid="9102460144086871903">"Onemogočanje prekodiranja"</string>
+ <string name="transcode_skip_apps" msgid="8249721984597390142">"Omogočanje prekodiranja za aplikacije"</string>
<string name="runningservices_settings_title" msgid="6460099290493086515">"Zagnane storitve"</string>
<string name="runningservices_settings_summary" msgid="1046080643262665743">"Preglejte in nadzorujte storitve, ki so trenutno zagnane"</string>
<string name="select_webview_provider_title" msgid="3917815648099445503">"Izvedba spletnega pogleda"</string>
@@ -449,6 +449,8 @@
<string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"Še <xliff:g id="TIME">%1$s</xliff:g> do polne napolnjenosti"</string>
<string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> do polne napolnjenosti"</string>
+ <!-- no translation found for power_charging_limited (5902301801611726210) -->
+ <skip />
<string name="battery_info_status_unknown" msgid="268625384868401114">"Neznano"</string>
<string name="battery_info_status_charging" msgid="4279958015430387405">"Polnjenje"</string>
<string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Hitro polnjenje"</string>
diff --git a/packages/SettingsLib/res/values-sq/strings.xml b/packages/SettingsLib/res/values-sq/strings.xml
index 2d846c8ae178..b4589173f234 100644
--- a/packages/SettingsLib/res/values-sq/strings.xml
+++ b/packages/SettingsLib/res/values-sq/strings.xml
@@ -399,9 +399,9 @@
<string name="inactive_app_inactive_summary" msgid="3161222402614236260">"Joaktiv. Trokit për ta ndryshuar."</string>
<string name="inactive_app_active_summary" msgid="8047630990208722344">"Aktiv. Trokit për ta ndryshuar."</string>
<string name="standby_bucket_summary" msgid="5128193447550429600">"Gjendja e gatishmërisë e aplikacionit:<xliff:g id="BUCKET"> %s</xliff:g>"</string>
- <string name="transcode_settings_title" msgid="6700974145733932357">"Cilësimet e transkodimit të medias"</string>
- <string name="transcode_enable_all" msgid="4719796495995795404">"Aktivizo transkodimin për të gjitha aplikacionet"</string>
- <string name="transcode_skip_apps" msgid="5680997722349545778">"Çaktivizo transkodimin për aplikacionet"</string>
+ <string name="transcode_settings_title" msgid="2581975870429850549">"Cilësimet e transkodimit të multimediave"</string>
+ <string name="transcode_enable_all" msgid="9102460144086871903">"Çaktivizo transkodimin"</string>
+ <string name="transcode_skip_apps" msgid="8249721984597390142">"Aktivizo transkodimin për aplikacionet"</string>
<string name="runningservices_settings_title" msgid="6460099290493086515">"Shërbimet në ekzekutim"</string>
<string name="runningservices_settings_summary" msgid="1046080643262665743">"Shiko dhe kontrollo shërbimet që po ekzekutohen aktualisht"</string>
<string name="select_webview_provider_title" msgid="3917815648099445503">"Zbatimi i WebView"</string>
@@ -449,6 +449,8 @@
<string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"<xliff:g id="TIME">%1$s</xliff:g> të mbetura deri në karikim"</string>
<string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> derisa të karikohet"</string>
+ <!-- no translation found for power_charging_limited (5902301801611726210) -->
+ <skip />
<string name="battery_info_status_unknown" msgid="268625384868401114">"I panjohur"</string>
<string name="battery_info_status_charging" msgid="4279958015430387405">"Po karikohet"</string>
<string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Po ngarkon me shpejtësi"</string>
diff --git a/packages/SettingsLib/res/values-sr/strings.xml b/packages/SettingsLib/res/values-sr/strings.xml
index 34fd5552ff43..970c70f48c68 100644
--- a/packages/SettingsLib/res/values-sr/strings.xml
+++ b/packages/SettingsLib/res/values-sr/strings.xml
@@ -399,9 +399,9 @@
<string name="inactive_app_inactive_summary" msgid="3161222402614236260">"Неактивна. Додирните да бисте је активирали."</string>
<string name="inactive_app_active_summary" msgid="8047630990208722344">"Активна. Додирните да бисте је деактивирали."</string>
<string name="standby_bucket_summary" msgid="5128193447550429600">"Стање приправности апликације: <xliff:g id="BUCKET"> %s</xliff:g>"</string>
- <string name="transcode_settings_title" msgid="6700974145733932357">"Подешавања транскодирања медија"</string>
- <string name="transcode_enable_all" msgid="4719796495995795404">"Омогући транскодирање за све апликације"</string>
- <string name="transcode_skip_apps" msgid="5680997722349545778">"Онемогућите транскодирање за апликације"</string>
+ <string name="transcode_settings_title" msgid="2581975870429850549">"Подешавања транскодирања медија"</string>
+ <string name="transcode_enable_all" msgid="9102460144086871903">"Онемогући транскодирање"</string>
+ <string name="transcode_skip_apps" msgid="8249721984597390142">"Омогућите транскодирање за апликације"</string>
<string name="runningservices_settings_title" msgid="6460099290493086515">"Покренуте услуге"</string>
<string name="runningservices_settings_summary" msgid="1046080643262665743">"Приказ и контрола тренутно покренутих услуга"</string>
<string name="select_webview_provider_title" msgid="3917815648099445503">"Примена WebView-а"</string>
@@ -449,6 +449,8 @@
<string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"Напуниће се за <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> – напуниће се за <xliff:g id="TIME">%2$s</xliff:g>"</string>
+ <!-- no translation found for power_charging_limited (5902301801611726210) -->
+ <skip />
<string name="battery_info_status_unknown" msgid="268625384868401114">"Непознато"</string>
<string name="battery_info_status_charging" msgid="4279958015430387405">"Пуни се"</string>
<string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Брзо се пуни"</string>
diff --git a/packages/SettingsLib/res/values-sv/strings.xml b/packages/SettingsLib/res/values-sv/strings.xml
index 05e455a8e5e3..42d907734e30 100644
--- a/packages/SettingsLib/res/values-sv/strings.xml
+++ b/packages/SettingsLib/res/values-sv/strings.xml
@@ -399,9 +399,9 @@
<string name="inactive_app_inactive_summary" msgid="3161222402614236260">"Inaktiv. Tryck om du vill aktivera."</string>
<string name="inactive_app_active_summary" msgid="8047630990208722344">"Aktiv. Tryck om du vill inaktivera."</string>
<string name="standby_bucket_summary" msgid="5128193447550429600">"Status för strömsparfunktion för appar:<xliff:g id="BUCKET"> %s</xliff:g>"</string>
- <string name="transcode_settings_title" msgid="6700974145733932357">"Inställningar för medieomkodning"</string>
- <string name="transcode_enable_all" msgid="4719796495995795404">"Aktivera omkodning för alla appar"</string>
- <string name="transcode_skip_apps" msgid="5680997722349545778">"Inaktivera omkodning för appar"</string>
+ <string name="transcode_settings_title" msgid="2581975870429850549">"Inställningar för medieomkodning"</string>
+ <string name="transcode_enable_all" msgid="9102460144086871903">"Inaktivera omkodning"</string>
+ <string name="transcode_skip_apps" msgid="8249721984597390142">"Aktivera omkodning för appar"</string>
<string name="runningservices_settings_title" msgid="6460099290493086515">"Aktiva tjänster"</string>
<string name="runningservices_settings_summary" msgid="1046080643262665743">"Visa och styr aktiva tjänster"</string>
<string name="select_webview_provider_title" msgid="3917815648099445503">"WebView-implementering"</string>
@@ -449,6 +449,8 @@
<string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"<xliff:g id="TIME">%1$s</xliff:g> kvar till full laddning"</string>
<string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> till full laddning"</string>
+ <!-- no translation found for power_charging_limited (5902301801611726210) -->
+ <skip />
<string name="battery_info_status_unknown" msgid="268625384868401114">"Okänd"</string>
<string name="battery_info_status_charging" msgid="4279958015430387405">"Laddar"</string>
<string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Laddas snabbt"</string>
diff --git a/packages/SettingsLib/res/values-sw/strings.xml b/packages/SettingsLib/res/values-sw/strings.xml
index 365b0fd85835..f1a41994d2c8 100644
--- a/packages/SettingsLib/res/values-sw/strings.xml
+++ b/packages/SettingsLib/res/values-sw/strings.xml
@@ -399,9 +399,9 @@
<string name="inactive_app_inactive_summary" msgid="3161222402614236260">"Haitumika. Gusa ili ugeuze."</string>
<string name="inactive_app_active_summary" msgid="8047630990208722344">"Inatumika. Gusa ili ugeuze."</string>
<string name="standby_bucket_summary" msgid="5128193447550429600">"Hali ya kisitisha programu:<xliff:g id="BUCKET"> %s</xliff:g>"</string>
- <string name="transcode_settings_title" msgid="6700974145733932357">"Mipangilio ya kubadilisha muundo wa faili ya maudhui"</string>
- <string name="transcode_enable_all" msgid="4719796495995795404">"Washa ubadilishaji muundo wa faili kwenye programu zote"</string>
- <string name="transcode_skip_apps" msgid="5680997722349545778">"Zima ubadilishaji muundo wa faili kwenye programu"</string>
+ <string name="transcode_settings_title" msgid="2581975870429850549">"Mipangilio ya kubadilisha muundo wa faili ya maudhui"</string>
+ <string name="transcode_enable_all" msgid="9102460144086871903">"Zima ubadilishaji muundo wa faili"</string>
+ <string name="transcode_skip_apps" msgid="8249721984597390142">"Washa ubadilishaji muundo wa faili kwenye programu"</string>
<string name="runningservices_settings_title" msgid="6460099290493086515">"Huduma zinazoendeshwa"</string>
<string name="runningservices_settings_summary" msgid="1046080643262665743">"Onyesha na udhibiti huduma zinazoendeshwa kwa sasa"</string>
<string name="select_webview_provider_title" msgid="3917815648099445503">"Utekelezaji wa WebView"</string>
@@ -449,6 +449,8 @@
<string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"Imebakisha <xliff:g id="TIME">%1$s</xliff:g> ijae chaji"</string>
<string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> ijae chaji"</string>
+ <!-- no translation found for power_charging_limited (5902301801611726210) -->
+ <skip />
<string name="battery_info_status_unknown" msgid="268625384868401114">"Haijulikani"</string>
<string name="battery_info_status_charging" msgid="4279958015430387405">"Inachaji"</string>
<string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Inachaji kwa kasi"</string>
diff --git a/packages/SettingsLib/res/values-ta/strings.xml b/packages/SettingsLib/res/values-ta/strings.xml
index e546ad7ba697..2d696c5f79eb 100644
--- a/packages/SettingsLib/res/values-ta/strings.xml
+++ b/packages/SettingsLib/res/values-ta/strings.xml
@@ -399,9 +399,9 @@
<string name="inactive_app_inactive_summary" msgid="3161222402614236260">"செயலில் இல்லை. மாற்ற, தட்டவும்."</string>
<string name="inactive_app_active_summary" msgid="8047630990208722344">"செயலில் உள்ளது. மாற்ற, தட்டவும்."</string>
<string name="standby_bucket_summary" msgid="5128193447550429600">"காத்திருப்பில் உள்ள ஆப்ஸின் நிலை:<xliff:g id="BUCKET"> %s</xliff:g>"</string>
- <string name="transcode_settings_title" msgid="6700974145733932357">"மீடியா குறிமாற்ற அமைப்புகள்"</string>
- <string name="transcode_enable_all" msgid="4719796495995795404">"அனைத்து ஆப்ஸுக்கும் குறிமாற்றத்தை இயக்கு"</string>
- <string name="transcode_skip_apps" msgid="5680997722349545778">"அனைத்து ஆப்ஸுக்கும் குறிமாற்றத்தை முடக்கு"</string>
+ <string name="transcode_settings_title" msgid="2581975870429850549">"மீடியா குறிமாற்ற அமைப்புகள்"</string>
+ <string name="transcode_enable_all" msgid="9102460144086871903">"குறிமாற்றத்தை முடக்கு"</string>
+ <string name="transcode_skip_apps" msgid="8249721984597390142">"ஆப்ஸுக்குக் குறிமாற்றத்தை இயக்கு"</string>
<string name="runningservices_settings_title" msgid="6460099290493086515">"இயங்கும் சேவைகள்"</string>
<string name="runningservices_settings_summary" msgid="1046080643262665743">"தற்போது இயக்கத்தில் இருக்கும் சேவைகளைப் பார்த்து கட்டுப்படுத்து"</string>
<string name="select_webview_provider_title" msgid="3917815648099445503">"WebView செயல்படுத்தல்"</string>
@@ -449,6 +449,8 @@
<string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"முழு சார்ஜாக <xliff:g id="TIME">%1$s</xliff:g> ஆகும்"</string>
<string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - முழு சார்ஜாக <xliff:g id="TIME">%2$s</xliff:g> ஆகும்"</string>
+ <!-- no translation found for power_charging_limited (5902301801611726210) -->
+ <skip />
<string name="battery_info_status_unknown" msgid="268625384868401114">"அறியப்படாத"</string>
<string name="battery_info_status_charging" msgid="4279958015430387405">"சார்ஜ் ஆகிறது"</string>
<string name="battery_info_status_charging_fast" msgid="8027559755902954885">"வேகமாக சார்ஜாகிறது"</string>
diff --git a/packages/SettingsLib/res/values-te/strings.xml b/packages/SettingsLib/res/values-te/strings.xml
index c09d2e142487..8e0f0b603523 100644
--- a/packages/SettingsLib/res/values-te/strings.xml
+++ b/packages/SettingsLib/res/values-te/strings.xml
@@ -399,9 +399,9 @@
<string name="inactive_app_inactive_summary" msgid="3161222402614236260">"నిష్క్రియంగా ఉంది. టోగుల్ చేయడానికి నొక్కండి."</string>
<string name="inactive_app_active_summary" msgid="8047630990208722344">"సక్రియంగా ఉంది. టోగుల్ చేయడానికి నొక్కండి."</string>
<string name="standby_bucket_summary" msgid="5128193447550429600">"యాప్ స్టాండ్‌బై స్థితి:<xliff:g id="BUCKET"> %s</xliff:g>"</string>
- <string name="transcode_settings_title" msgid="6700974145733932357">"మీడియా ట్రాన్స్‌కోడింగ్ సెట్టింగ్‌లు"</string>
- <string name="transcode_enable_all" msgid="4719796495995795404">"అన్ని యాప్‌ల కోసం ట్రాన్స్‌కోడింగ్‌ని ఎనేబుల్ చేయండి"</string>
- <string name="transcode_skip_apps" msgid="5680997722349545778">"యాప్‌ల కోసం ట్రాన్స్‌కోడింగ్‌ని డిజేబుల్ చేయండి"</string>
+ <string name="transcode_settings_title" msgid="2581975870429850549">"మీడియా ట్రాన్స్‌కోడింగ్ సెట్టింగ్‌లు"</string>
+ <string name="transcode_enable_all" msgid="9102460144086871903">"ట్రాన్స్‌కోడింగ్‌ను డిజేబుల్ చేయండి"</string>
+ <string name="transcode_skip_apps" msgid="8249721984597390142">"యాప్‌ల కోసం ట్రాన్స్‌కోడింగ్‌ను ఎనేబుల్ చేయండి"</string>
<string name="runningservices_settings_title" msgid="6460099290493086515">"అమలులో ఉన్న సేవలు"</string>
<string name="runningservices_settings_summary" msgid="1046080643262665743">"ప్రస్తుతం అమలులో ఉన్న సేవలను వీక్షించండి మరియు నియంత్రించండి"</string>
<string name="select_webview_provider_title" msgid="3917815648099445503">"వెబ్ వీక్షణ అమలు"</string>
@@ -449,6 +449,8 @@
<string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"ఛార్జ్ అవ్వడానికి <xliff:g id="TIME">%1$s</xliff:g> సమయం మిగిలి ఉంది"</string>
<string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - ఛార్జ్ అవ్వడానికి <xliff:g id="TIME">%2$s</xliff:g> పడుతుంది"</string>
+ <!-- no translation found for power_charging_limited (5902301801611726210) -->
+ <skip />
<string name="battery_info_status_unknown" msgid="268625384868401114">"తెలియదు"</string>
<string name="battery_info_status_charging" msgid="4279958015430387405">"ఛార్జ్ అవుతోంది"</string>
<string name="battery_info_status_charging_fast" msgid="8027559755902954885">"వేగవంతమైన ఛార్జింగ్"</string>
diff --git a/packages/SettingsLib/res/values-th/strings.xml b/packages/SettingsLib/res/values-th/strings.xml
index fcfc11eff28e..81895b923a44 100644
--- a/packages/SettingsLib/res/values-th/strings.xml
+++ b/packages/SettingsLib/res/values-th/strings.xml
@@ -399,9 +399,9 @@
<string name="inactive_app_inactive_summary" msgid="3161222402614236260">"ไม่ได้ใช้งาน แตะเพื่อสลับ"</string>
<string name="inactive_app_active_summary" msgid="8047630990208722344">"ใช้งานอยู่ แตะเพื่อสลับ"</string>
<string name="standby_bucket_summary" msgid="5128193447550429600">"สถานะการสแตนด์บายของแอป:<xliff:g id="BUCKET"> %s</xliff:g>"</string>
- <string name="transcode_settings_title" msgid="6700974145733932357">"การตั้งค่าการแปลงสื่อ"</string>
- <string name="transcode_enable_all" msgid="4719796495995795404">"เปิดใช้การแปลงสำหรับแอปทั้งหมด"</string>
- <string name="transcode_skip_apps" msgid="5680997722349545778">"ปิดใช้การแปลงสำหรับแอป"</string>
+ <string name="transcode_settings_title" msgid="2581975870429850549">"การตั้งค่าการแปลงสื่อ"</string>
+ <string name="transcode_enable_all" msgid="9102460144086871903">"ปิดใช้การแปลง"</string>
+ <string name="transcode_skip_apps" msgid="8249721984597390142">"เปิดใช้การแปลงสำหรับแอป"</string>
<string name="runningservices_settings_title" msgid="6460099290493086515">"บริการที่ทำงานอยู่"</string>
<string name="runningservices_settings_summary" msgid="1046080643262665743">"ดูและควบคุมบริการที่ทำงานอยู่"</string>
<string name="select_webview_provider_title" msgid="3917815648099445503">"การใช้งาน WebView"</string>
@@ -449,6 +449,8 @@
<string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"เหลือ <xliff:g id="TIME">%1$s</xliff:g> จนกว่าจะชาร์จเต็ม"</string>
<string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> จนกว่าจะชาร์จ"</string>
+ <!-- no translation found for power_charging_limited (5902301801611726210) -->
+ <skip />
<string name="battery_info_status_unknown" msgid="268625384868401114">"ไม่ทราบ"</string>
<string name="battery_info_status_charging" msgid="4279958015430387405">"กำลังชาร์จ"</string>
<string name="battery_info_status_charging_fast" msgid="8027559755902954885">"กำลังชาร์จอย่างเร็ว"</string>
diff --git a/packages/SettingsLib/res/values-tl/strings.xml b/packages/SettingsLib/res/values-tl/strings.xml
index cdd1d621da2c..5d1630f28675 100644
--- a/packages/SettingsLib/res/values-tl/strings.xml
+++ b/packages/SettingsLib/res/values-tl/strings.xml
@@ -399,9 +399,9 @@
<string name="inactive_app_inactive_summary" msgid="3161222402614236260">"Hindi aktibo. I-tap upang i-toggle."</string>
<string name="inactive_app_active_summary" msgid="8047630990208722344">"Aktibo. I-tap upang i-toggle."</string>
<string name="standby_bucket_summary" msgid="5128193447550429600">"Status ng app standby:<xliff:g id="BUCKET"> %s</xliff:g>"</string>
- <string name="transcode_settings_title" msgid="6700974145733932357">"Mga setting ng pagta-transcode ng media"</string>
- <string name="transcode_enable_all" msgid="4719796495995795404">"I-enable ang pagta-transcode para sa lahat ng app"</string>
- <string name="transcode_skip_apps" msgid="5680997722349545778">"I-disable ang pagta-transcode para sa mga app"</string>
+ <string name="transcode_settings_title" msgid="2581975870429850549">"Mga setting ng pag-transcode ng media"</string>
+ <string name="transcode_enable_all" msgid="9102460144086871903">"I-disable ang pag-transcode"</string>
+ <string name="transcode_skip_apps" msgid="8249721984597390142">"I-enable ang pag-transcode para sa mga app"</string>
<string name="runningservices_settings_title" msgid="6460099290493086515">"Mga tumatakbong serbisyo"</string>
<string name="runningservices_settings_summary" msgid="1046080643262665743">"Tingnan at kontrolin ang mga kasalukuyang tumatakbong serbisyo"</string>
<string name="select_webview_provider_title" msgid="3917815648099445503">"Pagpapatupad sa WebView"</string>
@@ -449,6 +449,8 @@
<string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"<xliff:g id="TIME">%1$s</xliff:g> ang natitira bago matapos mag-charge"</string>
<string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> hanggang matapos mag-charge"</string>
+ <!-- no translation found for power_charging_limited (5902301801611726210) -->
+ <skip />
<string name="battery_info_status_unknown" msgid="268625384868401114">"Hindi Kilala"</string>
<string name="battery_info_status_charging" msgid="4279958015430387405">"Nagcha-charge"</string>
<string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Mabilis na charge"</string>
diff --git a/packages/SettingsLib/res/values-tr/strings.xml b/packages/SettingsLib/res/values-tr/strings.xml
index 0916d8963b80..34c96a815616 100644
--- a/packages/SettingsLib/res/values-tr/strings.xml
+++ b/packages/SettingsLib/res/values-tr/strings.xml
@@ -399,9 +399,9 @@
<string name="inactive_app_inactive_summary" msgid="3161222402614236260">"Etkin değil. Geçiş yapmak için dokunun."</string>
<string name="inactive_app_active_summary" msgid="8047630990208722344">"Etkin. Geçiş yapmak için dokunun."</string>
<string name="standby_bucket_summary" msgid="5128193447550429600">"Uygulamayı beklemeye alma durumu: <xliff:g id="BUCKET"> %s</xliff:g>"</string>
- <string name="transcode_settings_title" msgid="6700974145733932357">"Medya kod dönüştürme ayarları"</string>
- <string name="transcode_enable_all" msgid="4719796495995795404">"Tüm uygulamalar için kod dönüştürmeyi etkinleştirir"</string>
- <string name="transcode_skip_apps" msgid="5680997722349545778">"Seçili uygulamalar için kod dönüştürmeyi devre dışı bırakır"</string>
+ <string name="transcode_settings_title" msgid="2581975870429850549">"Medya kod dönüştürme ayarları"</string>
+ <string name="transcode_enable_all" msgid="9102460144086871903">"Kod dönüştürmeyi devre dışı bırak"</string>
+ <string name="transcode_skip_apps" msgid="8249721984597390142">"Uygulamalar için kod dönüştürmeyi etkinleştir"</string>
<string name="runningservices_settings_title" msgid="6460099290493086515">"Çalışan hizmetler"</string>
<string name="runningservices_settings_summary" msgid="1046080643262665743">"Şu anda çalışan hizmetleri görüntüle ve denetle"</string>
<string name="select_webview_provider_title" msgid="3917815648099445503">"Web Görünümü kullanımı"</string>
@@ -449,6 +449,8 @@
<string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"Şarj olmaya <xliff:g id="TIME">%1$s</xliff:g> kaldı"</string>
<string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - şarj olmaya <xliff:g id="TIME">%2$s</xliff:g> kaldı"</string>
+ <!-- no translation found for power_charging_limited (5902301801611726210) -->
+ <skip />
<string name="battery_info_status_unknown" msgid="268625384868401114">"Bilinmiyor"</string>
<string name="battery_info_status_charging" msgid="4279958015430387405">"Şarj oluyor"</string>
<string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Hızlı şarj oluyor"</string>
diff --git a/packages/SettingsLib/res/values-uk/strings.xml b/packages/SettingsLib/res/values-uk/strings.xml
index 1558ce52cda9..de2456cce092 100644
--- a/packages/SettingsLib/res/values-uk/strings.xml
+++ b/packages/SettingsLib/res/values-uk/strings.xml
@@ -399,9 +399,9 @@
<string name="inactive_app_inactive_summary" msgid="3161222402614236260">"Неактивний додаток. Торкніться, щоб активувати."</string>
<string name="inactive_app_active_summary" msgid="8047630990208722344">"Активний додаток. Торкніться, щоб дезактивувати."</string>
<string name="standby_bucket_summary" msgid="5128193447550429600">"Режим очікування: <xliff:g id="BUCKET"> %s</xliff:g>"</string>
- <string name="transcode_settings_title" msgid="6700974145733932357">"Налаштування перекодування медіаконтенту"</string>
- <string name="transcode_enable_all" msgid="4719796495995795404">"Увімкнути перекодування для всіх додатків"</string>
- <string name="transcode_skip_apps" msgid="5680997722349545778">"Вимкнути перекодування для додатків"</string>
+ <string name="transcode_settings_title" msgid="2581975870429850549">"Налаштування перекодування медіафайлів"</string>
+ <string name="transcode_enable_all" msgid="9102460144086871903">"Вимкнути перекодування"</string>
+ <string name="transcode_skip_apps" msgid="8249721984597390142">"Увімкнути перекодування додатків"</string>
<string name="runningservices_settings_title" msgid="6460099290493086515">"Запущені сервіси"</string>
<string name="runningservices_settings_summary" msgid="1046080643262665743">"Переглянути й налаштувати запущені сервіси"</string>
<string name="select_webview_provider_title" msgid="3917815648099445503">"Застосування WebView"</string>
@@ -449,6 +449,8 @@
<string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"<xliff:g id="TIME">%1$s</xliff:g> до повного заряду"</string>
<string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> до повного заряду"</string>
+ <!-- no translation found for power_charging_limited (5902301801611726210) -->
+ <skip />
<string name="battery_info_status_unknown" msgid="268625384868401114">"Невідомо"</string>
<string name="battery_info_status_charging" msgid="4279958015430387405">"Заряджається"</string>
<string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Швидке заряджання"</string>
diff --git a/packages/SettingsLib/res/values-ur/strings.xml b/packages/SettingsLib/res/values-ur/strings.xml
index 507f8ccae491..7842ba9bcdbf 100644
--- a/packages/SettingsLib/res/values-ur/strings.xml
+++ b/packages/SettingsLib/res/values-ur/strings.xml
@@ -399,11 +399,11 @@
<string name="inactive_app_inactive_summary" msgid="3161222402614236260">"غیر فعال۔ ٹوگل کرنے کیلئے تھپتھپائیں۔"</string>
<string name="inactive_app_active_summary" msgid="8047630990208722344">"فعال۔ ٹوگل کرنے کیلئے تھپتھپائیں۔"</string>
<string name="standby_bucket_summary" msgid="5128193447550429600">"ایپ اسٹینڈ بائی کی حالت:<xliff:g id="BUCKET"> %s</xliff:g>"</string>
- <!-- no translation found for transcode_settings_title (6700974145733932357) -->
+ <!-- no translation found for transcode_settings_title (2581975870429850549) -->
<skip />
- <!-- no translation found for transcode_enable_all (4719796495995795404) -->
+ <!-- no translation found for transcode_enable_all (9102460144086871903) -->
<skip />
- <!-- no translation found for transcode_skip_apps (5680997722349545778) -->
+ <!-- no translation found for transcode_skip_apps (8249721984597390142) -->
<skip />
<string name="runningservices_settings_title" msgid="6460099290493086515">"چل رہی سروسز"</string>
<string name="runningservices_settings_summary" msgid="1046080643262665743">"فی الحال چل رہی سروسز دیکھیں اور انہیں کنٹرول کریں"</string>
@@ -452,6 +452,8 @@
<string name="power_charging" msgid="6727132649743436802">"‎<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>‎"</string>
<string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"چارج ہونے میں <xliff:g id="TIME">%1$s</xliff:g> باقی"</string>
<string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> چارج ہونے تک"</string>
+ <!-- no translation found for power_charging_limited (5902301801611726210) -->
+ <skip />
<string name="battery_info_status_unknown" msgid="268625384868401114">"نامعلوم"</string>
<string name="battery_info_status_charging" msgid="4279958015430387405">"چارج ہو رہا ہے"</string>
<string name="battery_info_status_charging_fast" msgid="8027559755902954885">"تیزی سے چارج ہو رہا ہے"</string>
diff --git a/packages/SettingsLib/res/values-uz/strings.xml b/packages/SettingsLib/res/values-uz/strings.xml
index 84207bf99c9f..9457d9001a88 100644
--- a/packages/SettingsLib/res/values-uz/strings.xml
+++ b/packages/SettingsLib/res/values-uz/strings.xml
@@ -399,9 +399,9 @@
<string name="inactive_app_inactive_summary" msgid="3161222402614236260">"Nofaol. O‘zgartirish uchun bu yerga bosing."</string>
<string name="inactive_app_active_summary" msgid="8047630990208722344">"Faol. O‘zgartirish uchun bu yerga bosing."</string>
<string name="standby_bucket_summary" msgid="5128193447550429600">"Kutish rejimi holati: <xliff:g id="BUCKET"> %s</xliff:g>"</string>
- <string name="transcode_settings_title" msgid="6700974145733932357">"Media transkripsiya sozlamalari"</string>
- <string name="transcode_enable_all" msgid="4719796495995795404">"Barcha ilovalar transkripsiyasini yoqish"</string>
- <string name="transcode_skip_apps" msgid="5680997722349545778">"Barcha ilovalar transkripsiyasini faolsizlantirish"</string>
+ <string name="transcode_settings_title" msgid="2581975870429850549">"Media transkripsiyasi sozlamalari"</string>
+ <string name="transcode_enable_all" msgid="9102460144086871903">"Transkripsiyani faolsizlantirish"</string>
+ <string name="transcode_skip_apps" msgid="8249721984597390142">"Ilovalar uchun transkripsiyani yoqish"</string>
<string name="runningservices_settings_title" msgid="6460099290493086515">"Ishlab turgan ilovalar"</string>
<string name="runningservices_settings_summary" msgid="1046080643262665743">"Ishlab turgan ilovalarni ko‘rish va boshqarish"</string>
<string name="select_webview_provider_title" msgid="3917815648099445503">"WebView ta’minotchisi"</string>
@@ -449,6 +449,8 @@
<string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"<xliff:g id="TIME">%1$s</xliff:g> ichida toʻladi"</string>
<string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> ichida toʻladi"</string>
+ <!-- no translation found for power_charging_limited (5902301801611726210) -->
+ <skip />
<string name="battery_info_status_unknown" msgid="268625384868401114">"Noma’lum"</string>
<string name="battery_info_status_charging" msgid="4279958015430387405">"Quvvat olmoqda"</string>
<string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Tezkor quvvat olmoqda"</string>
diff --git a/packages/SettingsLib/res/values-vi/strings.xml b/packages/SettingsLib/res/values-vi/strings.xml
index 14a97f3c8f05..235987c423d5 100644
--- a/packages/SettingsLib/res/values-vi/strings.xml
+++ b/packages/SettingsLib/res/values-vi/strings.xml
@@ -399,9 +399,9 @@
<string name="inactive_app_inactive_summary" msgid="3161222402614236260">"Không hoạt động. Nhấn để chuyển đổi."</string>
<string name="inactive_app_active_summary" msgid="8047630990208722344">"Hiện hoạt. Nhấn để chuyển đổi."</string>
<string name="standby_bucket_summary" msgid="5128193447550429600">"Trạng thái chờ ứng dụng:<xliff:g id="BUCKET"> %s</xliff:g>"</string>
- <string name="transcode_settings_title" msgid="6700974145733932357">"Tùy chọn chuyển mã ứng dụng"</string>
- <string name="transcode_enable_all" msgid="4719796495995795404">"Bật tùy chọn chuyển mã cho tất cả ứng dụng"</string>
- <string name="transcode_skip_apps" msgid="5680997722349545778">"Tắt tùy chọn chuyển mã cho ứng dụng"</string>
+ <string name="transcode_settings_title" msgid="2581975870429850549">"Cài đặt chuyển mã nội dung nghe nhìn"</string>
+ <string name="transcode_enable_all" msgid="9102460144086871903">"Tắt tùy chọn chuyển mã"</string>
+ <string name="transcode_skip_apps" msgid="8249721984597390142">"Bật tùy chọn chuyển mã cho ứng dụng"</string>
<string name="runningservices_settings_title" msgid="6460099290493086515">"Các dịch vụ đang chạy"</string>
<string name="runningservices_settings_summary" msgid="1046080643262665743">"Xem và kiểm soát các dịch vụ đang chạy"</string>
<string name="select_webview_provider_title" msgid="3917815648099445503">"Triển khai WebView"</string>
@@ -449,6 +449,8 @@
<string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"Còn <xliff:g id="TIME">%1$s</xliff:g> nữa là sạc đầy"</string>
<string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> nữa là sạc đầy"</string>
+ <!-- no translation found for power_charging_limited (5902301801611726210) -->
+ <skip />
<string name="battery_info_status_unknown" msgid="268625384868401114">"Không xác định"</string>
<string name="battery_info_status_charging" msgid="4279958015430387405">"Đang sạc"</string>
<string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Đang sạc nhanh"</string>
diff --git a/packages/SettingsLib/res/values-zh-rCN/strings.xml b/packages/SettingsLib/res/values-zh-rCN/strings.xml
index 9d312b61e75c..46188e9859e6 100644
--- a/packages/SettingsLib/res/values-zh-rCN/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rCN/strings.xml
@@ -399,9 +399,9 @@
<string name="inactive_app_inactive_summary" msgid="3161222402614236260">"未启用。点按即可切换。"</string>
<string name="inactive_app_active_summary" msgid="8047630990208722344">"已启用。点按即可切换。"</string>
<string name="standby_bucket_summary" msgid="5128193447550429600">"应用待机状态:<xliff:g id="BUCKET"> %s</xliff:g>"</string>
- <string name="transcode_settings_title" msgid="6700974145733932357">"媒体转码设置"</string>
- <string name="transcode_enable_all" msgid="4719796495995795404">"为所有应用启用转码"</string>
- <string name="transcode_skip_apps" msgid="5680997722349545778">"为应用停用转码"</string>
+ <string name="transcode_settings_title" msgid="2581975870429850549">"媒体转码设置"</string>
+ <string name="transcode_enable_all" msgid="9102460144086871903">"停用转码功能"</string>
+ <string name="transcode_skip_apps" msgid="8249721984597390142">"为应用启用转码功能"</string>
<string name="runningservices_settings_title" msgid="6460099290493086515">"正在运行的服务"</string>
<string name="runningservices_settings_summary" msgid="1046080643262665743">"查看和控制当前正在运行的服务"</string>
<string name="select_webview_provider_title" msgid="3917815648099445503">"WebView 实现"</string>
@@ -449,6 +449,8 @@
<string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"还剩 <xliff:g id="TIME">%1$s</xliff:g>充满电"</string>
<string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>后充满电"</string>
+ <!-- no translation found for power_charging_limited (5902301801611726210) -->
+ <skip />
<string name="battery_info_status_unknown" msgid="268625384868401114">"未知"</string>
<string name="battery_info_status_charging" msgid="4279958015430387405">"正在充电"</string>
<string name="battery_info_status_charging_fast" msgid="8027559755902954885">"正在快速充电"</string>
diff --git a/packages/SettingsLib/res/values-zh-rHK/strings.xml b/packages/SettingsLib/res/values-zh-rHK/strings.xml
index a8eb24624946..6f5c0253e94f 100644
--- a/packages/SettingsLib/res/values-zh-rHK/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rHK/strings.xml
@@ -399,9 +399,9 @@
<string name="inactive_app_inactive_summary" msgid="3161222402614236260">"未啟用。輕按即可切換。"</string>
<string name="inactive_app_active_summary" msgid="8047630990208722344">"已啟用。輕按即可切換。"</string>
<string name="standby_bucket_summary" msgid="5128193447550429600">"備用應用程式狀態:<xliff:g id="BUCKET"> %s</xliff:g>"</string>
- <string name="transcode_settings_title" msgid="6700974145733932357">"媒體轉碼設定"</string>
- <string name="transcode_enable_all" msgid="4719796495995795404">"為所有應用程式啟用轉碼功能"</string>
- <string name="transcode_skip_apps" msgid="5680997722349545778">"為所有應用程式停用轉碼功能"</string>
+ <string name="transcode_settings_title" msgid="2581975870429850549">"媒體轉碼功能設定"</string>
+ <string name="transcode_enable_all" msgid="9102460144086871903">"停用轉碼功能"</string>
+ <string name="transcode_skip_apps" msgid="8249721984597390142">"替應用程式啟用轉碼功能"</string>
<string name="runningservices_settings_title" msgid="6460099290493086515">"執行中的服務"</string>
<string name="runningservices_settings_summary" msgid="1046080643262665743">"查看並控制目前正在執行中的服務"</string>
<string name="select_webview_provider_title" msgid="3917815648099445503">"WebView 設置"</string>
@@ -449,6 +449,8 @@
<string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"還需 <xliff:g id="TIME">%1$s</xliff:g>才能充滿電"</string>
<string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - 還需 <xliff:g id="TIME">%2$s</xliff:g>才能充滿電"</string>
+ <!-- no translation found for power_charging_limited (5902301801611726210) -->
+ <skip />
<string name="battery_info_status_unknown" msgid="268625384868401114">"未知"</string>
<string name="battery_info_status_charging" msgid="4279958015430387405">"充電中"</string>
<string name="battery_info_status_charging_fast" msgid="8027559755902954885">"正在快速充電"</string>
diff --git a/packages/SettingsLib/res/values-zh-rTW/strings.xml b/packages/SettingsLib/res/values-zh-rTW/strings.xml
index 73692e46605d..f966df68e0c3 100644
--- a/packages/SettingsLib/res/values-zh-rTW/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rTW/strings.xml
@@ -399,9 +399,9 @@
<string name="inactive_app_inactive_summary" msgid="3161222402614236260">"未啟用。輕觸即可切換。"</string>
<string name="inactive_app_active_summary" msgid="8047630990208722344">"已啟用。輕觸即可切換。"</string>
<string name="standby_bucket_summary" msgid="5128193447550429600">"應用程式待命狀態:<xliff:g id="BUCKET"> %s</xliff:g>"</string>
- <string name="transcode_settings_title" msgid="6700974145733932357">"媒體轉碼設定"</string>
- <string name="transcode_enable_all" msgid="4719796495995795404">"替所有應用程式啟用轉碼功能"</string>
- <string name="transcode_skip_apps" msgid="5680997722349545778">"替應用程式停用轉碼功能"</string>
+ <string name="transcode_settings_title" msgid="2581975870429850549">"媒體轉碼功能設定"</string>
+ <string name="transcode_enable_all" msgid="9102460144086871903">"停用轉碼功能"</string>
+ <string name="transcode_skip_apps" msgid="8249721984597390142">"替應用程式啟用轉碼功能"</string>
<string name="runningservices_settings_title" msgid="6460099290493086515">"正在運作的服務"</string>
<string name="runningservices_settings_summary" msgid="1046080643262665743">"查看並管理目前正在執行的服務"</string>
<string name="select_webview_provider_title" msgid="3917815648099445503">"WebView 實作"</string>
@@ -449,6 +449,8 @@
<string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"<xliff:g id="TIME">%1$s</xliff:g>後充飽電"</string>
<string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>後充飽電"</string>
+ <!-- no translation found for power_charging_limited (5902301801611726210) -->
+ <skip />
<string name="battery_info_status_unknown" msgid="268625384868401114">"不明"</string>
<string name="battery_info_status_charging" msgid="4279958015430387405">"充電中"</string>
<string name="battery_info_status_charging_fast" msgid="8027559755902954885">"快速充電中"</string>
diff --git a/packages/SettingsLib/res/values-zu/strings.xml b/packages/SettingsLib/res/values-zu/strings.xml
index ead2800b208a..8ad37d330bc4 100644
--- a/packages/SettingsLib/res/values-zu/strings.xml
+++ b/packages/SettingsLib/res/values-zu/strings.xml
@@ -399,9 +399,9 @@
<string name="inactive_app_inactive_summary" msgid="3161222402614236260">"Akusebenzi. Thepha ukuze ushintshe."</string>
<string name="inactive_app_active_summary" msgid="8047630990208722344">"Kuyasebenza. Thepha ukuze ushintshe."</string>
<string name="standby_bucket_summary" msgid="5128193447550429600">"Isimo sokulinda kohlelo lokusebenza:<xliff:g id="BUCKET"> %s</xliff:g>"</string>
- <string name="transcode_settings_title" msgid="6700974145733932357">"Amasethingi emidiya yokudlulisela ikhodi"</string>
- <string name="transcode_enable_all" msgid="4719796495995795404">"Nikela amandla ukudlulisela ikhodi kuzonke izinhlelo zokusebenza"</string>
- <string name="transcode_skip_apps" msgid="5680997722349545778">"Khubaza ukudlulisela ikhodi kwezinhlelo zokusebenza"</string>
+ <string name="transcode_settings_title" msgid="2581975870429850549">"Amasethingi wemidiya yokudlulisela ikhodi"</string>
+ <string name="transcode_enable_all" msgid="9102460144086871903">"Khubaza ukudlulisela ikhodi"</string>
+ <string name="transcode_skip_apps" msgid="8249721984597390142">"Nika amandla ukudlulisela ikhodi kwezinhlelo zokusebenza"</string>
<string name="runningservices_settings_title" msgid="6460099290493086515">"Amasevisi asebenzayo"</string>
<string name="runningservices_settings_summary" msgid="1046080643262665743">"Buka futhi ulawule amasevisi asebenzayo okwamanje"</string>
<string name="select_webview_provider_title" msgid="3917815648099445503">"Ukufakwa ke-WebView"</string>
@@ -449,6 +449,8 @@
<string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"<xliff:g id="TIME">%1$s</xliff:g> esele ize ishaje"</string>
<string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> ize igcwale"</string>
+ <!-- no translation found for power_charging_limited (5902301801611726210) -->
+ <skip />
<string name="battery_info_status_unknown" msgid="268625384868401114">"Akwaziwa"</string>
<string name="battery_info_status_charging" msgid="4279958015430387405">"Iyashaja"</string>
<string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Ishaja ngokushesha"</string>
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/emergencynumber/EmergencyNumberUtilsTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/emergencynumber/EmergencyNumberUtilsTest.java
new file mode 100644
index 000000000000..140363127dff
--- /dev/null
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/emergencynumber/EmergencyNumberUtilsTest.java
@@ -0,0 +1,124 @@
+/*
+ * 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.settingslib.emergencynumber;
+
+import static android.telephony.emergency.EmergencyNumber.EMERGENCY_SERVICE_CATEGORY_POLICE;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import android.content.ContentResolver;
+import android.content.Context;
+import android.content.pm.PackageManager;
+import android.provider.Settings;
+import android.telephony.SubscriptionManager;
+import android.telephony.TelephonyManager;
+import android.telephony.emergency.EmergencyNumber;
+import android.util.ArrayMap;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RobolectricTestRunner;
+import org.robolectric.RuntimeEnvironment;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+@RunWith(RobolectricTestRunner.class)
+public class EmergencyNumberUtilsTest {
+ private static final String TELEPHONY_EMERGENCY_NUMBER = "1234";
+ private static final String USER_OVERRIDE_EMERGENCY_NUMBER = "5678";
+
+ @Mock
+ private Context mContext;
+ @Mock
+ private PackageManager mPackageManager;
+ @Mock
+ private TelephonyManager mTelephonyManager;
+ private EmergencyNumberUtils mUtils;
+
+ @Before
+ public void setup() {
+ MockitoAnnotations.initMocks(this);
+ when(mContext.getPackageManager()).thenReturn(mPackageManager);
+ }
+
+ @Test
+ public void getDefaultPoliceNumber_noTelephony_shouldReturnDefault() {
+ when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_TELEPHONY)).thenReturn(false);
+ mUtils = new EmergencyNumberUtils(mContext);
+
+ assertThat(mUtils.getDefaultPoliceNumber()).isEqualTo(
+ EmergencyNumberUtils.FALL_BACK_NUMBER);
+ }
+
+ @Test
+ public void getDefaultPoliceNumber_hasTelephony_shouldLoadFromTelephony() {
+ when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_TELEPHONY)).thenReturn(true);
+ when(mContext.getSystemService(TelephonyManager.class)).thenReturn(mTelephonyManager);
+ addEmergencyNumberToTelephony();
+ mUtils = new EmergencyNumberUtils(mContext);
+
+
+ assertThat(mUtils.getDefaultPoliceNumber()).isEqualTo(TELEPHONY_EMERGENCY_NUMBER);
+ }
+
+ @Test
+ public void getPoliceNumber_hasUserOverride_shouldLoadFromUserOverride() {
+ when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_TELEPHONY)).thenReturn(true);
+ when(mContext.getSystemService(TelephonyManager.class)).thenReturn(mTelephonyManager);
+ addEmergencyNumberToTelephony();
+
+ ContentResolver resolver = RuntimeEnvironment.application.getContentResolver();
+ when(mContext.getContentResolver()).thenReturn(resolver);
+ Settings.Secure.putString(resolver, Settings.Secure.EMERGENCY_GESTURE_CALL_NUMBER,
+ USER_OVERRIDE_EMERGENCY_NUMBER);
+
+ mUtils = new EmergencyNumberUtils(mContext);
+
+ assertThat(mUtils.getPoliceNumber()).isEqualTo(USER_OVERRIDE_EMERGENCY_NUMBER);
+ }
+
+ @Test
+ public void getPoliceNumber_noUserOverride_shouldLoadFromTelephony() {
+ when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_TELEPHONY)).thenReturn(true);
+ when(mContext.getSystemService(TelephonyManager.class)).thenReturn(mTelephonyManager);
+ addEmergencyNumberToTelephony();
+
+ mUtils = new EmergencyNumberUtils(mContext);
+
+ assertThat(mUtils.getPoliceNumber()).isEqualTo(TELEPHONY_EMERGENCY_NUMBER);
+ }
+
+ private void addEmergencyNumberToTelephony() {
+ final int subId = SubscriptionManager.getDefaultSubscriptionId();
+ EmergencyNumber emergencyNumber = mock(EmergencyNumber.class);
+ Map<Integer, List<EmergencyNumber>> numbers = new ArrayMap<>();
+ List<EmergencyNumber> numbersForSubId = new ArrayList<>();
+ numbersForSubId.add(emergencyNumber);
+ numbers.put(subId, numbersForSubId);
+ when(mTelephonyManager.getEmergencyNumberList(
+ EMERGENCY_SERVICE_CATEGORY_POLICE)).thenReturn(numbers);
+ when(emergencyNumber.getNumber()).thenReturn(TELEPHONY_EMERGENCY_NUMBER);
+ }
+}
diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml
index 3de0fbdf8fb1..7120cc21c821 100644
--- a/packages/SystemUI/AndroidManifest.xml
+++ b/packages/SystemUI/AndroidManifest.xml
@@ -623,8 +623,7 @@
<service
android:name=".keyguard.KeyguardService"
- android:exported="true"
- android:enabled="@bool/config_enableKeyguardService" />
+ android:exported="true" />
<activity android:name=".keyguard.WorkLockActivity"
android:label="@string/accessibility_desc_work_lock"
diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/FalsingManager.java b/packages/SystemUI/plugin/src/com/android/systemui/plugins/FalsingManager.java
index 63f8b1f5dbb8..0f94bca1d815 100644
--- a/packages/SystemUI/plugin/src/com/android/systemui/plugins/FalsingManager.java
+++ b/packages/SystemUI/plugin/src/com/android/systemui/plugins/FalsingManager.java
@@ -21,6 +21,7 @@ import android.view.MotionEvent;
import com.android.systemui.plugins.annotations.ProvidesInterface;
+import java.io.FileDescriptor;
import java.io.PrintWriter;
/**
@@ -30,7 +31,7 @@ import java.io.PrintWriter;
*/
@ProvidesInterface(version = FalsingManager.VERSION)
public interface FalsingManager {
- int VERSION = 5;
+ int VERSION = 6;
void onSuccessfulUnlock();
@@ -45,6 +46,42 @@ public interface FalsingManager {
/** Returns true if the gesture should be rejected. */
boolean isFalseTouch(int interactionType);
+ /**
+ * Returns true if the FalsingManager thinks the last gesure was not a valid tap.
+ *
+ * Accepts one parameter, robustCheck, that distinctly changes behavior. When set to false,
+ * this method simply looks at the last gesture and returns whether it is a tap or not, (as
+ * opposed to a swipe or other non-tap gesture). When set to true, a more thorough analysis
+ * is performed that can include historical interactions and other contextual cues to see
+ * if the tap looks accidental.
+ *
+ * Set robustCheck to true if you want to validate a tap for launching an action, like opening
+ * a notification. Set to false if you simply want to know if the last gesture looked like a
+ * tap.
+ */
+ boolean isFalseTap(boolean robustCheck);
+
+ /**
+ * Returns true if the last two gestures do not look like a double tap.
+ *
+ * Only works on data that has already been reported to the FalsingManager. Be sure that
+ * {@link #onTouchEvent(MotionEvent, int, int)} has already been called for all of the
+ * taps you want considered.
+ *
+ * This looks at the last two gestures on the screen, ensuring that they meet the following
+ * criteria:
+ *
+ * a) There are at least two gestures.
+ * b) The last two gestures look like taps.
+ * c) The last two gestures look like a double tap taken together.
+ *
+ * This method is _not_ context aware. That is to say, if two taps occur on two neighboring
+ * views, but are otherwise close to one another, this will report a successful double tap.
+ * It is up to the caller to decide
+ * @return
+ */
+ boolean isFalseDoubleTap();
+
void onNotificatonStopDraggingDown();
void setNotificationExpanded();
@@ -103,7 +140,8 @@ public interface FalsingManager {
void onTouchEvent(MotionEvent ev, int width, int height);
- void dump(PrintWriter pw);
+ /** From com.android.systemui.Dumpable. */
+ void dump(FileDescriptor fd, PrintWriter pw, String[] args);
void cleanup();
}
diff --git a/packages/SystemUI/res-keyguard/layout/keyguard_clock_switch.xml b/packages/SystemUI/res-keyguard/layout/keyguard_clock_switch.xml
index 7816d6252267..b75c2c4cea6c 100644
--- a/packages/SystemUI/res-keyguard/layout/keyguard_clock_switch.xml
+++ b/packages/SystemUI/res-keyguard/layout/keyguard_clock_switch.xml
@@ -82,6 +82,28 @@
android:elegantTextHeight="false"
/>
</FrameLayout>
+ <FrameLayout
+ android:id="@+id/new_lockscreen_clock_view_large"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_below="@id/keyguard_status_area"
+ android:paddingTop="20dp"
+ android:visibility="gone">
+ <com.android.keyguard.AnimatableClockView
+ android:id="@+id/animatable_clock_view_large"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_horizontal"
+ android:gravity="center_horizontal"
+ android:textSize="170dp"
+ android:letterSpacing="0.02"
+ android:lineSpacingMultiplier=".8"
+ android:includeFontPadding="false"
+ android:fontFamily="@font/clock"
+ android:typeface="monospace"
+ android:elegantTextHeight="false"
+ />
+ </FrameLayout>
<include layout="@layout/keyguard_status_area"
android:id="@+id/keyguard_status_area"
android:layout_width="match_parent"
diff --git a/packages/SystemUI/res-keyguard/values-af/strings.xml b/packages/SystemUI/res-keyguard/values-af/strings.xml
index 92dd9fd96111..276fa23e8578 100644
--- a/packages/SystemUI/res-keyguard/values-af/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-af/strings.xml
@@ -38,6 +38,8 @@
<string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Laai tans"</string>
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Laai tans vinnig"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Laai tans stadig"</string>
+ <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) -->
+ <skip />
<string name="keyguard_low_battery" msgid="1868012396800230904">"Koppel jou laaier."</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Druk Kieslys om te ontsluit."</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"Netwerk is gesluit"</string>
diff --git a/packages/SystemUI/res-keyguard/values-am/strings.xml b/packages/SystemUI/res-keyguard/values-am/strings.xml
index f94c20f9ad01..ae5d1f675c52 100644
--- a/packages/SystemUI/res-keyguard/values-am/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-am/strings.xml
@@ -38,6 +38,8 @@
<string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ኃይል በመሙላት ላይ"</string>
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • በፍጥነት ኃይልን በመሙላት ላይ"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • በዝግታ ኃይልን በመሙላት ላይ"</string>
+ <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) -->
+ <skip />
<string name="keyguard_low_battery" msgid="1868012396800230904">"ኃይል መሙያዎን ያያይዙ።"</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"ለመክፈት ምናሌ ተጫን።"</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"አውታረ መረብ ተቆልፏል"</string>
diff --git a/packages/SystemUI/res-keyguard/values-ar/strings.xml b/packages/SystemUI/res-keyguard/values-ar/strings.xml
index 65e3f0dbd176..fb03fe340c3a 100644
--- a/packages/SystemUI/res-keyguard/values-ar/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-ar/strings.xml
@@ -38,6 +38,8 @@
<string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • جارٍ الشحن"</string>
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • جارٍ الشحن سريعًا"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • جارٍ الشحن ببطء"</string>
+ <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) -->
+ <skip />
<string name="keyguard_low_battery" msgid="1868012396800230904">"توصيل جهاز الشحن."</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"اضغط على \"القائمة\" لإلغاء التأمين."</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"الشبكة مؤمّنة"</string>
diff --git a/packages/SystemUI/res-keyguard/values-as/strings.xml b/packages/SystemUI/res-keyguard/values-as/strings.xml
index 3b51e480b7dd..8e8b13d0a160 100644
--- a/packages/SystemUI/res-keyguard/values-as/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-as/strings.xml
@@ -38,6 +38,8 @@
<string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • চ্চার্জ কৰি থকা হৈছে"</string>
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • দ্ৰুত গতিৰে চ্চাৰ্জ কৰি থকা হৈছে"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • লাহে লাহে চ্চাৰ্জ কৰি থকা হৈছে"</string>
+ <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) -->
+ <skip />
<string name="keyguard_low_battery" msgid="1868012396800230904">"আপোনাৰ চ্চার্জাৰ সংযোগ কৰক।"</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"আনলক কৰিবলৈ মেনু টিপক।"</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"নেটৱর্ক লক কৰা অৱস্থাত আছে"</string>
diff --git a/packages/SystemUI/res-keyguard/values-az/strings.xml b/packages/SystemUI/res-keyguard/values-az/strings.xml
index ea07c3db4354..f9bff73a671f 100644
--- a/packages/SystemUI/res-keyguard/values-az/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-az/strings.xml
@@ -38,6 +38,8 @@
<string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Enerji yığır"</string>
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Sürətlə enerji yığır"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Yavaş enerji yığır"</string>
+ <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) -->
+ <skip />
<string name="keyguard_low_battery" msgid="1868012396800230904">"Adapteri qoşun."</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Kilidi açmaq üçün Menyu düyməsinə basın."</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"Şəbəkə kilidlidir"</string>
diff --git a/packages/SystemUI/res-keyguard/values-b+sr+Latn/strings.xml b/packages/SystemUI/res-keyguard/values-b+sr+Latn/strings.xml
index e206958d1e95..3434ac67bb73 100644
--- a/packages/SystemUI/res-keyguard/values-b+sr+Latn/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-b+sr+Latn/strings.xml
@@ -38,6 +38,8 @@
<string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Puni se"</string>
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Brzo se puni"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Sporo se puni"</string>
+ <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) -->
+ <skip />
<string name="keyguard_low_battery" msgid="1868012396800230904">"Priključite punjač."</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Pritisnite Meni da biste otključali."</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"Mreža je zaključana"</string>
diff --git a/packages/SystemUI/res-keyguard/values-be/strings.xml b/packages/SystemUI/res-keyguard/values-be/strings.xml
index 569e705fbcc2..07d682f69f56 100644
--- a/packages/SystemUI/res-keyguard/values-be/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-be/strings.xml
@@ -38,6 +38,8 @@
<string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Ідзе зарадка"</string>
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Ідзе хуткая зарадка"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Ідзе павольная зарадка"</string>
+ <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) -->
+ <skip />
<string name="keyguard_low_battery" msgid="1868012396800230904">"Падключыце зарадную прыладу."</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Націсніце кнопку \"Меню\", каб разблакіраваць."</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"Сетка заблакіравана"</string>
diff --git a/packages/SystemUI/res-keyguard/values-bg/strings.xml b/packages/SystemUI/res-keyguard/values-bg/strings.xml
index d015be320e20..3890c11f9450 100644
--- a/packages/SystemUI/res-keyguard/values-bg/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-bg/strings.xml
@@ -38,6 +38,8 @@
<string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Зарежда се"</string>
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Зарежда се бързо"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Зарежда се бавно"</string>
+ <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) -->
+ <skip />
<string name="keyguard_low_battery" msgid="1868012396800230904">"Свържете зарядното си устройство."</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Натиснете „Меню“, за да отключите."</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"Мрежата е заключена"</string>
diff --git a/packages/SystemUI/res-keyguard/values-bn/strings.xml b/packages/SystemUI/res-keyguard/values-bn/strings.xml
index 8eae6e6e2e18..f9163747aff7 100644
--- a/packages/SystemUI/res-keyguard/values-bn/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-bn/strings.xml
@@ -38,6 +38,8 @@
<string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • চার্জ হচ্ছে"</string>
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • দ্রুত চার্জ হচ্ছে"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ধীরে চার্জ হচ্ছে"</string>
+ <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) -->
+ <skip />
<string name="keyguard_low_battery" msgid="1868012396800230904">"আপনার চার্জার সংযুক্ত করুন।"</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"আনলক করতে মেনুতে টিপুন।"</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"নেটওয়ার্ক লক করা আছে"</string>
diff --git a/packages/SystemUI/res-keyguard/values-bs/strings.xml b/packages/SystemUI/res-keyguard/values-bs/strings.xml
index 286b08be1c5e..59a881db8e33 100644
--- a/packages/SystemUI/res-keyguard/values-bs/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-bs/strings.xml
@@ -38,6 +38,8 @@
<string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Punjenje"</string>
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Brzo punjenje"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Sporo punjenje"</string>
+ <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) -->
+ <skip />
<string name="keyguard_low_battery" msgid="1868012396800230904">"Priključite punjač."</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Pritisnite meni da otključate."</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"Mreža je zaključana"</string>
diff --git a/packages/SystemUI/res-keyguard/values-ca/strings.xml b/packages/SystemUI/res-keyguard/values-ca/strings.xml
index cb7fa37b281d..82d63c157441 100644
--- a/packages/SystemUI/res-keyguard/values-ca/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-ca/strings.xml
@@ -38,6 +38,8 @@
<string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • S\'està carregant"</string>
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • S\'està carregant ràpidament"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • S\'està carregant lentament"</string>
+ <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) -->
+ <skip />
<string name="keyguard_low_battery" msgid="1868012396800230904">"Connecta el carregador."</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Prem Menú per desbloquejar."</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"La xarxa està bloquejada"</string>
diff --git a/packages/SystemUI/res-keyguard/values-cs/strings.xml b/packages/SystemUI/res-keyguard/values-cs/strings.xml
index 4f0c0ffa4962..a4e653f19678 100644
--- a/packages/SystemUI/res-keyguard/values-cs/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-cs/strings.xml
@@ -38,6 +38,8 @@
<string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Nabíjení"</string>
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Rychlé nabíjení"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Pomalé nabíjení"</string>
+ <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) -->
+ <skip />
<string name="keyguard_low_battery" msgid="1868012396800230904">"Připojte dobíjecí zařízení."</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Klávesy odemknete stisknutím tlačítka nabídky."</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"Síť je blokována"</string>
diff --git a/packages/SystemUI/res-keyguard/values-da/strings.xml b/packages/SystemUI/res-keyguard/values-da/strings.xml
index e486fc625699..604852cfeb45 100644
--- a/packages/SystemUI/res-keyguard/values-da/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-da/strings.xml
@@ -38,6 +38,8 @@
<string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Oplader"</string>
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Oplader hurtigt"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Oplader langsomt"</string>
+ <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) -->
+ <skip />
<string name="keyguard_low_battery" msgid="1868012396800230904">"Tilslut din oplader."</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Tryk på menuen for at låse op."</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"Netværket er låst"</string>
diff --git a/packages/SystemUI/res-keyguard/values-de/strings.xml b/packages/SystemUI/res-keyguard/values-de/strings.xml
index 06d012f4e84d..0e2ea136f263 100644
--- a/packages/SystemUI/res-keyguard/values-de/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-de/strings.xml
@@ -38,6 +38,8 @@
<string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Wird geladen"</string>
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Wird schnell geladen"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Wird langsam geladen"</string>
+ <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) -->
+ <skip />
<string name="keyguard_low_battery" msgid="1868012396800230904">"Ladegerät anschließen."</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Zum Entsperren die Menütaste drücken."</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"Netzwerk gesperrt"</string>
diff --git a/packages/SystemUI/res-keyguard/values-el/strings.xml b/packages/SystemUI/res-keyguard/values-el/strings.xml
index 176428421476..90e255031dd1 100644
--- a/packages/SystemUI/res-keyguard/values-el/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-el/strings.xml
@@ -38,6 +38,8 @@
<string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Φόρτιση"</string>
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Γρήγορη φόρτιση"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Αργή φόρτιση"</string>
+ <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) -->
+ <skip />
<string name="keyguard_low_battery" msgid="1868012396800230904">"Συνδέστε τον φορτιστή."</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Πατήστε \"Μενού\" για ξεκλείδωμα."</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"Κλειδωμένο δίκτυο"</string>
diff --git a/packages/SystemUI/res-keyguard/values-en-rAU/strings.xml b/packages/SystemUI/res-keyguard/values-en-rAU/strings.xml
index 92a15949a8ab..7b0c638dcdf3 100644
--- a/packages/SystemUI/res-keyguard/values-en-rAU/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-en-rAU/strings.xml
@@ -38,6 +38,7 @@
<string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Charging"</string>
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Charging rapidly"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Charging slowly"</string>
+ <string name="keyguard_plugged_in_charging_limited" msgid="8190982388514496109">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Battery limited temporarily"</string>
<string name="keyguard_low_battery" msgid="1868012396800230904">"Connect your charger."</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Press Menu to unlock."</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"Network locked"</string>
diff --git a/packages/SystemUI/res-keyguard/values-en-rCA/strings.xml b/packages/SystemUI/res-keyguard/values-en-rCA/strings.xml
index 719f1a18a744..2ef720e44735 100644
--- a/packages/SystemUI/res-keyguard/values-en-rCA/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-en-rCA/strings.xml
@@ -38,6 +38,7 @@
<string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Charging"</string>
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Charging rapidly"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Charging slowly"</string>
+ <string name="keyguard_plugged_in_charging_limited" msgid="8190982388514496109">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Battery limited temporarily"</string>
<string name="keyguard_low_battery" msgid="1868012396800230904">"Connect your charger."</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Press Menu to unlock."</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"Network locked"</string>
diff --git a/packages/SystemUI/res-keyguard/values-en-rGB/strings.xml b/packages/SystemUI/res-keyguard/values-en-rGB/strings.xml
index 92a15949a8ab..7b0c638dcdf3 100644
--- a/packages/SystemUI/res-keyguard/values-en-rGB/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-en-rGB/strings.xml
@@ -38,6 +38,7 @@
<string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Charging"</string>
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Charging rapidly"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Charging slowly"</string>
+ <string name="keyguard_plugged_in_charging_limited" msgid="8190982388514496109">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Battery limited temporarily"</string>
<string name="keyguard_low_battery" msgid="1868012396800230904">"Connect your charger."</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Press Menu to unlock."</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"Network locked"</string>
diff --git a/packages/SystemUI/res-keyguard/values-en-rIN/strings.xml b/packages/SystemUI/res-keyguard/values-en-rIN/strings.xml
index 92a15949a8ab..7b0c638dcdf3 100644
--- a/packages/SystemUI/res-keyguard/values-en-rIN/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-en-rIN/strings.xml
@@ -38,6 +38,7 @@
<string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Charging"</string>
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Charging rapidly"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Charging slowly"</string>
+ <string name="keyguard_plugged_in_charging_limited" msgid="8190982388514496109">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Battery limited temporarily"</string>
<string name="keyguard_low_battery" msgid="1868012396800230904">"Connect your charger."</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Press Menu to unlock."</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"Network locked"</string>
diff --git a/packages/SystemUI/res-keyguard/values-en-rXC/strings.xml b/packages/SystemUI/res-keyguard/values-en-rXC/strings.xml
index 975b1f644ef8..471ef8ba83d9 100644
--- a/packages/SystemUI/res-keyguard/values-en-rXC/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-en-rXC/strings.xml
@@ -38,6 +38,7 @@
<string name="keyguard_plugged_in" msgid="8169926454348380863">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‎‎‏‎‏‏‎‎‎‎‏‎‏‏‎‏‎‎‎‏‏‎‏‎‎‏‎‏‏‏‏‏‎‎‎‏‎‎‎‎‎‎‎‎‏‏‏‏‎‏‎‏‎‏‏‏‏‏‏‎‎‏‎‎‏‏‎<xliff:g id="PERCENTAGE">%s</xliff:g>‎‏‎‎‏‏‏‎ • Charging‎‏‎‎‏‎"</string>
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‏‎‎‏‏‏‎‎‎‎‎‎‏‎‏‎‎‎‎‎‎‎‏‎‏‎‏‏‎‏‎‏‏‏‎‎‏‎‎‎‏‏‏‏‏‎‏‎‎‎‎‏‎‎‎‏‎‏‎‎‎‏‎‎‏‏‎<xliff:g id="PERCENTAGE">%s</xliff:g>‎‏‎‎‏‏‏‎ • Charging rapidly‎‏‎‎‏‎"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‎‎‎‎‏‏‎‎‎‏‎‏‏‏‏‏‎‏‎‎‏‏‎‏‎‏‏‎‎‎‏‎‎‏‎‎‏‎‏‏‏‏‎‏‏‏‎‏‎‎‏‎‎‎‏‎‎‏‏‎<xliff:g id="PERCENTAGE">%s</xliff:g>‎‏‎‎‏‏‏‎ • Charging slowly‎‏‎‎‏‎"</string>
+ <string name="keyguard_plugged_in_charging_limited" msgid="8190982388514496109">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‎‎‏‏‎‏‎‏‏‎‎‎‎‏‏‎‏‏‏‎‎‎‏‎‏‎‏‏‎‏‎‏‏‎‎‏‏‏‎‎‎‏‏‎‎‎‏‏‏‏‎‎‏‏‎‏‏‎‏‎‎‏‎‎‏‏‎<xliff:g id="PERCENTAGE">%s</xliff:g>‎‏‎‎‏‏‏‎ • Battery limited temporarily‎‏‎‎‏‎"</string>
<string name="keyguard_low_battery" msgid="1868012396800230904">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‎‎‏‏‏‏‎‏‏‎‎‏‎‎‎‎‎‏‏‎‏‏‎‎‎‎‎‏‎‏‏‎‎‏‏‎‏‎‎‏‏‎‏‏‏‎‎‎‏‎‏‏‏‏‏‏‎‎‎‎Connect your charger.‎‏‎‎‏‎"</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‏‎‏‎‏‎‎‎‎‎‎‎‎‏‎‏‏‏‎‏‎‏‎‎‎‏‏‎‏‎‏‏‎‏‏‎‎‎‏‏‎‎‎‏‎‎‏‏‏‎‎‎‎‏‏‏‎‏‎‎Press Menu to unlock.‎‏‎‎‏‎"</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‎‏‏‏‎‏‏‎‏‎‎‏‏‎‎‏‎‎‏‎‏‏‏‏‏‎‏‎‏‏‏‏‏‎‎‏‎‎‎‏‏‎‎‏‎‏‏‎‎‏‎‏‎‎‎‎‎‎‎‎‎‎‎Network locked‎‏‎‎‏‎"</string>
diff --git a/packages/SystemUI/res-keyguard/values-es-rUS/strings.xml b/packages/SystemUI/res-keyguard/values-es-rUS/strings.xml
index 25ab6159998e..a5750b550295 100644
--- a/packages/SystemUI/res-keyguard/values-es-rUS/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-es-rUS/strings.xml
@@ -38,6 +38,8 @@
<string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Cargando"</string>
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Cargando rápidamente"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Cargando lentamente"</string>
+ <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) -->
+ <skip />
<string name="keyguard_low_battery" msgid="1868012396800230904">"Conecta tu cargador."</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Presiona Menú para desbloquear."</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"Bloqueada para la red"</string>
diff --git a/packages/SystemUI/res-keyguard/values-es/strings.xml b/packages/SystemUI/res-keyguard/values-es/strings.xml
index 0754681215cc..69488da11576 100644
--- a/packages/SystemUI/res-keyguard/values-es/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-es/strings.xml
@@ -38,6 +38,8 @@
<string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Cargando"</string>
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Cargando rápidamente"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Cargando lentamente"</string>
+ <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) -->
+ <skip />
<string name="keyguard_low_battery" msgid="1868012396800230904">"Conecta el cargador."</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Pulsa el menú para desbloquear la pantalla."</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"Bloqueada para la red"</string>
diff --git a/packages/SystemUI/res-keyguard/values-et/strings.xml b/packages/SystemUI/res-keyguard/values-et/strings.xml
index 331a95c73c5e..948e134e68ec 100644
--- a/packages/SystemUI/res-keyguard/values-et/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-et/strings.xml
@@ -38,6 +38,8 @@
<string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Laadimine"</string>
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Kiirlaadimine"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Aeglane laadimine"</string>
+ <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) -->
+ <skip />
<string name="keyguard_low_battery" msgid="1868012396800230904">"Ühendage laadija."</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Vajutage avamiseks menüüklahvi."</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"Võrk on lukus"</string>
diff --git a/packages/SystemUI/res-keyguard/values-eu/strings.xml b/packages/SystemUI/res-keyguard/values-eu/strings.xml
index 3ff224b9e55a..b1aa206364a4 100644
--- a/packages/SystemUI/res-keyguard/values-eu/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-eu/strings.xml
@@ -38,6 +38,8 @@
<string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Kargatzen"</string>
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Bizkor kargatzen"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Mantso kargatzen"</string>
+ <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) -->
+ <skip />
<string name="keyguard_low_battery" msgid="1868012396800230904">"Konektatu kargagailua."</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Desblokeatzeko, sakatu Menua."</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"Sarea blokeatuta dago"</string>
diff --git a/packages/SystemUI/res-keyguard/values-fa/strings.xml b/packages/SystemUI/res-keyguard/values-fa/strings.xml
index 5e696369634e..8fecdd3ee980 100644
--- a/packages/SystemUI/res-keyguard/values-fa/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-fa/strings.xml
@@ -38,6 +38,8 @@
<string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • درحال شارژ شدن"</string>
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • درحال شارژ سریع"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • آهسته‌آهسته شارژ می‌شود"</string>
+ <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) -->
+ <skip />
<string name="keyguard_low_battery" msgid="1868012396800230904">"شارژر را وصل کنید."</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"برای باز کردن قفل روی «منو» فشار دهید."</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"شبکه قفل شد"</string>
diff --git a/packages/SystemUI/res-keyguard/values-fi/strings.xml b/packages/SystemUI/res-keyguard/values-fi/strings.xml
index 54bc4d8cba58..c47de5dc8cf7 100644
--- a/packages/SystemUI/res-keyguard/values-fi/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-fi/strings.xml
@@ -38,6 +38,8 @@
<string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Ladataan"</string>
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Ladataan nopeasti"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Ladataan hitaasti"</string>
+ <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) -->
+ <skip />
<string name="keyguard_low_battery" msgid="1868012396800230904">"Kytke laturi."</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Poista lukitus painamalla Valikkoa."</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"Verkko lukittu"</string>
diff --git a/packages/SystemUI/res-keyguard/values-fr-rCA/strings.xml b/packages/SystemUI/res-keyguard/values-fr-rCA/strings.xml
index 2eafc2faa21a..b330452f5bbe 100644
--- a/packages/SystemUI/res-keyguard/values-fr-rCA/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-fr-rCA/strings.xml
@@ -38,6 +38,8 @@
<string name="keyguard_plugged_in" msgid="8169926454348380863">"En recharge : <xliff:g id="PERCENTAGE">%s</xliff:g>"</string>
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"En recharge rapide : <xliff:g id="PERCENTAGE">%s</xliff:g>"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"En recharge lente : <xliff:g id="PERCENTAGE">%s</xliff:g>"</string>
+ <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) -->
+ <skip />
<string name="keyguard_low_battery" msgid="1868012396800230904">"Branchez votre chargeur."</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Appuyez sur la touche Menu pour déverrouiller l\'appareil."</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"Réseau verrouillé"</string>
diff --git a/packages/SystemUI/res-keyguard/values-fr/strings.xml b/packages/SystemUI/res-keyguard/values-fr/strings.xml
index 824ea41811f7..0c13c0f0cb0d 100644
--- a/packages/SystemUI/res-keyguard/values-fr/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-fr/strings.xml
@@ -38,6 +38,8 @@
<string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Recharge…"</string>
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Recharge rapide…"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Recharge lente…"</string>
+ <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) -->
+ <skip />
<string name="keyguard_low_battery" msgid="1868012396800230904">"Branchez votre chargeur."</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Appuyez sur \"Menu\" pour déverrouiller le clavier."</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"Réseau verrouillé"</string>
diff --git a/packages/SystemUI/res-keyguard/values-gl/strings.xml b/packages/SystemUI/res-keyguard/values-gl/strings.xml
index 09488718fd1a..601b2e23aba1 100644
--- a/packages/SystemUI/res-keyguard/values-gl/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-gl/strings.xml
@@ -38,6 +38,8 @@
<string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Cargando"</string>
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Cargando rapidamente"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Cargando lentamente"</string>
+ <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) -->
+ <skip />
<string name="keyguard_low_battery" msgid="1868012396800230904">"Conecta o cargador."</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Preme Menú para desbloquear."</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"Bloqueada pola rede"</string>
diff --git a/packages/SystemUI/res-keyguard/values-gu/strings.xml b/packages/SystemUI/res-keyguard/values-gu/strings.xml
index b02d3d97b39f..296124fc743d 100644
--- a/packages/SystemUI/res-keyguard/values-gu/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-gu/strings.xml
@@ -38,6 +38,8 @@
<string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ચાર્જિંગ"</string>
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ઝડપથી ચાર્જિંગ"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ધીમેથી ચાર્જિંગ"</string>
+ <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) -->
+ <skip />
<string name="keyguard_low_battery" msgid="1868012396800230904">"તમારું ચાર્જર કનેક્ટ કરો."</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"અનલૉક કરવા માટે મેનૂ દબાવો."</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"નેટવર્ક લૉક થયું"</string>
diff --git a/packages/SystemUI/res-keyguard/values-hi/strings.xml b/packages/SystemUI/res-keyguard/values-hi/strings.xml
index f6b15de0e97e..c1c9dd57a64f 100644
--- a/packages/SystemUI/res-keyguard/values-hi/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-hi/strings.xml
@@ -38,6 +38,8 @@
<string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • चार्ज हो रहा है"</string>
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • तेज़ चार्ज हो रहा है"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • धीरे चार्ज हो रहा है"</string>
+ <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) -->
+ <skip />
<string name="keyguard_low_battery" msgid="1868012396800230904">"अपना चार्जर कनेक्‍ट करें."</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"लॉक खोलने के लिए मेन्यू दबाएं."</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"नेटवर्क लॉक किया हुआ है"</string>
diff --git a/packages/SystemUI/res-keyguard/values-hr/strings.xml b/packages/SystemUI/res-keyguard/values-hr/strings.xml
index 49db3f88669a..1b51b33c9843 100644
--- a/packages/SystemUI/res-keyguard/values-hr/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-hr/strings.xml
@@ -38,6 +38,8 @@
<string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • punjenje"</string>
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • brzo punjenje"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • sporo punjenje"</string>
+ <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) -->
+ <skip />
<string name="keyguard_low_battery" msgid="1868012396800230904">"Priključite punjač."</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Pritisnite Izbornik da biste otključali."</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"Mreža je zaključana"</string>
diff --git a/packages/SystemUI/res-keyguard/values-hu/strings.xml b/packages/SystemUI/res-keyguard/values-hu/strings.xml
index c26998f01ff0..4dcb22971979 100644
--- a/packages/SystemUI/res-keyguard/values-hu/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-hu/strings.xml
@@ -38,6 +38,8 @@
<string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Töltés"</string>
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Gyors töltés"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Lassú töltés"</string>
+ <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) -->
+ <skip />
<string name="keyguard_low_battery" msgid="1868012396800230904">"Csatlakoztassa a töltőt."</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"A feloldáshoz nyomja meg a Menü gombot."</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"Hálózat zárolva"</string>
diff --git a/packages/SystemUI/res-keyguard/values-hy/strings.xml b/packages/SystemUI/res-keyguard/values-hy/strings.xml
index ad949d48fe0c..354d93208f15 100644
--- a/packages/SystemUI/res-keyguard/values-hy/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-hy/strings.xml
@@ -38,6 +38,8 @@
<string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Լիցքավորում"</string>
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Արագ լիցքավորում"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Դանդաղ լիցքավորում"</string>
+ <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) -->
+ <skip />
<string name="keyguard_low_battery" msgid="1868012396800230904">"Միացրեք լիցքավորիչը:"</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Ապակողպելու համար սեղմեք Ընտրացանկը:"</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"Ցանցը կողպված է"</string>
diff --git a/packages/SystemUI/res-keyguard/values-in/strings.xml b/packages/SystemUI/res-keyguard/values-in/strings.xml
index 85b2a4726fa2..d43823cea147 100644
--- a/packages/SystemUI/res-keyguard/values-in/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-in/strings.xml
@@ -38,6 +38,8 @@
<string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Mengisi daya"</string>
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Mengisi daya dengan cepat"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Mengisi daya dengan lambat"</string>
+ <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) -->
+ <skip />
<string name="keyguard_low_battery" msgid="1868012396800230904">"Hubungkan pengisi daya."</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Tekan Menu untuk membuka kunci."</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"Jaringan terkunci"</string>
diff --git a/packages/SystemUI/res-keyguard/values-is/strings.xml b/packages/SystemUI/res-keyguard/values-is/strings.xml
index e40cdca33034..233402b33f26 100644
--- a/packages/SystemUI/res-keyguard/values-is/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-is/strings.xml
@@ -38,6 +38,8 @@
<string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Í hleðslu"</string>
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Hröð hleðsla"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Hæg hleðsla"</string>
+ <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) -->
+ <skip />
<string name="keyguard_low_battery" msgid="1868012396800230904">"Tengdu hleðslutækið."</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Ýttu á valmyndarhnappinn til að taka úr lás."</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"Net læst"</string>
diff --git a/packages/SystemUI/res-keyguard/values-it/strings.xml b/packages/SystemUI/res-keyguard/values-it/strings.xml
index e1c9ee8b7d34..87fd81cb1581 100644
--- a/packages/SystemUI/res-keyguard/values-it/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-it/strings.xml
@@ -38,6 +38,7 @@
<string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • In carica"</string>
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Ricarica veloce"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Ricarica lenta"</string>
+ <string name="keyguard_plugged_in_charging_limited" msgid="8190982388514496109">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Batteria momentaneamente limitata"</string>
<string name="keyguard_low_battery" msgid="1868012396800230904">"Collega il caricabatterie."</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Premi Menu per sbloccare."</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"Rete bloccata"</string>
diff --git a/packages/SystemUI/res-keyguard/values-iw/strings.xml b/packages/SystemUI/res-keyguard/values-iw/strings.xml
index e054f629836e..6af70b4cebf3 100644
--- a/packages/SystemUI/res-keyguard/values-iw/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-iw/strings.xml
@@ -38,6 +38,8 @@
<string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • בטעינה"</string>
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • בטעינה מהירה"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • בטעינה איטית"</string>
+ <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) -->
+ <skip />
<string name="keyguard_low_battery" msgid="1868012396800230904">"חבר את המטען."</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"לחץ על \'תפריט\' כדי לבטל את הנעילה."</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"הרשת נעולה"</string>
diff --git a/packages/SystemUI/res-keyguard/values-ja/strings.xml b/packages/SystemUI/res-keyguard/values-ja/strings.xml
index 957d78a8b440..ab5a13c16bad 100644
--- a/packages/SystemUI/res-keyguard/values-ja/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-ja/strings.xml
@@ -38,6 +38,8 @@
<string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • 充電中"</string>
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • 急速充電中"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • 低速充電中"</string>
+ <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) -->
+ <skip />
<string name="keyguard_low_battery" msgid="1868012396800230904">"充電してください。"</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"メニューからロックを解除できます。"</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"ネットワークがロックされました"</string>
diff --git a/packages/SystemUI/res-keyguard/values-ka/strings.xml b/packages/SystemUI/res-keyguard/values-ka/strings.xml
index d0d15fec7172..b10ab615abd0 100644
--- a/packages/SystemUI/res-keyguard/values-ka/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-ka/strings.xml
@@ -38,6 +38,7 @@
<string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • იტენება"</string>
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • სწრაფად იტენება"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ნელა იტენება"</string>
+ <string name="keyguard_plugged_in_charging_limited" msgid="8190982388514496109">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ბატარეა დროებით შეზღუდულია"</string>
<string name="keyguard_low_battery" msgid="1868012396800230904">"შეაერთეთ დამტენი."</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"განსაბლოკად დააჭირეთ მენიუს."</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"ქსელი ჩაკეტილია"</string>
diff --git a/packages/SystemUI/res-keyguard/values-kk/strings.xml b/packages/SystemUI/res-keyguard/values-kk/strings.xml
index 62afd1e45df8..c415bbbe1a72 100644
--- a/packages/SystemUI/res-keyguard/values-kk/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-kk/strings.xml
@@ -38,6 +38,8 @@
<string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Зарядталуда"</string>
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Жылдам зарядталуда"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Баяу зарядталуда"</string>
+ <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) -->
+ <skip />
<string name="keyguard_low_battery" msgid="1868012396800230904">"Зарядтағышты қосыңыз."</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Ашу үшін \"Мәзір\" пернесін басыңыз."</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"Желі құлыптаулы"</string>
diff --git a/packages/SystemUI/res-keyguard/values-km/strings.xml b/packages/SystemUI/res-keyguard/values-km/strings.xml
index 52b7fab768c5..1a278e8262c8 100644
--- a/packages/SystemUI/res-keyguard/values-km/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-km/strings.xml
@@ -38,6 +38,8 @@
<string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • កំពុង​សាកថ្ម"</string>
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • កំពុង​សាកថ្មយ៉ាង​ឆាប់រហ័ស"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • កំពុង​សាកថ្មយឺត"</string>
+ <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) -->
+ <skip />
<string name="keyguard_low_battery" msgid="1868012396800230904">"សូមសាក​ថ្ម​របស់​អ្នក។"</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"ចុចម៉ឺនុយ ​ដើម្បី​ដោះ​សោ។"</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"បណ្ដាញ​ជាប់​សោ"</string>
diff --git a/packages/SystemUI/res-keyguard/values-kn/strings.xml b/packages/SystemUI/res-keyguard/values-kn/strings.xml
index 785ca4338326..961fcec69853 100644
--- a/packages/SystemUI/res-keyguard/values-kn/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-kn/strings.xml
@@ -38,6 +38,8 @@
<string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ಚಾರ್ಜ್‌ ಮಾಡಲಾಗುತ್ತಿದೆ"</string>
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ವೇಗವಾಗಿ ಚಾರ್ಜ್‌ಮಾಡಲಾಗುತ್ತಿದೆ"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ನಿಧಾನವಾಗಿ ಚಾರ್ಜ್ ಮಾಡಲಾಗುತ್ತಿದೆ"</string>
+ <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) -->
+ <skip />
<string name="keyguard_low_battery" msgid="1868012396800230904">"ನಿಮ್ಮ ಚಾರ್ಜರ್ ಸಂಪರ್ಕಗೊಳಿಸಿ."</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"ಅನ್‌ಲಾಕ್ ಮಾಡಲು ಮೆನು ಒತ್ತಿರಿ."</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"ನೆಟ್‌ವರ್ಕ್ ಲಾಕ್ ಆಗಿದೆ"</string>
diff --git a/packages/SystemUI/res-keyguard/values-ko/strings.xml b/packages/SystemUI/res-keyguard/values-ko/strings.xml
index 848490ebb9b8..2f93af920e17 100644
--- a/packages/SystemUI/res-keyguard/values-ko/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-ko/strings.xml
@@ -38,6 +38,8 @@
<string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • 충전 중"</string>
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • 고속 충전 중"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • 저속 충전 중"</string>
+ <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) -->
+ <skip />
<string name="keyguard_low_battery" msgid="1868012396800230904">"충전기를 연결하세요."</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"잠금 해제하려면 메뉴를 누르세요."</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"네트워크 잠김"</string>
diff --git a/packages/SystemUI/res-keyguard/values-ky/strings.xml b/packages/SystemUI/res-keyguard/values-ky/strings.xml
index d868788a3eca..7e929199f1bc 100644
--- a/packages/SystemUI/res-keyguard/values-ky/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-ky/strings.xml
@@ -38,6 +38,8 @@
<string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Кубатталууда"</string>
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Тез кубатталууда"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Жай кубатталууда"</string>
+ <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) -->
+ <skip />
<string name="keyguard_low_battery" msgid="1868012396800230904">"Кубаттагычка туташтырыңыз."</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Кулпуну ачуу үчүн Менюну басыңыз."</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"Тармак кулпуланган"</string>
diff --git a/packages/SystemUI/res-keyguard/values-lo/strings.xml b/packages/SystemUI/res-keyguard/values-lo/strings.xml
index ebaffb13d5b4..b96a2bb4aa4c 100644
--- a/packages/SystemUI/res-keyguard/values-lo/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-lo/strings.xml
@@ -38,6 +38,8 @@
<string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ກຳລັງສາກ"</string>
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ກຳລັງສາກແບບດ່ວນ"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ກຳລັງສາກແບບຊ້າ"</string>
+ <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) -->
+ <skip />
<string name="keyguard_low_battery" msgid="1868012396800230904">"ເຊື່ອມຕໍ່ສາຍສາກຂອງທ່ານ."</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"ກົດ \"ເມນູ\" ເພື່ອປົດລັອກ."</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"ເຄືອຂ່າຍຖືກລັອກ"</string>
diff --git a/packages/SystemUI/res-keyguard/values-lt/strings.xml b/packages/SystemUI/res-keyguard/values-lt/strings.xml
index 4d598f6bfb6d..773f7c42ebd1 100644
--- a/packages/SystemUI/res-keyguard/values-lt/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-lt/strings.xml
@@ -38,6 +38,8 @@
<string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Įkraunama"</string>
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Greitai įkraunama"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Lėtai įkraunama"</string>
+ <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) -->
+ <skip />
<string name="keyguard_low_battery" msgid="1868012396800230904">"Prijunkite kroviklį."</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Paspauskite meniu, jei norite atrakinti."</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"Tinklas užrakintas"</string>
diff --git a/packages/SystemUI/res-keyguard/values-lv/strings.xml b/packages/SystemUI/res-keyguard/values-lv/strings.xml
index fad67d536e58..68bf4cde3086 100644
--- a/packages/SystemUI/res-keyguard/values-lv/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-lv/strings.xml
@@ -38,6 +38,8 @@
<string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Notiek uzlāde"</string>
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Notiek ātrā uzlāde"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Notiek lēnā uzlāde"</string>
+ <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) -->
+ <skip />
<string name="keyguard_low_battery" msgid="1868012396800230904">"Pievienojiet uzlādes ierīci."</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Lai atbloķētu, nospiediet izvēlnes ikonu."</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"Tīkls ir bloķēts."</string>
diff --git a/packages/SystemUI/res-keyguard/values-mk/strings.xml b/packages/SystemUI/res-keyguard/values-mk/strings.xml
index 1397f467e116..e51f77488726 100644
--- a/packages/SystemUI/res-keyguard/values-mk/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-mk/strings.xml
@@ -38,6 +38,8 @@
<string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Се полни"</string>
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Брзо полнење"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Бавно полнење"</string>
+ <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) -->
+ <skip />
<string name="keyguard_low_battery" msgid="1868012396800230904">"Поврзете го полначот."</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Притиснете „Мени“ за отклучување."</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"Мрежата е заклучена"</string>
diff --git a/packages/SystemUI/res-keyguard/values-ml/strings.xml b/packages/SystemUI/res-keyguard/values-ml/strings.xml
index f82f822ca26c..4b4391482833 100644
--- a/packages/SystemUI/res-keyguard/values-ml/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-ml/strings.xml
@@ -38,6 +38,8 @@
<string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ചാർജ് ചെയ്യുന്നു"</string>
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • വേഗത്തിൽ ചാർജ് ചെയ്യുന്നു"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • പതുക്കെ ചാർജ് ചെയ്യുന്നു"</string>
+ <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) -->
+ <skip />
<string name="keyguard_low_battery" msgid="1868012396800230904">"നിങ്ങളുടെ ചാർജർ കണക്റ്റുചെയ്യുക."</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"അൺലോക്കുചെയ്യാൻ മെനു അമർത്തുക."</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"നെറ്റ്‌വർക്ക് ലോക്കുചെയ്‌തു"</string>
diff --git a/packages/SystemUI/res-keyguard/values-mn/strings.xml b/packages/SystemUI/res-keyguard/values-mn/strings.xml
index 462017af1922..4667252546c5 100644
--- a/packages/SystemUI/res-keyguard/values-mn/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-mn/strings.xml
@@ -38,6 +38,8 @@
<string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Цэнэглэж байна"</string>
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Хурдан цэнэглэж байна"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Удаан цэнэглэж байна"</string>
+ <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) -->
+ <skip />
<string name="keyguard_low_battery" msgid="1868012396800230904">"Цэнэглэгчээ холбоно уу."</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Түгжээг тайлах бол цэсийг дарна уу."</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"Сүлжээ түгжигдсэн"</string>
diff --git a/packages/SystemUI/res-keyguard/values-mr/strings.xml b/packages/SystemUI/res-keyguard/values-mr/strings.xml
index 0166791dc3ba..bdd390475c4a 100644
--- a/packages/SystemUI/res-keyguard/values-mr/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-mr/strings.xml
@@ -38,6 +38,8 @@
<string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • चार्ज होत आहे"</string>
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • वेगाने चार्ज होत आहे"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • सावकाश चार्ज होत आहे"</string>
+ <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) -->
+ <skip />
<string name="keyguard_low_battery" msgid="1868012396800230904">"तुमचा चार्जर कनेक्ट करा."</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"अनलॉक करण्यासाठी मेनू दाबा."</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"नेटवर्क लॉक केले"</string>
diff --git a/packages/SystemUI/res-keyguard/values-ms/strings.xml b/packages/SystemUI/res-keyguard/values-ms/strings.xml
index 67500866f3d4..a5179887ce5d 100644
--- a/packages/SystemUI/res-keyguard/values-ms/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-ms/strings.xml
@@ -38,6 +38,8 @@
<string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Mengecas"</string>
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Mengecas dengan cepat"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Mengecas dengan perlahan"</string>
+ <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) -->
+ <skip />
<string name="keyguard_low_battery" msgid="1868012396800230904">"Sambungkan pengecas anda."</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Tekan Menu untuk membuka kunci."</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"Rangkaian dikunci"</string>
diff --git a/packages/SystemUI/res-keyguard/values-my/strings.xml b/packages/SystemUI/res-keyguard/values-my/strings.xml
index 3b32f06e19cd..07f3d38aa8c8 100644
--- a/packages/SystemUI/res-keyguard/values-my/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-my/strings.xml
@@ -38,6 +38,8 @@
<string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • အားသွင်းနေသည်"</string>
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • အမြန်အားသွင်းနေသည်"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • နှေးကွေးစွာ အားသွင်းနေသည်"</string>
+ <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) -->
+ <skip />
<string name="keyguard_low_battery" msgid="1868012396800230904">"အားသွင်းကိရိယာကို ချိတ်ဆက်ပါ။"</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"မီနူးကို နှိပ်၍ လော့ခ်ဖွင့်ပါ။"</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"ကွန်ရက်ကို လော့ခ်ချထားသည်"</string>
diff --git a/packages/SystemUI/res-keyguard/values-nb/strings.xml b/packages/SystemUI/res-keyguard/values-nb/strings.xml
index ebd8f2922ba2..a391b9293c05 100644
--- a/packages/SystemUI/res-keyguard/values-nb/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-nb/strings.xml
@@ -38,6 +38,8 @@
<string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Lader"</string>
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Lader raskt"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Lader sakte"</string>
+ <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) -->
+ <skip />
<string name="keyguard_low_battery" msgid="1868012396800230904">"Koble til en batterilader."</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Trykk på menyknappen for å låse opp."</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"Nettverket er låst"</string>
diff --git a/packages/SystemUI/res-keyguard/values-ne/strings.xml b/packages/SystemUI/res-keyguard/values-ne/strings.xml
index ce05e38dca10..812aa38d4622 100644
--- a/packages/SystemUI/res-keyguard/values-ne/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-ne/strings.xml
@@ -38,6 +38,8 @@
<string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • चार्ज गरिँदै"</string>
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • द्रुत गतिमा चार्ज गरिँदै"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • मन्द गतिमा चार्ज गरिँदै"</string>
+ <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) -->
+ <skip />
<string name="keyguard_low_battery" msgid="1868012396800230904">"तपाईंको चार्जर जोड्नुहोस्।"</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"अनलक गर्न मेनु थिच्नुहोस्।"</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"नेटवर्क लक भएको छ"</string>
diff --git a/packages/SystemUI/res-keyguard/values-nl/strings.xml b/packages/SystemUI/res-keyguard/values-nl/strings.xml
index aa783e84b892..f1c2033baaa8 100644
--- a/packages/SystemUI/res-keyguard/values-nl/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-nl/strings.xml
@@ -38,6 +38,8 @@
<string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Opladen"</string>
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Snel opladen"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Langzaam opladen"</string>
+ <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) -->
+ <skip />
<string name="keyguard_low_battery" msgid="1868012396800230904">"Sluit de oplader aan."</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Druk op Menu om te ontgrendelen."</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"Netwerk vergrendeld"</string>
diff --git a/packages/SystemUI/res-keyguard/values-or/strings.xml b/packages/SystemUI/res-keyguard/values-or/strings.xml
index 8bbdcf1e9eb6..be6e2856bd27 100644
--- a/packages/SystemUI/res-keyguard/values-or/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-or/strings.xml
@@ -38,6 +38,8 @@
<string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ଚାର୍ଜ ହେଉଛି"</string>
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ଦ୍ରୁତ ଭାବେ ଚାର୍ଜ ହେଉଛି"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ଧୀରେ ଚାର୍ଜ ହେଉଛି"</string>
+ <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) -->
+ <skip />
<string name="keyguard_low_battery" msgid="1868012396800230904">"ଆପଣଙ୍କ ଚାର୍ଜର୍‍ ସଂଯୋଗ କରନ୍ତୁ।"</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"ଅନଲକ୍‌ କରିବା ପାଇଁ ମେନୁକୁ ଦବାନ୍ତୁ।"</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"ନେଟୱର୍କକୁ ଲକ୍‌ କରାଯାଇଛି"</string>
diff --git a/packages/SystemUI/res-keyguard/values-pa/strings.xml b/packages/SystemUI/res-keyguard/values-pa/strings.xml
index 78e066526840..a6ea6aaf4162 100644
--- a/packages/SystemUI/res-keyguard/values-pa/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-pa/strings.xml
@@ -38,6 +38,8 @@
<string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ਚਾਰਜ ਹੋ ਰਿਹਾ ਹੈ"</string>
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ਤੇਜ਼ੀ ਨਾਲ ਚਾਰਜ ਹੋ ਰਿਹਾ ਹੈ"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ਹੌਲੀ-ਹੌਲੀ ਚਾਰਜ ਹੋ ਰਿਹਾ ਹੈ"</string>
+ <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) -->
+ <skip />
<string name="keyguard_low_battery" msgid="1868012396800230904">"ਆਪਣਾ ਚਾਰਜਰ ਕਨੈਕਟ ਕਰੋ।"</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"ਅਣਲਾਕ ਕਰਨ ਲਈ \"ਮੀਨੂ\" ਦਬਾਓ।"</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"ਨੈੱਟਵਰਕ ਲਾਕ ਕੀਤਾ ਗਿਆ"</string>
diff --git a/packages/SystemUI/res-keyguard/values-pl/strings.xml b/packages/SystemUI/res-keyguard/values-pl/strings.xml
index 5094cf9983a1..9c6f27118600 100644
--- a/packages/SystemUI/res-keyguard/values-pl/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-pl/strings.xml
@@ -38,6 +38,8 @@
<string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Ładowanie"</string>
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Szybkie ładowanie"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Wolne ładowanie"</string>
+ <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) -->
+ <skip />
<string name="keyguard_low_battery" msgid="1868012396800230904">"Podłącz ładowarkę."</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Naciśnij Menu, aby odblokować."</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"Sieć zablokowana"</string>
diff --git a/packages/SystemUI/res-keyguard/values-pt-rBR/strings.xml b/packages/SystemUI/res-keyguard/values-pt-rBR/strings.xml
index 5bfc3dbc900d..d2d5fb9d159a 100644
--- a/packages/SystemUI/res-keyguard/values-pt-rBR/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-pt-rBR/strings.xml
@@ -38,6 +38,7 @@
<string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Carregando"</string>
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Carregando rapidamente"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Carregando lentamente"</string>
+ <string name="keyguard_plugged_in_charging_limited" msgid="8190982388514496109">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Bateria limitada temporariamente"</string>
<string name="keyguard_low_battery" msgid="1868012396800230904">"Conecte o seu carregador."</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Pressione Menu para desbloquear."</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"Rede bloqueada"</string>
diff --git a/packages/SystemUI/res-keyguard/values-pt-rPT/strings.xml b/packages/SystemUI/res-keyguard/values-pt-rPT/strings.xml
index 5af8bc09a05b..7f0a4d883ee5 100644
--- a/packages/SystemUI/res-keyguard/values-pt-rPT/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-pt-rPT/strings.xml
@@ -38,6 +38,7 @@
<string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • A carregar…"</string>
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • A carregar rapidamente…"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • A carregar lentamente…"</string>
+ <string name="keyguard_plugged_in_charging_limited" msgid="8190982388514496109">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Bateria limitada temporariamente."</string>
<string name="keyguard_low_battery" msgid="1868012396800230904">"Ligue o carregador."</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Prima Menu para desbloquear."</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"Rede bloqueada"</string>
diff --git a/packages/SystemUI/res-keyguard/values-pt/strings.xml b/packages/SystemUI/res-keyguard/values-pt/strings.xml
index 5bfc3dbc900d..d2d5fb9d159a 100644
--- a/packages/SystemUI/res-keyguard/values-pt/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-pt/strings.xml
@@ -38,6 +38,7 @@
<string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Carregando"</string>
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Carregando rapidamente"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Carregando lentamente"</string>
+ <string name="keyguard_plugged_in_charging_limited" msgid="8190982388514496109">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Bateria limitada temporariamente"</string>
<string name="keyguard_low_battery" msgid="1868012396800230904">"Conecte o seu carregador."</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Pressione Menu para desbloquear."</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"Rede bloqueada"</string>
diff --git a/packages/SystemUI/res-keyguard/values-ro/strings.xml b/packages/SystemUI/res-keyguard/values-ro/strings.xml
index 8122241e6613..572c1dbd0830 100644
--- a/packages/SystemUI/res-keyguard/values-ro/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-ro/strings.xml
@@ -38,6 +38,8 @@
<string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Se încarcă"</string>
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Se încarcă rapid"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Se încarcă lent"</string>
+ <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) -->
+ <skip />
<string name="keyguard_low_battery" msgid="1868012396800230904">"Conectați încărcătorul."</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Apăsați pe Meniu pentru a debloca."</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"Rețea blocată"</string>
diff --git a/packages/SystemUI/res-keyguard/values-ru/strings.xml b/packages/SystemUI/res-keyguard/values-ru/strings.xml
index b80b479ca29a..2c87608f9b9b 100644
--- a/packages/SystemUI/res-keyguard/values-ru/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-ru/strings.xml
@@ -38,6 +38,8 @@
<string name="keyguard_plugged_in" msgid="8169926454348380863">"Идет зарядка (<xliff:g id="PERCENTAGE">%s</xliff:g>)"</string>
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"Идет быстрая зарядка (<xliff:g id="PERCENTAGE">%s</xliff:g>)"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"Идет медленная зарядка (<xliff:g id="PERCENTAGE">%s</xliff:g>)"</string>
+ <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) -->
+ <skip />
<string name="keyguard_low_battery" msgid="1868012396800230904">"Подключите зарядное устройство."</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Для разблокировки нажмите \"Меню\"."</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"Сеть заблокирована"</string>
diff --git a/packages/SystemUI/res-keyguard/values-si/strings.xml b/packages/SystemUI/res-keyguard/values-si/strings.xml
index 1cd876f15d47..8682192ce32a 100644
--- a/packages/SystemUI/res-keyguard/values-si/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-si/strings.xml
@@ -38,6 +38,8 @@
<string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ආරෝපණය වෙමින්"</string>
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • වේගයෙන් ආරෝපණය වෙමින්"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • සෙමින් ආරෝපණය වෙමින්"</string>
+ <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) -->
+ <skip />
<string name="keyguard_low_battery" msgid="1868012396800230904">"ඔබගේ ආරෝපකයට සම්බන්ධ කරන්න."</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"අගුලු හැරීමට මෙනුව ඔබන්න."</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"ජාලය අගුළු දමා ඇත"</string>
diff --git a/packages/SystemUI/res-keyguard/values-sk/strings.xml b/packages/SystemUI/res-keyguard/values-sk/strings.xml
index 801a7dbccf6d..d5e6093b1a83 100644
--- a/packages/SystemUI/res-keyguard/values-sk/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-sk/strings.xml
@@ -38,6 +38,8 @@
<string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Nabíja sa"</string>
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Nabíja sa rýchlo"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Nabíja sa pomaly"</string>
+ <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) -->
+ <skip />
<string name="keyguard_low_battery" msgid="1868012396800230904">"Pripojte nabíjačku."</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Odomknete stlačením tlačidla ponuky."</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"Sieť je zablokovaná"</string>
diff --git a/packages/SystemUI/res-keyguard/values-sl/strings.xml b/packages/SystemUI/res-keyguard/values-sl/strings.xml
index 967255cb50e7..82d5c5493010 100644
--- a/packages/SystemUI/res-keyguard/values-sl/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-sl/strings.xml
@@ -38,6 +38,8 @@
<string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • polnjenje"</string>
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • hitro polnjenje"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • počasno polnjenje"</string>
+ <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) -->
+ <skip />
<string name="keyguard_low_battery" msgid="1868012396800230904">"Priključite napajalnik."</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Če želite odkleniti, pritisnite meni."</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"Omrežje je zaklenjeno"</string>
diff --git a/packages/SystemUI/res-keyguard/values-sq/strings.xml b/packages/SystemUI/res-keyguard/values-sq/strings.xml
index 382a4dcafed7..a67413fdf5c2 100644
--- a/packages/SystemUI/res-keyguard/values-sq/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-sq/strings.xml
@@ -38,6 +38,8 @@
<string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Po karikohet"</string>
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Po karikohet me shpejtësi"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Po karikohet ngadalë"</string>
+ <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) -->
+ <skip />
<string name="keyguard_low_battery" msgid="1868012396800230904">"Lidh karikuesin."</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Shtyp \"Meny\" për të shkyçur."</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"Rrjeti është i kyçur"</string>
diff --git a/packages/SystemUI/res-keyguard/values-sr/strings.xml b/packages/SystemUI/res-keyguard/values-sr/strings.xml
index f83df3f8925e..dec31650308e 100644
--- a/packages/SystemUI/res-keyguard/values-sr/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-sr/strings.xml
@@ -38,6 +38,8 @@
<string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Пуни се"</string>
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Брзо се пуни"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Споро се пуни"</string>
+ <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) -->
+ <skip />
<string name="keyguard_low_battery" msgid="1868012396800230904">"Прикључите пуњач."</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Притисните Мени да бисте откључали."</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"Мрежа је закључана"</string>
diff --git a/packages/SystemUI/res-keyguard/values-sv/strings.xml b/packages/SystemUI/res-keyguard/values-sv/strings.xml
index a037bffa4da2..3ef2dfe87e88 100644
--- a/packages/SystemUI/res-keyguard/values-sv/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-sv/strings.xml
@@ -38,6 +38,8 @@
<string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Laddas"</string>
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Laddas snabbt"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Laddas långsamt"</string>
+ <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) -->
+ <skip />
<string name="keyguard_low_battery" msgid="1868012396800230904">"Anslut laddaren."</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Lås upp genom att trycka på Meny."</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"Nätverk låst"</string>
diff --git a/packages/SystemUI/res-keyguard/values-sw/strings.xml b/packages/SystemUI/res-keyguard/values-sw/strings.xml
index efa5ecfd44fd..5c5fc10fe77e 100644
--- a/packages/SystemUI/res-keyguard/values-sw/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-sw/strings.xml
@@ -38,6 +38,8 @@
<string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Inachaji"</string>
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Inachaji kwa kasi"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Inachaji pole pole"</string>
+ <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) -->
+ <skip />
<string name="keyguard_low_battery" msgid="1868012396800230904">"Unganisha chaja yako."</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Bonyeza Menyu ili kufungua."</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"Mtandao umefungwa"</string>
diff --git a/packages/SystemUI/res-keyguard/values-ta/strings.xml b/packages/SystemUI/res-keyguard/values-ta/strings.xml
index 96dbbb0314d6..c188301bb7ed 100644
--- a/packages/SystemUI/res-keyguard/values-ta/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-ta/strings.xml
@@ -38,6 +38,8 @@
<string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • சார்ஜாகிறது"</string>
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • வேகமாகச் சார்ஜாகிறது"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • மெதுவாகச் சார்ஜாகிறது"</string>
+ <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) -->
+ <skip />
<string name="keyguard_low_battery" msgid="1868012396800230904">"சார்ஜரை இணைக்கவும்."</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"திறக்க, மெனுவை அழுத்தவும்."</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"நெட்வொர்க் பூட்டப்பட்டது"</string>
diff --git a/packages/SystemUI/res-keyguard/values-te/strings.xml b/packages/SystemUI/res-keyguard/values-te/strings.xml
index d44003bc5b95..27a5b285c485 100644
--- a/packages/SystemUI/res-keyguard/values-te/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-te/strings.xml
@@ -38,6 +38,8 @@
<string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ఛార్జ్ అవుతోంది"</string>
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • వేగంగా ఛార్జ్ అవుతోంది"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • నెమ్మదిగా ఛార్జ్ అవుతోంది"</string>
+ <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) -->
+ <skip />
<string name="keyguard_low_battery" msgid="1868012396800230904">"మీ ఛార్జర్‌ను కనెక్ట్ చేయండి."</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"అన్‌లాక్ చేయడానికి మెనుని నొక్కండి."</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"నెట్‌వర్క్ లాక్ చేయబడింది"</string>
diff --git a/packages/SystemUI/res-keyguard/values-th/strings.xml b/packages/SystemUI/res-keyguard/values-th/strings.xml
index e157be4ac18e..e506745d637e 100644
--- a/packages/SystemUI/res-keyguard/values-th/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-th/strings.xml
@@ -38,6 +38,8 @@
<string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • กำลังชาร์จ"</string>
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • กำลังชาร์จอย่างเร็ว"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • กำลังชาร์จอย่างช้าๆ"</string>
+ <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) -->
+ <skip />
<string name="keyguard_low_battery" msgid="1868012396800230904">"เสียบที่ชาร์จของคุณ"</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"กด \"เมนู\" เพื่อปลดล็อก"</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"เครือข่ายถูกล็อก"</string>
diff --git a/packages/SystemUI/res-keyguard/values-tl/strings.xml b/packages/SystemUI/res-keyguard/values-tl/strings.xml
index 7b7e17dc8dcb..912fd9529f09 100644
--- a/packages/SystemUI/res-keyguard/values-tl/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-tl/strings.xml
@@ -38,6 +38,8 @@
<string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Nagcha-charge"</string>
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Mabilis na nagcha-charge"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Mabagal na nagcha-charge"</string>
+ <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) -->
+ <skip />
<string name="keyguard_low_battery" msgid="1868012396800230904">"Ikonekta ang iyong charger."</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Pindutin ang Menu upang i-unlock."</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"Naka-lock ang network"</string>
diff --git a/packages/SystemUI/res-keyguard/values-tr/strings.xml b/packages/SystemUI/res-keyguard/values-tr/strings.xml
index 8c0caead0bdb..5390c4c5c4eb 100644
--- a/packages/SystemUI/res-keyguard/values-tr/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-tr/strings.xml
@@ -38,6 +38,8 @@
<string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Şarj oluyor"</string>
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Hızlı şarj oluyor"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Yavaş şarj oluyor"</string>
+ <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) -->
+ <skip />
<string name="keyguard_low_battery" msgid="1868012396800230904">"Şarj cihazınızı takın."</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Kilidi açmak için Menü\'ye basın."</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"Ağ kilitli"</string>
diff --git a/packages/SystemUI/res-keyguard/values-uk/strings.xml b/packages/SystemUI/res-keyguard/values-uk/strings.xml
index 6e5ce0f142dc..6263d79fd645 100644
--- a/packages/SystemUI/res-keyguard/values-uk/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-uk/strings.xml
@@ -38,6 +38,8 @@
<string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Заряджання"</string>
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Швидке заряджання"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Повільне заряджання"</string>
+ <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) -->
+ <skip />
<string name="keyguard_low_battery" msgid="1868012396800230904">"Підключіть зарядний пристрій."</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Натисніть меню, щоб розблокувати."</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"Мережу заблоковано"</string>
diff --git a/packages/SystemUI/res-keyguard/values-ur/strings.xml b/packages/SystemUI/res-keyguard/values-ur/strings.xml
index 0fd5e17c953e..bf936cb86b51 100644
--- a/packages/SystemUI/res-keyguard/values-ur/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-ur/strings.xml
@@ -38,6 +38,8 @@
<string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • چارج ہو رہا ہے"</string>
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • تیزی سے چارج ہو رہا ہے"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • آہستہ چارج ہو رہا ہے"</string>
+ <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) -->
+ <skip />
<string name="keyguard_low_battery" msgid="1868012396800230904">"اپنا چارجر منسلک کریں۔"</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"غیر مقفل کرنے کیلئے مینو دبائیں۔"</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"نیٹ ورک مقفل ہو گیا"</string>
diff --git a/packages/SystemUI/res-keyguard/values-uz/strings.xml b/packages/SystemUI/res-keyguard/values-uz/strings.xml
index 323fea5a608e..0b23e16ddd2f 100644
--- a/packages/SystemUI/res-keyguard/values-uz/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-uz/strings.xml
@@ -38,6 +38,8 @@
<string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Quvvat olmoqda"</string>
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Tezkor quvvat olmoqda"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Sekin quvvat olmoqda"</string>
+ <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) -->
+ <skip />
<string name="keyguard_low_battery" msgid="1868012396800230904">"Quvvatlash moslamasini ulang."</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Qulfdan chiqarish uchun Menyu tugmasini bosing."</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"Tarmoq qulflangan"</string>
diff --git a/packages/SystemUI/res-keyguard/values-vi/strings.xml b/packages/SystemUI/res-keyguard/values-vi/strings.xml
index 2ba5089c7ed9..9357eba66432 100644
--- a/packages/SystemUI/res-keyguard/values-vi/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-vi/strings.xml
@@ -38,6 +38,8 @@
<string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Đang sạc"</string>
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Đang sạc nhanh"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Đang sạc chậm"</string>
+ <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) -->
+ <skip />
<string name="keyguard_low_battery" msgid="1868012396800230904">"Kết nối bộ sạc của bạn."</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Nhấn vào Menu để mở khóa."</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"Mạng đã bị khóa"</string>
diff --git a/packages/SystemUI/res-keyguard/values-zh-rCN/strings.xml b/packages/SystemUI/res-keyguard/values-zh-rCN/strings.xml
index b4bff5fab6d6..96728ab6cead 100644
--- a/packages/SystemUI/res-keyguard/values-zh-rCN/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-zh-rCN/strings.xml
@@ -38,6 +38,8 @@
<string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • 正在充电"</string>
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • 正在快速充电"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • 正在慢速充电"</string>
+ <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) -->
+ <skip />
<string name="keyguard_low_battery" msgid="1868012396800230904">"请连接充电器。"</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"按“菜单”即可解锁。"</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"网络已锁定"</string>
diff --git a/packages/SystemUI/res-keyguard/values-zh-rHK/strings.xml b/packages/SystemUI/res-keyguard/values-zh-rHK/strings.xml
index b3d387706fa5..c683529d81ac 100644
--- a/packages/SystemUI/res-keyguard/values-zh-rHK/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-zh-rHK/strings.xml
@@ -38,6 +38,8 @@
<string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • 正在充電"</string>
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • 正在快速充電"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> •正在慢速充電"</string>
+ <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) -->
+ <skip />
<string name="keyguard_low_battery" msgid="1868012396800230904">"請連接充電器。"</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"按下 [選單] 即可解鎖。"</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"網絡已鎖定"</string>
diff --git a/packages/SystemUI/res-keyguard/values-zh-rTW/strings.xml b/packages/SystemUI/res-keyguard/values-zh-rTW/strings.xml
index 03dec4852771..7a3b5c52acf7 100644
--- a/packages/SystemUI/res-keyguard/values-zh-rTW/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-zh-rTW/strings.xml
@@ -38,6 +38,8 @@
<string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • 充電中"</string>
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • 快速充電中"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • 慢速充電中"</string>
+ <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) -->
+ <skip />
<string name="keyguard_low_battery" msgid="1868012396800230904">"請連接充電器。"</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"按選單鍵解鎖。"</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"網路已鎖定"</string>
diff --git a/packages/SystemUI/res-keyguard/values-zu/strings.xml b/packages/SystemUI/res-keyguard/values-zu/strings.xml
index 5ab567f706c3..ec38cbef456e 100644
--- a/packages/SystemUI/res-keyguard/values-zu/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-zu/strings.xml
@@ -38,6 +38,8 @@
<string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Iyashaja"</string>
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Ishaja kaningi"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Ishaja kancane"</string>
+ <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) -->
+ <skip />
<string name="keyguard_low_battery" msgid="1868012396800230904">"Xhuma ishaja yakho."</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Chofoza Menyu ukuvula."</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"Inethiwekhi ivaliwe"</string>
diff --git a/packages/SystemUI/res-product/values-de/strings.xml b/packages/SystemUI/res-product/values-de/strings.xml
index 5c8f842fa2d3..a84413d825c2 100644
--- a/packages/SystemUI/res-product/values-de/strings.xml
+++ b/packages/SystemUI/res-product/values-de/strings.xml
@@ -21,7 +21,7 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="dock_alignment_slow_charging" product="default" msgid="6997633396534416792">"Smartphone genau platzieren, um es schneller zu laden"</string>
<string name="dock_alignment_not_charging" product="default" msgid="3980752926226749808">"Smartphone genau platzieren, um es kabellos zu laden"</string>
- <string name="inattentive_sleep_warning_message" product="tv" msgid="6844464574089665063">"Das Android TV-Gerät wird gleich ausgeschaltet. Falls es eingeschaltet bleiben soll, drücke beispielsweise eine Taste oder berühre den Bildschirm."</string>
+ <string name="inattentive_sleep_warning_message" product="tv" msgid="6844464574089665063">"Das Android TV-Gerät wird gleich ausgeschaltet. Falls es eingeschaltet bleiben soll, drücke eine Taste."</string>
<string name="inattentive_sleep_warning_message" product="default" msgid="5693904520452332224">"Das Gerät wird gleich ausgeschaltet. Falls es eingeschaltet bleiben soll, drücke beispielsweise eine Taste oder berühre den Bildschirm."</string>
<string name="keyguard_missing_sim_message" product="tablet" msgid="5018086454277963787">"Keine SIM-Karte im Tablet."</string>
<string name="keyguard_missing_sim_message" product="default" msgid="7053347843877341391">"Keine SIM-Karte im Smartphone."</string>
diff --git a/packages/SystemUI/res-product/values-pl/strings.xml b/packages/SystemUI/res-product/values-pl/strings.xml
index 9a9980a02782..5ac3d8420783 100644
--- a/packages/SystemUI/res-product/values-pl/strings.xml
+++ b/packages/SystemUI/res-product/values-pl/strings.xml
@@ -34,10 +34,10 @@
<string name="kg_failed_attempts_almost_at_erase_user" product="default" msgid="8110939900089863103">"Po raz <xliff:g id="NUMBER_0">%1$d</xliff:g> próbowano nieprawidłowo odblokować telefon. Po kolejnych <xliff:g id="NUMBER_1">%2$d</xliff:g> nieudanych próbach użytkownik zostanie usunięty, co spowoduje skasowanie wszystkich jego danych."</string>
<string name="kg_failed_attempts_now_erasing_user" product="tablet" msgid="8509811676952707883">"Po raz <xliff:g id="NUMBER">%d</xliff:g> próbowano nieprawidłowo odblokować tablet. Użytkownik zostanie usunięty, co spowoduje skasowanie wszystkich jego danych."</string>
<string name="kg_failed_attempts_now_erasing_user" product="default" msgid="3051962486994265014">"Po raz <xliff:g id="NUMBER">%d</xliff:g> próbowano nieprawidłowo odblokować telefon. Użytkownik zostanie usunięty, co spowoduje skasowanie wszystkich jego danych."</string>
- <string name="kg_failed_attempts_almost_at_erase_profile" product="tablet" msgid="1049523640263353830">"Po raz <xliff:g id="NUMBER_0">%1$d</xliff:g> próbowano nieprawidłowo odblokować tablet. Po kolejnych <xliff:g id="NUMBER_1">%2$d</xliff:g> nieudanych próbach profil do pracy zostanie usunięty, co spowoduje skasowanie wszystkich jego danych."</string>
- <string name="kg_failed_attempts_almost_at_erase_profile" product="default" msgid="3280816298678433681">"Po raz <xliff:g id="NUMBER_0">%1$d</xliff:g> próbowano nieprawidłowo odblokować telefon. Po kolejnych <xliff:g id="NUMBER_1">%2$d</xliff:g> nieudanych próbach profil do pracy zostanie usunięty, co spowoduje skasowanie wszystkich jego danych."</string>
- <string name="kg_failed_attempts_now_erasing_profile" product="tablet" msgid="4417100487251371559">"Po raz <xliff:g id="NUMBER">%d</xliff:g> próbowano nieprawidłowo odblokować tablet. Profil do pracy zostanie usunięty, co spowoduje skasowanie wszystkich jego danych."</string>
- <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"Po raz <xliff:g id="NUMBER">%d</xliff:g> próbowano nieprawidłowo odblokować telefon. Profil do pracy zostanie usunięty, co spowoduje skasowanie wszystkich jego danych."</string>
+ <string name="kg_failed_attempts_almost_at_erase_profile" product="tablet" msgid="1049523640263353830">"Po raz <xliff:g id="NUMBER_0">%1$d</xliff:g> próbowano nieprawidłowo odblokować tablet. Po kolejnych <xliff:g id="NUMBER_1">%2$d</xliff:g> nieudanych próbach profil służbowy zostanie usunięty, co spowoduje skasowanie wszystkich jego danych."</string>
+ <string name="kg_failed_attempts_almost_at_erase_profile" product="default" msgid="3280816298678433681">"Po raz <xliff:g id="NUMBER_0">%1$d</xliff:g> próbowano nieprawidłowo odblokować telefon. Po kolejnych <xliff:g id="NUMBER_1">%2$d</xliff:g> nieudanych próbach profil służbowy zostanie usunięty, co spowoduje skasowanie wszystkich jego danych."</string>
+ <string name="kg_failed_attempts_now_erasing_profile" product="tablet" msgid="4417100487251371559">"Po raz <xliff:g id="NUMBER">%d</xliff:g> próbowano nieprawidłowo odblokować tablet. Profil służbowy zostanie usunięty, co spowoduje skasowanie wszystkich jego danych."</string>
+ <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"Po raz <xliff:g id="NUMBER">%d</xliff:g> próbowano nieprawidłowo odblokować telefon. Profil służbowy zostanie usunięty, co spowoduje skasowanie wszystkich jego danych."</string>
<string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"Po raz <xliff:g id="NUMBER_0">%1$d</xliff:g> nieprawidłowo narysowano wzór odblokowania. Po kolejnych <xliff:g id="NUMBER_1">%2$d</xliff:g> nieudanych próbach konieczne będzie odblokowanie tabletu przy użyciu konta e-mail.\n\n Spróbuj ponownie za <xliff:g id="NUMBER_2">%3$d</xliff:g> s."</string>
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"Po raz <xliff:g id="NUMBER_0">%1$d</xliff:g> nieprawidłowo narysowano wzór odblokowania. Po kolejnych <xliff:g id="NUMBER_1">%2$d</xliff:g> nieudanych próbach konieczne będzie odblokowanie telefonu przy użyciu konta e-mail.\n\n Spróbuj ponownie za <xliff:g id="NUMBER_2">%3$d</xliff:g> s."</string>
<string name="global_action_lock_message" product="default" msgid="7092460751050168771">"Odblokuj telefon, by wyświetlić więcej opcji"</string>
diff --git a/packages/SystemUI/res/layout/super_notification_shade.xml b/packages/SystemUI/res/layout/super_notification_shade.xml
index 0ba546eff689..f9841005e8f7 100644
--- a/packages/SystemUI/res/layout/super_notification_shade.xml
+++ b/packages/SystemUI/res/layout/super_notification_shade.xml
@@ -78,7 +78,8 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/status_bar_height"
- android:layout_gravity="top|center_horizontal">
+ android:layout_gravity="top|center_horizontal"
+ android:gravity="center_horizontal">
<com.android.systemui.statusbar.phone.LockIcon
android:id="@+id/lock_icon"
android:layout_width="@dimen/keyguard_lock_width"
diff --git a/packages/SystemUI/res/values-fr-rCA/strings.xml b/packages/SystemUI/res/values-fr-rCA/strings.xml
index 8d86478259fa..6b598da2826d 100644
--- a/packages/SystemUI/res/values-fr-rCA/strings.xml
+++ b/packages/SystemUI/res/values-fr-rCA/strings.xml
@@ -944,7 +944,7 @@
<string name="instant_apps_title" msgid="8942706782103036910">"<xliff:g id="APP">%1$s</xliff:g> en cours d\'exécution"</string>
<string name="instant_apps_message" msgid="6112428971833011754">"Application ouverte sans avoir été installée."</string>
<string name="instant_apps_message_with_help" msgid="1816952263531203932">"Application ouverte sans avoir été installée. Touchez ici pour en savoir plus."</string>
- <string name="app_info" msgid="5153758994129963243">"Détails de l\'applic."</string>
+ <string name="app_info" msgid="5153758994129963243">"Détails de l\'appli"</string>
<string name="go_to_web" msgid="636673528981366511">"Ouvrir le navigateur"</string>
<string name="mobile_data" msgid="4564407557775397216">"Données cellulaires"</string>
<string name="mobile_data_text_format" msgid="6806501540022589786">"<xliff:g id="ID_1">%1$s</xliff:g> : <xliff:g id="ID_2">%2$s</xliff:g>"</string>
diff --git a/packages/SystemUI/res/values-kk/strings.xml b/packages/SystemUI/res/values-kk/strings.xml
index 160e05d3dbc7..df86e8a4774c 100644
--- a/packages/SystemUI/res/values-kk/strings.xml
+++ b/packages/SystemUI/res/values-kk/strings.xml
@@ -33,8 +33,8 @@
<string name="invalid_charger_title" msgid="938685362320735167">"USB арқылы зарядтау мүмкін емес"</string>
<string name="invalid_charger_text" msgid="2339310107232691577">"Құрылғымен бірге берілген зарядтау құралын пайдаланыңыз"</string>
<string name="battery_low_why" msgid="2056750982959359863">"Параметрлер"</string>
- <string name="battery_saver_confirmation_title" msgid="1234998463717398453">"Battery Saver функциясын қосу керек пе?"</string>
- <string name="battery_saver_confirmation_title_generic" msgid="2299231884234959849">"Battery Saver туралы ақпарат"</string>
+ <string name="battery_saver_confirmation_title" msgid="1234998463717398453">"Батареяны үнемдеу режимін қосу керек пе?"</string>
+ <string name="battery_saver_confirmation_title_generic" msgid="2299231884234959849">"Батареяны үнемдеу режимі туралы ақпарат"</string>
<string name="battery_saver_confirmation_ok" msgid="5042136476802816494">"Қосу"</string>
<string name="battery_saver_start_action" msgid="4553256017945469937">"Battery saver функциясын қосу"</string>
<string name="status_bar_settings_settings_button" msgid="534331565185171556">"Параметрлер"</string>
@@ -501,7 +501,7 @@
<string name="user_remove_user_title" msgid="9124124694835811874">"Пайдаланушы жойылсын ба?"</string>
<string name="user_remove_user_message" msgid="6702834122128031833">"Осы пайдаланушының барлық қолданбалары мен деректері жойылады."</string>
<string name="user_remove_user_remove" msgid="8387386066949061256">"Жою"</string>
- <string name="battery_saver_notification_title" msgid="8419266546034372562">"Battery saver қосулы"</string>
+ <string name="battery_saver_notification_title" msgid="8419266546034372562">"Батареяны үнемдеу режимі қосулы"</string>
<string name="battery_saver_notification_text" msgid="2617841636449016951">"Өнімділікті және фондық деректерді азайтады"</string>
<string name="battery_saver_notification_action_text" msgid="6022091913807026887">"Battery saver функциясын өшіру"</string>
<string name="media_projection_dialog_text" msgid="1755705274910034772">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> жазу не трансляциялау кезінде экранда көрсетілетін немесе дыбысталатын барлық ақпаратты пайдалана алады. Бұған құпия сөздер, төлем туралы мәліметтер, суреттер, хабарлар және аудиоматериалдар кіреді."</string>
@@ -777,7 +777,7 @@
<item quantity="one">%d минут</item>
</plurals>
<string name="battery_panel_title" msgid="5931157246673665963">"Батареяны пайдалану"</string>
- <string name="battery_detail_charging_summary" msgid="8821202155297559706">"Зарядтау кезінде Батарея үнемдегіш қол жетімді емес"</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>
<string name="keyboard_key_button_template" msgid="8005673627272051429">"<xliff:g id="NAME">%1$s</xliff:g> түймесі"</string>
@@ -965,7 +965,7 @@
<string name="slice_permission_checkbox" msgid="4242888137592298523">"<xliff:g id="APP">%1$s</xliff:g> қолданбасына кез келген қолданбаның үзіндісін көрсетуге рұқсат беру"</string>
<string name="slice_permission_allow" msgid="6340449521277951123">"Рұқсат беру"</string>
<string name="slice_permission_deny" msgid="6870256451658176895">"Тыйым салу"</string>
- <string name="auto_saver_title" msgid="6873691178754086596">"Түймені түртіп, Battery Saver функциясын реттеңіз"</string>
+ <string name="auto_saver_title" msgid="6873691178754086596">"Түймені түртіп, Батареяны үнемдеу режимін реттеңіз"</string>
<string name="auto_saver_text" msgid="3214960308353838764">"Батареяның заряды бітуге жақындағанда қосыңыз."</string>
<string name="no_auto_saver_action" msgid="7467924389609773835">"Жоқ, рақмет"</string>
<string name="auto_saver_enabled_title" msgid="4294726198280286333">"Battery Saver кестесі қосылды"</string>
diff --git a/packages/SystemUI/res/values-mn/strings.xml b/packages/SystemUI/res/values-mn/strings.xml
index b841fa95a57f..0d605c11cd1d 100644
--- a/packages/SystemUI/res/values-mn/strings.xml
+++ b/packages/SystemUI/res/values-mn/strings.xml
@@ -508,7 +508,7 @@
<string name="media_projection_dialog_service_text" msgid="958000992162214611">"Энэ функцийг ажиллуулж байгаа үйлчилгээ нь бичлэг хийх эсвэл дамжуулах үед таны дэлгэц дээр харагдах эсвэл таны төхөөрөмжөөс тоглуулах бүх мэдээлэлд хандах боломжтой байна. Үүнд нууц үг, төлбөрийн дэлгэрэнгүй, зураг болон таны тоглуулдаг аудио зэрэг мэдээлэл багтана."</string>
<string name="media_projection_dialog_service_title" msgid="2888507074107884040">"Бичлэг хийх эсвэл дамжуулахыг эхлүүлэх үү?"</string>
<string name="media_projection_dialog_title" msgid="3316063622495360646">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>-тай бичлэг хийж эсвэл дамжуулж эхлэх үү?"</string>
- <string name="media_projection_remember_text" msgid="6896767327140422951">"Дахиж үл харуулах"</string>
+ <string name="media_projection_remember_text" msgid="6896767327140422951">"Дахиж бүү харуул"</string>
<string name="clear_all_notifications_text" msgid="348312370303046130">"Бүгдийг арилгах"</string>
<string name="manage_notifications_text" msgid="6885645344647733116">"Удирдах"</string>
<string name="manage_notifications_history_text" msgid="57055985396576230">"Түүх"</string>
@@ -874,12 +874,12 @@
<string-array name="clock_options">
<item msgid="3986445361435142273">"Цаг, минут, секундийг харуулах"</item>
<item msgid="1271006222031257266">"Цаг, минутыг харуулах (өгөгдмөл)"</item>
- <item msgid="6135970080453877218">"Энэ дүрс тэмдгийг бүү үзүүл"</item>
+ <item msgid="6135970080453877218">"Энэ дүрс тэмдгийг бүү харуул"</item>
</string-array>
<string-array name="battery_options">
<item msgid="7714004721411852551">"Хувийг тогтмол харуулах"</item>
<item msgid="3805744470661798712">"Цэнэглэх үед хувийг тогтмол харуулах (өгөгдмөл)"</item>
- <item msgid="8619482474544321778">"Энэ дүрс тэмдгийг бүү үзүүл"</item>
+ <item msgid="8619482474544321778">"Энэ дүрс тэмдгийг бүү харуул"</item>
</string-array>
<string name="tuner_low_priority" msgid="8412666814123009820">"Бага ач холбогдолтой мэдэгдлийн дүрс тэмдгийг харуулах"</string>
<string name="other" msgid="429768510980739978">"Бусад"</string>
diff --git a/packages/SystemUI/res/values-ne/strings.xml b/packages/SystemUI/res/values-ne/strings.xml
index 621c4977d674..881be66c00c2 100644
--- a/packages/SystemUI/res/values-ne/strings.xml
+++ b/packages/SystemUI/res/values-ne/strings.xml
@@ -692,7 +692,7 @@
<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">"सशक्त सूचना नियन्त्रणहरू मार्फत तपाईं अनुप्रयाेगका सूचनाहरूका लागि ० देखि ५ सम्मको महत्व सम्बन्धी स्तर सेट गर्न सक्नुहुन्छ। \n\n"<b>"स्तर ५"</b>" \n- सूचनाको सूचीको माथिल्लो भागमा देखाउने \n- पूर्ण स्क्रिनमा अवरोधका लागि अनुमति दिने \n- सधैँ चियाउने \n\n"<b>"स्तर ४"</b>" \n- पूर्ण स्क्रिनमा अवरोधलाई रोक्ने \n- सधैँ चियाउने \n\n"<b>"स्तर ३"</b>" \n- पूर्ण स्क्रिनमा अवरोधलाई रोक्ने \n- कहिल्यै नचियाउने \n\n"<b>"स्तर २"</b>" \n- पूर्ण स्क्रिनमा अवरोधलाई रोक्ने \n- कहिल्यै नचियाउने \n- कहिल्यै पनि आवाज ननिकाल्ने र कम्पन नगर्ने \n\n"<b>"स्तर १"</b>" \n- पूर्ण स्क्रिनमा अवरोध रोक्ने \n- कहिल्यै नचियाउने \n- कहिल्यै पनि आवाज ननिकाल्ने वा कम्पन नगर्ने \n- लक स्क्रिन र वस्तुस्थिति पट्टीबाट लुकाउने \n- सूचनाको सूचीको तल्लो भागमा देखाउने \n\n"<b>"स्तर ०"</b>" \n- अनुप्रयोगका सबै सूचनाहरूलाई रोक्ने"</string>
+ <string name="power_notification_controls_description" msgid="1334963837572708952">"सशक्त सूचना नियन्त्रणहरू मार्फत तपाईं अनुप्रयाेगका सूचनाहरूका लागि ० देखि ५ सम्मको महत्व सम्बन्धी स्तर सेट गर्न सक्नुहुन्छ। \n\n"<b>"स्तर ५"</b>" \n- सूचनाको सूचीको माथिल्लो भागमा देखाउने \n- पूर्ण स्क्रिनमा अवरोधका लागि अनुमति दिने \n- सधैँ चियाउने \n\n"<b>"स्तर ४"</b>" \n- पूर्ण स्क्रिनमा अवरोधलाई रोक्ने \n- सधैँ चियाउने \n\n"<b>"स्तर ३"</b>" \n- पूर्ण स्क्रिनमा अवरोधलाई रोक्ने \n- कहिल्यै नचियाउने \n\n"<b>"स्तर २"</b>" \n- पूर्ण स्क्रिनमा अवरोधलाई रोक्ने \n- कहिल्यै नचियाउने \n- कहिल्यै पनि आवाज ननिकाल्ने र कम्पन नगर्ने \n\n"<b>"स्तर १"</b>" \n- पूर्ण स्क्रिनमा अवरोध रोक्ने \n- कहिल्यै नचियाउने \n- कहिल्यै पनि आवाज ननिकाल्ने वा कम्पन नगर्ने \n- लक स्क्रिन र वस्तुस्थिति पट्टीबाट लुकाउने \n- सूचनाको सूचीको तल्लो भागमा देखाउने \n\n"<b>"स्तर ०"</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>
@@ -712,7 +712,7 @@
<string name="inline_silent_button_alert" msgid="5705343216858250354">"सतर्क गराउने"</string>
<string name="inline_silent_button_keep_alerting" msgid="6577845442184724992">"सर्तक गराइरहनुहोस्"</string>
<string name="inline_turn_off_notifications" msgid="8543989584403106071">"सूचनाहरू निष्क्रिय पार्नुहोस्"</string>
- <string name="inline_keep_showing_app" msgid="4393429060390649757">"यो अनुप्रयोगका सूचनाहरू देखाउने क्रम जारी राख्ने हो?"</string>
+ <string name="inline_keep_showing_app" msgid="4393429060390649757">"यो एपका सूचनाहरू देखाउने क्रम जारी राख्ने हो?"</string>
<string name="notification_silence_title" msgid="8608090968400832335">"मौन"</string>
<string name="notification_alert_title" msgid="3656229781017543655">"पूर्वनिर्धारित"</string>
<string name="notification_automatic_title" msgid="3745465364578762652">"स्वचालित"</string>
diff --git a/packages/SystemUI/res/values-pl/strings.xml b/packages/SystemUI/res/values-pl/strings.xml
index 1c6b6a1d7961..3e944b5f7317 100644
--- a/packages/SystemUI/res/values-pl/strings.xml
+++ b/packages/SystemUI/res/values-pl/strings.xml
@@ -538,8 +538,8 @@
<string name="quick_settings_disclosure_named_management" msgid="3476472755775165827">"Właściciel tego urządzenia: <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g>"</string>
<string name="quick_settings_disclosure_management_vpns" msgid="371835422690053154">"To urządzenie należy do Twojej organizacji i jest połączone z sieciami VPN"</string>
<string name="quick_settings_disclosure_named_management_vpns" msgid="4046375645500668555">"To urządzenie należy do organizacji <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> i jest połączone z sieciami VPN"</string>
- <string name="quick_settings_disclosure_managed_profile_monitoring" msgid="1423899084754272514">"Twoja organizacja może monitorować ruch w sieci w Twoim profilu do pracy"</string>
- <string name="quick_settings_disclosure_named_managed_profile_monitoring" msgid="8321469176706219860">"Organizacja <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> może monitorować ruch w sieci w Twoim profilu do pracy"</string>
+ <string name="quick_settings_disclosure_managed_profile_monitoring" msgid="1423899084754272514">"Twoja organizacja może monitorować ruch w sieci w Twoim profilu służbowym"</string>
+ <string name="quick_settings_disclosure_named_managed_profile_monitoring" msgid="8321469176706219860">"Organizacja <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> może monitorować ruch w sieci w Twoim profilu służbowym"</string>
<string name="quick_settings_disclosure_monitoring" msgid="8548019955631378680">"Sieć może być monitorowana"</string>
<string name="quick_settings_disclosure_vpns" msgid="7213546797022280246">"To urządzenie jest połączone z sieciami VPN"</string>
<string name="quick_settings_disclosure_managed_profile_named_vpn" msgid="8117568745060010789">"Twój profil służbowy jest połączony z siecią <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
@@ -558,7 +558,7 @@
<string name="monitoring_description_named_management" msgid="505833016545056036">"To urządzenie należy do organizacji <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g>.\n\nAdministrator IT może monitorować ustawienia, firmowe uprawnienia dostępu, aplikacje, dane dotyczące urządzenia i lokalizacji oraz nimi zarządzać.\n\nAby dowiedzieć się więcej, skontaktuj się z administratorem IT."</string>
<string name="monitoring_description_management" msgid="4308879039175729014">"To urządzenie należy do Twojej organizacji.\n\nAdministrator IT może monitorować ustawienia, firmowe uprawnienia dostępu, aplikacje, dane dotyczące urządzenia i lokalizacji oraz nimi zarządzać.\n\nAby dowiedzieć się więcej, skontaktuj się z administratorem IT."</string>
<string name="monitoring_description_management_ca_certificate" msgid="7785013130658110130">"Twoja organizacja zainstalowała urząd certyfikacji na tym urządzeniu. Zabezpieczony ruch w sieci może być monitorowany i zmieniany."</string>
- <string name="monitoring_description_managed_profile_ca_certificate" msgid="7904323416598435647">"Twoja organizacja zainstalowała urząd certyfikacji w Twoim profilu do pracy. Zabezpieczony ruch w sieci może być monitorowany i zmieniany."</string>
+ <string name="monitoring_description_managed_profile_ca_certificate" msgid="7904323416598435647">"Twoja organizacja zainstalowała urząd certyfikacji w Twoim profilu służbowym. Zabezpieczony ruch w sieci może być monitorowany i zmieniany."</string>
<string name="monitoring_description_ca_certificate" msgid="448923057059097497">"Urząd certyfikacji zainstalowany na tym urządzeniu. Twój zabezpieczony ruch w sieci może być monitorowany i zmieniany."</string>
<string name="monitoring_description_management_network_logging" msgid="216983105036994771">"Administrator włączył rejestrowanie sieciowe, które pozwala monitorować ruch na Twoim urządzeniu."</string>
<string name="monitoring_description_named_vpn" msgid="5749932930634037027">"Łączysz się z aplikacją <xliff:g id="VPN_APP">%1$s</xliff:g>, która może monitorować Twoją aktywność w sieci, w tym e-maile, aplikacje i strony internetowe."</string>
@@ -577,14 +577,14 @@
<string name="monitoring_description_ca_cert_settings" msgid="8329781950135541003">"Otwórz zaufane certyfikaty"</string>
<string name="monitoring_description_network_logging" msgid="577305979174002252">"Administrator włączył rejestrowanie sieciowe, które pozwala monitorować ruch na Twoim urządzeniu.\n\nAby dowiedzieć się więcej, skontaktuj się z administratorem."</string>
<string name="monitoring_description_vpn" msgid="1685428000684586870">"Aplikacja otrzymała od Ciebie uprawnienia do konfigurowania połączenia VPN.\n\nMoże ona monitorować Twoją aktywność na urządzeniu i w sieci, w tym e-maile, aplikacje i strony internetowe."</string>
- <string name="monitoring_description_vpn_profile_owned" msgid="4964237035412372751">"Twoim profilem do pracy zarządza <xliff:g id="ORGANIZATION">%1$s</xliff:g>.\n\nAdministrator może monitorować Twoją aktywność w sieci, w tym e-maile, aplikacje i strony internetowe.\n\nAby dowiedzieć się więcej, skontaktuj się z administratorem.\n\nŁączysz się też z siecią VPN, która może monitorować Twoją aktywność w sieci."</string>
+ <string name="monitoring_description_vpn_profile_owned" msgid="4964237035412372751">"Twoim profilem służbowym zarządza <xliff:g id="ORGANIZATION">%1$s</xliff:g>.\n\nAdministrator może monitorować Twoją aktywność w sieci, w tym e-maile, aplikacje i strony internetowe.\n\nAby dowiedzieć się więcej, skontaktuj się z administratorem.\n\nŁączysz się też z siecią VPN, która może monitorować Twoją aktywność w sieci."</string>
<string name="monitoring_description_parental_controls" msgid="8184693528917051626">"Tym urządzeniem zarządza Twój rodzic. Rodzic może zobaczyć różne informacje, np. o aplikacjach, których używasz, lokalizacji i czasie korzystania z urządzenia, a także zarządzać tymi danymi."</string>
<string name="legacy_vpn_name" msgid="4174223520162559145">"VPN"</string>
<string name="monitoring_description_app" msgid="376868879287922929">"Łączysz się z aplikacją <xliff:g id="APPLICATION">%1$s</xliff:g>, która może monitorować Twoją aktywność w sieci, w tym e-maile, aplikacje i strony internetowe."</string>
<string name="monitoring_description_app_personal" msgid="1970094872688265987">"Masz połączenie z aplikacją <xliff:g id="APPLICATION">%1$s</xliff:g>, która może monitorować Twoją prywatną aktywność w sieci, w tym e-maile, aplikacje i strony internetowe."</string>
<string name="branded_monitoring_description_app_personal" msgid="1703511985892688885">"Masz połączenie z aplikacją <xliff:g id="APPLICATION">%1$s</xliff:g>, która może monitorować Twoją prywatną aktywność w sieci, w tym e-maile, aplikacje i strony internetowe."</string>
- <string name="monitoring_description_app_work" msgid="3713084153786663662">"Organizacja <xliff:g id="ORGANIZATION">%1$s</xliff:g> zarządza Twoim profilem do pracy. Profil jest połączony z aplikacją <xliff:g id="APPLICATION">%2$s</xliff:g>, która może monitorować Twoją aktywność w sieci, w tym e-maile, aplikacje i strony internetowe.\n\nSkontaktuj się z administratorem, aby uzyskać więcej informacji."</string>
- <string name="monitoring_description_app_personal_work" msgid="6175816356939166101">"Organizacja <xliff:g id="ORGANIZATION">%1$s</xliff:g> zarządza Twoim profilem do pracy. Profil jest połączony z aplikacją <xliff:g id="APPLICATION_WORK">%2$s</xliff:g>, która może monitorować Twoją aktywność w sieci, w tym e-maile, aplikacje i strony internetowe.\n\nMasz też połączenie z aplikacją <xliff:g id="APPLICATION_PERSONAL">%3$s</xliff:g>, która może monitorować Twoją osobistą aktywność w sieci."</string>
+ <string name="monitoring_description_app_work" msgid="3713084153786663662">"Organizacja <xliff:g id="ORGANIZATION">%1$s</xliff:g> zarządza Twoim profilem służbowym. Profil jest połączony z aplikacją <xliff:g id="APPLICATION">%2$s</xliff:g>, która może monitorować Twoją aktywność w sieci, w tym e-maile, aplikacje i strony internetowe.\n\nSkontaktuj się z administratorem, aby uzyskać więcej informacji."</string>
+ <string name="monitoring_description_app_personal_work" msgid="6175816356939166101">"Organizacja <xliff:g id="ORGANIZATION">%1$s</xliff:g> zarządza Twoim profilem służbowym. Profil jest połączony z aplikacją <xliff:g id="APPLICATION_WORK">%2$s</xliff:g>, która może monitorować Twoją aktywność w sieci, w tym e-maile, aplikacje i strony internetowe.\n\nMasz też połączenie z aplikacją <xliff:g id="APPLICATION_PERSONAL">%3$s</xliff:g>, która może monitorować Twoją osobistą aktywność w sieci."</string>
<string name="keyguard_indication_trust_unlocked" msgid="7395154975733744547">"Blokada anulowana przez agenta zaufania"</string>
<string name="keyguard_indication_trust_disabled" msgid="6820793704816727918">"Urządzenie pozostanie zablokowane, aż odblokujesz je ręcznie"</string>
<string name="keyguard_indication_trust_unlocked_plugged_in" msgid="2323452175329362855">"<xliff:g id="KEYGUARD_INDICATION">%1$s</xliff:g>\n<xliff:g id="POWER_INDICATION">%2$s</xliff:g>"</string>
diff --git a/packages/SystemUI/res/values-television/config.xml b/packages/SystemUI/res/values-television/config.xml
index cebe1e83ceed..09ec439b183e 100644
--- a/packages/SystemUI/res/values-television/config.xml
+++ b/packages/SystemUI/res/values-television/config.xml
@@ -44,6 +44,9 @@
<item>com.android.systemui.wmshell.WMShell</item>
</string-array>
+ <!-- Svelte specific logic, see RecentsConfiguration.SVELTE_* constants. -->
+ <integer name="recents_svelte_level">3</integer>
+
<!-- Show a separate icon for low and high volume on the volume dialog -->
<bool name="config_showLowMediaVolumeIcon">true</bool>
diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml
index 4407d8faeaa6..880dd378e390 100644
--- a/packages/SystemUI/res/values/config.xml
+++ b/packages/SystemUI/res/values/config.xml
@@ -161,9 +161,6 @@
<!-- The number of milliseconds to extend ambient pulse by when prompted (e.g. on touch) -->
<integer name="ambient_notification_extension_time">10000</integer>
- <!-- Whether to enable KeyguardService or not -->
- <bool name="config_enableKeyguardService">true</bool>
-
<!-- The maximum count of notifications on Keyguard. The rest will be collapsed in an overflow
card. -->
<integer name="keyguard_max_notification_count">3</integer>
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java b/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java
index d731840c38ae..68405a1fca68 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java
@@ -76,6 +76,7 @@ public class KeyguardClockSwitch extends RelativeLayout {
* Frame for clock when mode != KeyguardUpdateMonitor.LOCK_SCREEN_MODE_NORMAL.
*/
private FrameLayout mNewLockscreenClockFrame;
+ private FrameLayout mNewLockscreenLargeClockFrame;
/**
* Frame for default and custom clock.
@@ -154,14 +155,12 @@ public class KeyguardClockSwitch extends RelativeLayout {
mNewLockscreenClockFrame.setVisibility(VISIBLE);
statusAreaLP.removeRule(RelativeLayout.BELOW);
- statusAreaLP.addRule(RelativeLayout.LEFT_OF, R.id.new_lockscreen_clock_view);
statusAreaLP.addRule(RelativeLayout.ALIGN_PARENT_START);
} else {
setPaddingRelative(0, 0, 0, 0);
mSmallClockFrame.setVisibility(VISIBLE);
mNewLockscreenClockFrame.setVisibility(GONE);
- statusAreaLP.removeRule(RelativeLayout.LEFT_OF);
statusAreaLP.removeRule(RelativeLayout.ALIGN_PARENT_START);
statusAreaLP.addRule(RelativeLayout.BELOW, R.id.clock_view);
}
@@ -175,6 +174,7 @@ public class KeyguardClockSwitch extends RelativeLayout {
mClockView = findViewById(R.id.default_clock_view);
mClockViewBold = findViewById(R.id.default_clock_view_bold);
mNewLockscreenClockFrame = findViewById(R.id.new_lockscreen_clock_view);
+ mNewLockscreenLargeClockFrame = findViewById(R.id.new_lockscreen_clock_view_large);
mSmallClockFrame = findViewById(R.id.clock_view);
mKeyguardStatusArea = findViewById(R.id.keyguard_status_area);
}
@@ -292,6 +292,33 @@ public class KeyguardClockSwitch extends RelativeLayout {
mClockViewBold.setFormat24Hour(format);
}
+ private void updateClockLayout(boolean useLargeClock) {
+ if (mLockScreenMode != KeyguardUpdateMonitor.LOCK_SCREEN_MODE_LAYOUT_1) return;
+
+ Fade fadeIn = new Fade();
+ fadeIn.setDuration(KeyguardSliceView.DEFAULT_ANIM_DURATION);
+ fadeIn.setInterpolator(Interpolators.LINEAR_OUT_SLOW_IN);
+
+ Fade fadeOut = new Fade();
+ fadeOut.setDuration(KeyguardSliceView.DEFAULT_ANIM_DURATION / 2);
+ fadeOut.setInterpolator(Interpolators.FAST_OUT_LINEAR_IN);
+
+ if (useLargeClock) {
+ TransitionManager.beginDelayedTransition(mNewLockscreenClockFrame, fadeOut);
+ TransitionManager.beginDelayedTransition(mNewLockscreenLargeClockFrame, fadeIn);
+
+ mNewLockscreenClockFrame.setVisibility(View.INVISIBLE);
+ addView(mNewLockscreenLargeClockFrame);
+ mNewLockscreenLargeClockFrame.setVisibility(View.VISIBLE);
+ } else {
+ TransitionManager.beginDelayedTransition(mNewLockscreenClockFrame, fadeIn);
+ TransitionManager.beginDelayedTransition(mNewLockscreenLargeClockFrame, fadeOut);
+
+ removeView(mNewLockscreenLargeClockFrame);
+ mNewLockscreenClockFrame.setVisibility(View.VISIBLE);
+ }
+ }
+
/**
* Set the amount (ratio) that the device has transitioned to doze.
*
@@ -312,6 +339,8 @@ public class KeyguardClockSwitch extends RelativeLayout {
if (hasVisibleNotifications == mHasVisibleNotifications) {
return;
}
+ updateClockLayout(!hasVisibleNotifications);
+
mHasVisibleNotifications = hasVisibleNotifications;
if (mDarkAmount == 0f && mBigClockContainer != null) {
// Starting a fade transition since the visibility of the big clock will change.
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitchController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitchController.java
index 6c695341680f..c5c36e920d45 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitchController.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitchController.java
@@ -61,6 +61,7 @@ public class KeyguardClockSwitchController extends ViewController<KeyguardClockS
*/
private AnimatableClockController mNewLockScreenClockViewController;
private FrameLayout mNewLockScreenClockFrame;
+ private AnimatableClockController mNewLockScreenLargeClockViewController;
private int mLockScreenMode = KeyguardUpdateMonitor.LOCK_SCREEN_MODE_NORMAL;
@@ -189,6 +190,7 @@ public class KeyguardClockSwitchController extends ViewController<KeyguardClockS
void refresh() {
if (mNewLockScreenClockViewController != null) {
mNewLockScreenClockViewController.refreshTime();
+ mNewLockScreenLargeClockViewController.refreshTime();
}
mView.refresh();
@@ -221,9 +223,15 @@ public class KeyguardClockSwitchController extends ViewController<KeyguardClockS
mView.findViewById(R.id.animatable_clock_view),
mStatusBarStateController);
mNewLockScreenClockViewController.init();
+ mNewLockScreenLargeClockViewController =
+ new AnimatableClockController(
+ mView.findViewById(R.id.animatable_clock_view_large),
+ mStatusBarStateController);
+ mNewLockScreenLargeClockViewController.init();
}
} else {
mNewLockScreenClockViewController = null;
+ mNewLockScreenLargeClockViewController = null;
}
mView.updateLockScreenMode(mLockScreenMode);
updateAodIcons();
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardStatusView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardStatusView.java
index 2036b3321bda..97aa26fb7f68 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardStatusView.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardStatusView.java
@@ -178,6 +178,13 @@ public class KeyguardStatusView extends GridLayout {
return mLogoutView.getVisibility() == VISIBLE ? mLogoutView.getHeight() : 0;
}
+ int getOwnerInfoHeight() {
+ if (mOwnerInfo == null) {
+ return 0;
+ }
+ return mOwnerInfo.getVisibility() == VISIBLE ? mOwnerInfo.getHeight() : 0;
+ }
+
void updateLogoutView() {
if (mLogoutView == null) {
return;
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardStatusViewController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardStatusViewController.java
index dcb306e6110a..c0e06e87b753 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardStatusViewController.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardStatusViewController.java
@@ -130,6 +130,13 @@ public class KeyguardStatusViewController extends ViewController<KeyguardStatusV
}
/**
+ * Get the height of the logout button.
+ */
+ public int getOwnerInfoHeight() {
+ return mView.getOwnerInfoHeight();
+ }
+
+ /**
* Set keyguard status view alpha.
*/
public void setAlpha(float alpha) {
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
index 767afa78b935..611131f6e216 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
@@ -1861,7 +1861,6 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
@Override
public void onChange(boolean selfChange) {
updateLockScreenMode();
- mHandler.sendEmptyMessage(MSG_LOCK_SCREEN_MODE);
}
};
mContext.getContentResolver().registerContentObserver(
@@ -1870,14 +1869,22 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
}
private void updateLockScreenMode() {
- mLockScreenMode = Settings.Global.getInt(mContext.getContentResolver(),
+ final int newMode = Settings.Global.getInt(mContext.getContentResolver(),
Settings.Global.SHOW_NEW_LOCKSCREEN,
isUdfpsEnrolled() ? 1 : 0);
+ if (newMode != mLockScreenMode) {
+ mLockScreenMode = newMode;
+ mHandler.sendEmptyMessage(MSG_LOCK_SCREEN_MODE);
+ }
}
private void updateUdfpsEnrolled(int userId) {
mIsUdfpsEnrolled = mAuthController.isUdfpsEnrolled(userId);
}
+
+ /**
+ * @return true if there's at least one udfps enrolled
+ */
public boolean isUdfpsEnrolled() {
return mIsUdfpsEnrolled;
}
@@ -1917,6 +1924,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
return;
}
+ // TODO: Add support for multiple fingerprint sensors, b/173730729
boolean shouldListenForFingerprint =
isUdfpsEnrolled() ? shouldListenForUdfps() : shouldListenForFingerprint();
boolean runningOrRestarting = mFingerprintRunningState == BIOMETRIC_STATE_RUNNING
diff --git a/packages/SystemUI/src/com/android/systemui/SwipeHelper.java b/packages/SystemUI/src/com/android/systemui/SwipeHelper.java
index 8aa3493cc105..6151ac7a242b 100644
--- a/packages/SystemUI/src/com/android/systemui/SwipeHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/SwipeHelper.java
@@ -24,6 +24,7 @@ import android.animation.ObjectAnimator;
import android.animation.ValueAnimator;
import android.animation.ValueAnimator.AnimatorUpdateListener;
import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.content.res.Resources;
import android.graphics.RectF;
import android.os.Handler;
@@ -78,9 +79,9 @@ public class SwipeHelper implements Gefingerpoken {
private float mInitialTouchPos;
private float mPerpendicularInitialTouchPos;
- private boolean mDragging;
+ private boolean mIsSwiping;
private boolean mSnappingChild;
- private View mCurrView;
+ private View mTouchedView;
private boolean mCanCurrViewBeDimissed;
private float mDensityScale;
private float mTranslation = 0;
@@ -95,14 +96,14 @@ public class SwipeHelper implements Gefingerpoken {
@Override
public void run() {
- if (mCurrView != null && !mLongPressSent) {
+ if (mTouchedView != null && !mLongPressSent) {
mLongPressSent = true;
- if (mCurrView instanceof ExpandableNotificationRow) {
- mCurrView.getLocationOnScreen(mViewOffset);
+ if (mTouchedView instanceof ExpandableNotificationRow) {
+ mTouchedView.getLocationOnScreen(mViewOffset);
final int x = (int) mDownLocation[0] - mViewOffset[0];
final int y = (int) mDownLocation[1] - mViewOffset[1];
- mCurrView.sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_LONG_CLICKED);
- ((ExpandableNotificationRow) mCurrView).doLongClickCallback(x, y);
+ mTouchedView.sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_LONG_CLICKED);
+ ((ExpandableNotificationRow) mTouchedView).doLongClickCallback(x, y);
}
}
}
@@ -281,10 +282,10 @@ public class SwipeHelper implements Gefingerpoken {
@Override
public boolean onInterceptTouchEvent(final MotionEvent ev) {
- if (mCurrView instanceof ExpandableNotificationRow) {
- NotificationMenuRowPlugin nmr = ((ExpandableNotificationRow) mCurrView).getProvider();
+ if (mTouchedView instanceof ExpandableNotificationRow) {
+ NotificationMenuRowPlugin nmr = ((ExpandableNotificationRow) mTouchedView).getProvider();
if (nmr != null) {
- mMenuRowIntercepting = nmr.onInterceptTouchEvent(mCurrView, ev);
+ mMenuRowIntercepting = nmr.onInterceptTouchEvent(mTouchedView, ev);
}
}
final int action = ev.getAction();
@@ -292,19 +293,19 @@ public class SwipeHelper implements Gefingerpoken {
switch (action) {
case MotionEvent.ACTION_DOWN:
mTouchAboveFalsingThreshold = false;
- mDragging = false;
+ mIsSwiping = false;
mSnappingChild = false;
mLongPressSent = false;
mVelocityTracker.clear();
- mCurrView = mCallback.getChildAtPosition(ev);
+ mTouchedView = mCallback.getChildAtPosition(ev);
- if (mCurrView != null) {
- onDownUpdate(mCurrView, ev);
- mCanCurrViewBeDimissed = mCallback.canChildBeDismissed(mCurrView);
+ if (mTouchedView != null) {
+ onDownUpdate(mTouchedView, ev);
+ mCanCurrViewBeDimissed = mCallback.canChildBeDismissed(mTouchedView);
mVelocityTracker.addMovement(ev);
mInitialTouchPos = getPos(ev);
mPerpendicularInitialTouchPos = getPerpendicularPos(ev);
- mTranslation = getTranslation(mCurrView);
+ mTranslation = getTranslation(mTouchedView);
mDownLocation[0] = ev.getRawX();
mDownLocation[1] = ev.getRawY();
mHandler.postDelayed(mPerformLongPress, mLongPressTimeout);
@@ -312,7 +313,7 @@ public class SwipeHelper implements Gefingerpoken {
break;
case MotionEvent.ACTION_MOVE:
- if (mCurrView != null && !mLongPressSent) {
+ if (mTouchedView != null && !mLongPressSent) {
mVelocityTracker.addMovement(ev);
float pos = getPos(ev);
float perpendicularPos = getPerpendicularPos(ev);
@@ -325,11 +326,11 @@ public class SwipeHelper implements Gefingerpoken {
: mPagingTouchSlop;
if (Math.abs(delta) > pagingTouchSlop
&& Math.abs(delta) > Math.abs(deltaPerpendicular)) {
- if (mCallback.canChildBeDragged(mCurrView)) {
- mCallback.onBeginDrag(mCurrView);
- mDragging = true;
+ if (mCallback.canChildBeDragged(mTouchedView)) {
+ mCallback.onBeginDrag(mTouchedView);
+ mIsSwiping = true;
mInitialTouchPos = getPos(ev);
- mTranslation = getTranslation(mCurrView);
+ mTranslation = getTranslation(mTouchedView);
}
cancelLongPress();
} else if (ev.getClassification() == MotionEvent.CLASSIFICATION_DEEP_PRESS
@@ -343,16 +344,16 @@ public class SwipeHelper implements Gefingerpoken {
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_CANCEL:
- final boolean captured = (mDragging || mLongPressSent || mMenuRowIntercepting);
- mDragging = false;
- mCurrView = null;
+ final boolean captured = (mIsSwiping || mLongPressSent || mMenuRowIntercepting);
+ mIsSwiping = false;
+ mTouchedView = null;
mLongPressSent = false;
mMenuRowIntercepting = false;
cancelLongPress();
if (captured) return true;
break;
}
- return mDragging || mLongPressSent || mMenuRowIntercepting;
+ return mIsSwiping || mLongPressSent || mMenuRowIntercepting;
}
/**
@@ -451,6 +452,7 @@ public class SwipeHelper implements Gefingerpoken {
}
if (!mCancelled || wasRemoved) {
mCallback.onChildDismissed(animView);
+ resetSwipeState();
}
if (endAction != null) {
endAction.run();
@@ -501,6 +503,7 @@ public class SwipeHelper implements Gefingerpoken {
updateSwipeProgressFromOffset(animView, canBeDismissed);
onChildSnappedBack(animView, targetLeft);
mCallback.onChildSnappedBack(animView, targetLeft);
+ resetSwipeState();
}
}
});
@@ -563,7 +566,7 @@ public class SwipeHelper implements Gefingerpoken {
* @param targetLeft the target to snap to.
*/
public void snapChildIfNeeded(final View view, boolean animate, float targetLeft) {
- if ((mDragging && mCurrView == view) || mSnappingChild) {
+ if ((mIsSwiping && mTouchedView == view) || mSnappingChild) {
return;
}
boolean needToSnap = false;
@@ -589,7 +592,7 @@ public class SwipeHelper implements Gefingerpoken {
return true;
}
- if (!mDragging && !mMenuRowIntercepting) {
+ if (!mIsSwiping && !mMenuRowIntercepting) {
if (mCallback.getChildAtPosition(ev) != null) {
// We are dragging directly over a card, make sure that we also catch the gesture
@@ -610,7 +613,7 @@ public class SwipeHelper implements Gefingerpoken {
switch (action) {
case MotionEvent.ACTION_OUTSIDE:
case MotionEvent.ACTION_MOVE:
- if (mCurrView != null) {
+ if (mTouchedView != null) {
float delta = getPos(ev) - mInitialTouchPos;
float absDelta = Math.abs(delta);
if (absDelta >= getFalsingThreshold()) {
@@ -618,9 +621,10 @@ public class SwipeHelper implements Gefingerpoken {
}
// don't let items that can't be dismissed be dragged more than
// maxScrollDistance
- if (CONSTRAIN_SWIPE && !mCallback.canChildBeDismissedInDirection(mCurrView,
+ if (CONSTRAIN_SWIPE && !mCallback.canChildBeDismissedInDirection(
+ mTouchedView,
delta > 0)) {
- float size = getSize(mCurrView);
+ float size = getSize(mTouchedView);
float maxScrollDistance = MAX_SCROLL_SIZE_FRACTION * size;
if (absDelta >= size) {
delta = delta > 0 ? maxScrollDistance : -maxScrollDistance;
@@ -636,32 +640,30 @@ public class SwipeHelper implements Gefingerpoken {
}
}
- setTranslation(mCurrView, mTranslation + delta);
- updateSwipeProgressFromOffset(mCurrView, mCanCurrViewBeDimissed);
- onMoveUpdate(mCurrView, ev, mTranslation + delta, delta);
+ setTranslation(mTouchedView, mTranslation + delta);
+ updateSwipeProgressFromOffset(mTouchedView, mCanCurrViewBeDimissed);
+ onMoveUpdate(mTouchedView, ev, mTranslation + delta, delta);
}
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_CANCEL:
- if (mCurrView == null) {
+ if (mTouchedView == null) {
break;
}
mVelocityTracker.computeCurrentVelocity(1000 /* px/sec */, getMaxVelocity());
float velocity = getVelocity(mVelocityTracker);
- if (!handleUpEvent(ev, mCurrView, velocity, getTranslation(mCurrView))) {
+ if (!handleUpEvent(ev, mTouchedView, velocity, getTranslation(mTouchedView))) {
if (isDismissGesture(ev)) {
- // flingadingy
- dismissChild(mCurrView, velocity,
+ dismissChild(mTouchedView, velocity,
!swipedFastEnough() /* useAccelerateInterpolator */);
} else {
- // snappity
- mCallback.onDragCancelled(mCurrView);
- snapChild(mCurrView, 0 /* leftTarget */, velocity);
+ mCallback.onDragCancelled(mTouchedView);
+ snapChild(mTouchedView, 0 /* leftTarget */, velocity);
}
- mCurrView = null;
+ mTouchedView = null;
}
- mDragging = false;
+ mIsSwiping = false;
break;
}
return true;
@@ -689,17 +691,18 @@ public class SwipeHelper implements Gefingerpoken {
}
protected boolean swipedFarEnough() {
- float translation = getTranslation(mCurrView);
+ float translation = getTranslation(mTouchedView);
return DISMISS_IF_SWIPED_FAR_ENOUGH
- && Math.abs(translation) > SWIPED_FAR_ENOUGH_SIZE_FRACTION * getSize(mCurrView);
+ && Math.abs(translation) > SWIPED_FAR_ENOUGH_SIZE_FRACTION * getSize(
+ mTouchedView);
}
public boolean isDismissGesture(MotionEvent ev) {
- float translation = getTranslation(mCurrView);
+ float translation = getTranslation(mTouchedView);
return ev.getActionMasked() == MotionEvent.ACTION_UP
&& !mFalsingManager.isUnlockingDisabled()
&& !isFalseGesture() && (swipedFastEnough() || swipedFarEnough())
- && mCallback.canChildBeDismissedInDirection(mCurrView, translation > 0);
+ && mCallback.canChildBeDismissedInDirection(mTouchedView, translation > 0);
}
/** Returns true if the gesture should be rejected. */
@@ -715,7 +718,7 @@ public class SwipeHelper implements Gefingerpoken {
protected boolean swipedFastEnough() {
float velocity = getVelocity(mVelocityTracker);
- float translation = getTranslation(mCurrView);
+ float translation = getTranslation(mTouchedView);
boolean ret = (Math.abs(velocity) > getEscapeVelocity())
&& (velocity > 0) == (translation > 0);
return ret;
@@ -726,6 +729,20 @@ public class SwipeHelper implements Gefingerpoken {
return false;
}
+ public boolean isSwiping() {
+ return mIsSwiping;
+ }
+
+ @Nullable
+ public View getSwipedView() {
+ return mIsSwiping ? mTouchedView : null;
+ }
+
+ public void resetSwipeState() {
+ mTouchedView = null;
+ mIsSwiping = false;
+ }
+
public interface Callback {
View getChildAtPosition(MotionEvent ev);
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java
index 8776532debcd..7bb8a8490160 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java
@@ -194,6 +194,7 @@ class UdfpsController implements DozeReceiver {
mCoreLayoutParams.setFitInsetsTypes(0);
mCoreLayoutParams.layoutInDisplayCutoutMode =
WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
+ mCoreLayoutParams.privateFlags = WindowManager.LayoutParams.PRIVATE_FLAG_TRUSTED_OVERLAY;
mView = (UdfpsView) inflater.inflate(R.layout.udfps_view, null, false);
mView.setSensorProperties(mSensorProps);
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/AccelerationClassifier.java b/packages/SystemUI/src/com/android/systemui/classifier/AccelerationClassifier.java
deleted file mode 100644
index 4585fe9fb868..000000000000
--- a/packages/SystemUI/src/com/android/systemui/classifier/AccelerationClassifier.java
+++ /dev/null
@@ -1,99 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-package com.android.systemui.classifier;
-
-import android.view.MotionEvent;
-
-import java.util.HashMap;
-
-/**
- * A classifier which looks at the speed and distance between successive points of a Stroke.
- * It looks at two consecutive speeds between two points and calculates the ratio between them.
- * The final result is the maximum of these values. It does the same for distances. If some speed
- * or distance is equal to zero then the ratio between this and the next part is not calculated. To
- * the duration of each part there is added one nanosecond so that it is always possible to
- * calculate the speed of a part.
- */
-public class AccelerationClassifier extends StrokeClassifier {
- private final HashMap<Stroke, Data> mStrokeMap = new HashMap<>();
-
- public AccelerationClassifier(ClassifierData classifierData) {
- mClassifierData = classifierData;
- }
-
- @Override
- public String getTag() {
- return "ACC";
- }
-
- @Override
- public void onTouchEvent(MotionEvent event) {
- int action = event.getActionMasked();
-
- if (action == MotionEvent.ACTION_DOWN) {
- mStrokeMap.clear();
- }
-
- for (int i = 0; i < event.getPointerCount(); i++) {
- Stroke stroke = mClassifierData.getStroke(event.getPointerId(i));
- Point point = stroke.getPoints().get(stroke.getPoints().size() - 1);
- if (mStrokeMap.get(stroke) == null) {
- mStrokeMap.put(stroke, new Data(point));
- } else {
- mStrokeMap.get(stroke).addPoint(point);
- }
- }
- }
-
- @Override
- public float getFalseTouchEvaluation(int type, Stroke stroke) {
- Data data = mStrokeMap.get(stroke);
- return 2 * SpeedRatioEvaluator.evaluate(data.maxSpeedRatio);
- }
-
- private static class Data {
-
- static final float MILLIS_TO_NANOS = 1e6f;
-
- Point previousPoint;
- float previousSpeed = 0;
- float maxSpeedRatio = 0;
-
- public Data(Point point) {
- previousPoint = point;
- }
-
- public void addPoint(Point point) {
- float distance = previousPoint.dist(point);
- float duration = (float) (point.timeOffsetNano - previousPoint.timeOffsetNano + 1);
- float speed = distance / duration;
-
- if (duration > 20 * MILLIS_TO_NANOS || duration < 5 * MILLIS_TO_NANOS) {
- // reject this segment and ensure we won't use data about it in the next round.
- previousSpeed = 0;
- previousPoint = point;
- return;
- }
- if (previousSpeed != 0.0f) {
- maxSpeedRatio = Math.max(maxSpeedRatio, speed / previousSpeed);
- }
-
- previousSpeed = speed;
- previousPoint = point;
- }
- }
-} \ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/AnglesClassifier.java b/packages/SystemUI/src/com/android/systemui/classifier/AnglesClassifier.java
deleted file mode 100644
index 6d13973d23b5..000000000000
--- a/packages/SystemUI/src/com/android/systemui/classifier/AnglesClassifier.java
+++ /dev/null
@@ -1,207 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-package com.android.systemui.classifier;
-
-import android.os.Build;
-import android.os.SystemProperties;
-import android.view.MotionEvent;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-
-/**
- * A classifier which calculates the variance of differences between successive angles in a stroke.
- * For each stroke it keeps its last three points. If some successive points are the same, it
- * ignores the repetitions. If a new point is added, the classifier calculates the angle between
- * the last three points. After that, it calculates the difference between this angle and the
- * previously calculated angle. Then it calculates the variance of the differences from a stroke.
- * To the differences there is artificially added value 0.0 and the difference between the first
- * angle and PI (angles are in radians). It helps with strokes which have few points and punishes
- * more strokes which are not smooth.
- *
- * This classifier also tries to split the stroke into two parts in the place in which the biggest
- * angle is. It calculates the angle variance of the two parts and sums them up. The reason the
- * classifier is doing this, is because some human swipes at the beginning go for a moment in one
- * direction and then they rapidly change direction for the rest of the stroke (like a tick). The
- * final result is the minimum of angle variance of the whole stroke and the sum of angle variances
- * of the two parts split up. The classifier tries the tick option only if the first part is
- * shorter than the second part.
- *
- * Additionally, the classifier classifies the angles as left angles (those angles which value is
- * in [0.0, PI - ANGLE_DEVIATION) interval), straight angles
- * ([PI - ANGLE_DEVIATION, PI + ANGLE_DEVIATION] interval) and right angles
- * ((PI + ANGLE_DEVIATION, 2 * PI) interval) and then calculates the percentage of angles which are
- * in the same direction (straight angles can be left angels or right angles)
- */
-public class AnglesClassifier extends StrokeClassifier {
- private HashMap<Stroke, Data> mStrokeMap = new HashMap<>();
-
- public static final boolean VERBOSE = SystemProperties.getBoolean("debug.falsing_log.ang",
- Build.IS_DEBUGGABLE);
-
- private static String TAG = "ANG";
-
- public AnglesClassifier(ClassifierData classifierData) {
- mClassifierData = classifierData;
- }
-
- @Override
- public String getTag() {
- return TAG;
- }
-
- @Override
- public void onTouchEvent(MotionEvent event) {
- int action = event.getActionMasked();
-
- if (action == MotionEvent.ACTION_DOWN) {
- mStrokeMap.clear();
- }
-
- for (int i = 0; i < event.getPointerCount(); i++) {
- Stroke stroke = mClassifierData.getStroke(event.getPointerId(i));
-
- if (mStrokeMap.get(stroke) == null) {
- mStrokeMap.put(stroke, new Data());
- }
- mStrokeMap.get(stroke).addPoint(stroke.getPoints().get(stroke.getPoints().size() - 1));
- }
- }
-
- @Override
- public float getFalseTouchEvaluation(int type, Stroke stroke) {
- Data data = mStrokeMap.get(stroke);
- return AnglesVarianceEvaluator.evaluate(data.getAnglesVariance(), type)
- + AnglesPercentageEvaluator.evaluate(data.getAnglesPercentage(), type);
- }
-
- private static class Data {
- private final float ANGLE_DEVIATION = (float) Math.PI / 20.0f;
-
- private List<Point> mLastThreePoints = new ArrayList<>();
- private float mFirstAngleVariance;
- private float mPreviousAngle;
- private float mBiggestAngle;
- private float mSumSquares;
- private float mSecondSumSquares;
- private float mSum;
- private float mSecondSum;
- private float mCount;
- private float mSecondCount;
- private float mFirstLength;
- private float mLength;
- private float mAnglesCount;
- private float mLeftAngles;
- private float mRightAngles;
- private float mStraightAngles;
-
- public Data() {
- mFirstAngleVariance = 0.0f;
- mPreviousAngle = (float) Math.PI;
- mBiggestAngle = 0.0f;
- mSumSquares = mSecondSumSquares = 0.0f;
- mSum = mSecondSum = 0.0f;
- mCount = mSecondCount = 1.0f;
- mLength = mFirstLength = 0.0f;
- mAnglesCount = mLeftAngles = mRightAngles = mStraightAngles = 0.0f;
- }
-
- public void addPoint(Point point) {
- // Checking if the added point is different than the previously added point
- // Repetitions are being ignored so that proper angles are calculated.
- if (mLastThreePoints.isEmpty()
- || !mLastThreePoints.get(mLastThreePoints.size() - 1).equals(point)) {
- if (!mLastThreePoints.isEmpty()) {
- mLength += mLastThreePoints.get(mLastThreePoints.size() - 1).dist(point);
- }
- mLastThreePoints.add(point);
- if (mLastThreePoints.size() == 4) {
- mLastThreePoints.remove(0);
-
- float angle = mLastThreePoints.get(1).getAngle(mLastThreePoints.get(0),
- mLastThreePoints.get(2));
-
- mAnglesCount++;
- if (angle < Math.PI - ANGLE_DEVIATION) {
- mLeftAngles++;
- } else if (angle <= Math.PI + ANGLE_DEVIATION) {
- mStraightAngles++;
- } else {
- mRightAngles++;
- }
-
- float difference = angle - mPreviousAngle;
-
- // If this is the biggest angle of the stroke so then we save the value of
- // the angle variance so far and start to count the values for the angle
- // variance of the second part.
- if (mBiggestAngle < angle) {
- mBiggestAngle = angle;
- mFirstLength = mLength;
- mFirstAngleVariance = getAnglesVariance(mSumSquares, mSum, mCount);
- mSecondSumSquares = 0.0f;
- mSecondSum = 0.0f;
- mSecondCount = 1.0f;
- } else {
- mSecondSum += difference;
- mSecondSumSquares += difference * difference;
- mSecondCount += 1.0;
- }
-
- mSum += difference;
- mSumSquares += difference * difference;
- mCount += 1.0;
- mPreviousAngle = angle;
- }
- }
- }
-
- public float getAnglesVariance(float sumSquares, float sum, float count) {
- return sumSquares / count - (sum / count) * (sum / count);
- }
-
- public float getAnglesVariance() {
- float anglesVariance = getAnglesVariance(mSumSquares, mSum, mCount);
- if (VERBOSE) {
- FalsingLog.i(TAG, "getAnglesVariance: (first pass) " + anglesVariance);
- FalsingLog.i(TAG, " - mFirstLength=" + mFirstLength);
- FalsingLog.i(TAG, " - mLength=" + mLength);
- }
- if (mFirstLength < mLength / 2f) {
- anglesVariance = Math.min(anglesVariance, mFirstAngleVariance
- + getAnglesVariance(mSecondSumSquares, mSecondSum, mSecondCount));
- if (VERBOSE) FalsingLog.i(TAG, "getAnglesVariance: (second pass) " + anglesVariance);
- }
- return anglesVariance;
- }
-
- public float getAnglesPercentage() {
- if (mAnglesCount == 0.0f) {
- if (VERBOSE) FalsingLog.i(TAG, "getAnglesPercentage: count==0, result=1");
- return 1.0f;
- }
- final float result = (Math.max(mLeftAngles, mRightAngles) + mStraightAngles) / mAnglesCount;
- if (VERBOSE) {
- FalsingLog.i(TAG, "getAnglesPercentage: left=" + mLeftAngles + " right="
- + mRightAngles + " straight=" + mStraightAngles + " count=" + mAnglesCount
- + " result=" + result);
- }
- return result;
- }
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/AnglesPercentageEvaluator.java b/packages/SystemUI/src/com/android/systemui/classifier/AnglesPercentageEvaluator.java
deleted file mode 100644
index e6e42f2d0eef..000000000000
--- a/packages/SystemUI/src/com/android/systemui/classifier/AnglesPercentageEvaluator.java
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-package com.android.systemui.classifier;
-
-public class AnglesPercentageEvaluator {
- public static float evaluate(float value, int type) {
- final boolean secureUnlock = type == Classifier.BOUNCER_UNLOCK;
- float evaluation = 0.0f;
- if (value < 1.00 && !secureUnlock) evaluation++;
- if (value < 0.90 && !secureUnlock) evaluation++;
- if (value < 0.70) evaluation++;
- return evaluation;
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/AnglesVarianceEvaluator.java b/packages/SystemUI/src/com/android/systemui/classifier/AnglesVarianceEvaluator.java
deleted file mode 100644
index 9ffe783fbded..000000000000
--- a/packages/SystemUI/src/com/android/systemui/classifier/AnglesVarianceEvaluator.java
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-package com.android.systemui.classifier;
-
-public class AnglesVarianceEvaluator {
- public static float evaluate(float value, int type) {
- float evaluation = 0.0f;
- if (value > 0.20) evaluation++;
- if (value > 0.40) evaluation++;
- if (value > 0.80) evaluation++;
- if (value > 1.50) evaluation++;
- return evaluation;
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/Classifier.java b/packages/SystemUI/src/com/android/systemui/classifier/Classifier.java
index ae7d142a9e45..c7ad3e8f78eb 100644
--- a/packages/SystemUI/src/com/android/systemui/classifier/Classifier.java
+++ b/packages/SystemUI/src/com/android/systemui/classifier/Classifier.java
@@ -54,11 +54,6 @@ public abstract class Classifier {
public @interface InteractionType {}
/**
- * Contains all the information about touch events from which the classifier can query
- */
- protected ClassifierData mClassifierData;
-
- /**
* Informs the classifier that a new touch event has occurred
*/
public void onTouchEvent(MotionEvent event) {
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/ClassifierData.java b/packages/SystemUI/src/com/android/systemui/classifier/ClassifierData.java
deleted file mode 100644
index 587abba47932..000000000000
--- a/packages/SystemUI/src/com/android/systemui/classifier/ClassifierData.java
+++ /dev/null
@@ -1,101 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-package com.android.systemui.classifier;
-
-import android.util.SparseArray;
-import android.view.MotionEvent;
-
-import java.util.ArrayList;
-
-/**
- * Contains data which is used to classify interaction sequences on the lockscreen. It does, for
- * example, provide information on the current touch state.
- */
-public class ClassifierData {
- private static final long MINIMUM_DT_NANOS = 16666666; // 60Hz
- private static final long MINIMUM_DT_SMEAR_NANOS = 2500000; // 2.5ms
-
- private SparseArray<Stroke> mCurrentStrokes = new SparseArray<>();
- private ArrayList<Stroke> mEndingStrokes = new ArrayList<>();
- private final float mDpi;
-
- public ClassifierData(float dpi) {
- mDpi = dpi;
- }
-
- /** Returns true if the event should be considered, false otherwise. */
- public boolean update(MotionEvent event) {
- // We limit to 60hz sampling. Drop anything happening faster than that.
- // Legacy code was created with an assumed sampling rate. As devices increase their
- // sampling rate, this creates potentialy false positives.
- if (event.getActionMasked() == MotionEvent.ACTION_MOVE
- && mCurrentStrokes.size() != 0
- && event.getEventTimeNano() - mCurrentStrokes.valueAt(0).getLastEventTimeNano()
- < MINIMUM_DT_NANOS - MINIMUM_DT_SMEAR_NANOS) {
- return false;
- }
-
- mEndingStrokes.clear();
- int action = event.getActionMasked();
- if (action == MotionEvent.ACTION_DOWN) {
- mCurrentStrokes.clear();
- }
-
- for (int i = 0; i < event.getPointerCount(); i++) {
- int id = event.getPointerId(i);
- if (mCurrentStrokes.get(id) == null) {
- mCurrentStrokes.put(id, new Stroke(event.getEventTimeNano(), mDpi));
- }
- mCurrentStrokes.get(id).addPoint(event.getX(i), event.getY(i),
- event.getEventTimeNano());
-
- if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_CANCEL
- || (action == MotionEvent.ACTION_POINTER_UP && i == event.getActionIndex())) {
- mEndingStrokes.add(getStroke(id));
- }
- }
-
- return true;
- }
-
- public void cleanUp(MotionEvent event) {
- mEndingStrokes.clear();
- int action = event.getActionMasked();
- for (int i = 0; i < event.getPointerCount(); i++) {
- int id = event.getPointerId(i);
- if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_CANCEL
- || (action == MotionEvent.ACTION_POINTER_UP && i == event.getActionIndex())) {
- mCurrentStrokes.remove(id);
- }
- }
- }
-
- /**
- * @return the list of Strokes which are ending in the recently added MotionEvent
- */
- public ArrayList<Stroke> getEndingStrokes() {
- return mEndingStrokes;
- }
-
- /**
- * @param id the id from MotionEvent
- * @return the Stroke assigned to the id
- */
- public Stroke getStroke(int id) {
- return mCurrentStrokes.get(id);
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/DirectionClassifier.java b/packages/SystemUI/src/com/android/systemui/classifier/DirectionClassifier.java
deleted file mode 100644
index 610e21983b5d..000000000000
--- a/packages/SystemUI/src/com/android/systemui/classifier/DirectionClassifier.java
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-package com.android.systemui.classifier;
-
-/**
- * A classifier which looks at the general direction of a stroke and evaluates it depending on
- * the type of action that takes place.
- */
-public class DirectionClassifier extends StrokeClassifier {
- public DirectionClassifier(ClassifierData classifierData) {
- }
-
- @Override
- public String getTag() {
- return "DIR";
- }
-
- @Override
- public float getFalseTouchEvaluation(int type, Stroke stroke) {
- Point firstPoint = stroke.getPoints().get(0);
- Point lastPoint = stroke.getPoints().get(stroke.getPoints().size() - 1);
- return DirectionEvaluator.evaluate(lastPoint.x - firstPoint.x, lastPoint.y - firstPoint.y,
- type);
- }
-} \ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/DirectionEvaluator.java b/packages/SystemUI/src/com/android/systemui/classifier/DirectionEvaluator.java
deleted file mode 100644
index 78b41683a32b..000000000000
--- a/packages/SystemUI/src/com/android/systemui/classifier/DirectionEvaluator.java
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-package com.android.systemui.classifier;
-
-public class DirectionEvaluator {
- public static float evaluate(float xDiff, float yDiff, int type) {
- float falsingEvaluation = 5.5f;
- boolean vertical = Math.abs(yDiff) >= Math.abs(xDiff);
- switch (type) {
- case Classifier.QUICK_SETTINGS:
- case Classifier.PULSE_EXPAND:
- case Classifier.NOTIFICATION_DRAG_DOWN:
- if (!vertical || yDiff <= 0.0) {
- return falsingEvaluation;
- }
- break;
- case Classifier.NOTIFICATION_DISMISS:
- if (vertical) {
- return falsingEvaluation;
- }
- break;
- case Classifier.UNLOCK:
- case Classifier.BOUNCER_UNLOCK:
- if (!vertical || yDiff >= 0.0) {
- return falsingEvaluation;
- }
- break;
- case Classifier.LEFT_AFFORDANCE:
- if (xDiff < 0.0 && yDiff > 0.0) {
- return falsingEvaluation;
- }
- break;
- case Classifier.RIGHT_AFFORDANCE:
- if (xDiff > 0.0 && yDiff > 0.0) {
- return falsingEvaluation;
- }
- default:
- break;
- }
- return 0.0f;
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/DurationCountClassifier.java b/packages/SystemUI/src/com/android/systemui/classifier/DurationCountClassifier.java
deleted file mode 100644
index 77fda2001f3c..000000000000
--- a/packages/SystemUI/src/com/android/systemui/classifier/DurationCountClassifier.java
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-package com.android.systemui.classifier;
-
-/**
- * A classifier which looks at the ratio between the duration of the stroke and its number of
- * points.
- */
-public class DurationCountClassifier extends StrokeClassifier {
- public DurationCountClassifier(ClassifierData classifierData) {
- }
-
- @Override
- public String getTag() {
- return "DUR";
- }
-
- @Override
- public float getFalseTouchEvaluation(int type, Stroke stroke) {
- return DurationCountEvaluator.evaluate(stroke.getDurationSeconds() / stroke.getCount());
- }
-} \ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/DurationCountEvaluator.java b/packages/SystemUI/src/com/android/systemui/classifier/DurationCountEvaluator.java
deleted file mode 100644
index 5395983968f7..000000000000
--- a/packages/SystemUI/src/com/android/systemui/classifier/DurationCountEvaluator.java
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-package com.android.systemui.classifier;
-
-
-public class DurationCountEvaluator {
- public static float evaluate(float value) {
- float evaluation = 0.0f;
- if (value < 0.0105) evaluation++;
- if (value < 0.00909) evaluation++;
- if (value < 0.00667) evaluation++;
- if (value > 0.0333) evaluation++;
- if (value > 0.0500) evaluation++;
- return evaluation;
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/EndPointLengthClassifier.java b/packages/SystemUI/src/com/android/systemui/classifier/EndPointLengthClassifier.java
deleted file mode 100644
index de8a18860c38..000000000000
--- a/packages/SystemUI/src/com/android/systemui/classifier/EndPointLengthClassifier.java
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-package com.android.systemui.classifier;
-
-/**
- * A classifier which looks at the distance between the first and the last point from the stroke.
- */
-public class EndPointLengthClassifier extends StrokeClassifier {
- public EndPointLengthClassifier(ClassifierData classifierData) {
- }
-
- @Override
- public String getTag() {
- return "END_LNGTH";
- }
-
- @Override
- public float getFalseTouchEvaluation(int type, Stroke stroke) {
- return EndPointLengthEvaluator.evaluate(stroke.getEndPointLength());
- }
-} \ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/EndPointLengthEvaluator.java b/packages/SystemUI/src/com/android/systemui/classifier/EndPointLengthEvaluator.java
deleted file mode 100644
index bb2f1c4e355d..000000000000
--- a/packages/SystemUI/src/com/android/systemui/classifier/EndPointLengthEvaluator.java
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-package com.android.systemui.classifier;
-
-public class EndPointLengthEvaluator {
- public static float evaluate(float value) {
- float evaluation = 0.0f;
- if (value < 0.05) evaluation += 2.0;
- if (value < 0.1) evaluation += 2.0;
- if (value < 0.2) evaluation += 2.0;
- if (value < 0.3) evaluation += 2.0;
- if (value < 0.4) evaluation += 2.0;
- if (value < 0.5) evaluation += 2.0;
- return evaluation;
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/EndPointRatioClassifier.java b/packages/SystemUI/src/com/android/systemui/classifier/EndPointRatioClassifier.java
deleted file mode 100644
index 9b6ddc8ffb2f..000000000000
--- a/packages/SystemUI/src/com/android/systemui/classifier/EndPointRatioClassifier.java
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-package com.android.systemui.classifier;
-
-/**
- * A classifier which looks at the ratio between the total length covered by the stroke and the
- * distance between the first and last point from this stroke.
- */
-public class EndPointRatioClassifier extends StrokeClassifier {
- public EndPointRatioClassifier(ClassifierData classifierData) {
- mClassifierData = classifierData;
- }
-
- @Override
- public String getTag() {
- return "END_RTIO";
- }
-
- @Override
- public float getFalseTouchEvaluation(int type, Stroke stroke) {
- float ratio;
- if (stroke.getTotalLength() == 0.0f) {
- ratio = 1.0f;
- } else {
- ratio = stroke.getEndPointLength() / stroke.getTotalLength();
- }
- return EndPointRatioEvaluator.evaluate(ratio);
- }
-} \ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/EndPointRatioEvaluator.java b/packages/SystemUI/src/com/android/systemui/classifier/EndPointRatioEvaluator.java
deleted file mode 100644
index 529fcec2710e..000000000000
--- a/packages/SystemUI/src/com/android/systemui/classifier/EndPointRatioEvaluator.java
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-package com.android.systemui.classifier;
-
-public class EndPointRatioEvaluator {
- public static float evaluate(float value) {
- float evaluation = 0.0f;
- if (value < 0.85) evaluation++;
- if (value < 0.75) evaluation++;
- if (value < 0.65) evaluation++;
- if (value < 0.55) evaluation++;
- if (value < 0.45) evaluation++;
- if (value < 0.35) evaluation++;
- return evaluation;
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/FalsingLog.java b/packages/SystemUI/src/com/android/systemui/classifier/FalsingLog.java
deleted file mode 100644
index 8105c6a6e940..000000000000
--- a/packages/SystemUI/src/com/android/systemui/classifier/FalsingLog.java
+++ /dev/null
@@ -1,169 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * 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.classifier;
-
-import android.app.ActivityThread;
-import android.app.Application;
-import android.os.Build;
-import android.os.SystemProperties;
-import android.util.Log;
-
-import java.io.File;
-import java.io.IOException;
-import java.io.PrintWriter;
-import java.text.SimpleDateFormat;
-import java.util.ArrayDeque;
-import java.util.Date;
-import java.util.Locale;
-
-/**
- * Keeps track of interesting falsing data.
- *
- * By default the log only gets collected on userdebug builds. To turn it on on user:
- * adb shell setprop debug.falsing_log true
- *
- * The log gets dumped as part of the SystemUI services. To dump on demand:
- * adb shell dumpsys activity service com.android.systemui StatusBar | grep -A 999 FALSING | less
- *
- * To dump into logcat:
- * adb shell setprop debug.falsing_logcat true
- *
- * To adjust the log buffer size:
- * adb shell setprop debug.falsing_log_size 200
- */
-public class FalsingLog {
- public static final boolean ENABLED = SystemProperties.getBoolean("debug.falsing_log",
- Build.IS_DEBUGGABLE);
- private static final boolean LOGCAT = SystemProperties.getBoolean("debug.falsing_logcat",
- false);
-
- public static final boolean VERBOSE = false;
-
- private static final int MAX_SIZE = SystemProperties.getInt("debug.falsing_log_size", 100);
-
- private static final String TAG = "FalsingLog";
-
- private final ArrayDeque<String> mLog = new ArrayDeque<>(MAX_SIZE);
- private final SimpleDateFormat mFormat = new SimpleDateFormat("MM-dd HH:mm:ss", Locale.US);
-
- private static FalsingLog sInstance;
-
- private FalsingLog() {
- }
-
- public static void v(String tag, String s) {
- if (!VERBOSE) {
- return;
- }
- if (LOGCAT) {
- Log.v(TAG, tag + "\t" + s);
- }
- log("V", tag, s);
- }
-
- public static void i(String tag, String s) {
- if (LOGCAT) {
- Log.i(TAG, tag + "\t" + s);
- }
- log("I", tag, s);
- }
-
- public static void wLogcat(String tag, String s) {
- Log.w(TAG, tag + "\t" + s);
- log("W", tag, s);
- }
-
- public static void w(String tag, String s) {
- if (LOGCAT) {
- Log.w(TAG, tag + "\t" + s);
- }
- log("W", tag, s);
- }
-
- public static void e(String tag, String s) {
- if (LOGCAT) {
- Log.e(TAG, tag + "\t" + s);
- }
- log("E", tag, s);
- }
-
- public static synchronized void log(String level, String tag, String s) {
- if (!ENABLED) {
- return;
- }
- if (sInstance == null) {
- sInstance = new FalsingLog();
- }
-
- if (sInstance.mLog.size() >= MAX_SIZE) {
- sInstance.mLog.removeFirst();
- }
- String entry = new StringBuilder().append(sInstance.mFormat.format(new Date()))
- .append(" ").append(level).append(" ")
- .append(tag).append(" ").append(s).toString();
- sInstance.mLog.add(entry);
- }
-
- public static synchronized void dump(PrintWriter pw) {
- pw.println("FALSING LOG:");
- if (!ENABLED) {
- pw.println("Disabled, to enable: setprop debug.falsing_log 1");
- pw.println();
- return;
- }
- if (sInstance == null || sInstance.mLog.isEmpty()) {
- pw.println("<empty>");
- pw.println();
- return;
- }
- for (String s : sInstance.mLog) {
- pw.println(s);
- }
- pw.println();
- }
-
- public static synchronized void wtf(String tag, String s, Throwable here) {
- if (!ENABLED) {
- return;
- }
- e(tag, s);
-
- Application application = ActivityThread.currentApplication();
- String fileMessage = "";
- if (Build.IS_DEBUGGABLE && application != null) {
- File f = new File(application.getDataDir(), "falsing-"
- + new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss").format(new Date()) + ".txt");
- PrintWriter pw = null;
- try {
- pw = new PrintWriter(f);
- dump(pw);
- pw.close();
- fileMessage = "Log written to " + f.getAbsolutePath();
- } catch (IOException e) {
- Log.e(TAG, "Unable to write falsing log", e);
- } finally {
- if (pw != null) {
- pw.close();
- }
- }
- } else {
- Log.e(TAG, "Unable to write log, build must be debuggable.");
- }
-
- Log.wtf(TAG, tag + " " + s + "; " + fileMessage, here);
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/FalsingManagerFake.java b/packages/SystemUI/src/com/android/systemui/classifier/FalsingManagerFake.java
index 6961b45c3c37..121484303b99 100644
--- a/packages/SystemUI/src/com/android/systemui/classifier/FalsingManagerFake.java
+++ b/packages/SystemUI/src/com/android/systemui/classifier/FalsingManagerFake.java
@@ -22,6 +22,7 @@ import android.view.MotionEvent;
import com.android.internal.annotations.VisibleForTesting;
import com.android.systemui.plugins.FalsingManager;
+import java.io.FileDescriptor;
import java.io.PrintWriter;
/**
@@ -29,10 +30,13 @@ import java.io.PrintWriter;
*/
public class FalsingManagerFake implements FalsingManager {
private boolean mIsFalseTouch;
+ private boolean mIsFalseTap;
+ private boolean mIsFalseDoubleTap;
private boolean mIsUnlockingDisabled;
private boolean mIsClassiferEnabled;
private boolean mShouldEnforceBouncer;
private boolean mIsReportingEnabled;
+ private boolean mIsFalseRobustTap;
@Override
public void onSuccessfulUnlock() {
@@ -74,6 +78,28 @@ public class FalsingManagerFake implements FalsingManager {
return mIsFalseTouch;
}
+ public void setFalseRobustTap(boolean falseRobustTap) {
+ mIsFalseRobustTap = falseRobustTap;
+ }
+
+ public void setFalseTap(boolean falseTap) {
+ mIsFalseTap = falseTap;
+ }
+
+ public void setFalseDoubleTap(boolean falseDoubleTap) {
+ mIsFalseDoubleTap = falseDoubleTap;
+ }
+
+ @Override
+ public boolean isFalseTap(boolean robustCheck) {
+ return robustCheck ? mIsFalseRobustTap : mIsFalseTap;
+ }
+
+ @Override
+ public boolean isFalseDoubleTap() {
+ return mIsFalseDoubleTap;
+ }
+
@Override
public void onNotificatonStopDraggingDown() {
@@ -236,8 +262,7 @@ public class FalsingManagerFake implements FalsingManager {
}
@Override
- public void dump(PrintWriter pw) {
-
+ public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/FalsingManagerImpl.java b/packages/SystemUI/src/com/android/systemui/classifier/FalsingManagerImpl.java
deleted file mode 100644
index decaec10e572..000000000000
--- a/packages/SystemUI/src/com/android/systemui/classifier/FalsingManagerImpl.java
+++ /dev/null
@@ -1,579 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.classifier;
-
-import android.app.ActivityManager;
-import android.content.Context;
-import android.database.ContentObserver;
-import android.hardware.Sensor;
-import android.hardware.SensorEvent;
-import android.hardware.SensorEventListener;
-import android.hardware.SensorManager;
-import android.hardware.biometrics.BiometricSourceType;
-import android.net.Uri;
-import android.os.Handler;
-import android.os.Looper;
-import android.os.PowerManager;
-import android.os.UserHandle;
-import android.provider.Settings;
-import android.view.InputDevice;
-import android.view.MotionEvent;
-import android.view.accessibility.AccessibilityManager;
-
-import com.android.internal.logging.MetricsLogger;
-import com.android.keyguard.KeyguardUpdateMonitor;
-import com.android.keyguard.KeyguardUpdateMonitorCallback;
-import com.android.systemui.Dependency;
-import com.android.systemui.analytics.DataCollector;
-import com.android.systemui.dagger.qualifiers.UiBackground;
-import com.android.systemui.plugins.FalsingManager;
-import com.android.systemui.plugins.statusbar.StatusBarStateController;
-import com.android.systemui.plugins.statusbar.StatusBarStateController.StateListener;
-import com.android.systemui.statusbar.StatusBarState;
-import com.android.systemui.util.sensors.AsyncSensorManager;
-
-import java.io.PrintWriter;
-import java.util.concurrent.Executor;
-
-/**
- * When the phone is locked, listens to touch, sensor and phone events and sends them to
- * DataCollector and HumanInteractionClassifier.
- *
- * It does not collect touch events when the bouncer shows up.
- */
-public class FalsingManagerImpl implements FalsingManager {
- private static final String ENFORCE_BOUNCER = "falsing_manager_enforce_bouncer";
-
- private static final int[] CLASSIFIER_SENSORS = new int[] {
- Sensor.TYPE_PROXIMITY,
- };
-
- private static final int[] COLLECTOR_SENSORS = new int[] {
- Sensor.TYPE_ACCELEROMETER,
- Sensor.TYPE_GYROSCOPE,
- Sensor.TYPE_PROXIMITY,
- Sensor.TYPE_LIGHT,
- Sensor.TYPE_ROTATION_VECTOR,
- };
- public static final String FALSING_REMAIN_LOCKED = "falsing_failure_after_attempts";
- public static final String FALSING_SUCCESS = "falsing_success_after_attempts";
-
- private final Handler mHandler = new Handler(Looper.getMainLooper());
- private final Context mContext;
-
- private final SensorManager mSensorManager;
- private final DataCollector mDataCollector;
- private final HumanInteractionClassifier mHumanInteractionClassifier;
- private final AccessibilityManager mAccessibilityManager;
- private final Executor mUiBgExecutor;
-
- private boolean mEnforceBouncer = false;
- private boolean mBouncerOn = false;
- private boolean mBouncerOffOnDown = false;
- private boolean mSessionActive = false;
- private boolean mIsTouchScreen = true;
- private boolean mJustUnlockedWithFace = false;
- private int mState = StatusBarState.SHADE;
- private boolean mScreenOn;
- private boolean mShowingAod;
- private Runnable mPendingWtf;
- private int mIsFalseTouchCalls;
- private MetricsLogger mMetricsLogger;
-
- private SensorEventListener mSensorEventListener = new SensorEventListener() {
- @Override
- public synchronized void onSensorChanged(SensorEvent event) {
- mDataCollector.onSensorChanged(event);
- mHumanInteractionClassifier.onSensorChanged(event);
- }
-
- @Override
- public void onAccuracyChanged(Sensor sensor, int accuracy) {
- mDataCollector.onAccuracyChanged(sensor, accuracy);
- }
- };
-
- public StateListener mStatusBarStateListener = new StateListener() {
- @Override
- public void onStateChanged(int newState) {
- if (FalsingLog.ENABLED) {
- FalsingLog.i("setStatusBarState", new StringBuilder()
- .append("from=").append(StatusBarState.toShortString(mState))
- .append(" to=").append(StatusBarState.toShortString(newState))
- .toString());
- }
- mState = newState;
- updateSessionActive();
- }
- };
-
- protected final ContentObserver mSettingsObserver = new ContentObserver(mHandler) {
- @Override
- public void onChange(boolean selfChange) {
- updateConfiguration();
- }
- };
- private final KeyguardUpdateMonitorCallback mKeyguardUpdateCallback =
- new KeyguardUpdateMonitorCallback() {
- @Override
- public void onBiometricAuthenticated(int userId,
- BiometricSourceType biometricSourceType,
- boolean isStrongBiometric) {
- if (userId == KeyguardUpdateMonitor.getCurrentUser()
- && biometricSourceType == BiometricSourceType.FACE) {
- mJustUnlockedWithFace = true;
- }
- }
- };
-
- FalsingManagerImpl(Context context, @UiBackground Executor uiBgExecutor) {
- mContext = context;
- mSensorManager = Dependency.get(AsyncSensorManager.class);
- mAccessibilityManager = context.getSystemService(AccessibilityManager.class);
- mDataCollector = DataCollector.getInstance(mContext);
- mHumanInteractionClassifier = HumanInteractionClassifier.getInstance(mContext);
- mUiBgExecutor = uiBgExecutor;
- mScreenOn = context.getSystemService(PowerManager.class).isInteractive();
- mMetricsLogger = new MetricsLogger();
-
- mContext.getContentResolver().registerContentObserver(
- Settings.Secure.getUriFor(ENFORCE_BOUNCER), false,
- mSettingsObserver,
- UserHandle.USER_ALL);
-
- updateConfiguration();
- Dependency.get(StatusBarStateController.class).addCallback(mStatusBarStateListener);
- Dependency.get(KeyguardUpdateMonitor.class).registerCallback(mKeyguardUpdateCallback);
- }
-
- private void updateConfiguration() {
- mEnforceBouncer = 0 != Settings.Secure.getInt(mContext.getContentResolver(),
- ENFORCE_BOUNCER, 0);
- }
-
- private boolean shouldSessionBeActive() {
- if (FalsingLog.ENABLED && FalsingLog.VERBOSE) {
- FalsingLog.v("shouldBeActive", new StringBuilder()
- .append("enabled=").append(isEnabled() ? 1 : 0)
- .append(" mScreenOn=").append(mScreenOn ? 1 : 0)
- .append(" mState=").append(StatusBarState.toShortString(mState))
- .append(" mShowingAod=").append(mShowingAod ? 1 : 0)
- .toString()
- );
- }
- return isEnabled() && mScreenOn && (mState == StatusBarState.KEYGUARD) && !mShowingAod;
- }
-
- private boolean sessionEntrypoint() {
- if (!mSessionActive && shouldSessionBeActive()) {
- onSessionStart();
- return true;
- }
- return false;
- }
-
- private void sessionExitpoint(boolean force) {
- if (mSessionActive && (force || !shouldSessionBeActive())) {
- mSessionActive = false;
- if (mIsFalseTouchCalls != 0) {
- if (FalsingLog.ENABLED) {
- FalsingLog.i(
- "isFalseTouchCalls", "Calls before failure: " + mIsFalseTouchCalls);
- }
- mMetricsLogger.histogram(FALSING_REMAIN_LOCKED, mIsFalseTouchCalls);
- mIsFalseTouchCalls = 0;
- }
-
- // This can be expensive, and doesn't need to happen on the main thread.
- mUiBgExecutor.execute(() -> {
- mSensorManager.unregisterListener(mSensorEventListener);
- });
- }
- }
-
- public void updateSessionActive() {
- if (shouldSessionBeActive()) {
- sessionEntrypoint();
- } else {
- sessionExitpoint(false /* force */);
- }
- }
-
- private void onSessionStart() {
- if (FalsingLog.ENABLED) {
- FalsingLog.i("onSessionStart", "classifierEnabled=" + isClassifierEnabled());
- clearPendingWtf();
- }
- mBouncerOn = false;
- mSessionActive = true;
- mJustUnlockedWithFace = false;
- mIsFalseTouchCalls = 0;
-
- if (mHumanInteractionClassifier.isEnabled()) {
- registerSensors(CLASSIFIER_SENSORS);
- }
- if (mDataCollector.isEnabledFull()) {
- registerSensors(COLLECTOR_SENSORS);
- }
- if (mDataCollector.isEnabled()) {
- mDataCollector.onFalsingSessionStarted();
- }
- }
-
- private void registerSensors(int [] sensors) {
- for (int sensorType : sensors) {
- Sensor s = mSensorManager.getDefaultSensor(sensorType);
- if (s != null) {
-
- // This can be expensive, and doesn't need to happen on the main thread.
- mUiBgExecutor.execute(() -> {
- mSensorManager.registerListener(
- mSensorEventListener, s, SensorManager.SENSOR_DELAY_GAME);
- });
- }
- }
- }
-
- public boolean isClassifierEnabled() {
- return mHumanInteractionClassifier.isEnabled();
- }
-
- private boolean isEnabled() {
- return mHumanInteractionClassifier.isEnabled() || mDataCollector.isEnabled();
- }
-
- public boolean isUnlockingDisabled() {
- return mDataCollector.isUnlockingDisabled();
- }
- /**
- * @return true if the classifier determined that this is not a human interacting with the phone
- */
- public boolean isFalseTouch(@Classifier.InteractionType int interactionType) {
- if (FalsingLog.ENABLED) {
- // We're getting some false wtfs from touches that happen after the device went
- // to sleep. Only report missing sessions that happen when the device is interactive.
- if (!mSessionActive && mContext.getSystemService(PowerManager.class).isInteractive()
- && mPendingWtf == null) {
- int enabled = isEnabled() ? 1 : 0;
- int screenOn = mScreenOn ? 1 : 0;
- String state = StatusBarState.toShortString(mState);
- Throwable here = new Throwable("here");
- FalsingLog.wLogcat("isFalseTouch", new StringBuilder()
- .append("Session is not active, yet there's a query for a false touch.")
- .append(" enabled=").append(enabled)
- .append(" mScreenOn=").append(screenOn)
- .append(" mState=").append(state)
- .append(". Escalating to WTF if screen does not turn on soon.")
- .toString());
-
- // Unfortunately we're also getting false positives for touches that happen right
- // after the screen turns on, but before that notification has made it to us.
- // Unfortunately there's no good way to catch that, except to wait and see if we get
- // the screen on notification soon.
- mPendingWtf = () -> FalsingLog.wtf("isFalseTouch", new StringBuilder()
- .append("Session did not become active after query for a false touch.")
- .append(" enabled=").append(enabled)
- .append('/').append(isEnabled() ? 1 : 0)
- .append(" mScreenOn=").append(screenOn)
- .append('/').append(mScreenOn ? 1 : 0)
- .append(" mState=").append(state)
- .append('/').append(StatusBarState.toShortString(mState))
- .append(". Look for warnings ~1000ms earlier to see root cause.")
- .toString(), here);
- mHandler.postDelayed(mPendingWtf, 1000);
- }
- }
- if (ActivityManager.isRunningInUserTestHarness()) {
- // This is a test device running UiAutomator code.
- return false;
- }
- if (mAccessibilityManager.isTouchExplorationEnabled()) {
- // Touch exploration triggers false positives in the classifier and
- // already sufficiently prevents false unlocks.
- return false;
- }
- if (!mIsTouchScreen) {
- // Unlocking with input devices besides the touchscreen should already be sufficiently
- // anti-falsed.
- return false;
- }
- if (mJustUnlockedWithFace) {
- // Unlocking with face is a strong user presence signal, we can assume the user
- // is present until the next session starts.
- return false;
- }
- mIsFalseTouchCalls++;
- boolean isFalse = mHumanInteractionClassifier.isFalseTouch();
- if (!isFalse) {
- if (FalsingLog.ENABLED) {
- FalsingLog.i("isFalseTouchCalls", "Calls before success: " + mIsFalseTouchCalls);
- }
- mMetricsLogger.histogram(FALSING_SUCCESS, mIsFalseTouchCalls);
- mIsFalseTouchCalls = 0;
- }
- return isFalse;
- }
-
- private void clearPendingWtf() {
- if (mPendingWtf != null) {
- mHandler.removeCallbacks(mPendingWtf);
- mPendingWtf = null;
- }
- }
-
-
- public boolean shouldEnforceBouncer() {
- return mEnforceBouncer;
- }
-
- public void setShowingAod(boolean showingAod) {
- mShowingAod = showingAod;
- updateSessionActive();
- }
-
- public void onScreenTurningOn() {
- if (FalsingLog.ENABLED) {
- FalsingLog.i("onScreenTurningOn", new StringBuilder()
- .append("from=").append(mScreenOn ? 1 : 0)
- .toString());
- clearPendingWtf();
- }
- mScreenOn = true;
- if (sessionEntrypoint()) {
- mDataCollector.onScreenTurningOn();
- }
- }
-
- public void onScreenOnFromTouch() {
- if (FalsingLog.ENABLED) {
- FalsingLog.i("onScreenOnFromTouch", new StringBuilder()
- .append("from=").append(mScreenOn ? 1 : 0)
- .toString());
- }
- mScreenOn = true;
- if (sessionEntrypoint()) {
- mDataCollector.onScreenOnFromTouch();
- }
- }
-
- public void onScreenOff() {
- if (FalsingLog.ENABLED) {
- FalsingLog.i("onScreenOff", new StringBuilder()
- .append("from=").append(mScreenOn ? 1 : 0)
- .toString());
- }
- mDataCollector.onScreenOff();
- mScreenOn = false;
- sessionExitpoint(false /* force */);
- }
-
- public void onSuccessfulUnlock() {
- if (FalsingLog.ENABLED) {
- FalsingLog.i("onSucccessfulUnlock", "");
- }
- mDataCollector.onSucccessfulUnlock();
- }
-
- public void onBouncerShown() {
- if (FalsingLog.ENABLED) {
- FalsingLog.i("onBouncerShown", new StringBuilder()
- .append("from=").append(mBouncerOn ? 1 : 0)
- .toString());
- }
- if (!mBouncerOn) {
- mBouncerOn = true;
- mDataCollector.onBouncerShown();
- }
- }
-
- public void onBouncerHidden() {
- if (FalsingLog.ENABLED) {
- FalsingLog.i("onBouncerHidden", new StringBuilder()
- .append("from=").append(mBouncerOn ? 1 : 0)
- .toString());
- }
- if (mBouncerOn) {
- mBouncerOn = false;
- mDataCollector.onBouncerHidden();
- }
- }
-
- public void onQsDown() {
- if (FalsingLog.ENABLED) {
- FalsingLog.i("onQsDown", "");
- }
- mHumanInteractionClassifier.setType(Classifier.QUICK_SETTINGS);
- mDataCollector.onQsDown();
- }
-
- public void setQsExpanded(boolean expanded) {
- mDataCollector.setQsExpanded(expanded);
- }
-
- public void onTrackingStarted(boolean secure) {
- if (FalsingLog.ENABLED) {
- FalsingLog.i("onTrackingStarted", "");
- }
- mHumanInteractionClassifier.setType(secure
- ? Classifier.BOUNCER_UNLOCK : Classifier.UNLOCK);
- mDataCollector.onTrackingStarted();
- }
-
- public void onTrackingStopped() {
- mDataCollector.onTrackingStopped();
- }
-
- public void onNotificationActive() {
- mDataCollector.onNotificationActive();
- }
-
- public void onNotificationDoubleTap(boolean accepted, float dx, float dy) {
- if (FalsingLog.ENABLED) {
- FalsingLog.i("onNotificationDoubleTap", "accepted=" + accepted
- + " dx=" + dx + " dy=" + dy + " (px)");
- }
- mDataCollector.onNotificationDoubleTap();
- }
-
- public void setNotificationExpanded() {
- mDataCollector.setNotificationExpanded();
- }
-
- public void onNotificatonStartDraggingDown() {
- if (FalsingLog.ENABLED) {
- FalsingLog.i("onNotificatonStartDraggingDown", "");
- }
- mHumanInteractionClassifier.setType(Classifier.NOTIFICATION_DRAG_DOWN);
- mDataCollector.onNotificatonStartDraggingDown();
- }
-
- public void onStartExpandingFromPulse() {
- if (FalsingLog.ENABLED) {
- FalsingLog.i("onStartExpandingFromPulse", "");
- }
- mHumanInteractionClassifier.setType(Classifier.PULSE_EXPAND);
- mDataCollector.onStartExpandingFromPulse();
- }
-
- public void onNotificatonStopDraggingDown() {
- mDataCollector.onNotificatonStopDraggingDown();
- }
-
- public void onExpansionFromPulseStopped() {
- mDataCollector.onExpansionFromPulseStopped();
- }
-
- public void onNotificationDismissed() {
- mDataCollector.onNotificationDismissed();
- }
-
- public void onNotificationStartDismissing() {
- if (FalsingLog.ENABLED) {
- FalsingLog.i("onNotificationStartDismissing", "");
- }
- mHumanInteractionClassifier.setType(Classifier.NOTIFICATION_DISMISS);
- mDataCollector.onNotificatonStartDismissing();
- }
-
- public void onNotificationStopDismissing() {
- mDataCollector.onNotificatonStopDismissing();
- }
-
- public void onCameraOn() {
- mDataCollector.onCameraOn();
- }
-
- public void onLeftAffordanceOn() {
- mDataCollector.onLeftAffordanceOn();
- }
-
- public void onAffordanceSwipingStarted(boolean rightCorner) {
- if (FalsingLog.ENABLED) {
- FalsingLog.i("onAffordanceSwipingStarted", "");
- }
- if (rightCorner) {
- mHumanInteractionClassifier.setType(Classifier.RIGHT_AFFORDANCE);
- } else {
- mHumanInteractionClassifier.setType(Classifier.LEFT_AFFORDANCE);
- }
- mDataCollector.onAffordanceSwipingStarted(rightCorner);
- }
-
- public void onAffordanceSwipingAborted() {
- mDataCollector.onAffordanceSwipingAborted();
- }
-
- public void onUnlockHintStarted() {
- mDataCollector.onUnlockHintStarted();
- }
-
- public void onCameraHintStarted() {
- mDataCollector.onCameraHintStarted();
- }
-
- public void onLeftAffordanceHintStarted() {
- mDataCollector.onLeftAffordanceHintStarted();
- }
-
- public void onTouchEvent(MotionEvent event, int width, int height) {
- if (event.getAction() == MotionEvent.ACTION_DOWN) {
- mIsTouchScreen = event.isFromSource(InputDevice.SOURCE_TOUCHSCREEN);
- // If the bouncer was not shown during the down event,
- // we want the entire gesture going to HumanInteractionClassifier
- mBouncerOffOnDown = !mBouncerOn;
- }
- if (mSessionActive) {
- if (!mBouncerOn) {
- // In case bouncer is "visible", but onFullyShown has not yet been called,
- // avoid adding the event to DataCollector
- mDataCollector.onTouchEvent(event, width, height);
- }
- if (mBouncerOffOnDown) {
- mHumanInteractionClassifier.onTouchEvent(event);
- }
- }
- }
-
- public void dump(PrintWriter pw) {
- pw.println("FALSING MANAGER");
- pw.print("classifierEnabled="); pw.println(isClassifierEnabled() ? 1 : 0);
- pw.print("mSessionActive="); pw.println(mSessionActive ? 1 : 0);
- pw.print("mBouncerOn="); pw.println(mSessionActive ? 1 : 0);
- pw.print("mState="); pw.println(StatusBarState.toShortString(mState));
- pw.print("mScreenOn="); pw.println(mScreenOn ? 1 : 0);
- pw.println();
- }
-
- @Override
- public void cleanup() {
- mSensorManager.unregisterListener(mSensorEventListener);
- mContext.getContentResolver().unregisterContentObserver(mSettingsObserver);
- Dependency.get(StatusBarStateController.class).removeCallback(mStatusBarStateListener);
- Dependency.get(KeyguardUpdateMonitor.class).removeCallback(mKeyguardUpdateCallback);
- }
-
- public Uri reportRejectedTouch() {
- if (mDataCollector.isEnabled()) {
- return mDataCollector.reportRejectedTouch();
- }
- return null;
- }
-
- public boolean isReportingEnabled() {
- return mDataCollector.isReportingEnabled();
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/FalsingManagerProxy.java b/packages/SystemUI/src/com/android/systemui/classifier/FalsingManagerProxy.java
index 2c31862e9b79..814fff9c6d43 100644
--- a/packages/SystemUI/src/com/android/systemui/classifier/FalsingManagerProxy.java
+++ b/packages/SystemUI/src/com/android/systemui/classifier/FalsingManagerProxy.java
@@ -16,13 +16,13 @@
package com.android.systemui.classifier;
-import static com.android.internal.config.sysui.SystemUiDeviceConfigFlags.BRIGHTLINE_FALSING_MANAGER_ENABLED;
-
import android.content.Context;
+import android.content.res.Resources;
import android.hardware.SensorManager;
import android.net.Uri;
import android.provider.DeviceConfig;
import android.view.MotionEvent;
+import android.view.ViewConfiguration;
import androidx.annotation.NonNull;
@@ -33,7 +33,6 @@ import com.android.systemui.classifier.brightline.BrightLineFalsingManager;
import com.android.systemui.classifier.brightline.FalsingDataProvider;
import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.dagger.qualifiers.Main;
-import com.android.systemui.dagger.qualifiers.UiBackground;
import com.android.systemui.dock.DockManager;
import com.android.systemui.dump.DumpManager;
import com.android.systemui.plugins.FalsingManager;
@@ -53,52 +52,63 @@ import javax.inject.Inject;
/**
* Simple passthrough implementation of {@link FalsingManager} allowing plugins to swap in.
*
- * {@link FalsingManagerImpl} is used when a Plugin is not loaded.
+ * {@link BrightLineFalsingManager} is used when a Plugin is not loaded.
*/
@SysUISingleton
public class FalsingManagerProxy implements FalsingManager, Dumpable {
private static final String PROXIMITY_SENSOR_TAG = "FalsingManager";
+ private static final String DUMPABLE_TAG = "FalsingManager";
+ public static final String FALSING_REMAIN_LOCKED = "falsing_failure_after_attempts";
+ public static final String FALSING_SUCCESS = "falsing_success_after_attempts";
+ private final PluginManager mPluginManager;
private final ProximitySensor mProximitySensor;
+ private final Resources mResources;
+ private final ViewConfiguration mViewConfiguration;
private final FalsingDataProvider mFalsingDataProvider;
- private FalsingManager mInternalFalsingManager;
- private DeviceConfig.OnPropertiesChangedListener mDeviceConfigListener;
private final DeviceConfigProxy mDeviceConfig;
- private boolean mBrightlineEnabled;
private final DockManager mDockManager;
private final KeyguardUpdateMonitor mKeyguardUpdateMonitor;
- private Executor mUiBgExecutor;
+ private final DumpManager mDumpManager;
private final StatusBarStateController mStatusBarStateController;
+ final PluginListener<FalsingPlugin> mPluginListener;
+
+ private FalsingManager mInternalFalsingManager;
+
+ private final DeviceConfig.OnPropertiesChangedListener mDeviceConfigListener =
+ properties -> onDeviceConfigPropertiesChanged(properties.getNamespace());
@Inject
- FalsingManagerProxy(Context context, PluginManager pluginManager, @Main Executor executor,
+ FalsingManagerProxy(PluginManager pluginManager, @Main Executor executor,
ProximitySensor proximitySensor,
DeviceConfigProxy deviceConfig, DockManager dockManager,
KeyguardUpdateMonitor keyguardUpdateMonitor,
DumpManager dumpManager,
- @UiBackground Executor uiBgExecutor,
StatusBarStateController statusBarStateController,
+ @Main Resources resources,
+ ViewConfiguration viewConfiguration,
FalsingDataProvider falsingDataProvider) {
+ mPluginManager = pluginManager;
mProximitySensor = proximitySensor;
mDockManager = dockManager;
mKeyguardUpdateMonitor = keyguardUpdateMonitor;
- mUiBgExecutor = uiBgExecutor;
+ mDumpManager = dumpManager;
mStatusBarStateController = statusBarStateController;
+ mResources = resources;
+ mViewConfiguration = viewConfiguration;
mFalsingDataProvider = falsingDataProvider;
mProximitySensor.setTag(PROXIMITY_SENSOR_TAG);
mProximitySensor.setDelay(SensorManager.SENSOR_DELAY_GAME);
mDeviceConfig = deviceConfig;
- mDeviceConfigListener =
- properties -> onDeviceConfigPropertiesChanged(context, properties.getNamespace());
- setupFalsingManager(context);
+ setupFalsingManager();
mDeviceConfig.addOnPropertiesChangedListener(
DeviceConfig.NAMESPACE_SYSTEMUI,
executor,
mDeviceConfigListener
);
- final PluginListener<FalsingPlugin> mPluginListener = new PluginListener<FalsingPlugin>() {
+ mPluginListener = new PluginListener<FalsingPlugin>() {
public void onPluginConnected(FalsingPlugin plugin, Context context) {
FalsingManager pluginFalsingManager = plugin.getFalsingManager(context);
if (pluginFalsingManager != null) {
@@ -108,49 +118,42 @@ public class FalsingManagerProxy implements FalsingManager, Dumpable {
}
public void onPluginDisconnected(FalsingPlugin plugin) {
- mInternalFalsingManager = new FalsingManagerImpl(context, mUiBgExecutor);
+ setupFalsingManager();
}
};
- pluginManager.addPluginListener(mPluginListener, FalsingPlugin.class);
+ mPluginManager.addPluginListener(mPluginListener, FalsingPlugin.class);
- dumpManager.registerDumpable("FalsingManager", this);
+ mDumpManager.registerDumpable(DUMPABLE_TAG, this);
}
- private void onDeviceConfigPropertiesChanged(Context context, String namespace) {
+ private void onDeviceConfigPropertiesChanged(String namespace) {
if (!DeviceConfig.NAMESPACE_SYSTEMUI.equals(namespace)) {
return;
}
- setupFalsingManager(context);
+ setupFalsingManager();
}
/**
- * Chooses the FalsingManager implementation.
+ * Setup the FalsingManager implementation.
+ *
+ * If multiple implementations are available, this is where the choice is made.
*/
- private void setupFalsingManager(Context context) {
- boolean brightlineEnabled = mDeviceConfig.getBoolean(
- DeviceConfig.NAMESPACE_SYSTEMUI, BRIGHTLINE_FALSING_MANAGER_ENABLED, true);
- if (brightlineEnabled == mBrightlineEnabled && mInternalFalsingManager != null) {
- return;
- }
- mBrightlineEnabled = brightlineEnabled;
-
+ private void setupFalsingManager() {
if (mInternalFalsingManager != null) {
mInternalFalsingManager.cleanup();
}
- if (!brightlineEnabled) {
- mInternalFalsingManager = new FalsingManagerImpl(context, mUiBgExecutor);
- } else {
- mInternalFalsingManager = new BrightLineFalsingManager(
- mFalsingDataProvider,
- mKeyguardUpdateMonitor,
- mProximitySensor,
- mDeviceConfig,
- mDockManager,
- mStatusBarStateController
- );
- }
+ mInternalFalsingManager = new BrightLineFalsingManager(
+ mFalsingDataProvider,
+ mKeyguardUpdateMonitor,
+ mProximitySensor,
+ mDeviceConfig,
+ mResources,
+ mViewConfiguration,
+ mDockManager,
+ mStatusBarStateController
+ );
}
/**
@@ -191,6 +194,17 @@ public class FalsingManagerProxy implements FalsingManager, Dumpable {
return mInternalFalsingManager.isFalseTouch(interactionType);
}
+
+ @Override
+ public boolean isFalseTap(boolean robustCheck) {
+ return mInternalFalsingManager.isFalseTap(robustCheck);
+ }
+
+ @Override
+ public boolean isFalseDoubleTap() {
+ return mInternalFalsingManager.isFalseDoubleTap();
+ }
+
@Override
public void onNotificatonStopDraggingDown() {
mInternalFalsingManager.onNotificatonStartDraggingDown();
@@ -338,17 +352,14 @@ public class FalsingManagerProxy implements FalsingManager, Dumpable {
@Override
public void dump(@NonNull FileDescriptor fd, @NonNull PrintWriter pw, @NonNull String[] args) {
- mInternalFalsingManager.dump(pw);
- }
-
- @Override
- public void dump(PrintWriter pw) {
- mInternalFalsingManager.dump(pw);
+ mInternalFalsingManager.dump(fd, pw, args);
}
@Override
public void cleanup() {
mDeviceConfig.removeOnPropertiesChangedListener(mDeviceConfigListener);
+ mPluginManager.removePluginListener(mPluginListener);
+ mDumpManager.unregisterDumpable(DUMPABLE_TAG);
mInternalFalsingManager.cleanup();
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/GestureClassifier.java b/packages/SystemUI/src/com/android/systemui/classifier/GestureClassifier.java
deleted file mode 100644
index 11388fc49594..000000000000
--- a/packages/SystemUI/src/com/android/systemui/classifier/GestureClassifier.java
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-package com.android.systemui.classifier;
-
-/**
- * An abstract class for classifiers which classify the whole gesture (all the strokes which
- * occurred from DOWN event to UP/CANCEL event)
- */
-public abstract class GestureClassifier extends Classifier {
-
- /**
- * @param type the type of action for which this method is called
- * @return a non-negative value which is used to determine whether the most recent gesture is a
- * false interaction; the bigger the value the greater the chance that this a false
- * interaction.
- */
- public abstract float getFalseTouchEvaluation(int type);
-}
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/HistoryEvaluator.java b/packages/SystemUI/src/com/android/systemui/classifier/HistoryEvaluator.java
deleted file mode 100644
index 4c647118a105..000000000000
--- a/packages/SystemUI/src/com/android/systemui/classifier/HistoryEvaluator.java
+++ /dev/null
@@ -1,117 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-package com.android.systemui.classifier;
-
-import android.os.SystemClock;
-
-import java.util.ArrayList;
-
-/**
- * Holds the evaluations for ended strokes and gestures. These values are decreased through time.
- */
-public class HistoryEvaluator {
- private static final float INTERVAL = 50.0f;
- private static final float HISTORY_FACTOR = 0.9f;
- private static final float EPSILON = 1e-5f;
-
- private final ArrayList<Data> mStrokes = new ArrayList<>();
- private final ArrayList<Data> mGestureWeights = new ArrayList<>();
- private long mLastUpdate;
-
- public HistoryEvaluator() {
- mLastUpdate = SystemClock.elapsedRealtime();
- }
-
- public void addStroke(float evaluation) {
- decayValue();
- mStrokes.add(new Data(evaluation));
- }
-
- public void addGesture(float evaluation) {
- decayValue();
- mGestureWeights.add(new Data(evaluation));
- }
-
- /**
- * Calculates the weighted average of strokes and adds to it the weighted average of gestures
- */
- public float getEvaluation() {
- return weightedAverage(mStrokes) + weightedAverage(mGestureWeights);
- }
-
- private float weightedAverage(ArrayList<Data> list) {
- float sumValue = 0.0f;
- float sumWeight = 0.0f;
- int size = list.size();
- for (int i = 0; i < size; i++) {
- Data data = list.get(i);
- sumValue += data.evaluation * data.weight;
- sumWeight += data.weight;
- }
-
- if (sumWeight == 0.0f) {
- return 0.0f;
- }
-
- return sumValue / sumWeight;
- }
-
- private void decayValue() {
- long time = SystemClock.elapsedRealtime();
-
- if (time <= mLastUpdate) {
- return;
- }
-
- // All weights are multiplied by HISTORY_FACTOR after each INTERVAL milliseconds.
- float factor = (float) Math.pow(HISTORY_FACTOR, (time - mLastUpdate) / INTERVAL);
-
- decayValue(mStrokes, factor);
- decayValue(mGestureWeights, factor);
- mLastUpdate = time;
- }
-
- private void decayValue(ArrayList<Data> list, float factor) {
- int size = list.size();
- for (int i = 0; i < size; i++) {
- list.get(i).weight *= factor;
- }
-
- // Removing evaluations with such small weights that they do not matter anymore
- while (!list.isEmpty() && isZero(list.get(0).weight)) {
- list.remove(0);
- }
- }
-
- private boolean isZero(float x) {
- return x <= EPSILON && x >= -EPSILON;
- }
-
- /**
- * For each stroke it holds its initial value and the current weight. Initially the
- * weight is set to 1.0
- */
- private static class Data {
- public float evaluation;
- public float weight;
-
- public Data(float evaluation) {
- this.evaluation = evaluation;
- weight = 1.0f;
- }
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/HumanInteractionClassifier.java b/packages/SystemUI/src/com/android/systemui/classifier/HumanInteractionClassifier.java
deleted file mode 100644
index 86dccb222875..000000000000
--- a/packages/SystemUI/src/com/android/systemui/classifier/HumanInteractionClassifier.java
+++ /dev/null
@@ -1,241 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-package com.android.systemui.classifier;
-
-import android.content.Context;
-import android.database.ContentObserver;
-import android.hardware.SensorEvent;
-import android.os.Handler;
-import android.os.Looper;
-import android.os.UserHandle;
-import android.provider.Settings;
-import android.util.DisplayMetrics;
-import android.view.MotionEvent;
-
-import com.android.systemui.R;
-
-import java.util.ArrayDeque;
-
-/**
- * An classifier trying to determine whether it is a human interacting with the phone or not.
- */
-public class HumanInteractionClassifier extends Classifier {
- private static final String HIC_ENABLE = "HIC_enable";
- private static final float FINGER_DISTANCE = 0.1f;
-
- private static HumanInteractionClassifier sInstance = null;
-
- private final Handler mHandler = new Handler(Looper.getMainLooper());
- private final Context mContext;
-
- private final StrokeClassifier[] mStrokeClassifiers;
- private final GestureClassifier[] mGestureClassifiers;
- private final ArrayDeque<MotionEvent> mBufferedEvents = new ArrayDeque<>();
- private final HistoryEvaluator mHistoryEvaluator;
- private final float mDpi;
-
- private boolean mEnableClassifier = false;
- private int mCurrentType = Classifier.GENERIC;
-
- protected final ContentObserver mSettingsObserver = new ContentObserver(mHandler) {
- @Override
- public void onChange(boolean selfChange) {
- updateConfiguration();
- }
- };
-
- private HumanInteractionClassifier(Context context) {
- mContext = context;
- DisplayMetrics displayMetrics = mContext.getResources().getDisplayMetrics();
-
- // If the phone is rotated to landscape, the calculations would be wrong if xdpi and ydpi
- // were to be used separately. Due negligible differences in xdpi and ydpi we can just
- // take the average.
- // Note that xdpi and ydpi are the physical pixels per inch and are not affected by scaling.
- mDpi = (displayMetrics.xdpi + displayMetrics.ydpi) / 2.0f;
- mClassifierData = new ClassifierData(mDpi);
- mHistoryEvaluator = new HistoryEvaluator();
-
- mStrokeClassifiers = new StrokeClassifier[]{
- new AnglesClassifier(mClassifierData),
- new SpeedClassifier(mClassifierData),
- new DurationCountClassifier(mClassifierData),
- new EndPointRatioClassifier(mClassifierData),
- new EndPointLengthClassifier(mClassifierData),
- new AccelerationClassifier(mClassifierData),
- new SpeedAnglesClassifier(mClassifierData),
- new LengthCountClassifier(mClassifierData),
- new DirectionClassifier(mClassifierData),
- };
-
- mGestureClassifiers = new GestureClassifier[] {
- new PointerCountClassifier(mClassifierData),
- new ProximityClassifier(mClassifierData)
- };
-
- mContext.getContentResolver().registerContentObserver(
- Settings.Global.getUriFor(HIC_ENABLE), false,
- mSettingsObserver,
- UserHandle.USER_ALL);
-
- updateConfiguration();
- }
-
- public static HumanInteractionClassifier getInstance(Context context) {
- if (sInstance == null) {
- sInstance = new HumanInteractionClassifier(context);
- }
- return sInstance;
- }
-
- private void updateConfiguration() {
- boolean defaultValue = mContext.getResources().getBoolean(
- R.bool.config_lockscreenAntiFalsingClassifierEnabled);
-
- mEnableClassifier = 0 != Settings.Global.getInt(
- mContext.getContentResolver(),
- HIC_ENABLE, defaultValue ? 1 : 0);
- }
-
- public void setType(int type) {
- mCurrentType = type;
- }
-
- @Override
- public void onTouchEvent(MotionEvent event) {
- if (!mEnableClassifier) {
- return;
- }
-
- // If the user is dragging down the notification, they might want to drag it down
- // enough to see the content, read it for a while and then lift the finger to open
- // the notification. This kind of motion scores very bad in the Classifier so the
- // MotionEvents which are close to the current position of the finger are not
- // sent to the classifiers until the finger moves far enough. When the finger if lifted
- // up, the last MotionEvent which was far enough from the finger is set as the final
- // MotionEvent and sent to the Classifiers.
- if (mCurrentType == Classifier.NOTIFICATION_DRAG_DOWN
- || mCurrentType == Classifier.PULSE_EXPAND) {
- mBufferedEvents.add(MotionEvent.obtain(event));
- Point pointEnd = new Point(event.getX() / mDpi, event.getY() / mDpi);
-
- while (pointEnd.dist(new Point(mBufferedEvents.getFirst().getX() / mDpi,
- mBufferedEvents.getFirst().getY() / mDpi)) > FINGER_DISTANCE) {
- addTouchEvent(mBufferedEvents.getFirst());
- mBufferedEvents.remove();
- }
-
- int action = event.getActionMasked();
- if (action == MotionEvent.ACTION_UP) {
- mBufferedEvents.getFirst().setAction(MotionEvent.ACTION_UP);
- addTouchEvent(mBufferedEvents.getFirst());
- mBufferedEvents.clear();
- }
- } else {
- addTouchEvent(event);
- }
- }
-
- private void addTouchEvent(MotionEvent event) {
- if (!mClassifierData.update(event)) {
- return;
- }
-
- for (StrokeClassifier c : mStrokeClassifiers) {
- c.onTouchEvent(event);
- }
-
- for (GestureClassifier c : mGestureClassifiers) {
- c.onTouchEvent(event);
- }
-
- int size = mClassifierData.getEndingStrokes().size();
- for (int i = 0; i < size; i++) {
- Stroke stroke = mClassifierData.getEndingStrokes().get(i);
- float evaluation = 0.0f;
- StringBuilder sb = FalsingLog.ENABLED ? new StringBuilder("stroke") : null;
- for (StrokeClassifier c : mStrokeClassifiers) {
- float e = c.getFalseTouchEvaluation(mCurrentType, stroke);
- if (FalsingLog.ENABLED) {
- String tag = c.getTag();
- sb.append(" ").append(e >= 1f ? tag : tag.toLowerCase()).append("=").append(e);
- }
- evaluation += e;
- }
-
- if (FalsingLog.ENABLED) {
- FalsingLog.i(" addTouchEvent", sb.toString());
- }
- mHistoryEvaluator.addStroke(evaluation);
- }
-
- int action = event.getActionMasked();
- if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_CANCEL) {
- float evaluation = 0.0f;
- StringBuilder sb = FalsingLog.ENABLED ? new StringBuilder("gesture") : null;
- for (GestureClassifier c : mGestureClassifiers) {
- float e = c.getFalseTouchEvaluation(mCurrentType);
- if (FalsingLog.ENABLED) {
- String tag = c.getTag();
- sb.append(" ").append(e >= 1f ? tag : tag.toLowerCase()).append("=").append(e);
- }
- evaluation += e;
- }
- if (FalsingLog.ENABLED) {
- FalsingLog.i(" addTouchEvent", sb.toString());
- }
- mHistoryEvaluator.addGesture(evaluation);
- setType(Classifier.GENERIC);
- }
-
- mClassifierData.cleanUp(event);
- }
-
- @Override
- public void onSensorChanged(SensorEvent event) {
- for (Classifier c : mStrokeClassifiers) {
- c.onSensorChanged(event);
- }
-
- for (Classifier c : mGestureClassifiers) {
- c.onSensorChanged(event);
- }
- }
-
- public boolean isFalseTouch() {
- if (mEnableClassifier) {
- float evaluation = mHistoryEvaluator.getEvaluation();
- boolean result = evaluation >= 5.0f;
- if (FalsingLog.ENABLED) {
- FalsingLog.i("isFalseTouch", new StringBuilder()
- .append("eval=").append(evaluation).append(" result=")
- .append(result ? 1 : 0).toString());
- }
- return result;
- }
- return false;
- }
-
- public boolean isEnabled() {
- return mEnableClassifier;
- }
-
- @Override
- public String getTag() {
- return "HIC";
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/LengthCountClassifier.java b/packages/SystemUI/src/com/android/systemui/classifier/LengthCountClassifier.java
deleted file mode 100644
index 53678a6d1730..000000000000
--- a/packages/SystemUI/src/com/android/systemui/classifier/LengthCountClassifier.java
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-package com.android.systemui.classifier;
-
-/**
- * A classifier which looks at the ratio between the length of the stroke and its number of
- * points. The number of points is subtracted by 2 because the UP event comes in with some delay
- * and it should not influence the ratio and also strokes which are long and have a small number
- * of points are punished more (these kind of strokes are usually bad ones and they tend to score
- * well in other classifiers).
- */
-public class LengthCountClassifier extends StrokeClassifier {
- public LengthCountClassifier(ClassifierData classifierData) {
- }
-
- @Override
- public String getTag() {
- return "LEN_CNT";
- }
-
- @Override
- public float getFalseTouchEvaluation(int type, Stroke stroke) {
- return LengthCountEvaluator.evaluate(stroke.getTotalLength()
- / Math.max(1.0f, stroke.getCount() - 2));
- }
-} \ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/LengthCountEvaluator.java b/packages/SystemUI/src/com/android/systemui/classifier/LengthCountEvaluator.java
deleted file mode 100644
index dac7a6f720a7..000000000000
--- a/packages/SystemUI/src/com/android/systemui/classifier/LengthCountEvaluator.java
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-package com.android.systemui.classifier;
-
-/**
- * A classifier which looks at the ratio between the length of the stroke and its number of
- * points.
- */
-public class LengthCountEvaluator {
- public static float evaluate(float value) {
- float evaluation = 0.0f;
- if (value < 0.09) evaluation++;
- if (value < 0.05) evaluation++;
- if (value < 0.02) evaluation++;
- if (value > 0.6) evaluation++;
- if (value > 0.9) evaluation++;
- if (value > 1.2) evaluation++;
- return evaluation;
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/Point.java b/packages/SystemUI/src/com/android/systemui/classifier/Point.java
deleted file mode 100644
index f3dc2be4144b..000000000000
--- a/packages/SystemUI/src/com/android/systemui/classifier/Point.java
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-package com.android.systemui.classifier;
-
-public class Point {
- public float x;
- public float y;
- public long timeOffsetNano;
-
- public Point(float x, float y) {
- this.x = x;
- this.y = y;
- this.timeOffsetNano = 0;
- }
-
- public Point(float x, float y, long timeOffsetNano) {
- this.x = x;
- this.y = y;
- this.timeOffsetNano = timeOffsetNano;
- }
-
- public boolean equals(Point p) {
- return x == p.x && y == p.y;
- }
-
- public float dist(Point a) {
- return (float) Math.hypot(a.x - x, a.y - y);
- }
-
- /**
- * Calculates the cross product of vec(this, a) and vec(this, b) where vec(x,y) is the
- * vector from point x to point y
- */
- public float crossProduct(Point a, Point b) {
- return (a.x - x) * (b.y - y) - (a.y - y) * (b.x - x);
- }
-
- /**
- * Calculates the dot product of vec(this, a) and vec(this, b) where vec(x,y) is the
- * vector from point x to point y
- */
- public float dotProduct(Point a, Point b) {
- return (a.x - x) * (b.x - x) + (a.y - y) * (b.y - y);
- }
-
- /**
- * Calculates the angle in radians created by points (a, this, b). If any two of these points
- * are the same, the method will return 0.0f
- *
- * @return the angle in radians
- */
- public float getAngle(Point a, Point b) {
- float dist1 = dist(a);
- float dist2 = dist(b);
-
- if (dist1 == 0.0f || dist2 == 0.0f) {
- return 0.0f;
- }
-
- float crossProduct = crossProduct(a, b);
- float dotProduct = dotProduct(a, b);
- float cos = Math.min(1.0f, Math.max(-1.0f, dotProduct / dist1 / dist2));
- float angle = (float) Math.acos(cos);
- if (crossProduct < 0.0) {
- angle = 2.0f * (float) Math.PI - angle;
- }
- return angle;
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/PointerCountClassifier.java b/packages/SystemUI/src/com/android/systemui/classifier/PointerCountClassifier.java
deleted file mode 100644
index 136c43345c9d..000000000000
--- a/packages/SystemUI/src/com/android/systemui/classifier/PointerCountClassifier.java
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-package com.android.systemui.classifier;
-
-import android.view.MotionEvent;
-
-/**
- * A classifier which looks at the total number of traces in the whole gesture.
- */
-public class PointerCountClassifier extends GestureClassifier {
- private int mCount;
-
- public PointerCountClassifier(ClassifierData classifierData) {
- mCount = 0;
- }
-
- @Override
- public String getTag() {
- return "PTR_CNT";
- }
-
- @Override
- public void onTouchEvent(MotionEvent event) {
- int action = event.getActionMasked();
-
- if (action == MotionEvent.ACTION_DOWN) {
- mCount = 1;
- }
-
- if (action == MotionEvent.ACTION_POINTER_DOWN) {
- ++mCount;
- }
- }
-
- @Override
- public float getFalseTouchEvaluation(int type) {
- return PointerCountEvaluator.evaluate(mCount);
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/ProximityClassifier.java b/packages/SystemUI/src/com/android/systemui/classifier/ProximityClassifier.java
deleted file mode 100644
index 62adfc85621b..000000000000
--- a/packages/SystemUI/src/com/android/systemui/classifier/ProximityClassifier.java
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-package com.android.systemui.classifier;
-
-import android.hardware.Sensor;
-import android.hardware.SensorEvent;
-import android.view.MotionEvent;
-
-/**
- * A classifier which looks at the proximity sensor during the gesture. It calculates the percentage
- * the proximity sensor showing the near state during the whole gesture
- */
-public class ProximityClassifier extends GestureClassifier {
- private long mGestureStartTimeNano;
- private long mNearStartTimeNano;
- private long mNearDuration;
- private boolean mNear;
- private float mAverageNear;
-
- public ProximityClassifier(ClassifierData classifierData) {
- }
-
- @Override
- public String getTag() {
- return "PROX";
- }
-
- @Override
- public void onSensorChanged(SensorEvent event) {
- if (event.sensor.getType() == Sensor.TYPE_PROXIMITY) {
- update(event.values[0] < event.sensor.getMaximumRange(), event.timestamp);
- }
- }
-
- @Override
- public void onTouchEvent(MotionEvent event) {
- int action = event.getActionMasked();
-
- if (action == MotionEvent.ACTION_DOWN) {
- mGestureStartTimeNano = event.getEventTimeNano();
- mNearStartTimeNano = event.getEventTimeNano();
- mNearDuration = 0;
- }
-
- if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_CANCEL) {
- update(mNear, event.getEventTimeNano());
- long duration = event.getEventTimeNano() - mGestureStartTimeNano;
-
- if (duration == 0) {
- mAverageNear = mNear ? 1.0f : 0.0f;
- } else {
- mAverageNear = (float) mNearDuration / (float) duration;
- }
- }
- }
-
-
- /**
- * @param near is the sensor showing the near state right now
- * @param timestampNano time of this event in nanoseconds
- */
- private void update(boolean near, long timestampNano) {
- // This if is necessary because MotionEvents and SensorEvents do not come in
- // chronological order
- if (timestampNano > mNearStartTimeNano) {
- // if the state before was near then add the difference of the current time and
- // mNearStartTimeNano to mNearDuration.
- if (mNear) {
- mNearDuration += timestampNano - mNearStartTimeNano;
- }
-
- // if the new state is near, set mNearStartTimeNano equal to this moment.
- if (near) {
- mNearStartTimeNano = timestampNano;
- }
- }
- mNear = near;
- }
-
- @Override
- public float getFalseTouchEvaluation(int type) {
- return ProximityEvaluator.evaluate(mAverageNear, type);
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/ProximityEvaluator.java b/packages/SystemUI/src/com/android/systemui/classifier/ProximityEvaluator.java
deleted file mode 100644
index 91002bf1291c..000000000000
--- a/packages/SystemUI/src/com/android/systemui/classifier/ProximityEvaluator.java
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-package com.android.systemui.classifier;
-
-public class ProximityEvaluator {
- public static float evaluate(float value, int type) {
- float evaluation = 0.0f;
- float threshold = 0.1f;
- if (type == Classifier.QUICK_SETTINGS) {
- threshold = 1.0f;
- }
- if (value >= threshold) evaluation += 2.0;
- return evaluation;
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/SpeedAnglesClassifier.java b/packages/SystemUI/src/com/android/systemui/classifier/SpeedAnglesClassifier.java
deleted file mode 100644
index 66f0cf68d8c1..000000000000
--- a/packages/SystemUI/src/com/android/systemui/classifier/SpeedAnglesClassifier.java
+++ /dev/null
@@ -1,164 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-package com.android.systemui.classifier;
-
-import android.os.Build;
-import android.os.SystemProperties;
-import android.view.MotionEvent;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-
-/**
- * A classifier which for each point from a stroke, it creates a point on plane with coordinates
- * (timeOffsetNano, distanceCoveredUpToThisPoint) (scaled by DURATION_SCALE and LENGTH_SCALE)
- * and then it calculates the angle variance of these points like the class
- * {@link AnglesClassifier} (without splitting it into two parts). The classifier ignores
- * the last point of a stroke because the UP event comes in with some delay and this ruins the
- * smoothness of this curve. Additionally, the classifier classifies calculates the percentage of
- * angles which value is in [PI - ANGLE_DEVIATION, 2* PI) interval. The reason why the classifier
- * does that is because the speed of a good stroke is most often increases, so most of these angels
- * should be in this interval.
- */
-public class SpeedAnglesClassifier extends StrokeClassifier {
- public static final boolean VERBOSE = SystemProperties.getBoolean("debug.falsing_log.spd_ang",
- Build.IS_DEBUGGABLE);
- public static final String TAG = "SPD_ANG";
-
- private HashMap<Stroke, Data> mStrokeMap = new HashMap<>();
-
- public SpeedAnglesClassifier(ClassifierData classifierData) {
- mClassifierData = classifierData;
- }
-
- @Override
- public String getTag() {
- return TAG;
- }
-
- @Override
- public void onTouchEvent(MotionEvent event) {
- int action = event.getActionMasked();
-
- if (action == MotionEvent.ACTION_DOWN) {
- mStrokeMap.clear();
- }
-
- for (int i = 0; i < event.getPointerCount(); i++) {
- Stroke stroke = mClassifierData.getStroke(event.getPointerId(i));
-
- if (mStrokeMap.get(stroke) == null) {
- mStrokeMap.put(stroke, new Data());
- }
-
- if (action != MotionEvent.ACTION_UP && action != MotionEvent.ACTION_CANCEL
- && !(action == MotionEvent.ACTION_POINTER_UP && i == event.getActionIndex())) {
- mStrokeMap.get(stroke).addPoint(
- stroke.getPoints().get(stroke.getPoints().size() - 1));
- }
- }
- }
-
- @Override
- public float getFalseTouchEvaluation(int type, Stroke stroke) {
- Data data = mStrokeMap.get(stroke);
- return SpeedVarianceEvaluator.evaluate(data.getAnglesVariance())
- + SpeedAnglesPercentageEvaluator.evaluate(data.getAnglesPercentage());
- }
-
- private static class Data {
- private final float DURATION_SCALE = 1e8f;
- private final float LENGTH_SCALE = 1.0f;
- private final float ANGLE_DEVIATION = (float) Math.PI / 10.0f;
-
- private List<Point> mLastThreePoints = new ArrayList<>();
- private Point mPreviousPoint;
- private float mPreviousAngle;
- private float mSumSquares;
- private float mSum;
- private float mCount;
- private float mDist;
- private float mAnglesCount;
- private float mAcceleratingAngles;
-
- public Data() {
- mPreviousPoint = null;
- mPreviousAngle = (float) Math.PI;
- mSumSquares = 0.0f;
- mSum = 0.0f;
- mCount = 1.0f;
- mDist = 0.0f;
- mAnglesCount = mAcceleratingAngles = 0.0f;
- }
-
- public void addPoint(Point point) {
- if (mPreviousPoint != null) {
- mDist += mPreviousPoint.dist(point);
- }
-
- mPreviousPoint = point;
- Point speedPoint = new Point((float) point.timeOffsetNano / DURATION_SCALE,
- mDist / LENGTH_SCALE);
-
- // Checking if the added point is different than the previously added point
- // Repetitions are being ignored so that proper angles are calculated.
- if (mLastThreePoints.isEmpty()
- || !mLastThreePoints.get(mLastThreePoints.size() - 1).equals(speedPoint)) {
- mLastThreePoints.add(speedPoint);
- if (mLastThreePoints.size() == 4) {
- mLastThreePoints.remove(0);
-
- float angle = mLastThreePoints.get(1).getAngle(mLastThreePoints.get(0),
- mLastThreePoints.get(2));
-
- mAnglesCount++;
- if (angle >= (float) Math.PI - ANGLE_DEVIATION) {
- mAcceleratingAngles++;
- }
-
- float difference = angle - mPreviousAngle;
- mSum += difference;
- mSumSquares += difference * difference;
- mCount += 1.0;
- mPreviousAngle = angle;
- }
- }
- }
-
- public float getAnglesVariance() {
- final float v = mSumSquares / mCount - (mSum / mCount) * (mSum / mCount);
- if (VERBOSE) {
- FalsingLog.i(TAG, "getAnglesVariance: sum^2=" + mSumSquares
- + " count=" + mCount + " result=" + v);
- }
- return v;
- }
-
- public float getAnglesPercentage() {
- if (mAnglesCount == 0.0f) {
- return 1.0f;
- }
- final float v = (mAcceleratingAngles) / mAnglesCount;
- if (VERBOSE) {
- FalsingLog.i(TAG, "getAnglesPercentage: angles=" + mAcceleratingAngles
- + " count=" + mAnglesCount + " result=" + v);
- }
- return v;
- }
- }
-} \ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/SpeedAnglesPercentageEvaluator.java b/packages/SystemUI/src/com/android/systemui/classifier/SpeedAnglesPercentageEvaluator.java
deleted file mode 100644
index d50d406f2fef..000000000000
--- a/packages/SystemUI/src/com/android/systemui/classifier/SpeedAnglesPercentageEvaluator.java
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-package com.android.systemui.classifier;
-
-public class SpeedAnglesPercentageEvaluator {
- public static float evaluate(float value) {
- float evaluation = 0.0f;
- if (value < 1.00) evaluation++;
- if (value < 0.90) evaluation++;
- if (value < 0.70) evaluation++;
- return evaluation;
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/SpeedClassifier.java b/packages/SystemUI/src/com/android/systemui/classifier/SpeedClassifier.java
deleted file mode 100644
index 01fcc377ddbd..000000000000
--- a/packages/SystemUI/src/com/android/systemui/classifier/SpeedClassifier.java
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-package com.android.systemui.classifier;
-
-/**
- * A classifier that looks at the speed of the stroke. It calculates the speed of a stroke in
- * inches per second.
- */
-public class SpeedClassifier extends StrokeClassifier {
- private final float NANOS_TO_SECONDS = 1e9f;
-
- public SpeedClassifier(ClassifierData classifierData) {
- }
-
- @Override
- public String getTag() {
- return "SPD";
- }
-
- @Override
- public float getFalseTouchEvaluation(int type, Stroke stroke) {
- float duration = (float) stroke.getDurationNanos() / NANOS_TO_SECONDS;
- if (duration == 0.0f) {
- return SpeedEvaluator.evaluate(0.0f);
- }
- return SpeedEvaluator.evaluate(stroke.getTotalLength() / duration);
- }
-} \ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/SpeedEvaluator.java b/packages/SystemUI/src/com/android/systemui/classifier/SpeedEvaluator.java
deleted file mode 100644
index afd8d0152172..000000000000
--- a/packages/SystemUI/src/com/android/systemui/classifier/SpeedEvaluator.java
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-package com.android.systemui.classifier;
-
-public class SpeedEvaluator {
- public static float evaluate(float value) {
- float evaluation = 0.0f;
- if (value < 4.0) evaluation++;
- if (value < 2.2) evaluation++;
- if (value > 35.0) evaluation++;
- if (value > 50.0) evaluation++;
- return evaluation;
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/SpeedRatioEvaluator.java b/packages/SystemUI/src/com/android/systemui/classifier/SpeedRatioEvaluator.java
deleted file mode 100644
index e34f222d3799..000000000000
--- a/packages/SystemUI/src/com/android/systemui/classifier/SpeedRatioEvaluator.java
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-package com.android.systemui.classifier;
-
-public class SpeedRatioEvaluator {
- public static float evaluate(float value) {
- float evaluation = 0.0f;
- if (value == 0) return 0;
- if (value <= 1.0) evaluation++;
- if (value <= 0.5) evaluation++;
- if (value > 9.0) evaluation++;
- if (value > 18.0) evaluation++;
- return evaluation;
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/SpeedVarianceEvaluator.java b/packages/SystemUI/src/com/android/systemui/classifier/SpeedVarianceEvaluator.java
deleted file mode 100644
index 48b1b6e0dbf1..000000000000
--- a/packages/SystemUI/src/com/android/systemui/classifier/SpeedVarianceEvaluator.java
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-package com.android.systemui.classifier;
-
-public class SpeedVarianceEvaluator {
- public static float evaluate(float value) {
- float evaluation = 0.0f;
- if (value > 0.06) evaluation++;
- if (value > 0.15) evaluation++;
- if (value > 0.3) evaluation++;
- if (value > 0.6) evaluation++;
- return evaluation;
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/Stroke.java b/packages/SystemUI/src/com/android/systemui/classifier/Stroke.java
deleted file mode 100644
index 977a2d0b528a..000000000000
--- a/packages/SystemUI/src/com/android/systemui/classifier/Stroke.java
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-package com.android.systemui.classifier;
-
-import java.util.ArrayList;
-
-/**
- * Contains data about a stroke (a single trace, all the events from a given id from the
- * DOWN/POINTER_DOWN event till the UP/POINTER_UP/CANCEL event.)
- */
-public class Stroke {
- private final float NANOS_TO_SECONDS = 1e9f;
-
- private ArrayList<Point> mPoints = new ArrayList<>();
- private long mStartTimeNano;
- private long mEndTimeNano;
- private float mLength;
- private final float mDpi;
-
- public Stroke(long eventTimeNano, float dpi) {
- mDpi = dpi;
- mStartTimeNano = mEndTimeNano = eventTimeNano;
- }
-
- public void addPoint(float x, float y, long eventTimeNano) {
- mEndTimeNano = eventTimeNano;
- Point point = new Point(x / mDpi, y / mDpi, eventTimeNano - mStartTimeNano);
- if (!mPoints.isEmpty()) {
- mLength += mPoints.get(mPoints.size() - 1).dist(point);
- }
- mPoints.add(point);
- }
-
- public int getCount() {
- return mPoints.size();
- }
-
- public float getTotalLength() {
- return mLength;
- }
-
- public float getEndPointLength() {
- return mPoints.get(0).dist(mPoints.get(mPoints.size() - 1));
- }
-
- public long getDurationNanos() {
- return mEndTimeNano - mStartTimeNano;
- }
-
- public float getDurationSeconds() {
- return (float) getDurationNanos() / NANOS_TO_SECONDS;
- }
-
- public ArrayList<Point> getPoints() {
- return mPoints;
- }
-
- public long getLastEventTimeNano() {
- if (mPoints.isEmpty()) {
- return mStartTimeNano;
- }
-
- return mPoints.get(mPoints.size() - 1).timeOffsetNano;
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/StrokeClassifier.java b/packages/SystemUI/src/com/android/systemui/classifier/StrokeClassifier.java
deleted file mode 100644
index 5da392f31d63..000000000000
--- a/packages/SystemUI/src/com/android/systemui/classifier/StrokeClassifier.java
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-package com.android.systemui.classifier;
-
-/**
- * An abstract class for classifiers which classify each stroke separately.
- */
-public abstract class StrokeClassifier extends Classifier {
-
- /**
- * @param type the type of action for which this method is called
- * @param stroke the stroke for which the evaluation will be calculated
- * @return a non-negative value which is used to determine whether this a false touch; the
- * bigger the value the greater the chance that this a false touch
- */
- public abstract float getFalseTouchEvaluation(int type, Stroke stroke);
-}
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/brightline/BrightLineFalsingManager.java b/packages/SystemUI/src/com/android/systemui/classifier/brightline/BrightLineFalsingManager.java
index 9d847ca62465..334102d68507 100644
--- a/packages/SystemUI/src/com/android/systemui/classifier/brightline/BrightLineFalsingManager.java
+++ b/packages/SystemUI/src/com/android/systemui/classifier/brightline/BrightLineFalsingManager.java
@@ -16,29 +16,37 @@
package com.android.systemui.classifier.brightline;
-import static com.android.systemui.classifier.FalsingManagerImpl.FALSING_REMAIN_LOCKED;
-import static com.android.systemui.classifier.FalsingManagerImpl.FALSING_SUCCESS;
+import static com.android.systemui.classifier.FalsingManagerProxy.FALSING_REMAIN_LOCKED;
+import static com.android.systemui.classifier.FalsingManagerProxy.FALSING_SUCCESS;
import android.app.ActivityManager;
+import android.content.res.Resources;
import android.hardware.biometrics.BiometricSourceType;
import android.net.Uri;
import android.os.Build;
+import android.util.IndentingPrintWriter;
import android.util.Log;
import android.view.MotionEvent;
+import android.view.ViewConfiguration;
+
+import androidx.annotation.NonNull;
import com.android.internal.logging.MetricsLogger;
-import com.android.internal.util.IndentingPrintWriter;
import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.keyguard.KeyguardUpdateMonitorCallback;
+import com.android.systemui.R;
import com.android.systemui.classifier.Classifier;
+import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.dock.DockManager;
import com.android.systemui.plugins.FalsingManager;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.StatusBarState;
+import com.android.systemui.statusbar.phone.NotificationTapHelper;
import com.android.systemui.util.DeviceConfigProxy;
import com.android.systemui.util.sensors.ProximitySensor;
import com.android.systemui.util.sensors.ThresholdSensor;
+import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.ArrayDeque;
import java.util.ArrayList;
@@ -64,6 +72,8 @@ public class BrightLineFalsingManager implements FalsingManager {
private final ProximitySensor mProximitySensor;
private final DockManager mDockManager;
private final StatusBarStateController mStatusBarStateController;
+ private final SingleTapClassifier mSingleTapClassifier;
+ private final DoubleTapClassifier mDoubleTapClassifier;
private boolean mSessionStarted;
private MetricsLogger mMetricsLogger;
private int mIsFalseTouchCalls;
@@ -106,8 +116,9 @@ public class BrightLineFalsingManager implements FalsingManager {
public BrightLineFalsingManager(FalsingDataProvider falsingDataProvider,
KeyguardUpdateMonitor keyguardUpdateMonitor, ProximitySensor proximitySensor,
- DeviceConfigProxy deviceConfigProxy,
- DockManager dockManager, StatusBarStateController statusBarStateController) {
+ DeviceConfigProxy deviceConfigProxy, @Main Resources resources,
+ ViewConfiguration viewConfiguration, DockManager dockManager,
+ StatusBarStateController statusBarStateController) {
mKeyguardUpdateMonitor = keyguardUpdateMonitor;
mDataProvider = falsingDataProvider;
mProximitySensor = proximitySensor;
@@ -129,6 +140,12 @@ public class BrightLineFalsingManager implements FalsingManager {
mClassifiers.add(distanceClassifier);
mClassifiers.add(proximityClassifier);
mClassifiers.add(new ZigZagClassifier(mDataProvider, deviceConfigProxy));
+
+ mSingleTapClassifier = new SingleTapClassifier(
+ mDataProvider, viewConfiguration.getScaledTouchSlop());
+ mDoubleTapClassifier = new DoubleTapClassifier(mDataProvider, mSingleTapClassifier,
+ resources.getDimension(R.dimen.double_tap_slop),
+ NotificationTapHelper.DOUBLE_TAP_TIMEOUT_MS);
}
private void registerSensors() {
@@ -237,6 +254,36 @@ public class BrightLineFalsingManager implements FalsingManager {
}
@Override
+ public boolean isFalseTap(boolean robustCheck) {
+ if (!mSingleTapClassifier.isTap(mDataProvider.getRecentMotionEvents())) {
+ logInfo(String.format(
+ (Locale) null, "{classifier=%s}", mSingleTapClassifier.getClass().getName()));
+ String reason = mSingleTapClassifier.getReason();
+ if (reason != null) {
+ logInfo(reason);
+ }
+ return true;
+ }
+
+ // TODO(b/172655679): we always reject single-taps when doing a robust check for now.
+ return robustCheck;
+ }
+
+ @Override
+ public boolean isFalseDoubleTap() {
+ boolean result = mDoubleTapClassifier.isFalseTouch();
+ if (result) {
+ logInfo(String.format(
+ (Locale) null, "{classifier=%s}", mDoubleTapClassifier.getClass().getName()));
+ String reason = mDoubleTapClassifier.getReason();
+ if (reason != null) {
+ logInfo(reason);
+ }
+ }
+ return result;
+ }
+
+ @Override
public void onTouchEvent(MotionEvent motionEvent, int width, int height) {
// TODO: some of these classifiers might allow us to abort early, meaning we don't have to
// make these calls.
@@ -413,7 +460,7 @@ public class BrightLineFalsingManager implements FalsingManager {
}
@Override
- public void dump(PrintWriter pw) {
+ public void dump(@NonNull FileDescriptor fd, @NonNull PrintWriter pw, @NonNull String[] args) {
IndentingPrintWriter ipw = new IndentingPrintWriter(pw, " ");
ipw.println("BRIGHTLINE FALSING MANAGER");
ipw.print("classifierEnabled=");
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/brightline/DoubleTapClassifier.java b/packages/SystemUI/src/com/android/systemui/classifier/brightline/DoubleTapClassifier.java
new file mode 100644
index 000000000000..d3af1c347048
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/classifier/brightline/DoubleTapClassifier.java
@@ -0,0 +1,106 @@
+/*
+ * 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.classifier.brightline;
+
+import android.view.MotionEvent;
+
+import java.util.List;
+import java.util.Queue;
+
+/**
+ * Returns a false touch if the most two recent gestures are not taps or are too far apart.
+ */
+public class DoubleTapClassifier extends FalsingClassifier {
+
+ private final SingleTapClassifier mSingleTapClassifier;
+ private final float mDoubleTapSlop;
+ private final long mDoubleTapTimeMs;
+
+ private StringBuilder mReason = new StringBuilder();
+
+ DoubleTapClassifier(FalsingDataProvider dataProvider, SingleTapClassifier singleTapClassifier,
+ float doubleTapSlop, long doubleTapTimeMs) {
+ super(dataProvider);
+ mSingleTapClassifier = singleTapClassifier;
+ mDoubleTapSlop = doubleTapSlop;
+ mDoubleTapTimeMs = doubleTapTimeMs;
+ }
+
+ @Override
+ boolean isFalseTouch() {
+ List<MotionEvent> secondTapEvents = getRecentMotionEvents();
+ Queue<? extends List<MotionEvent>> historicalEvents = getHistoricalEvents();
+ List<MotionEvent> firstTapEvents = historicalEvents.peek();
+
+ mReason = new StringBuilder();
+
+ if (firstTapEvents == null) {
+ mReason.append("Only one gesture recorded");
+ return true;
+ }
+
+ return !isDoubleTap(firstTapEvents, secondTapEvents, mReason);
+ }
+
+ /** Returns true if the two supplied lists of {@link MotionEvent}s look like a double-tap. */
+ public boolean isDoubleTap(List<MotionEvent> firstEvents, List<MotionEvent> secondEvents,
+ StringBuilder reason) {
+
+ if (!mSingleTapClassifier.isTap(firstEvents)) {
+ reason.append("First gesture is not a tap. ").append(mSingleTapClassifier.getReason());
+ return false;
+ }
+
+ if (!mSingleTapClassifier.isTap(secondEvents)) {
+ reason.append("Second gesture is not a tap. ").append(mSingleTapClassifier.getReason());
+ return false;
+ }
+
+ MotionEvent firstFinalEvent = firstEvents.get(firstEvents.size() - 1);
+ MotionEvent secondFinalEvent = secondEvents.get(secondEvents.size() - 1);
+
+ long dt = secondFinalEvent.getEventTime() - firstFinalEvent.getEventTime();
+
+ if (dt > mDoubleTapTimeMs) {
+ reason.append("Time between taps too large: ").append(dt).append("ms");
+ return false;
+ }
+
+ if (Math.abs(firstFinalEvent.getX() - secondFinalEvent.getX()) >= mDoubleTapSlop) {
+ reason.append("Delta X between taps too large:")
+ .append(Math.abs(firstFinalEvent.getX() - secondFinalEvent.getX()))
+ .append(" vs ")
+ .append(mDoubleTapSlop);
+ return false;
+ }
+
+ if (Math.abs(firstFinalEvent.getY() - secondFinalEvent.getY()) >= mDoubleTapSlop) {
+ reason.append("Delta Y between taps too large:")
+ .append(Math.abs(firstFinalEvent.getY() - secondFinalEvent.getY()))
+ .append(" vs ")
+ .append(mDoubleTapSlop);
+ return false;
+ }
+
+ return true;
+ }
+
+ @Override
+ String getReason() {
+ return mReason.toString();
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/brightline/FalsingClassifier.java b/packages/SystemUI/src/com/android/systemui/classifier/brightline/FalsingClassifier.java
index 85e95a66bfe3..ed417b3d09ec 100644
--- a/packages/SystemUI/src/com/android/systemui/classifier/brightline/FalsingClassifier.java
+++ b/packages/SystemUI/src/com/android/systemui/classifier/brightline/FalsingClassifier.java
@@ -22,6 +22,7 @@ import com.android.systemui.classifier.Classifier;
import com.android.systemui.util.sensors.ProximitySensor;
import java.util.List;
+import java.util.Queue;
/**
* Base class for rules that determine False touches.
@@ -30,13 +31,17 @@ abstract class FalsingClassifier {
private final FalsingDataProvider mDataProvider;
FalsingClassifier(FalsingDataProvider dataProvider) {
- this.mDataProvider = dataProvider;
+ mDataProvider = dataProvider;
}
List<MotionEvent> getRecentMotionEvents() {
return mDataProvider.getRecentMotionEvents();
}
+ Queue<? extends List<MotionEvent>> getHistoricalEvents() {
+ return mDataProvider.getHistoricalMotionEvents();
+ }
+
MotionEvent getFirstMotionEvent() {
return mDataProvider.getFirstRecentMotionEvent();
}
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/brightline/FalsingDataProvider.java b/packages/SystemUI/src/com/android/systemui/classifier/brightline/FalsingDataProvider.java
index 8d067489a8cc..4681f9709a7d 100644
--- a/packages/SystemUI/src/com/android/systemui/classifier/brightline/FalsingDataProvider.java
+++ b/packages/SystemUI/src/com/android/systemui/classifier/brightline/FalsingDataProvider.java
@@ -23,9 +23,13 @@ import android.view.MotionEvent.PointerProperties;
import com.android.systemui.classifier.Classifier;
import com.android.systemui.statusbar.policy.BatteryController;
+import com.android.systemui.util.time.SystemClock;
import java.util.ArrayList;
+import java.util.Deque;
+import java.util.LinkedList;
import java.util.List;
+import java.util.Queue;
import javax.inject.Inject;
@@ -35,18 +39,21 @@ import javax.inject.Inject;
public class FalsingDataProvider {
private static final long MOTION_EVENT_AGE_MS = 1000;
+ private static final long EXTENDED_MOTION_EVENT_AGE_MS = 30 * 1000;
private static final float THREE_HUNDRED_SIXTY_DEG = (float) (2 * Math.PI);
private final int mWidthPixels;
private final int mHeightPixels;
private final BatteryController mBatteryController;
+ private final SystemClock mSystemClock;
private final float mXdpi;
private final float mYdpi;
private @Classifier.InteractionType int mInteractionType;
- private final TimeLimitedMotionEventBuffer mRecentMotionEvents =
- new TimeLimitedMotionEventBuffer(MOTION_EVENT_AGE_MS);
+ private final Deque<TimeLimitedMotionEventBuffer> mExtendedMotionEvents = new LinkedList<>();
+ private TimeLimitedMotionEventBuffer mRecentMotionEvents =
+ new TimeLimitedMotionEventBuffer(MOTION_EVENT_AGE_MS);
private boolean mDirty = true;
private float mAngle = 0;
@@ -55,12 +62,14 @@ public class FalsingDataProvider {
private MotionEvent mLastMotionEvent;
@Inject
- public FalsingDataProvider(DisplayMetrics displayMetrics, BatteryController batteryController) {
+ public FalsingDataProvider(DisplayMetrics displayMetrics, BatteryController batteryController,
+ SystemClock systemClock) {
mXdpi = displayMetrics.xdpi;
mYdpi = displayMetrics.ydpi;
mWidthPixels = displayMetrics.widthPixels;
mHeightPixels = displayMetrics.heightPixels;
mBatteryController = batteryController;
+ mSystemClock = systemClock;
FalsingClassifier.logInfo("xdpi, ydpi: " + getXdpi() + ", " + getYdpi());
FalsingClassifier.logInfo("width, height: " + getWidthPixels() + ", " + getHeightPixels());
@@ -81,7 +90,10 @@ public class FalsingDataProvider {
}
if (motionEvent.getActionMasked() == MotionEvent.ACTION_DOWN) {
- mRecentMotionEvents.clear();
+ if (!mRecentMotionEvents.isEmpty()) {
+ mExtendedMotionEvents.addFirst(mRecentMotionEvents);
+ mRecentMotionEvents = new TimeLimitedMotionEventBuffer(MOTION_EVENT_AGE_MS);
+ }
}
mRecentMotionEvents.addAll(motionEvents);
@@ -112,6 +124,16 @@ public class FalsingDataProvider {
return mRecentMotionEvents;
}
+ /** Returns recent gestures, exclusive of the most recent gesture. Newer gestures come first. */
+ Queue<? extends List<MotionEvent>> getHistoricalMotionEvents() {
+ long nowMs = mSystemClock.uptimeMillis();
+
+ mExtendedMotionEvents.removeIf(
+ motionEvents -> motionEvents.isFullyExpired(nowMs - EXTENDED_MOTION_EVENT_AGE_MS));
+
+ return mExtendedMotionEvents;
+ }
+
/**
* interactionType is defined by {@link com.android.systemui.classifier.Classifier}.
*/
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/brightline/SingleTapClassifier.java b/packages/SystemUI/src/com/android/systemui/classifier/brightline/SingleTapClassifier.java
new file mode 100644
index 000000000000..47708f4dd789
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/classifier/brightline/SingleTapClassifier.java
@@ -0,0 +1,68 @@
+/*
+ * 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.classifier.brightline;
+
+import android.view.MotionEvent;
+
+import java.util.List;
+
+/**
+ * Falsing classifier that accepts or rejects a single gesture as a tap.
+ */
+public class SingleTapClassifier extends FalsingClassifier {
+ private final float mTouchSlop;
+ private String mReason;
+
+ SingleTapClassifier(FalsingDataProvider dataProvider, float touchSlop) {
+ super(dataProvider);
+ mTouchSlop = touchSlop;
+ }
+
+ @Override
+ boolean isFalseTouch() {
+ return !isTap(getRecentMotionEvents());
+ }
+
+ /** Given a list of {@link android.view.MotionEvent}'s, returns true if the look like a tap. */
+ public boolean isTap(List<MotionEvent> motionEvents) {
+ float downX = motionEvents.get(0).getX();
+ float downY = motionEvents.get(0).getY();
+
+ for (MotionEvent event : motionEvents) {
+ if (Math.abs(event.getX() - downX) >= mTouchSlop) {
+ mReason = "dX too big for a tap: "
+ + Math.abs(event.getX() - downX)
+ + "vs "
+ + mTouchSlop;
+ return false;
+ } else if (Math.abs(event.getY() - downY) >= mTouchSlop) {
+ mReason = "dY too big for a tap: "
+ + Math.abs(event.getY() - downY)
+ + "vs "
+ + mTouchSlop;
+ return false;
+ }
+ }
+ mReason = "";
+ return true;
+ }
+
+ @Override
+ String getReason() {
+ return mReason;
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/brightline/TimeLimitedMotionEventBuffer.java b/packages/SystemUI/src/com/android/systemui/classifier/brightline/TimeLimitedMotionEventBuffer.java
index 9a83b5bd8328..92aa7c5b2f44 100644
--- a/packages/SystemUI/src/com/android/systemui/classifier/brightline/TimeLimitedMotionEventBuffer.java
+++ b/packages/SystemUI/src/com/android/systemui/classifier/brightline/TimeLimitedMotionEventBuffer.java
@@ -34,12 +34,24 @@ import java.util.ListIterator;
public class TimeLimitedMotionEventBuffer implements List<MotionEvent> {
private final LinkedList<MotionEvent> mMotionEvents;
- private long mMaxAgeMs;
+ private final long mMaxAgeMs;
TimeLimitedMotionEventBuffer(long maxAgeMs) {
super();
- this.mMaxAgeMs = maxAgeMs;
- this.mMotionEvents = new LinkedList<>();
+ mMaxAgeMs = maxAgeMs;
+ mMotionEvents = new LinkedList<>();
+ }
+
+ /**
+ * Returns true if the most recent event in the buffer is past the expiration time.
+ *
+ * This method does not mutate the underlying data. This method does imply that, if the supplied
+ * expiration time is old enough and a new {@link MotionEvent} gets added to the buffer, all
+ * prior events would be removed.
+ */
+ public boolean isFullyExpired(long expirationMs) {
+ return mMotionEvents.isEmpty()
+ || mMotionEvents.getLast().getEventTime() <= expirationMs;
}
private void ejectOldEvents() {
diff --git a/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsControllerImpl.kt b/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsControllerImpl.kt
index d3d24be0ad9d..96f207215f71 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsControllerImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsControllerImpl.kt
@@ -478,7 +478,7 @@ class ControlsControllerImpl @Inject constructor (
val pendingIntent = PendingIntent.getActivity(context,
componentName.hashCode(),
intent,
- 0)
+ PendingIntent.FLAG_IMMUTABLE)
val control = Control.StatelessBuilder(controlInfo.controlId, pendingIntent)
.setTitle(controlInfo.controlTitle)
.setSubtitle(controlInfo.controlSubtitle)
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
index 4c68312b9378..aea0dd0ee4b1 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
@@ -34,10 +34,12 @@ import android.app.PendingIntent;
import android.app.StatusBarManager;
import android.app.trust.TrustManager;
import android.content.BroadcastReceiver;
+import android.content.ComponentName;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
+import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.UserInfo;
import android.hardware.biometrics.BiometricSourceType;
import android.media.AudioAttributes;
@@ -88,6 +90,7 @@ import com.android.systemui.SystemUI;
import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.dagger.qualifiers.UiBackground;
import com.android.systemui.dump.DumpManager;
+import com.android.systemui.keyguard.KeyguardService;
import com.android.systemui.keyguard.dagger.KeyguardModule;
import com.android.systemui.navigationbar.NavigationModeController;
import com.android.systemui.plugins.FalsingManager;
@@ -779,7 +782,7 @@ public class KeyguardViewMediator extends SystemUI implements Dumpable {
// Assume keyguard is showing (unless it's disabled) until we know for sure, unless Keyguard
// is disabled.
- if (mContext.getResources().getBoolean(R.bool.config_enableKeyguardService)) {
+ if (isKeyguardServiceEnabled()) {
setShowingLocked(!shouldWaitForProvisioning()
&& !mLockPatternUtils.isLockScreenDisabled(
KeyguardUpdateMonitor.getCurrentUser()), true /* forceCallbacks */);
@@ -957,6 +960,15 @@ public class KeyguardViewMediator extends SystemUI implements Dumpable {
mUpdateMonitor.dispatchFinishedGoingToSleep(why);
}
+ private boolean isKeyguardServiceEnabled() {
+ try {
+ return mContext.getPackageManager().getServiceInfo(
+ new ComponentName(mContext, KeyguardService.class), 0).isEnabled();
+ } catch (NameNotFoundException e) {
+ return true;
+ }
+ }
+
private long getLockTimeout(int userId) {
// if the screen turned off because of timeout or the user hit the power button
// and we don't need to lock immediately, set an alarm
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSContainerImpl.java b/packages/SystemUI/src/com/android/systemui/qs/QSContainerImpl.java
index 19a8dabb31fc..16e95900052f 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSContainerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSContainerImpl.java
@@ -61,7 +61,7 @@ public class QSContainerImpl extends FrameLayout {
private float mQsExpansion;
private QSCustomizer mQSCustomizer;
private View mDragHandle;
- private View mQSPanelContainer;
+ private NonInterceptingScrollView mQSPanelContainer;
private View mBackground;
@@ -126,18 +126,12 @@ public class QSContainerImpl extends FrameLayout {
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
// QSPanel will show as many rows as it can (up to TileLayout.MAX_ROWS) such that the
// bottom and footer are inside the screen.
- Configuration config = getResources().getConfiguration();
- boolean navBelow = config.smallestScreenWidthDp >= 600
- || config.orientation != Configuration.ORIENTATION_LANDSCAPE;
MarginLayoutParams layoutParams = (MarginLayoutParams) mQSPanelContainer.getLayoutParams();
// The footer is pinned to the bottom of QSPanel (same bottoms), therefore we don't need to
// subtract its height. We do not care if the collapsed notifications fit in the screen.
int maxQs = getDisplayHeight() - layoutParams.topMargin - layoutParams.bottomMargin
- getPaddingBottom();
- if (navBelow) {
- maxQs -= getResources().getDimensionPixelSize(R.dimen.navigation_bar_height);
- }
int padding = mPaddingLeft + mPaddingRight + layoutParams.leftMargin
+ layoutParams.rightMargin;
@@ -217,12 +211,13 @@ public class QSContainerImpl extends FrameLayout {
public void updateExpansion(boolean animate) {
int height = calculateContainerHeight();
+ int scrollBottom = calculateContainerBottom();
setBottom(getTop() + height);
- mQSDetail.setBottom(getTop() + height);
+ mQSDetail.setBottom(getTop() + scrollBottom);
// Pin the drag handle to the bottom of the panel.
- mDragHandle.setTranslationY(height - mDragHandle.getHeight());
+ mDragHandle.setTranslationY(scrollBottom - mDragHandle.getHeight());
mBackground.setTop(mQSPanelContainer.getTop());
- updateBackgroundBottom(height, animate);
+ updateBackgroundBottom(scrollBottom, animate);
}
private void updateBackgroundBottom(int height, boolean animated) {
@@ -246,6 +241,15 @@ public class QSContainerImpl extends FrameLayout {
+ mHeader.getHeight();
}
+ int calculateContainerBottom() {
+ int heightOverride = mHeightOverride != -1 ? mHeightOverride : getMeasuredHeight();
+ return mQSCustomizer.isCustomizing() ? mQSCustomizer.getHeight()
+ : Math.round(mQsExpansion
+ * (heightOverride + mQSPanelContainer.getScrollRange()
+ - mQSPanelContainer.getScrollY() - mHeader.getHeight()))
+ + mHeader.getHeight();
+ }
+
public void setExpansion(float expansion) {
mQsExpansion = expansion;
mDragHandle.setAlpha(1.0f - expansion);
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java b/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java
index 043f5f1610a6..dbdd04a1e3ba 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java
@@ -300,7 +300,7 @@ public class QSFragment extends LifecycleFragment implements QS, CommandQueue.Ca
? View.VISIBLE
: View.INVISIBLE);
mHeader.setExpanded((keyguardShowing && !mHeaderAnimating && !mShowCollapsedOnKeyguard)
- || (mQsExpanded && !mStackScrollerOverscrolling));
+ || (mQsExpanded && !mStackScrollerOverscrolling), mQuickQSPanelController);
mFooter.setVisibility(
!mQsDisabled && (mQsExpanded || !keyguardShowing || mHeaderAnimating
|| mShowCollapsedOnKeyguard)
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
index c080eccc1d8c..87a8da0cfa95 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
@@ -16,7 +16,6 @@
package com.android.systemui.qs;
-import static com.android.systemui.util.InjectionInflationController.VIEW_CONTEXT;
import static com.android.systemui.util.Utils.useQsMediaPlayer;
import android.annotation.NonNull;
@@ -40,7 +39,6 @@ import com.android.internal.widget.RemeasuringLinearLayout;
import com.android.systemui.R;
import com.android.systemui.plugins.qs.DetailAdapter;
import com.android.systemui.plugins.qs.QSTile;
-import com.android.systemui.qs.logging.QSLogger;
import com.android.systemui.settings.brightness.BrightnessSlider;
import com.android.systemui.statusbar.policy.BrightnessMirrorController;
import com.android.systemui.tuner.TunerService;
@@ -50,9 +48,6 @@ import java.util.ArrayList;
import java.util.List;
import java.util.function.Consumer;
-import javax.inject.Inject;
-import javax.inject.Named;
-
/** View that represents the quick settings tile panel (when expanded/pulled down). **/
public class QSPanel extends LinearLayout implements Tunable {
@@ -83,7 +78,6 @@ public class QSPanel extends LinearLayout implements Tunable {
protected boolean mListening;
private QSDetail.Callback mCallback;
- private final QSLogger mQSLogger;
protected QSTileHost mHost;
private final List<OnConfigurationChangedListener> mOnConfigurationChangedListeners =
new ArrayList<>();
@@ -119,19 +113,12 @@ public class QSPanel extends LinearLayout implements Tunable {
private int mFooterMarginStartHorizontal;
private Consumer<Boolean> mMediaVisibilityChangedListener;
-
- @Inject
- public QSPanel(
- @Named(VIEW_CONTEXT) Context context,
- AttributeSet attrs,
- QSLogger qsLogger
- ) {
+ public QSPanel(Context context, AttributeSet attrs) {
super(context, attrs);
mUsingMediaPlayer = useQsMediaPlayer(context);
mMediaTotalBottomMargin = getResources().getDimensionPixelSize(
R.dimen.quick_settings_bottom_margin_media);
mContext = context;
- mQSLogger = qsLogger;
setOrientation(VERTICAL);
@@ -161,7 +148,6 @@ public class QSPanel extends LinearLayout implements Tunable {
lp = new LayoutParams(LayoutParams.MATCH_PARENT, 0, 1);
addView(mHorizontalLinearLayout, lp);
}
- mQSLogger.logAllTilesChangeListening(mListening, getDumpableTag(), "");
}
protected void onMediaVisibilityChanged(Boolean visible) {
@@ -439,7 +425,6 @@ public class QSPanel extends LinearLayout implements Tunable {
public void setExpanded(boolean expanded) {
if (mExpanded == expanded) return;
- mQSLogger.logPanelExpanded(expanded, getDumpableTag());
mExpanded = expanded;
if (!mExpanded && mTileLayout instanceof PagedTileLayout) {
((PagedTileLayout) mTileLayout).setCurrentItem(0, false);
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSPanelControllerBase.java b/packages/SystemUI/src/com/android/systemui/qs/QSPanelControllerBase.java
index 18c2925b7fd9..4418a7415c60 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSPanelControllerBase.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSPanelControllerBase.java
@@ -108,6 +108,11 @@ public abstract class QSPanelControllerBase<T extends QSPanel> extends ViewContr
}
@Override
+ protected void onInit() {
+ mQSLogger.logAllTilesChangeListening(mView.isListening(), mView.getDumpableTag(), "");
+ }
+
+ @Override
protected void onViewAttached() {
mQsTileRevealController = createTileRevealController();
if (mQsTileRevealController != null) {
@@ -221,6 +226,11 @@ public abstract class QSPanelControllerBase<T extends QSPanel> extends ViewContr
/** */
public void setExpanded(boolean expanded) {
+ if (mView.isExpanded() == expanded) {
+ return;
+ }
+ mQSLogger.logPanelExpanded(expanded, mView.getDumpableTag());
+
mView.setExpanded(expanded);
mMetricsLogger.visibility(MetricsEvent.QS_PANEL, expanded);
if (!expanded) {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanel.java b/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanel.java
index bbd0c1abb239..c89f8e58f980 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanel.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanel.java
@@ -16,8 +16,6 @@
package com.android.systemui.qs;
-import static com.android.systemui.util.InjectionInflationController.VIEW_CONTEXT;
-
import android.content.Context;
import android.content.res.Configuration;
import android.graphics.Rect;
@@ -31,10 +29,6 @@ import com.android.systemui.R;
import com.android.systemui.plugins.qs.QSTile;
import com.android.systemui.plugins.qs.QSTile.SignalState;
import com.android.systemui.plugins.qs.QSTile.State;
-import com.android.systemui.qs.logging.QSLogger;
-
-import javax.inject.Inject;
-import javax.inject.Named;
/**
* Version of QSPanel that only shows N Quick Tiles in the QS Header.
@@ -49,14 +43,8 @@ public class QuickQSPanel extends QSPanel {
private boolean mDisabledByPolicy;
private int mMaxTiles;
-
- @Inject
- public QuickQSPanel(
- @Named(VIEW_CONTEXT) Context context,
- AttributeSet attrs,
- QSLogger qsLogger,
- UiEventLogger uiEventLogger) {
- super(context, attrs, qsLogger);
+ public QuickQSPanel(Context context, AttributeSet attrs) {
+ super(context, attrs);
mMaxTiles = Math.min(DEFAULT_MAX_TILES,
getResources().getInteger(R.integer.quick_qs_panel_max_columns));
applyBottomMargin((View) mRegularTileLayout);
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanelController.java b/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanelController.java
index ac85ca4dda63..cca0e1b0c0f0 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanelController.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanelController.java
@@ -40,8 +40,6 @@ import javax.inject.Named;
@QSScope
public class QuickQSPanelController extends QSPanelControllerBase<QuickQSPanel> {
- private List<QSTile> mAllTiles = new ArrayList<>();
-
private final QSPanel.OnConfigurationChangedListener mOnConfigurationChangedListener =
newConfig -> {
int newMaxTiles = getResources().getInteger(R.integer.quick_qs_panel_max_columns);
@@ -92,14 +90,14 @@ public class QuickQSPanelController extends QSPanelControllerBase<QuickQSPanel>
@Override
public void setTiles() {
- mAllTiles.clear();
+ List<QSTile> tiles = new ArrayList();
for (QSTile tile : mHost.getTiles()) {
- mAllTiles.add(tile);
- if (mAllTiles.size() == QuickQSPanel.DEFAULT_MAX_TILES) {
+ tiles.add(tile);
+ if (tiles.size() == mView.getNumQuickTiles()) {
break;
}
}
- super.setTiles(mAllTiles.subList(0, mView.getNumQuickTiles()), true);
+ super.setTiles(tiles, true);
}
/** */
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java b/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java
index 6020e21035a8..b85ad8195edd 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java
@@ -311,10 +311,11 @@ public class QuickStatusBarHeader extends RelativeLayout implements LifecycleOwn
.build();
}
- public void setExpanded(boolean expanded) {
+ /** */
+ public void setExpanded(boolean expanded, QuickQSPanelController quickQSPanelController) {
if (mExpanded == expanded) return;
mExpanded = expanded;
- mHeaderQsPanel.setExpanded(expanded);
+ quickQSPanelController.setExpanded(expanded);
updateEverything();
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationHeaderUtil.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationHeaderUtil.java
index 216b83f2b4d5..84818eea8a23 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationHeaderUtil.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationHeaderUtil.java
@@ -41,6 +41,7 @@ import java.util.Objects;
public class NotificationHeaderUtil {
private static final TextViewComparator sTextViewComparator = new TextViewComparator();
+ private static final TextViewComparator sAppNameComparator = new AppNameComparator();
private static final VisibilityApplicator sVisibilityApplicator = new VisibilityApplicator();
private static final VisibilityApplicator sAppNameApplicator = new AppNameApplicator();
private static final DataExtractor sIconExtractor = new DataExtractor() {
@@ -119,7 +120,7 @@ public class NotificationHeaderUtil {
mRow,
com.android.internal.R.id.app_name_text,
null,
- sTextViewComparator,
+ sAppNameComparator,
sAppNameApplicator));
mComparators.add(HeaderProcessor.forTextView(mRow,
com.android.internal.R.id.header_text));
@@ -389,4 +390,17 @@ public class NotificationHeaderUtil {
super.apply(parent, view, apply, reset);
}
}
+
+ private static class AppNameComparator extends TextViewComparator {
+ @Override
+ public boolean compare(View parent, View child, Object parentData, Object childData) {
+ if (isEmpty(child)) {
+ // In headerless notifications the AppName view exists but is usually GONE (and not
+ // populated). We need to treat this case as equal to the header in order to
+ // deduplicate the view.
+ return true;
+ }
+ return super.compare(parent, child, parentData, childData);
+ }
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ActivatableNotificationViewController.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ActivatableNotificationViewController.java
index 41ce51c2762f..0b79387fac77 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ActivatableNotificationViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ActivatableNotificationViewController.java
@@ -23,32 +23,44 @@ import android.view.accessibility.AccessibilityManager;
import com.android.systemui.Gefingerpoken;
import com.android.systemui.plugins.FalsingManager;
-import com.android.systemui.statusbar.phone.DoubleTapHelper;
+import com.android.systemui.statusbar.phone.NotificationTapHelper;
+import com.android.systemui.util.ViewController;
import javax.inject.Inject;
/**
* Controller for {@link ActivatableNotificationView}
*/
-public class ActivatableNotificationViewController {
- private final ActivatableNotificationView mView;
+public class ActivatableNotificationViewController
+ extends ViewController<ActivatableNotificationView> {
private final ExpandableOutlineViewController mExpandableOutlineViewController;
private final AccessibilityManager mAccessibilityManager;
private final FalsingManager mFalsingManager;
- private DoubleTapHelper mDoubleTapHelper;
- private boolean mNeedsDimming;
+ private final NotificationTapHelper mNotificationTapHelper;
+ private final TouchHandler mTouchHandler = new TouchHandler();
- private TouchHandler mTouchHandler = new TouchHandler();
+ private boolean mNeedsDimming;
@Inject
public ActivatableNotificationViewController(ActivatableNotificationView view,
+ NotificationTapHelper.Factory notificationTapHelpFactory,
ExpandableOutlineViewController expandableOutlineViewController,
AccessibilityManager accessibilityManager, FalsingManager falsingManager) {
- mView = view;
+ super(view);
mExpandableOutlineViewController = expandableOutlineViewController;
mAccessibilityManager = accessibilityManager;
mFalsingManager = falsingManager;
+ mNotificationTapHelper = notificationTapHelpFactory.create(
+ (active) -> {
+ if (active) {
+ mView.makeActive();
+ mFalsingManager.onNotificationActive();
+ } else {
+ mView.makeInactive(true /* animate */);
+ }
+ }, mView::performClick, mView::handleSlideBack);
+
mView.setOnActivatedListener(new ActivatableNotificationView.OnActivatedListener() {
@Override
public void onActivated(ActivatableNotificationView view) {
@@ -64,25 +76,25 @@ public class ActivatableNotificationViewController {
/**
* Initialize the controller, setting up handlers and other behavior.
*/
- public void init() {
+ @Override
+ public void onInit() {
mExpandableOutlineViewController.init();
- mDoubleTapHelper = new DoubleTapHelper(mView, (active) -> {
- if (active) {
- mView.makeActive();
- mFalsingManager.onNotificationActive();
- } else {
- mView.makeInactive(true /* animate */);
- }
- }, mView::performClick, mView::handleSlideBack,
- mFalsingManager::onNotificationDoubleTap);
mView.setOnTouchListener(mTouchHandler);
mView.setTouchHandler(mTouchHandler);
- mView.setOnDimmedListener(dimmed -> {
- mNeedsDimming = dimmed;
- });
+ mView.setOnDimmedListener(dimmed -> mNeedsDimming = dimmed);
mView.setAccessibilityManager(mAccessibilityManager);
}
+ @Override
+ protected void onViewAttached() {
+
+ }
+
+ @Override
+ protected void onViewDetached() {
+
+ }
+
class TouchHandler implements Gefingerpoken, View.OnTouchListener {
private boolean mBlockNextTouch;
@@ -103,7 +115,7 @@ public class ActivatableNotificationViewController {
// let's ensure we have a ripple
return false;
}
- result = mDoubleTapHelper.onTouchEvent(ev, mView.getActualHeight());
+ result = mNotificationTapHelper.onTouchEvent(ev, mView.getActualHeight());
} else {
return false;
}
@@ -117,7 +129,7 @@ public class ActivatableNotificationViewController {
&& !mAccessibilityManager.isTouchExplorationEnabled()) {
if (!mView.isActive()) {
return true;
- } else if (!mDoubleTapHelper.isWithinDoubleTapSlop(ev)) {
+ } else if (mFalsingManager.isFalseDoubleTap()) {
mBlockNextTouch = true;
mView.makeInactive(true /* animate */);
return true;
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 ea3906418032..5682c88edc63 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
@@ -666,8 +666,12 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
} else {
smallHeight = mMaxSmallHeightBeforeS;
}
- } else if (isMediaLayout && showCompactMediaSeekbar) {
- smallHeight = mMaxSmallHeightMedia;
+ } else if (isMediaLayout) {
+ // TODO(b/172652345): MediaStyle notifications currently look broken when we enforce
+ // the standard notification height, so we have to afford them more vertical space to
+ // make sure we don't crop them terribly. We actually need to revisit this and give
+ // them a headerless design, then remove this hack.
+ smallHeight = showCompactMediaSeekbar ? mMaxSmallHeightMedia : mMaxSmallHeightBeforeS;
} else if (isMessagingLayout) {
// TODO(b/173204301): MessagingStyle notifications currently look broken when we enforce
// the standard notification height, so we have to afford them more vertical space to
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentView.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentView.java
index 328774550f24..74e6c003041e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentView.java
@@ -1369,16 +1369,8 @@ public class NotificationContentView extends FrameLayout {
bubbleButton.setOnClickListener(mContainingNotification.getBubbleClickListener());
bubbleButton.setVisibility(VISIBLE);
actionContainer.setVisibility(VISIBLE);
-
- int paddingEnd = getResources().getDimensionPixelSize(
- com.android.internal.R.dimen.bubble_visible_padding_end);
- actionContainerLayout.setPaddingRelative(0, 0, paddingEnd, 0);
} else {
bubbleButton.setVisibility(GONE);
-
- int paddingEnd = getResources().getDimensionPixelSize(
- com.android.internal.R.dimen.bubble_gone_padding_end);
- actionContainerLayout.setPaddingRelative(0, 0, paddingEnd, 0);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationMenuRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationMenuRow.java
index 447fa43ef824..1034b1fd9031 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationMenuRow.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationMenuRow.java
@@ -295,7 +295,7 @@ public class NotificationMenuRow implements NotificationMenuRowPlugin, View.OnCl
mMenuContainer = new FrameLayout(mContext);
}
final boolean newFlowHideShelf = Settings.Global.getInt(mContext.getContentResolver(),
- Settings.Global.SHOW_NEW_NOTIF_DISMISS, 0) == 1;
+ Settings.Global.SHOW_NEW_NOTIF_DISMISS, 1 /* on by default */) == 1;
if (newFlowHideShelf) {
return;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationHeaderViewWrapper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationHeaderViewWrapper.java
index d228ce159d48..05db67d706cf 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationHeaderViewWrapper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationHeaderViewWrapper.java
@@ -56,6 +56,7 @@ public class NotificationHeaderViewWrapper extends NotificationViewWrapper {
private CachingIconView mIcon;
private NotificationExpandButton mExpandButton;
+ private View mAltExpandTarget;
protected NotificationHeaderView mNotificationHeader;
protected NotificationTopLineView mNotificationTopLine;
private TextView mHeaderText;
@@ -106,6 +107,7 @@ public class NotificationHeaderViewWrapper extends NotificationViewWrapper {
mHeaderText = mView.findViewById(com.android.internal.R.id.header_text);
mAppNameText = mView.findViewById(com.android.internal.R.id.app_name_text);
mExpandButton = mView.findViewById(com.android.internal.R.id.expand_button);
+ mAltExpandTarget = mView.findViewById(com.android.internal.R.id.alternate_expand_target);
mRightIcon = mView.findViewById(com.android.internal.R.id.right_icon);
mWorkProfileImage = mView.findViewById(com.android.internal.R.id.profile_badge);
mNotificationHeader = mView.findViewById(com.android.internal.R.id.notification_header);
@@ -260,6 +262,9 @@ public class NotificationHeaderViewWrapper extends NotificationViewWrapper {
public void updateExpandability(boolean expandable, View.OnClickListener onClickListener) {
mExpandButton.setVisibility(expandable ? View.VISIBLE : View.GONE);
mExpandButton.setOnClickListener(expandable ? onClickListener : null);
+ if (mAltExpandTarget != null) {
+ mAltExpandTarget.setOnClickListener(expandable ? onClickListener : null);
+ }
if (mNotificationHeader != null) {
mNotificationHeader.setOnClickListener(expandable ? onClickListener : null);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/AmbientState.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/AmbientState.java
index 8050fea562a7..885048df13f1 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/AmbientState.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/AmbientState.java
@@ -41,7 +41,6 @@ public class AmbientState {
private static final float MAX_PULSE_HEIGHT = 100000f;
private final SectionProvider mSectionProvider;
- private ArrayList<View> mDraggedViews = new ArrayList<>();
private int mScrollY;
private int mAnchorViewIndex;
private int mAnchorViewY;
@@ -161,19 +160,6 @@ public class AmbientState {
mAnchorViewY = anchorViewY;
}
- /** Call when dragging begins. */
- public void onBeginDrag(View view) {
- mDraggedViews.add(view);
- }
-
- public void onDragFinished(View view) {
- mDraggedViews.remove(view);
- }
-
- public ArrayList<View> getDraggedViews() {
- return mDraggedViews;
- }
-
/**
* @param dimmed Whether we are in a dimmed state (on the lockscreen), where the backgrounds are
* translucent and everything is scaled back a bit.
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
index 153ba514fc33..742e517e71e7 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
@@ -353,31 +353,24 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable
private boolean mContinuousShadowUpdate;
private boolean mContinuousBackgroundUpdate;
private ViewTreeObserver.OnPreDrawListener mShadowUpdater
- = new ViewTreeObserver.OnPreDrawListener() {
-
- @Override
- public boolean onPreDraw() {
- updateViewShadows();
- return true;
- }
- };
+ = () -> {
+ updateViewShadows();
+ return true;
+ };
private ViewTreeObserver.OnPreDrawListener mBackgroundUpdater = () -> {
updateBackground();
return true;
};
- private Comparator<ExpandableView> mViewPositionComparator = new Comparator<ExpandableView>() {
- @Override
- public int compare(ExpandableView view, ExpandableView otherView) {
- float endY = view.getTranslationY() + view.getActualHeight();
- float otherEndY = otherView.getTranslationY() + otherView.getActualHeight();
- if (endY < otherEndY) {
- return -1;
- } else if (endY > otherEndY) {
- return 1;
- } else {
- // The two notifications end at the same location
- return 0;
- }
+ private Comparator<ExpandableView> mViewPositionComparator = (view, otherView) -> {
+ float endY = view.getTranslationY() + view.getActualHeight();
+ float otherEndY = otherView.getTranslationY() + otherView.getActualHeight();
+ if (endY < otherEndY) {
+ return -1;
+ } else if (endY > otherEndY) {
+ return 1;
+ } else {
+ // The two notifications end at the same location
+ return 0;
}
};
private final ViewOutlineProvider mOutlineProvider = new ViewOutlineProvider() {
@@ -415,8 +408,6 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable
*/
private float mBackgroundXFactor = 1f;
- private boolean mSwipingInProgress;
-
private boolean mUsingLightTheme;
private boolean mQsExpanded;
private boolean mForwardScrollable;
@@ -834,9 +825,9 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable
if (!mShouldDrawNotificationBackground) {
return;
}
- final boolean clearUndershelf = Settings.Global.getInt(mContext.getContentResolver(),
- Settings.Global.SHOW_NEW_NOTIF_DISMISS, 0 /* show background by default */) == 1;
- if (clearUndershelf) {
+ final boolean newFlowHideShelf = Settings.Global.getInt(mContext.getContentResolver(),
+ Settings.Global.SHOW_NEW_NOTIF_DISMISS, 1 /* on by default */) == 1;
+ if (newFlowHideShelf) {
mBackgroundPaint.setColor(Color.TRANSPARENT);
invalidate();
return;
@@ -2557,7 +2548,7 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable
if (child.getVisibility() != View.GONE
&& !(child instanceof StackScrollerDecorView)
&& child != mShelf
- && !mAmbientState.getDraggedViews().contains(child)) {
+ && mSwipeHelper.getSwipedView() != child) {
children.add(child);
}
}
@@ -3578,7 +3569,10 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable
@Override
@ShadeViewRefactor(RefactorComponent.INPUT)
public boolean onGenericMotionEvent(MotionEvent event) {
- if (!isScrollingEnabled() || !mIsExpanded || mSwipingInProgress || mExpandingNotification
+ if (!isScrollingEnabled()
+ || !mIsExpanded
+ || mSwipeHelper.isSwiping()
+ || mExpandingNotification
|| mDisallowScrollingInThisMotion) {
return false;
}
@@ -4078,14 +4072,6 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable
return false;
}
- @ShadeViewRefactor(RefactorComponent.INPUT)
- void setSwipingInProgress(boolean swiping) {
- mSwipingInProgress = swiping;
- if (swiping) {
- requestDisallowInterceptTouchEvent(true);
- }
- }
-
@Override
@ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
public void onWindowFocusChanged(boolean hasWindowFocus) {
@@ -4128,9 +4114,8 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable
mStatusBar.resetUserExpandedStates();
clearTemporaryViews();
clearUserLockedViews();
- ArrayList<View> draggedViews = mAmbientState.getDraggedViews();
- if (draggedViews.size() > 0) {
- draggedViews.clear();
+ if (mSwipeHelper.isSwiping()) {
+ mSwipeHelper.resetSwipeState();
updateContinuousShadowDrawing();
}
}
@@ -5197,15 +5182,11 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable
ExpandableView child = (ExpandableView) getTransientView(i);
child.dump(fd, pw, args);
}
- ArrayList<View> draggedViews = mAmbientState.getDraggedViews();
- int draggedCount = draggedViews.size();
- pw.println(" Dragged Views: " + draggedCount);
- for (int i = 0; i < draggedCount; i++) {
- View view = draggedViews.get(i);
- if (view instanceof ExpandableView) {
- ExpandableView expandableView = (ExpandableView) view;
- expandableView.dump(fd, pw, args);
- }
+ View swipedView = mSwipeHelper.getSwipedView();
+ pw.println(" Swiped view: " + swipedView);
+ if (swipedView instanceof ExpandableView) {
+ ExpandableView expandableView = (ExpandableView) swipedView;
+ expandableView.dump(fd, pw, args);
}
}
@@ -5523,13 +5504,15 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable
mSwipedOutViews.add(v);
}
- void addDraggedView(View view) {
- mAmbientState.onBeginDrag(view);
+ void onSwipeBegin() {
+ requestDisallowInterceptTouchEvent(true);
updateFirstAndLastBackgroundViews();
+ updateContinuousShadowDrawing();
+ updateContinuousBackgroundDrawing();
+ requestChildrenUpdate();
}
- void removeDraggedView(View view) {
- mAmbientState.onDragFinished(view);
+ void onSwipeEnd() {
updateFirstAndLastBackgroundViews();
}
@@ -5542,10 +5525,6 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable
mAmbientState.setHasAlertEntries(numHeadsUp > 0);
}
- boolean getSwipingInProgress() {
- return mSwipingInProgress;
- }
-
public boolean getIsExpanded() {
return mIsExpanded;
}
@@ -5586,10 +5565,6 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable
mTouchHandler = touchHandler;
}
- boolean isSwipingInProgress() {
- return mSwipingInProgress;
- }
-
boolean getCheckSnoozeLeaveBehind() {
return mCheckForLeavebehind;
}
@@ -5664,9 +5639,17 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable
mSectionsManager.updateSectionBoundaries(reason);
}
+ boolean isSilkDismissEnabled() {
+ return Settings.Global.getInt(mContext.getContentResolver(),
+ Settings.Global.SHOW_NEW_NOTIF_DISMISS, 1 /* enabled by default */) == 1;
+ }
+
void updateContinuousBackgroundDrawing() {
+ if (isSilkDismissEnabled()) {
+ return;
+ }
boolean continuousBackground = !mAmbientState.isFullyAwake()
- && !mAmbientState.getDraggedViews().isEmpty();
+ && mSwipeHelper.isSwiping();
if (continuousBackground != mContinuousBackgroundUpdate) {
mContinuousBackgroundUpdate = continuousBackground;
if (continuousBackground) {
@@ -5680,7 +5663,7 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable
@ShadeViewRefactor(RefactorComponent.STATE_RESOLVER)
void updateContinuousShadowDrawing() {
boolean continuousShadowUpdate = mAnimationRunning
- || !mAmbientState.getDraggedViews().isEmpty();
+ || mSwipeHelper.isSwiping();
if (continuousShadowUpdate != mContinuousShadowUpdate) {
if (continuousShadowUpdate) {
getViewTreeObserver().addOnPreDrawListener(mShadowUpdater);
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 f5385050f063..006d8da91941 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
@@ -361,7 +361,6 @@ public class NotificationStackScrollLayoutController {
@Override
public void onDragCancelled(View v) {
- mView.setSwipingInProgress(false);
mFalsingManager.onNotificationStopDismissing();
}
@@ -392,14 +391,10 @@ public class NotificationStackScrollLayoutController {
*/
public void handleChildViewDismissed(View view) {
- mView.setSwipingInProgress(false);
if (mView.getDismissAllInProgress()) {
return;
}
-
- mView.removeDraggedView(view);
- mView.updateContinuousShadowDrawing();
-
+ mView.onSwipeEnd();
if (view instanceof ExpandableNotificationRow) {
ExpandableNotificationRow row = (ExpandableNotificationRow) view;
if (row.isHeadsUp()) {
@@ -454,18 +449,12 @@ public class NotificationStackScrollLayoutController {
@Override
public void onBeginDrag(View v) {
mFalsingManager.onNotificationStartDismissing();
- mView.setSwipingInProgress(true);
- mView.addDraggedView(v);
- mView.updateContinuousShadowDrawing();
- mView.updateContinuousBackgroundDrawing();
- mView.requestChildrenUpdate();
+ mView.onSwipeBegin();
}
@Override
public void onChildSnappedBack(View animView, float targetLeft) {
- mView.removeDraggedView(animView);
- mView.updateContinuousShadowDrawing();
- mView.updateContinuousBackgroundDrawing();
+ mView.onSwipeEnd();
if (animView instanceof ExpandableNotificationRow) {
ExpandableNotificationRow row = (ExpandableNotificationRow) animView;
if (row.isPinned() && !canChildBeDismissed(row)
@@ -1536,12 +1525,12 @@ public class NotificationStackScrollLayoutController {
NotificationGuts guts = mNotificationGutsManager.getExposedGuts();
boolean expandWantsIt = false;
- boolean swipingInProgress = mView.isSwipingInProgress();
- if (!swipingInProgress && !mView.getOnlyScrollingInThisMotion() && guts == null) {
+ if (!mSwipeHelper.isSwiping()
+ && !mView.getOnlyScrollingInThisMotion() && guts == null) {
expandWantsIt = mView.getExpandHelper().onInterceptTouchEvent(ev);
}
boolean scrollWantsIt = false;
- if (!swipingInProgress && !mView.isExpandingNotification()) {
+ if (!mSwipeHelper.isSwiping() && !mView.isExpandingNotification()) {
scrollWantsIt = mView.onInterceptTouchEventScroll(ev);
}
boolean swipeWantsIt = false;
@@ -1582,10 +1571,9 @@ public class NotificationStackScrollLayoutController {
|| ev.getActionMasked() == MotionEvent.ACTION_UP;
mView.handleEmptySpaceClick(ev);
boolean expandWantsIt = false;
- boolean swipingInProgress = mView.getSwipingInProgress();
boolean onlyScrollingInThisMotion = mView.getOnlyScrollingInThisMotion();
boolean expandingNotification = mView.isExpandingNotification();
- if (mView.getIsExpanded() && !swipingInProgress && !onlyScrollingInThisMotion
+ if (mView.getIsExpanded() && !mSwipeHelper.isSwiping() && !onlyScrollingInThisMotion
&& guts == null) {
ExpandHelper expandHelper = mView.getExpandHelper();
if (isCancelOrUp) {
@@ -1600,7 +1588,7 @@ public class NotificationStackScrollLayoutController {
}
}
boolean scrollerWantsIt = false;
- if (mView.isExpanded() && !swipingInProgress && !expandingNotification
+ if (mView.isExpanded() && !mSwipeHelper.isSwiping() && !expandingNotification
&& !mView.getDisallowScrollingInThisMotion()) {
scrollerWantsIt = mView.onScrollTouch(ev);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DoubleTapHelper.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DoubleTapHelper.java
deleted file mode 100644
index 78ea5c03a7b5..000000000000
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DoubleTapHelper.java
+++ /dev/null
@@ -1,176 +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.statusbar.phone;
-
-import android.view.MotionEvent;
-import android.view.View;
-import android.view.ViewConfiguration;
-
-import com.android.systemui.R;
-
-/**
- * Detects a double tap.
- */
-public class DoubleTapHelper {
-
- private static final long DOUBLETAP_TIMEOUT_MS = 1200;
-
- private final View mView;
- private final ActivationListener mActivationListener;
- private final DoubleTapListener mDoubleTapListener;
- private final SlideBackListener mSlideBackListener;
- private final DoubleTapLogListener mDoubleTapLogListener;
-
- private float mTouchSlop;
- private float mDoubleTapSlop;
-
- private boolean mActivated;
-
- private float mDownX;
- private float mDownY;
- private boolean mTrackTouch;
-
- private float mActivationX;
- private float mActivationY;
- private Runnable mTapTimeoutRunnable = this::makeInactive;
-
- public DoubleTapHelper(View view, ActivationListener activationListener,
- DoubleTapListener doubleTapListener, SlideBackListener slideBackListener,
- DoubleTapLogListener doubleTapLogListener) {
- mTouchSlop = ViewConfiguration.get(view.getContext()).getScaledTouchSlop();
- mDoubleTapSlop = view.getResources().getDimension(R.dimen.double_tap_slop);
- mView = view;
-
- mActivationListener = activationListener;
- mDoubleTapListener = doubleTapListener;
- mSlideBackListener = slideBackListener;
- mDoubleTapLogListener = doubleTapLogListener;
- }
-
- public boolean onTouchEvent(MotionEvent event) {
- return onTouchEvent(event, Integer.MAX_VALUE);
- }
-
- public boolean onTouchEvent(MotionEvent event, int maxTouchableHeight) {
- int action = event.getActionMasked();
- switch (action) {
- case MotionEvent.ACTION_DOWN:
- mDownX = event.getX();
- mDownY = event.getY();
- mTrackTouch = true;
- if (mDownY > maxTouchableHeight) {
- mTrackTouch = false;
- }
- break;
- case MotionEvent.ACTION_MOVE:
- if (!isWithinTouchSlop(event)) {
- makeInactive();
- mTrackTouch = false;
- }
- break;
- case MotionEvent.ACTION_UP:
- if (isWithinTouchSlop(event)) {
- if (mSlideBackListener != null && mSlideBackListener.onSlideBack()) {
- return true;
- }
- if (!mActivated) {
- makeActive();
- mView.postDelayed(mTapTimeoutRunnable, DOUBLETAP_TIMEOUT_MS);
- mActivationX = event.getX();
- mActivationY = event.getY();
- } else {
- boolean withinDoubleTapSlop = isWithinDoubleTapSlop(event);
- if (mDoubleTapLogListener != null) {
- mDoubleTapLogListener.onDoubleTapLog(withinDoubleTapSlop,
- event.getX() - mActivationX,
- event.getY() - mActivationY);
- }
- if (withinDoubleTapSlop) {
- makeInactive();
- if (!mDoubleTapListener.onDoubleTap()) {
- return false;
- }
- } else {
- makeInactive();
- mTrackTouch = false;
- }
- }
- } else {
- makeInactive();
- mTrackTouch = false;
- }
- break;
- case MotionEvent.ACTION_CANCEL:
- makeInactive();
- mTrackTouch = false;
- break;
- default:
- break;
- }
- return mTrackTouch;
- }
-
- private void makeActive() {
- if (!mActivated) {
- mActivated = true;
- mActivationListener.onActiveChanged(true);
- }
- }
-
- private void makeInactive() {
- if (mActivated) {
- mActivated = false;
- mActivationListener.onActiveChanged(false);
- mView.removeCallbacks(mTapTimeoutRunnable);
- }
- }
-
- private boolean isWithinTouchSlop(MotionEvent event) {
- return Math.abs(event.getX() - mDownX) < mTouchSlop
- && Math.abs(event.getY() - mDownY) < mTouchSlop;
- }
-
- public boolean isWithinDoubleTapSlop(MotionEvent event) {
- if (!mActivated) {
- // If we're not activated there's no double tap slop to satisfy.
- return true;
- }
-
- return Math.abs(event.getX() - mActivationX) < mDoubleTapSlop
- && Math.abs(event.getY() - mActivationY) < mDoubleTapSlop;
- }
-
- @FunctionalInterface
- public interface ActivationListener {
- void onActiveChanged(boolean active);
- }
-
- @FunctionalInterface
- public interface DoubleTapListener {
- boolean onDoubleTap();
- }
-
- @FunctionalInterface
- public interface SlideBackListener {
- boolean onSlideBack();
- }
-
- @FunctionalInterface
- public interface DoubleTapLogListener {
- void onDoubleTapLog(boolean accepted, float dx, float dy);
- }
-}
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 c936e82c2a16..6b8881168e4e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java
@@ -926,6 +926,8 @@ public class NotificationPanelViewController extends PanelViewController {
if (mUpdateMonitor.isUdfpsEnrolled()) {
availableSpace = mNotificationStackScrollLayoutController.getHeight()
- minPadding - shelfSize
+ - mKeyguardStatusViewController.getOwnerInfoHeight()
+ - mKeyguardStatusViewController.getLogoutButtonHeight()
- (mStatusBar.getDisplayHeight() - mAuthController.getUdfpsRegion().top);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationTapHelper.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationTapHelper.java
new file mode 100644
index 000000000000..50c8e2e0d710
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationTapHelper.java
@@ -0,0 +1,163 @@
+/*
+ * 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.statusbar.phone;
+
+import android.view.MotionEvent;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.systemui.dagger.qualifiers.Main;
+import com.android.systemui.plugins.FalsingManager;
+import com.android.systemui.util.concurrency.DelayableExecutor;
+
+import javax.inject.Inject;
+
+/**
+ * Detects single and double taps on notifications.
+ */
+public class NotificationTapHelper {
+
+ public static final long DOUBLE_TAP_TIMEOUT_MS = 1200;
+
+ private final ActivationListener mActivationListener;
+ private final DoubleTapListener mDoubleTapListener;
+ private final FalsingManager mFalsingManager;
+ private final DelayableExecutor mExecutor;
+ private final SlideBackListener mSlideBackListener;
+
+ private boolean mTrackTouch;
+ private Runnable mTimeoutCancel;
+
+ private NotificationTapHelper(FalsingManager falsingManager, DelayableExecutor executor,
+ ActivationListener activationListener, DoubleTapListener doubleTapListener,
+ SlideBackListener slideBackListener) {
+ mFalsingManager = falsingManager;
+ mExecutor = executor;
+ mActivationListener = activationListener;
+ mDoubleTapListener = doubleTapListener;
+ mSlideBackListener = slideBackListener;
+ }
+
+ @VisibleForTesting
+ boolean onTouchEvent(MotionEvent event) {
+ return onTouchEvent(event, Integer.MAX_VALUE);
+ }
+
+ /** Call to have the helper process a touch event. */
+ public boolean onTouchEvent(MotionEvent event, int maxTouchableHeight) {
+ int action = event.getActionMasked();
+ switch (action) {
+ case MotionEvent.ACTION_DOWN:
+ mTrackTouch = event.getY() <= maxTouchableHeight;
+ break;
+ case MotionEvent.ACTION_MOVE:
+ if (mTrackTouch && mFalsingManager.isFalseTap(false)) {
+ makeInactive();
+ mTrackTouch = false;
+ }
+ break;
+ case MotionEvent.ACTION_CANCEL:
+ makeInactive();
+ mTrackTouch = false;
+ break;
+ case MotionEvent.ACTION_UP:
+ mTrackTouch = false;
+
+ // 1) See if we have confidence that we can activate after a single tap.
+ // 2) Else, see if it looks like a tap at all and check for a double-tap.
+ if (!mFalsingManager.isFalseTap(true)) {
+ makeInactive();
+ return mDoubleTapListener.onDoubleTap();
+ } else if (!mFalsingManager.isFalseTap(false)) {
+ if (mSlideBackListener != null && mSlideBackListener.onSlideBack()) {
+ return true;
+ }
+ if (mTimeoutCancel == null) {
+ // first tap
+ makeActive();
+ return true;
+ } else {
+ // second tap
+ makeInactive();
+ if (!mFalsingManager.isFalseDoubleTap()) {
+ return mDoubleTapListener.onDoubleTap();
+ }
+ }
+ } else {
+ makeInactive();
+ }
+ break;
+ default:
+ break;
+ }
+ return mTrackTouch;
+ }
+
+ private void makeActive() {
+ mTimeoutCancel = mExecutor.executeDelayed(this::makeInactive, DOUBLE_TAP_TIMEOUT_MS);
+ mActivationListener.onActiveChanged(true);
+ }
+
+ private void makeInactive() {
+ mActivationListener.onActiveChanged(false);
+ if (mTimeoutCancel != null) {
+ mTimeoutCancel.run();
+ mTimeoutCancel = null;
+ }
+ }
+
+ /** */
+ @FunctionalInterface
+ public interface ActivationListener {
+ /** */
+ void onActiveChanged(boolean active);
+ }
+
+ /** */
+ @FunctionalInterface
+ public interface DoubleTapListener {
+ /** */
+ boolean onDoubleTap();
+ }
+
+ /** */
+ @FunctionalInterface
+ public interface SlideBackListener {
+ /** */
+ boolean onSlideBack();
+ }
+
+ /**
+ * Injectable factory that creates a {@link NotificationTapHelper}.
+ */
+ public static class Factory {
+ private final FalsingManager mFalsingManager;
+ private final DelayableExecutor mDelayableExecutor;
+
+ @Inject
+ public Factory(FalsingManager falsingManager, @Main DelayableExecutor delayableExecutor) {
+ mFalsingManager = falsingManager;
+ mDelayableExecutor = delayableExecutor;
+ }
+
+ /** Create a {@link NotificationTapHelper} */
+ public NotificationTapHelper create(ActivationListener activationListener,
+ DoubleTapListener doubleTapListener, SlideBackListener slideBackListener) {
+ return new NotificationTapHelper(mFalsingManager, mDelayableExecutor,
+ activationListener, doubleTapListener, slideBackListener);
+ }
+ }
+}
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 5d8424592cd2..e6ac7dcee8a7 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -147,7 +147,6 @@ import com.android.systemui.SystemUI;
import com.android.systemui.assist.AssistManager;
import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.charging.WirelessChargingAnimation;
-import com.android.systemui.classifier.FalsingLog;
import com.android.systemui.colorextraction.SysuiColorExtractor;
import com.android.systemui.dagger.qualifiers.UiBackground;
import com.android.systemui.demomode.DemoMode;
@@ -1250,10 +1249,6 @@ public class StatusBar extends SystemUI implements DemoMode,
message.write(SystemProperties.get("ro.serialno"));
message.write("\n");
- PrintWriter falsingPw = new PrintWriter(message);
- FalsingLog.dump(falsingPw);
- falsingPw.flush();
-
startActivityDismissingKeyguard(Intent.createChooser(new Intent(Intent.ACTION_SEND)
.setType("*/*")
.putExtra(Intent.EXTRA_SUBJECT, "Rejected touch report")
@@ -2676,9 +2671,6 @@ public class StatusBar extends SystemUI implements DemoMode,
mLightBarController.dump(fd, pw, args);
}
- mFalsingManager.dump(pw);
- FalsingLog.dump(pw);
-
pw.println("SharedPreferences:");
for (Map.Entry<String, ?> entry : Prefs.getAll(mContext).entrySet()) {
pw.print(" "); pw.print(entry.getKey()); pw.print("="); pw.println(entry.getValue());
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
index f9dfd7a769a7..b912614ba3e8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
@@ -26,13 +26,17 @@ import static com.android.systemui.statusbar.phone.BiometricUnlockController.MOD
import android.content.ComponentCallbacks2;
import android.content.Context;
import android.content.res.ColorStateList;
+import android.content.res.Configuration;
import android.os.Bundle;
import android.os.SystemClock;
+import android.util.TypedValue;
+import android.view.Gravity;
import android.view.KeyEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewRootImpl;
import android.view.WindowManagerGlobal;
+import android.widget.FrameLayout;
import androidx.annotation.VisibleForTesting;
@@ -160,6 +164,8 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb
private boolean mPulsing;
private boolean mGesturalNav;
private boolean mIsDocked;
+ private boolean mIsPortraitMode;
+ private int mScreenWidthDp;
protected boolean mFirstUpdate = true;
protected boolean mLastShowing;
@@ -174,6 +180,7 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb
private boolean mLastPulsing;
private int mLastBiometricMode;
private boolean mLastLockVisible;
+ private boolean mLastLockOrientationIsPortrait;
private OnDismissAction mAfterKeyguardGoneAction;
private Runnable mKeyguardGoneCancelAction;
@@ -263,6 +270,9 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb
mKeyguardUpdateManager.registerCallback(mUpdateMonitorCallback);
mStatusBarStateController.addCallback(this);
mConfigurationController.addCallback(this);
+ mIsPortraitMode = mContext.getResources().getConfiguration().orientation
+ == Configuration.ORIENTATION_PORTRAIT;
+ mScreenWidthDp = mContext.getResources().getConfiguration().screenWidthDp;
mGesturalNav = QuickStepContract.isGesturalMode(
mNavigationModeController.addListener(this));
if (mDockManager != null) {
@@ -272,6 +282,18 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb
}
@Override
+ public void onDensityOrFontScaleChanged() {
+ hideBouncer(true /* destroyView */);
+ }
+
+ @Override
+ public void onConfigChanged(Configuration newConfig) {
+ mIsPortraitMode = newConfig.orientation == Configuration.ORIENTATION_PORTRAIT;
+ mScreenWidthDp = newConfig.screenWidthDp;
+ updateLockIcon();
+ }
+
+ @Override
public void onPanelExpansionChanged(float expansion, boolean tracking) {
// We don't want to translate the bounce when:
// • Keyguard is occluded, because we're in a FLAG_SHOW_WHEN_LOCKED activity and need to
@@ -317,14 +339,32 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb
if (mLockIconContainer == null) {
return;
}
+
boolean keyguardWithoutQs = mStatusBarStateController.getState() == StatusBarState.KEYGUARD
&& !mNotificationPanelViewController.isQsExpanded();
boolean lockVisible = (mBouncer.isShowing() || keyguardWithoutQs)
&& !mBouncer.isAnimatingAway() && !mKeyguardStateController.isKeyguardFadingAway();
+ boolean orientationChange =
+ lockVisible && (mLastLockOrientationIsPortrait != mIsPortraitMode);
- if (mLastLockVisible != lockVisible) {
+ if (mLastLockVisible != lockVisible || orientationChange) {
mLastLockVisible = lockVisible;
+ mLastLockOrientationIsPortrait = mIsPortraitMode;
if (lockVisible) {
+ FrameLayout.LayoutParams lp =
+ (FrameLayout.LayoutParams) mLockIconContainer.getLayoutParams();
+ if (mIsPortraitMode) {
+ lp.gravity = Gravity.TOP | Gravity.CENTER_HORIZONTAL;
+ } else {
+ final int width = (int) TypedValue.applyDimension(
+ TypedValue.COMPLEX_UNIT_DIP,
+ mScreenWidthDp,
+ mContext.getResources().getDisplayMetrics()) / 3;
+ mLockIconContainer.setMinimumWidth(width);
+ lp.gravity = Gravity.TOP | Gravity.LEFT;
+ }
+ mLockIconContainer.setLayoutParams(lp);
+
CrossFadeHelper.fadeIn(mLockIconContainer,
AppearAnimationUtils.DEFAULT_APPEAR_DURATION /* duration */,
0 /* delay */);
@@ -685,11 +725,6 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb
}
@Override
- public void onDensityOrFontScaleChanged() {
- hideBouncer(true /* destroyView */);
- }
-
- @Override
public void onNavigationModeChanged(int mode) {
boolean gesturalNav = QuickStepContract.isGesturalMode(mode);
if (gesturalNav != mGesturalNav) {
diff --git a/packages/SystemUI/src/com/android/systemui/util/InjectionInflationController.java b/packages/SystemUI/src/com/android/systemui/util/InjectionInflationController.java
index 4b4e1df21bd0..cdc5d8795b91 100644
--- a/packages/SystemUI/src/com/android/systemui/util/InjectionInflationController.java
+++ b/packages/SystemUI/src/com/android/systemui/util/InjectionInflationController.java
@@ -24,8 +24,6 @@ import android.view.LayoutInflater;
import android.view.View;
import com.android.systemui.dagger.SysUISingleton;
-import com.android.systemui.qs.QSPanel;
-import com.android.systemui.qs.QuickQSPanel;
import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout;
import java.lang.reflect.InvocationTargetException;
@@ -93,16 +91,6 @@ public class InjectionInflationController {
* Creates the NotificationStackScrollLayout.
*/
NotificationStackScrollLayout createNotificationStackScrollLayout();
-
- /**
- * Creates the QSPanel.
- */
- QSPanel createQSPanel();
-
- /**
- * Creates the QuickQSPanel.
- */
- QuickQSPanel createQuickQSPanel();
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/classifier/FalsingManagerProxyTest.java b/packages/SystemUI/tests/src/com/android/systemui/classifier/FalsingManagerProxyTest.java
deleted file mode 100644
index c3c9ecc23d59..000000000000
--- a/packages/SystemUI/tests/src/com/android/systemui/classifier/FalsingManagerProxyTest.java
+++ /dev/null
@@ -1,128 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.classifier;
-
-import static com.android.internal.config.sysui.SystemUiDeviceConfigFlags.BRIGHTLINE_FALSING_MANAGER_ENABLED;
-
-import static org.hamcrest.CoreMatchers.instanceOf;
-import static org.junit.Assert.assertThat;
-
-import android.provider.DeviceConfig;
-import android.testing.AndroidTestingRunner;
-import android.util.DisplayMetrics;
-
-import androidx.test.filters.SmallTest;
-
-import com.android.internal.logging.testing.UiEventLoggerFake;
-import com.android.keyguard.KeyguardUpdateMonitor;
-import com.android.systemui.classifier.brightline.BrightLineFalsingManager;
-import com.android.systemui.classifier.brightline.FalsingDataProvider;
-import com.android.systemui.dock.DockManager;
-import com.android.systemui.dock.DockManagerFake;
-import com.android.systemui.dump.DumpManager;
-import com.android.systemui.plugins.statusbar.StatusBarStateController;
-import com.android.systemui.shared.plugins.PluginManager;
-import com.android.systemui.statusbar.StatusBarStateControllerImpl;
-import com.android.systemui.util.DeviceConfigProxy;
-import com.android.systemui.util.DeviceConfigProxyFake;
-import com.android.systemui.util.concurrency.FakeExecutor;
-import com.android.systemui.util.sensors.ProximitySensor;
-import com.android.systemui.util.time.FakeSystemClock;
-import com.android.systemui.utils.leaks.FakeBatteryController;
-import com.android.systemui.utils.leaks.LeakCheckedTest;
-
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
-
-@SmallTest
-@RunWith(AndroidTestingRunner.class)
-public class FalsingManagerProxyTest extends LeakCheckedTest {
- @Mock(stubOnly = true)
- PluginManager mPluginManager;
- @Mock(stubOnly = true)
- ProximitySensor mProximitySensor;
- @Mock(stubOnly = true)
- private KeyguardUpdateMonitor mKeyguardUpdateMonitor;
- @Mock DumpManager mDumpManager;
- private FalsingManagerProxy mProxy;
- private DeviceConfigProxy mDeviceConfig;
- private FalsingDataProvider mFalsingDataProvider;
- private FakeExecutor mExecutor = new FakeExecutor(new FakeSystemClock());
- private FakeExecutor mUiBgExecutor = new FakeExecutor(new FakeSystemClock());
- private DockManager mDockManager = new DockManagerFake();
- private StatusBarStateController mStatusBarStateController =
- new StatusBarStateControllerImpl(new UiEventLoggerFake());
-
- @Before
- public void setup() {
- MockitoAnnotations.initMocks(this);
- mDeviceConfig = new DeviceConfigProxyFake();
- mDeviceConfig.setProperty(DeviceConfig.NAMESPACE_SYSTEMUI,
- BRIGHTLINE_FALSING_MANAGER_ENABLED, "false", false);
- mFalsingDataProvider = new FalsingDataProvider(
- new DisplayMetrics(), new FakeBatteryController(getLeakCheck()));
- }
-
- @After
- public void tearDown() {
- if (mProxy != null) {
- mProxy.cleanup();
- }
- }
-
- @Test
- public void test_brightLineFalsingManagerDisabled() {
- mProxy = new FalsingManagerProxy(getContext(), mPluginManager, mExecutor,
- mProximitySensor, mDeviceConfig, mDockManager, mKeyguardUpdateMonitor,
- mDumpManager, mUiBgExecutor, mStatusBarStateController, mFalsingDataProvider);
- assertThat(mProxy.getInternalFalsingManager(), instanceOf(FalsingManagerImpl.class));
- }
-
- @Test
- public void test_brightLineFalsingManagerEnabled() throws InterruptedException {
- mDeviceConfig.setProperty(DeviceConfig.NAMESPACE_SYSTEMUI,
- BRIGHTLINE_FALSING_MANAGER_ENABLED, "true", false);
- mExecutor.runAllReady();
- mProxy = new FalsingManagerProxy(getContext(), mPluginManager, mExecutor,
- mProximitySensor, mDeviceConfig, mDockManager, mKeyguardUpdateMonitor,
- mDumpManager, mUiBgExecutor, mStatusBarStateController, mFalsingDataProvider);
- assertThat(mProxy.getInternalFalsingManager(), instanceOf(BrightLineFalsingManager.class));
- }
-
- @Test
- public void test_brightLineFalsingManagerToggled() throws InterruptedException {
- mProxy = new FalsingManagerProxy(getContext(), mPluginManager, mExecutor,
- mProximitySensor, mDeviceConfig, mDockManager, mKeyguardUpdateMonitor,
- mDumpManager, mUiBgExecutor, mStatusBarStateController, mFalsingDataProvider);
- assertThat(mProxy.getInternalFalsingManager(), instanceOf(FalsingManagerImpl.class));
-
- mDeviceConfig.setProperty(DeviceConfig.NAMESPACE_SYSTEMUI,
- BRIGHTLINE_FALSING_MANAGER_ENABLED, "true", false);
- mExecutor.runAllReady();
- assertThat(mProxy.getInternalFalsingManager(),
- instanceOf(BrightLineFalsingManager.class));
-
- mDeviceConfig.setProperty(DeviceConfig.NAMESPACE_SYSTEMUI,
- BRIGHTLINE_FALSING_MANAGER_ENABLED, "false", false);
- mExecutor.runAllReady();
- assertThat(mProxy.getInternalFalsingManager(), instanceOf(FalsingManagerImpl.class));
- }
-}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/classifier/brightline/BrightLineFalsingManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/classifier/brightline/BrightLineFalsingManagerTest.java
index 061664b4f6d4..30dddc02be90 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/classifier/brightline/BrightLineFalsingManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/classifier/brightline/BrightLineFalsingManagerTest.java
@@ -20,14 +20,18 @@ import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+import android.content.res.Resources;
import android.test.suitebuilder.annotation.SmallTest;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
import android.util.DisplayMetrics;
+import android.view.ViewConfiguration;
import com.android.internal.logging.testing.UiEventLoggerFake;
import com.android.keyguard.KeyguardUpdateMonitor;
+import com.android.systemui.R;
import com.android.systemui.dock.DockManager;
import com.android.systemui.dock.DockManagerFake;
import com.android.systemui.statusbar.StatusBarState;
@@ -37,6 +41,7 @@ import com.android.systemui.util.DeviceConfigProxy;
import com.android.systemui.util.DeviceConfigProxyFake;
import com.android.systemui.util.sensors.ProximitySensor;
import com.android.systemui.util.sensors.ThresholdSensor;
+import com.android.systemui.util.time.FakeSystemClock;
import com.android.systemui.utils.leaks.FakeBatteryController;
import com.android.systemui.utils.leaks.LeakCheckedTest;
@@ -56,6 +61,10 @@ public class BrightLineFalsingManagerTest extends LeakCheckedTest {
private KeyguardUpdateMonitor mKeyguardUpdateMonitor;
@Mock
private ProximitySensor mProximitySensor;
+ @Mock
+ private Resources mResources;
+ @Mock
+ private ViewConfiguration mViewConfiguration;
private SysuiStatusBarStateController mStatusBarStateController;
private FalsingDataProvider mFalsingDataProvider;
private FakeBatteryController mFakeBatteryController;
@@ -71,14 +80,17 @@ public class BrightLineFalsingManagerTest extends LeakCheckedTest {
dm.ydpi = 100;
dm.widthPixels = 100;
dm.heightPixels = 100;
- mFalsingDataProvider = new FalsingDataProvider(dm, mFakeBatteryController);
+ mFalsingDataProvider = new FalsingDataProvider(dm, mFakeBatteryController,
+ new FakeSystemClock());
DeviceConfigProxy deviceConfigProxy = new DeviceConfigProxyFake();
DockManager dockManager = new DockManagerFake();
mStatusBarStateController = new StatusBarStateControllerImpl(new UiEventLoggerFake());
mStatusBarStateController.setState(StatusBarState.KEYGUARD);
+ when(mResources.getDimension(R.dimen.double_tap_slop)).thenReturn(1f);
+ when(mViewConfiguration.getScaledTouchSlop()).thenReturn(1);
mFalsingManager = new BrightLineFalsingManager(mFalsingDataProvider,
- mKeyguardUpdateMonitor, mProximitySensor, deviceConfigProxy, dockManager,
- mStatusBarStateController);
+ mKeyguardUpdateMonitor, mProximitySensor, deviceConfigProxy, mResources,
+ mViewConfiguration, dockManager, mStatusBarStateController);
}
@Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/classifier/brightline/ClassifierTest.java b/packages/SystemUI/tests/src/com/android/systemui/classifier/brightline/ClassifierTest.java
index a4d198a14541..69d39fa10b72 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/classifier/brightline/ClassifierTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/classifier/brightline/ClassifierTest.java
@@ -21,6 +21,7 @@ import static com.android.systemui.classifier.Classifier.UNLOCK;
import android.util.DisplayMetrics;
import android.view.MotionEvent;
+import com.android.systemui.util.time.FakeSystemClock;
import com.android.systemui.utils.leaks.FakeBatteryController;
import com.android.systemui.utils.leaks.LeakCheckedTest;
@@ -44,7 +45,8 @@ public class ClassifierTest extends LeakCheckedTest {
displayMetrics.widthPixels = 1000;
displayMetrics.heightPixels = 1000;
mFakeBatteryController = new FakeBatteryController(getLeakCheck());
- mDataProvider = new FalsingDataProvider(displayMetrics, mFakeBatteryController);
+ mDataProvider = new FalsingDataProvider(displayMetrics, mFakeBatteryController,
+ new FakeSystemClock());
mDataProvider.setInteractionType(UNLOCK);
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/classifier/brightline/DoubleTapClassifierTest.java b/packages/SystemUI/tests/src/com/android/systemui/classifier/brightline/DoubleTapClassifierTest.java
new file mode 100644
index 000000000000..9f3a1e4821c9
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/classifier/brightline/DoubleTapClassifierTest.java
@@ -0,0 +1,182 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.classifier.brightline;
+
+import static org.hamcrest.CoreMatchers.is;
+import static org.junit.Assert.assertThat;
+import static org.mockito.ArgumentMatchers.anyList;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.when;
+
+import android.testing.AndroidTestingRunner;
+import android.view.MotionEvent;
+
+import androidx.test.filters.SmallTest;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+import java.util.ArrayList;
+import java.util.Deque;
+import java.util.LinkedList;
+import java.util.List;
+
+@SmallTest
+@RunWith(AndroidTestingRunner.class)
+public class DoubleTapClassifierTest extends ClassifierTest {
+
+ private static final int TOUCH_SLOP = 100;
+ private static final long DOUBLE_TAP_TIMEOUT_MS = 100;
+
+ private List<MotionEvent> mMotionEvents = new ArrayList<>();
+ private final Deque<List<MotionEvent>> mHistoricalMotionEvents = new LinkedList<>();
+
+ @Mock
+ private FalsingDataProvider mDataProvider;
+ @Mock
+ private SingleTapClassifier mSingleTapClassifier;
+ private DoubleTapClassifier mClassifier;
+
+ @Before
+ public void setup() {
+ super.setup();
+ MockitoAnnotations.initMocks(this);
+ mClassifier = new DoubleTapClassifier(mDataProvider, mSingleTapClassifier, TOUCH_SLOP,
+ DOUBLE_TAP_TIMEOUT_MS);
+ doReturn(mHistoricalMotionEvents).when(mDataProvider).getHistoricalMotionEvents();
+ }
+
+ @After
+ public void tearDown() {
+ for (MotionEvent motionEvent : mMotionEvents) {
+ motionEvent.recycle();
+ }
+
+ mMotionEvents.clear();
+ super.tearDown();
+ }
+
+
+ @Test
+ public void testSingleTap() {
+ when(mSingleTapClassifier.isTap(anyList())).thenReturn(true);
+ addMotionEvent(0, 0, MotionEvent.ACTION_DOWN, 1, 1);
+ addMotionEvent(0, 1, MotionEvent.ACTION_UP, TOUCH_SLOP, 1);
+
+ boolean result = mClassifier.isFalseTouch();
+ assertThat("Single tap recognized as a valid double tap", result, is(true));
+ }
+
+ @Test
+ public void testDoubleTap() {
+ when(mSingleTapClassifier.isTap(anyList())).thenReturn(true);
+
+ addMotionEvent(0, 0, MotionEvent.ACTION_DOWN, 1, 1);
+ addMotionEvent(0, 1, MotionEvent.ACTION_UP, 1, 1);
+
+ archiveMotionEvents();
+
+ addMotionEvent(2, 2, MotionEvent.ACTION_DOWN, TOUCH_SLOP, TOUCH_SLOP);
+ addMotionEvent(2, 3, MotionEvent.ACTION_UP, TOUCH_SLOP, TOUCH_SLOP);
+
+ boolean result = mClassifier.isFalseTouch();
+ assertThat(mClassifier.getReason(), result, is(false));
+ }
+
+ @Test
+ public void testBadFirstTap() {
+ when(mSingleTapClassifier.isTap(anyList())).thenReturn(false, true);
+
+ addMotionEvent(0, 0, MotionEvent.ACTION_DOWN, 1, 1);
+ addMotionEvent(0, 1, MotionEvent.ACTION_UP, 1, 1);
+
+ archiveMotionEvents();
+
+ addMotionEvent(2, 2, MotionEvent.ACTION_DOWN, 1, 1);
+ addMotionEvent(2, 3, MotionEvent.ACTION_UP, 1, 1);
+
+ boolean result = mClassifier.isFalseTouch();
+ assertThat("Bad first touch allowed", result, is(true));
+ }
+
+ @Test
+ public void testBadSecondTap() {
+ when(mSingleTapClassifier.isTap(anyList())).thenReturn(true, false);
+
+ addMotionEvent(0, 0, MotionEvent.ACTION_DOWN, 1, 1);
+ addMotionEvent(0, 1, MotionEvent.ACTION_UP, 1, 1);
+
+ archiveMotionEvents();
+
+ addMotionEvent(2, 2, MotionEvent.ACTION_DOWN, 1, 1);
+ addMotionEvent(2, 3, MotionEvent.ACTION_UP, 1, 1);
+
+ boolean result = mClassifier.isFalseTouch();
+ assertThat("Bad second touch allowed", result, is(true));
+ }
+
+ @Test
+ public void testBadTouchSlop() {
+ when(mSingleTapClassifier.isTap(anyList())).thenReturn(true);
+
+ addMotionEvent(0, 0, MotionEvent.ACTION_DOWN, 1, 1);
+ addMotionEvent(0, 1, MotionEvent.ACTION_UP, 1, 1);
+
+ archiveMotionEvents();
+
+ addMotionEvent(2, 2, MotionEvent.ACTION_DOWN, TOUCH_SLOP + 1, TOUCH_SLOP);
+ addMotionEvent(2, 3, MotionEvent.ACTION_UP, TOUCH_SLOP, TOUCH_SLOP + 1);
+
+ boolean result = mClassifier.isFalseTouch();
+ assertThat("Sloppy second touch allowed", result, is(true));
+ }
+
+ @Test
+ public void testBadTouchSlow() {
+ when(mSingleTapClassifier.isTap(anyList())).thenReturn(true);
+
+ addMotionEvent(0, 0, MotionEvent.ACTION_DOWN, 1, 1);
+ addMotionEvent(0, 1, MotionEvent.ACTION_UP, 1, 1);
+
+ archiveMotionEvents();
+
+ addMotionEvent(DOUBLE_TAP_TIMEOUT_MS + 1, DOUBLE_TAP_TIMEOUT_MS + 1,
+ MotionEvent.ACTION_DOWN, 1, 1);
+ addMotionEvent(DOUBLE_TAP_TIMEOUT_MS + 1, DOUBLE_TAP_TIMEOUT_MS + 2,
+ MotionEvent.ACTION_UP, 1, 1);
+
+ boolean result = mClassifier.isFalseTouch();
+ assertThat("Slow second tap allowed", result, is(true));
+ }
+
+ private void addMotionEvent(long downMs, long eventMs, int action, int x, int y) {
+ MotionEvent ev = MotionEvent.obtain(downMs, eventMs, action, x, y, 0);
+ mMotionEvents.add(ev);
+ when(mDataProvider.getRecentMotionEvents()).thenReturn(mMotionEvents);
+ }
+
+ private void archiveMotionEvents() {
+ mHistoricalMotionEvents.addFirst(mMotionEvents);
+ doReturn(mHistoricalMotionEvents).when(mDataProvider).getHistoricalMotionEvents();
+ mMotionEvents = new ArrayList<>();
+
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/classifier/brightline/FalsingDataProviderTest.java b/packages/SystemUI/tests/src/com/android/systemui/classifier/brightline/FalsingDataProviderTest.java
index f13bc7379436..be38f4419372 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/classifier/brightline/FalsingDataProviderTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/classifier/brightline/FalsingDataProviderTest.java
@@ -26,6 +26,7 @@ import android.view.MotionEvent;
import androidx.test.filters.SmallTest;
+import com.android.systemui.util.time.FakeSystemClock;
import com.android.systemui.utils.leaks.FakeBatteryController;
import org.junit.After;
@@ -51,7 +52,8 @@ public class FalsingDataProviderTest extends ClassifierTest {
displayMetrics.ydpi = 100;
displayMetrics.widthPixels = 1000;
displayMetrics.heightPixels = 1000;
- mDataProvider = new FalsingDataProvider(displayMetrics, mFakeBatteryController);
+ mDataProvider = new FalsingDataProvider(displayMetrics, mFakeBatteryController,
+ new FakeSystemClock());
}
@After
diff --git a/packages/SystemUI/tests/src/com/android/systemui/classifier/brightline/SingleTapClassifierTest.java b/packages/SystemUI/tests/src/com/android/systemui/classifier/brightline/SingleTapClassifierTest.java
new file mode 100644
index 000000000000..642b077f0dcf
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/classifier/brightline/SingleTapClassifierTest.java
@@ -0,0 +1,159 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.classifier.brightline;
+
+import static org.hamcrest.CoreMatchers.is;
+import static org.junit.Assert.assertThat;
+import static org.mockito.Mockito.when;
+
+import android.testing.AndroidTestingRunner;
+import android.view.MotionEvent;
+
+import androidx.test.filters.SmallTest;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+import java.util.ArrayList;
+import java.util.List;
+
+@SmallTest
+@RunWith(AndroidTestingRunner.class)
+public class SingleTapClassifierTest extends ClassifierTest {
+
+ private static final int TOUCH_SLOP = 100;
+
+ private final List<MotionEvent> mMotionEvents = new ArrayList<>();
+
+ @Mock
+ private FalsingDataProvider mDataProvider;
+ private SingleTapClassifier mClassifier;
+
+ @Before
+ public void setup() {
+ super.setup();
+ MockitoAnnotations.initMocks(this);
+ mClassifier = new SingleTapClassifier(mDataProvider, TOUCH_SLOP);
+ }
+
+ @After
+ public void tearDown() {
+ for (MotionEvent motionEvent : mMotionEvents) {
+ motionEvent.recycle();
+ }
+
+ mMotionEvents.clear();
+ super.tearDown();
+ }
+
+
+ @Test
+ public void testSimpleTap_XSlop() {
+ addMotionEvent(0, 0, MotionEvent.ACTION_DOWN, 1, 1);
+ addMotionEvent(0, 1, MotionEvent.ACTION_UP, TOUCH_SLOP, 1);
+
+ assertThat(mClassifier.isFalseTouch(), is(false));
+
+ mMotionEvents.clear();
+
+ addMotionEvent(0, 0, MotionEvent.ACTION_DOWN, 1, 1);
+ addMotionEvent(0, 1, MotionEvent.ACTION_UP, -TOUCH_SLOP + 2, 1);
+
+ assertThat(mClassifier.isFalseTouch(), is(false));
+
+ }
+
+ @Test
+ public void testSimpleTap_YSlop() {
+ addMotionEvent(0, 0, MotionEvent.ACTION_DOWN, 1, 1);
+ addMotionEvent(0, 1, MotionEvent.ACTION_UP, 1, TOUCH_SLOP);
+
+ assertThat(mClassifier.isFalseTouch(), is(false));
+
+ mMotionEvents.clear();
+
+ addMotionEvent(0, 0, MotionEvent.ACTION_DOWN, 1, 1);
+ addMotionEvent(0, 1, MotionEvent.ACTION_UP, 1, -TOUCH_SLOP + 2);
+
+ assertThat(mClassifier.isFalseTouch(), is(false));
+ }
+
+
+ @Test
+ public void testFalseTap_XSlop() {
+ addMotionEvent(0, 0, MotionEvent.ACTION_DOWN, 1, 1);
+ addMotionEvent(0, 1, MotionEvent.ACTION_UP, TOUCH_SLOP + 1, 1);
+
+ assertThat(mClassifier.isFalseTouch(), is(true));
+
+ mMotionEvents.clear();
+
+ addMotionEvent(0, 0, MotionEvent.ACTION_DOWN, 1, 1);
+ addMotionEvent(0, 1, MotionEvent.ACTION_UP, -TOUCH_SLOP - 1, 1);
+
+ assertThat(mClassifier.isFalseTouch(), is(true));
+
+ }
+
+ @Test
+ public void testFalseTap_YSlop() {
+ addMotionEvent(0, 0, MotionEvent.ACTION_DOWN, 1, 1);
+ addMotionEvent(0, 1, MotionEvent.ACTION_UP, 1, TOUCH_SLOP + 1);
+
+ assertThat(mClassifier.isFalseTouch(), is(true));
+
+ mMotionEvents.clear();
+
+ addMotionEvent(0, 0, MotionEvent.ACTION_DOWN, 1, 1);
+ addMotionEvent(0, 1, MotionEvent.ACTION_UP, 1, -TOUCH_SLOP - 1);
+
+ assertThat(mClassifier.isFalseTouch(), is(true));
+ }
+
+ @Test
+ public void testLargeMovementFalses() {
+ addMotionEvent(0, 0, MotionEvent.ACTION_DOWN, 1, 1);
+ addMotionEvent(0, 1, MotionEvent.ACTION_MOVE, 1, TOUCH_SLOP + 1);
+ addMotionEvent(0, 2, MotionEvent.ACTION_UP, 1, 1);
+
+ assertThat(mClassifier.isFalseTouch(), is(true));
+ }
+
+ @Test
+ public void testDirectlySuppliedMotionEvents() {
+ addMotionEvent(0, 0, MotionEvent.ACTION_DOWN, 1, 1);
+ addMotionEvent(0, 1, MotionEvent.ACTION_UP, 1, 1);
+
+ assertThat(mClassifier.isTap(mMotionEvents), is(true));
+
+ addMotionEvent(0, 0, MotionEvent.ACTION_DOWN, 1, 1);
+ addMotionEvent(0, 1, MotionEvent.ACTION_UP, 1, TOUCH_SLOP + 1);
+
+ assertThat(mClassifier.isTap(mMotionEvents), is(false));
+
+ }
+
+ private void addMotionEvent(long downMs, long eventMs, int action, int x, int y) {
+ MotionEvent ev = MotionEvent.obtain(downMs, eventMs, action, x, y, 0);
+ mMotionEvents.add(ev);
+ when(mDataProvider.getRecentMotionEvents()).thenReturn(mMotionEvents);
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/classifier/brightline/TimeLimitedMotionEventBufferTest.java b/packages/SystemUI/tests/src/com/android/systemui/classifier/brightline/TimeLimitedMotionEventBufferTest.java
new file mode 100644
index 000000000000..1dfffb271f02
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/classifier/brightline/TimeLimitedMotionEventBufferTest.java
@@ -0,0 +1,108 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.classifier.brightline;
+
+import static org.hamcrest.CoreMatchers.is;
+import static org.junit.Assert.assertThat;
+
+import android.testing.AndroidTestingRunner;
+import android.view.MotionEvent;
+
+import androidx.test.filters.SmallTest;
+
+import com.android.systemui.SysuiTestCase;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.MockitoAnnotations;
+
+@SmallTest
+@RunWith(AndroidTestingRunner.class)
+public class TimeLimitedMotionEventBufferTest extends SysuiTestCase {
+
+ private static final long MAX_AGE_MS = 100;
+
+ private TimeLimitedMotionEventBuffer mBuffer;
+
+ @Before
+ public void setup() {
+ MockitoAnnotations.initMocks(this);
+ mBuffer = new TimeLimitedMotionEventBuffer(MAX_AGE_MS);
+ }
+
+ @After
+ public void tearDown() {
+ for (MotionEvent motionEvent : mBuffer) {
+ motionEvent.recycle();
+ }
+ mBuffer.clear();
+ }
+
+ @Test
+ public void testAllEventsRetained() {
+ MotionEvent eventA = MotionEvent.obtain(0, 0, MotionEvent.ACTION_DOWN, 0, 0, 0);
+ MotionEvent eventB = MotionEvent.obtain(0, 1, MotionEvent.ACTION_MOVE, 0, 0, 0);
+ MotionEvent eventC = MotionEvent.obtain(0, 2, MotionEvent.ACTION_MOVE, 0, 0, 0);
+ MotionEvent eventD = MotionEvent.obtain(0, 3, MotionEvent.ACTION_UP, 0, 0, 0);
+
+ mBuffer.add(eventA);
+ mBuffer.add(eventB);
+ mBuffer.add(eventC);
+ mBuffer.add(eventD);
+
+ assertThat(mBuffer.size(), is(4));
+ }
+
+ @Test
+ public void testOlderEventsRemoved() {
+ MotionEvent eventA = MotionEvent.obtain(0, 0, MotionEvent.ACTION_DOWN, 0, 0, 0);
+ MotionEvent eventB = MotionEvent.obtain(0, 1, MotionEvent.ACTION_MOVE, 0, 0, 0);
+ MotionEvent eventC = MotionEvent.obtain(
+ 0, MAX_AGE_MS + 1, MotionEvent.ACTION_MOVE, 0, 0, 0);
+ MotionEvent eventD = MotionEvent.obtain(
+ 0, MAX_AGE_MS + 2, MotionEvent.ACTION_UP, 0, 0, 0);
+
+ mBuffer.add(eventA);
+ mBuffer.add(eventB);
+ assertThat(mBuffer.size(), is(2));
+
+ mBuffer.add(eventC);
+ mBuffer.add(eventD);
+ assertThat(mBuffer.size(), is(2));
+
+ assertThat(mBuffer.get(0), is(eventC));
+ assertThat(mBuffer.get(1), is(eventD));
+ }
+
+ @Test
+ public void testFullyExpired() {
+ MotionEvent eventA = MotionEvent.obtain(0, 0, MotionEvent.ACTION_DOWN, 0, 0, 0);
+ MotionEvent eventB = MotionEvent.obtain(0, 1, MotionEvent.ACTION_MOVE, 0, 0, 0);
+ MotionEvent eventC = MotionEvent.obtain(0, 2, MotionEvent.ACTION_MOVE, 0, 0, 0);
+ MotionEvent eventD = MotionEvent.obtain(0, 3, MotionEvent.ACTION_UP, 0, 0, 0);
+
+ mBuffer.add(eventA);
+ mBuffer.add(eventB);
+ mBuffer.add(eventC);
+ mBuffer.add(eventD);
+
+ assertThat(mBuffer.isFullyExpired(2), is(false));
+ assertThat(mBuffer.isFullyExpired(6), is(true));
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelControllerBaseTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelControllerBaseTest.java
index 3817703fe135..0dc268a3c186 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelControllerBaseTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelControllerBaseTest.java
@@ -168,14 +168,18 @@ public class QSPanelControllerBaseTest extends SysuiTestCase {
@Test
public void testSetExpanded_Metrics() {
+ when(mQSPanel.isExpanded()).thenReturn(false);
mController.setExpanded(true);
verify(mMetricsLogger).visibility(eq(MetricsEvent.QS_PANEL), eq(true));
+ verify(mQSLogger).logPanelExpanded(true, mQSPanel.getDumpableTag());
assertEquals(1, mUiEventLogger.numLogs());
assertEquals(QSEvent.QS_PANEL_EXPANDED.getId(), mUiEventLogger.eventId(0));
mUiEventLogger.getLogs().clear();
+ when(mQSPanel.isExpanded()).thenReturn(true);
mController.setExpanded(false);
verify(mMetricsLogger).visibility(eq(MetricsEvent.QS_PANEL), eq(false));
+ verify(mQSLogger).logPanelExpanded(false, mQSPanel.getDumpableTag());
assertEquals(1, mUiEventLogger.numLogs());
assertEquals(QSEvent.QS_PANEL_COLLAPSED.getId(), mUiEventLogger.eventId(0));
mUiEventLogger.getLogs().clear();
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelTest.java
index 900f989c3bdf..a726181fc702 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelTest.java
@@ -17,13 +17,10 @@ package com.android.systemui.qs;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyInt;
-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.Context;
-import android.os.UserManager;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
import android.testing.TestableLooper.RunWithLooper;
@@ -32,13 +29,11 @@ import android.widget.FrameLayout;
import androidx.test.filters.SmallTest;
-import com.android.systemui.Dependency;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.plugins.ActivityStarter;
import com.android.systemui.plugins.qs.QSTileView;
import com.android.systemui.qs.logging.QSLogger;
import com.android.systemui.qs.tileimpl.QSTileImpl;
-import com.android.systemui.statusbar.policy.SecurityController;
import org.junit.Before;
import org.junit.Test;
@@ -76,16 +71,16 @@ public class QSPanelTest extends SysuiTestCase {
MockitoAnnotations.initMocks(this);
mTestableLooper = TestableLooper.get(this);
- // Dependencies for QSSecurityFooter
- mDependency.injectTestDependency(ActivityStarter.class, mActivityStarter);
- mDependency.injectMockDependency(SecurityController.class);
- mDependency.injectTestDependency(Dependency.BG_LOOPER, mTestableLooper.getLooper());
- mContext.addMockSystemService(Context.USER_SERVICE, mock(UserManager.class));
+// // Dependencies for QSSecurityFooter
+// mDependency.injectTestDependency(ActivityStarter.class, mActivityStarter);
+// mDependency.injectMockDependency(SecurityController.class);
+// mDependency.injectTestDependency(Dependency.BG_LOOPER, mTestableLooper.getLooper());
+// mContext.addMockSystemService(Context.USER_SERVICE, mock(UserManager.class));
mDndTileRecord.tile = dndTile;
mDndTileRecord.tileView = mQSTileView;
mTestableLooper.runWithLooper(() -> {
- mQsPanel = new QSPanel(mContext, null, mQSLogger);
+ mQsPanel = new QSPanel(mContext, null);
mQsPanel.onFinishInflate();
// Provides a parent with non-zero size for QSPanel
mParentView = new FrameLayout(mContext);
@@ -100,15 +95,6 @@ public class QSPanelTest extends SysuiTestCase {
}
@Test
- public void testSetExpanded_Metrics() {
- mQsPanel.setExpanded(true);
- verify(mQSLogger).logPanelExpanded(true, mQsPanel.getDumpableTag());
-
- mQsPanel.setExpanded(false);
- verify(mQSLogger).logPanelExpanded(false, mQsPanel.getDumpableTag());
- }
-
- @Test
public void testOpenDetailsWithExistingTile_NoException() {
mTestableLooper.processAllMessages();
mQsPanel.openDetails(dndTile);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/QuickQSPanelControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/QuickQSPanelControllerTest.kt
new file mode 100644
index 000000000000..3f2b4da764e3
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/QuickQSPanelControllerTest.kt
@@ -0,0 +1,111 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.qs
+
+import android.testing.AndroidTestingRunner
+import androidx.test.filters.SmallTest
+import com.android.internal.logging.MetricsLogger
+import com.android.internal.logging.testing.UiEventLoggerFake
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.dump.DumpManager
+import com.android.systemui.media.MediaHost
+import com.android.systemui.plugins.qs.QSTile
+import com.android.systemui.qs.customize.QSCustomizerController
+import com.android.systemui.qs.logging.QSLogger
+import org.junit.After
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.Mock
+import org.mockito.Mockito.`when`
+import org.mockito.Mockito.any
+import org.mockito.Mockito.times
+import org.mockito.Mockito.verify
+import org.mockito.MockitoAnnotations
+
+@SmallTest
+@RunWith(AndroidTestingRunner::class)
+class QuickQSPanelControllerTest : SysuiTestCase() {
+
+ @Mock
+ private lateinit var quickQSPanel: QuickQSPanel
+ @Mock
+ private lateinit var qsTileHost: QSTileHost
+ @Mock
+ private lateinit var qsCustomizerController: QSCustomizerController
+ @Mock
+ private lateinit var mediaHost: MediaHost
+ @Mock
+ private lateinit var metricsLogger: MetricsLogger
+ private val uiEventLogger = UiEventLoggerFake()
+ @Mock
+ private lateinit var qsLogger: QSLogger
+ private val dumpManager = DumpManager()
+ @Mock
+ private lateinit var tile: QSTile
+ @Mock
+ private lateinit var tileLayout: TileLayout
+
+ private lateinit var controller: QuickQSPanelController
+
+ @Before
+ fun setUp() {
+ MockitoAnnotations.initMocks(this)
+
+ `when`(quickQSPanel.tileLayout).thenReturn(tileLayout)
+ `when`(quickQSPanel.dumpableTag).thenReturn("")
+
+ controller = QuickQSPanelController(
+ quickQSPanel,
+ qsTileHost,
+ qsCustomizerController,
+ false,
+ mediaHost,
+ metricsLogger,
+ uiEventLogger,
+ qsLogger,
+ dumpManager
+ )
+
+ controller.init()
+ }
+
+ @After
+ fun tearDown() {
+ controller.onViewDetached()
+ }
+
+ @Test
+ fun testTileSublistWithFewerTiles_noCrash() {
+ `when`(quickQSPanel.numQuickTiles).thenReturn(3)
+
+ `when`(qsTileHost.tiles).thenReturn(listOf(tile, tile))
+
+ controller.setTiles()
+ }
+
+ @Test
+ fun testTileSublistWithTooManyTiles() {
+ val limit = 3
+ `when`(quickQSPanel.numQuickTiles).thenReturn(limit)
+ `when`(qsTileHost.tiles).thenReturn(listOf(tile, tile, tile, tile))
+
+ controller.setTiles()
+
+ verify(quickQSPanel, times(limit)).addTile(any())
+ }
+} \ No newline at end of file
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationMenuRowTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationMenuRowTest.java
index 37e82185d228..c426c87215d7 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationMenuRowTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationMenuRowTest.java
@@ -15,6 +15,7 @@
package com.android.systemui.statusbar.notification.row;
import static android.provider.Settings.Secure.SHOW_NOTIFICATION_SNOOZE;
+import static android.provider.Settings.Global.SHOW_NEW_NOTIF_DISMISS;
import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertFalse;
@@ -96,6 +97,7 @@ public class NotificationMenuRowTest extends LeakCheckedTest {
@Test
public void testNoAppOpsInSlowSwipe() {
Settings.Secure.putInt(mContext.getContentResolver(), SHOW_NOTIFICATION_SNOOZE, 0);
+ Settings.Global.putInt(mContext.getContentResolver(), SHOW_NEW_NOTIF_DISMISS, 0);
NotificationMenuRow row = new NotificationMenuRow(mContext, mPeopleNotificationIdentifier);
row.createMenu(mRow, null);
@@ -108,6 +110,7 @@ public class NotificationMenuRowTest extends LeakCheckedTest {
@Test
public void testNoSnoozeInSlowSwipe() {
Settings.Secure.putInt(mContext.getContentResolver(), SHOW_NOTIFICATION_SNOOZE, 0);
+ Settings.Global.putInt(mContext.getContentResolver(), SHOW_NEW_NOTIF_DISMISS, 0);
NotificationMenuRow row = new NotificationMenuRow(mContext, mPeopleNotificationIdentifier);
row.createMenu(mRow, null);
@@ -120,6 +123,7 @@ public class NotificationMenuRowTest extends LeakCheckedTest {
@Test
public void testSnoozeInSlowSwipe() {
Settings.Secure.putInt(mContext.getContentResolver(), SHOW_NOTIFICATION_SNOOZE, 1);
+ Settings.Global.putInt(mContext.getContentResolver(), SHOW_NEW_NOTIF_DISMISS, 0);
NotificationMenuRow row = new NotificationMenuRow(mContext, mPeopleNotificationIdentifier);
row.createMenu(mRow, null);
@@ -130,6 +134,19 @@ public class NotificationMenuRowTest extends LeakCheckedTest {
}
@Test
+ public void testSlowSwipe_newDismiss() {
+ Settings.Secure.putInt(mContext.getContentResolver(), SHOW_NOTIFICATION_SNOOZE, 1);
+ Settings.Global.putInt(mContext.getContentResolver(), SHOW_NEW_NOTIF_DISMISS, 1);
+
+ NotificationMenuRow row = new NotificationMenuRow(mContext, mPeopleNotificationIdentifier);
+ row.createMenu(mRow, null);
+
+ ViewGroup container = (ViewGroup) row.getMenuView();
+ // Clear menu
+ assertEquals(0, container.getChildCount());
+ }
+
+ @Test
public void testIsSnappedAndOnSameSide() {
NotificationMenuRow row = Mockito.spy(
new NotificationMenuRow(mContext, mPeopleNotificationIdentifier));
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/DoubleTapHelperTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationTapHelperTest.java
index df1233af6406..4ed27463eecd 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/DoubleTapHelperTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationTapHelperTest.java
@@ -16,17 +16,12 @@
package com.android.systemui.statusbar.phone;
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.anyBoolean;
-import static org.mockito.ArgumentMatchers.anyFloat;
-import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.content.res.Resources;
-import android.os.SystemClock;
import android.testing.AndroidTestingRunner;
import android.view.MotionEvent;
import android.view.View;
@@ -36,48 +31,47 @@ import androidx.test.filters.SmallTest;
import com.android.systemui.R;
import com.android.systemui.SysuiTestCase;
+import com.android.systemui.classifier.FalsingManagerFake;
+import com.android.systemui.util.concurrency.FakeExecutor;
+import com.android.systemui.util.time.FakeSystemClock;
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;
@SmallTest
@RunWith(AndroidTestingRunner.class)
-public class DoubleTapHelperTest extends SysuiTestCase {
+public class NotificationTapHelperTest extends SysuiTestCase {
- private DoubleTapHelper mDoubleTapHelper;
- private int mTouchSlop;
- private int mDoubleTouchSlop;
+ private NotificationTapHelper mNotificationTapHelper;
+ private final FakeSystemClock mFakeSystemClock = new FakeSystemClock();
+ private final FalsingManagerFake mFalsingManager = new FalsingManagerFake();
+ private final FakeExecutor mFakeExecutor = new FakeExecutor(mFakeSystemClock);
@Mock private View mView;
- @Mock private DoubleTapHelper.ActivationListener mActivationListener;
- @Mock private DoubleTapHelper.DoubleTapListener mDoubleTapListener;
- @Mock private DoubleTapHelper.SlideBackListener mSlideBackListener;
- @Mock private DoubleTapHelper.DoubleTapLogListener mDoubleTapLogListener;
+ @Mock private NotificationTapHelper.ActivationListener mActivationListener;
+ @Mock private NotificationTapHelper.DoubleTapListener mDoubleTapListener;
+ @Mock private NotificationTapHelper.SlideBackListener mSlideBackListener;
@Mock private Resources mResources;
@Before
public void setup() {
MockitoAnnotations.initMocks(this);
- mTouchSlop = ViewConfiguration.get(mContext).getScaledTouchSlop();
- // The double tap slop has to be less than the regular slop, otherwise it has no effect.
- mDoubleTouchSlop = mTouchSlop - 1;
when(mView.getContext()).thenReturn(mContext);
when(mView.getResources()).thenReturn(mResources);
when(mResources.getDimension(R.dimen.double_tap_slop))
- .thenReturn((float) mDoubleTouchSlop);
+ .thenReturn((float) ViewConfiguration.get(mContext).getScaledTouchSlop() - 1);
- mDoubleTapHelper = new DoubleTapHelper(mView,
- mActivationListener,
- mDoubleTapListener,
- mSlideBackListener, mDoubleTapLogListener);
+ mFalsingManager.setFalseRobustTap(true); // Test double tapping most of the time.
+
+ mNotificationTapHelper = new NotificationTapHelper.Factory(mFalsingManager, mFakeExecutor)
+ .create(mActivationListener, mDoubleTapListener, mSlideBackListener);
}
@Test
public void testDoubleTap_success() {
- long downtimeA = SystemClock.uptimeMillis();
+ long downtimeA = 100;
long downtimeB = downtimeA + 100;
MotionEvent evDownA = MotionEvent.obtain(downtimeA,
@@ -105,16 +99,13 @@ public class DoubleTapHelperTest extends SysuiTestCase {
1,
0);
- mDoubleTapHelper.onTouchEvent(evDownA);
- mDoubleTapHelper.onTouchEvent(evUpA);
+ mNotificationTapHelper.onTouchEvent(evDownA);
+ mNotificationTapHelper.onTouchEvent(evUpA);
verify(mActivationListener).onActiveChanged(true);
- verify(mView).postDelayed(any(Runnable.class), anyLong());
- verify(mDoubleTapLogListener, never()).onDoubleTapLog(anyBoolean(), anyFloat(), anyFloat());
verify(mDoubleTapListener, never()).onDoubleTap();
- mDoubleTapHelper.onTouchEvent(evDownB);
- mDoubleTapHelper.onTouchEvent(evUpB);
- verify(mDoubleTapLogListener).onDoubleTapLog(true, 0, 0);
+ mNotificationTapHelper.onTouchEvent(evDownB);
+ mNotificationTapHelper.onTouchEvent(evUpB);
verify(mDoubleTapListener).onDoubleTap();
evDownA.recycle();
@@ -125,7 +116,7 @@ public class DoubleTapHelperTest extends SysuiTestCase {
@Test
public void testSingleTap_timeout() {
- long downtimeA = SystemClock.uptimeMillis();
+ long downtimeA = 100;
MotionEvent evDownA = MotionEvent.obtain(downtimeA,
downtimeA,
@@ -140,21 +131,19 @@ public class DoubleTapHelperTest extends SysuiTestCase {
1,
0);
- ArgumentCaptor<Runnable> runnableCaptor = ArgumentCaptor.forClass(Runnable.class);
- mDoubleTapHelper.onTouchEvent(evDownA);
- mDoubleTapHelper.onTouchEvent(evUpA);
- verify(mActivationListener).onActiveChanged(true);
- verify(mView).postDelayed(runnableCaptor.capture(), anyLong());
- runnableCaptor.getValue().run();
+ mNotificationTapHelper.onTouchEvent(evDownA);
+ mNotificationTapHelper.onTouchEvent(evUpA);
verify(mActivationListener).onActiveChanged(true);
+ drainExecutor();
+ verify(mActivationListener).onActiveChanged(false);
evDownA.recycle();
evUpA.recycle();
}
@Test
- public void testSingleTap_slop() {
- long downtimeA = SystemClock.uptimeMillis();
+ public void testSingleTap_falsed() {
+ long downtimeA = 100;
MotionEvent evDownA = MotionEvent.obtain(downtimeA,
downtimeA,
@@ -165,13 +154,13 @@ public class DoubleTapHelperTest extends SysuiTestCase {
MotionEvent evUpA = MotionEvent.obtain(downtimeA,
downtimeA + 1,
MotionEvent.ACTION_UP,
- 1 + mTouchSlop,
+ 1,
1,
0);
- ArgumentCaptor<Runnable> runnableCaptor = ArgumentCaptor.forClass(Runnable.class);
- mDoubleTapHelper.onTouchEvent(evDownA);
- mDoubleTapHelper.onTouchEvent(evUpA);
+ mFalsingManager.setFalseTap(true);
+ mNotificationTapHelper.onTouchEvent(evDownA);
+ mNotificationTapHelper.onTouchEvent(evUpA);
verify(mActivationListener, never()).onActiveChanged(true);
verify(mDoubleTapListener, never()).onDoubleTap();
@@ -180,8 +169,8 @@ public class DoubleTapHelperTest extends SysuiTestCase {
}
@Test
- public void testDoubleTap_slop() {
- long downtimeA = SystemClock.uptimeMillis();
+ public void testDoubleTap_falsed() {
+ long downtimeA = 100;
long downtimeB = downtimeA + 100;
MotionEvent evDownA = MotionEvent.obtain(downtimeA,
@@ -206,17 +195,17 @@ public class DoubleTapHelperTest extends SysuiTestCase {
downtimeB + 1,
MotionEvent.ACTION_UP,
1,
- 1 + mDoubleTouchSlop,
+ 1,
0);
- mDoubleTapHelper.onTouchEvent(evDownA);
- mDoubleTapHelper.onTouchEvent(evUpA);
+ mFalsingManager.setFalseDoubleTap(true);
+
+ mNotificationTapHelper.onTouchEvent(evDownA);
+ mNotificationTapHelper.onTouchEvent(evUpA);
verify(mActivationListener).onActiveChanged(true);
- verify(mView).postDelayed(any(Runnable.class), anyLong());
- mDoubleTapHelper.onTouchEvent(evDownB);
- mDoubleTapHelper.onTouchEvent(evUpB);
- verify(mDoubleTapLogListener).onDoubleTapLog(false, 0, mDoubleTouchSlop);
+ mNotificationTapHelper.onTouchEvent(evDownB);
+ mNotificationTapHelper.onTouchEvent(evUpB);
verify(mActivationListener).onActiveChanged(false);
verify(mDoubleTapListener, never()).onDoubleTap();
@@ -228,8 +217,7 @@ public class DoubleTapHelperTest extends SysuiTestCase {
@Test
public void testSlideBack() {
- long downtimeA = SystemClock.uptimeMillis();
- long downtimeB = downtimeA + 100;
+ long downtimeA = 100;
MotionEvent evDownA = MotionEvent.obtain(downtimeA,
downtimeA,
@@ -243,42 +231,24 @@ public class DoubleTapHelperTest extends SysuiTestCase {
1,
1,
0);
- MotionEvent evDownB = MotionEvent.obtain(downtimeB,
- downtimeB,
- MotionEvent.ACTION_DOWN,
- 1,
- 1,
- 0);
- MotionEvent evUpB = MotionEvent.obtain(downtimeB,
- downtimeB + 1,
- MotionEvent.ACTION_UP,
- 1,
- 1,
- 0);
when(mSlideBackListener.onSlideBack()).thenReturn(true);
- mDoubleTapHelper.onTouchEvent(evDownA);
- mDoubleTapHelper.onTouchEvent(evUpA);
- verify(mActivationListener, never()).onActiveChanged(true);
- verify(mActivationListener, never()).onActiveChanged(false);
- verify(mDoubleTapListener, never()).onDoubleTap();
- mDoubleTapHelper.onTouchEvent(evDownB);
- mDoubleTapHelper.onTouchEvent(evUpB);
+ mNotificationTapHelper.onTouchEvent(evDownA);
+ mNotificationTapHelper.onTouchEvent(evUpA);
verify(mActivationListener, never()).onActiveChanged(true);
verify(mActivationListener, never()).onActiveChanged(false);
verify(mDoubleTapListener, never()).onDoubleTap();
+ verify(mSlideBackListener).onSlideBack();
evDownA.recycle();
evUpA.recycle();
- evDownB.recycle();
- evUpB.recycle();
}
@Test
public void testMoreThanTwoTaps() {
- long downtimeA = SystemClock.uptimeMillis();
+ long downtimeA = 100;
long downtimeB = downtimeA + 100;
long downtimeC = downtimeB + 100;
long downtimeD = downtimeC + 100;
@@ -332,33 +302,26 @@ public class DoubleTapHelperTest extends SysuiTestCase {
1,
0);
- mDoubleTapHelper.onTouchEvent(evDownA);
- mDoubleTapHelper.onTouchEvent(evUpA);
+ mNotificationTapHelper.onTouchEvent(evDownA);
+ mNotificationTapHelper.onTouchEvent(evUpA);
verify(mActivationListener).onActiveChanged(true);
- verify(mView).postDelayed(any(Runnable.class), anyLong());
- verify(mDoubleTapLogListener, never()).onDoubleTapLog(anyBoolean(), anyFloat(), anyFloat());
verify(mDoubleTapListener, never()).onDoubleTap();
- mDoubleTapHelper.onTouchEvent(evDownB);
- mDoubleTapHelper.onTouchEvent(evUpB);
- verify(mDoubleTapLogListener).onDoubleTapLog(true, 0, 0);
+ mNotificationTapHelper.onTouchEvent(evDownB);
+ mNotificationTapHelper.onTouchEvent(evUpB);
verify(mDoubleTapListener).onDoubleTap();
reset(mView);
reset(mActivationListener);
- reset(mDoubleTapLogListener);
reset(mDoubleTapListener);
- mDoubleTapHelper.onTouchEvent(evDownC);
- mDoubleTapHelper.onTouchEvent(evUpC);
+ mNotificationTapHelper.onTouchEvent(evDownC);
+ mNotificationTapHelper.onTouchEvent(evUpC);
verify(mActivationListener).onActiveChanged(true);
- verify(mView).postDelayed(any(Runnable.class), anyLong());
- verify(mDoubleTapLogListener, never()).onDoubleTapLog(anyBoolean(), anyFloat(), anyFloat());
verify(mDoubleTapListener, never()).onDoubleTap();
- mDoubleTapHelper.onTouchEvent(evDownD);
- mDoubleTapHelper.onTouchEvent(evUpD);
- verify(mDoubleTapLogListener).onDoubleTapLog(true, 0, 0);
+ mNotificationTapHelper.onTouchEvent(evDownD);
+ mNotificationTapHelper.onTouchEvent(evUpD);
verify(mDoubleTapListener).onDoubleTap();
evDownA.recycle();
@@ -366,4 +329,9 @@ public class DoubleTapHelperTest extends SysuiTestCase {
evDownB.recycle();
evUpB.recycle();
}
+
+ private void drainExecutor() {
+ mFakeExecutor.advanceClockToLast();
+ mFakeExecutor.runAllReady();
+ }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java
index 9832d31f7b05..83030eccedd1 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java
@@ -33,6 +33,7 @@ import android.testing.TestableLooper;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewPropertyAnimator;
+import android.widget.FrameLayout;
import androidx.test.filters.SmallTest;
@@ -103,6 +104,7 @@ public class StatusBarKeyguardViewManagerTest extends SysuiTestCase {
when(mLockIconContainer.getParent()).thenReturn(mock(ViewGroup.class));
when(mLockIconContainer.animate()).thenReturn(mock(ViewPropertyAnimator.class,
RETURNS_DEEP_STUBS));
+ when(mLockIconContainer.getLayoutParams()).thenReturn(mock(FrameLayout.LayoutParams.class));
when(mKeyguardBouncerFactory.create(
any(ViewGroup.class),
diff --git a/packages/SystemUI/tests/src/com/android/systemui/util/time/FakeSystemClock.java b/packages/SystemUI/tests/src/com/android/systemui/util/time/FakeSystemClock.java
index ecfb357aa068..d8271e8292be 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/util/time/FakeSystemClock.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/util/time/FakeSystemClock.java
@@ -28,17 +28,16 @@ import java.util.List;
* backwards. uptimeMillis, elapsedRealtime, and currentThreadTimeMillis are all kept in sync.
*
* Unless otherwise specified, uptimeMillis and elapsedRealtime will advance the same amount with
- * every call to {@link #advanceTime(long)}. Thread time always lags by 50% of the uptime
+ * every call to {@link #advanceTime}. Thread time always lags by 50% of the uptime
* advancement to simulate time loss due to scheduling.
*/
public class FakeSystemClock implements SystemClock {
private long mUptimeMillis = 10000;
private long mElapsedRealtime = 10000;
private long mCurrentThreadTimeMillis = 10000;
-
private long mCurrentTimeMillis = 1555555500000L;
-
private final List<ClockTickListener> mListeners = new ArrayList<>();
+
@Override
public long uptimeMillis() {
return mUptimeMillis;
@@ -72,21 +71,38 @@ public class FakeSystemClock implements SystemClock {
mCurrentTimeMillis = millis;
}
- public void advanceTime(long uptime) {
- advanceTime(uptime, 0);
+ /**
+ * Advances the time tracked by the fake clock and notifies any listeners that the time has
+ * changed (for example, an attached {@link FakeExecutor} may fire its pending runnables).
+ *
+ * All tracked times increment by [millis], with the exception of currentThreadTimeMillis,
+ * which advances by [millis] * 0.5
+ */
+ public void advanceTime(long millis) {
+ advanceTime(millis, 0);
}
- public void advanceTime(long uptime, long sleepTime) {
- if (uptime < 0 || sleepTime < 0) {
+ /**
+ * Advances the time tracked by the fake clock and notifies any listeners that the time has
+ * changed (for example, an attached {@link FakeExecutor} may fire its pending runnables).
+ *
+ * The tracked times change as follows:
+ * - uptimeMillis increments by [awakeMillis]
+ * - currentThreadTimeMillis increments by [awakeMillis] * 0.5
+ * - elapsedRealtime increments by [awakeMillis] + [sleepMillis]
+ * - currentTimeMillis increments by [awakeMillis] + [sleepMillis]
+ */
+ public void advanceTime(long awakeMillis, long sleepMillis) {
+ if (awakeMillis < 0 || sleepMillis < 0) {
throw new IllegalArgumentException("Time cannot go backwards");
}
- if (uptime > 0 || sleepTime > 0) {
- mUptimeMillis += uptime;
- mElapsedRealtime += uptime + sleepTime;
- mCurrentTimeMillis += uptime + sleepTime;
+ if (awakeMillis > 0 || sleepMillis > 0) {
+ mUptimeMillis += awakeMillis;
+ mElapsedRealtime += awakeMillis + sleepMillis;
+ mCurrentTimeMillis += awakeMillis + sleepMillis;
- mCurrentThreadTimeMillis += Math.ceil(uptime * 0.5);
+ mCurrentThreadTimeMillis += Math.ceil(awakeMillis * 0.5);
for (ClockTickListener listener : mListeners) {
listener.onClockTick();
@@ -105,6 +121,4 @@ public class FakeSystemClock implements SystemClock {
public interface ClockTickListener {
void onClockTick();
}
-
- private static final long START_TIME = 10000;
}
diff --git a/services/core/Android.bp b/services/core/Android.bp
index 3a137263d182..069a5ea3b32f 100644
--- a/services/core/Android.bp
+++ b/services/core/Android.bp
@@ -75,6 +75,7 @@ java_library_static {
":platform-compat-config",
":display-device-config",
":cec-config",
+ ":device-state-config",
"java/com/android/server/EventLogTags.logtags",
"java/com/android/server/am/EventLogTags.logtags",
"java/com/android/server/wm/EventLogTags.logtags",
diff --git a/services/core/java/android/content/pm/PackageManagerInternal.java b/services/core/java/android/content/pm/PackageManagerInternal.java
index f20566280bc8..6989e320f465 100644
--- a/services/core/java/android/content/pm/PackageManagerInternal.java
+++ b/services/core/java/android/content/pm/PackageManagerInternal.java
@@ -77,6 +77,7 @@ public abstract class PackageManagerInternal {
PACKAGE_WIFI,
PACKAGE_COMPANION,
PACKAGE_RETAIL_DEMO,
+ PACKAGE_RECENTS,
})
@Retention(RetentionPolicy.SOURCE)
public @interface KnownPackage {}
@@ -97,9 +98,10 @@ public abstract class PackageManagerInternal {
public static final int PACKAGE_WIFI = 13;
public static final int PACKAGE_COMPANION = 14;
public static final int PACKAGE_RETAIL_DEMO = 15;
+ public static final int PACKAGE_RECENTS = 16;
// Integer value of the last known package ID. Increases as new ID is added to KnownPackage.
// Please note the numbers should be continuous.
- public static final int LAST_KNOWN_PACKAGE = PACKAGE_RETAIL_DEMO;
+ public static final int LAST_KNOWN_PACKAGE = PACKAGE_RECENTS;
@IntDef(flag = true, prefix = "RESOLVE_", value = {
RESOLVE_NON_BROWSER_ONLY,
@@ -1060,6 +1062,8 @@ public abstract class PackageManagerInternal {
return "Retail Demo";
case PACKAGE_OVERLAY_CONFIG_SIGNATURE:
return "Overlay Config Signature";
+ case PACKAGE_RECENTS:
+ return "Recents";
}
return "Unknown";
}
diff --git a/services/core/java/com/android/server/BatteryService.java b/services/core/java/com/android/server/BatteryService.java
index 9455051ad740..bb4bbd5bc6d4 100644
--- a/services/core/java/com/android/server/BatteryService.java
+++ b/services/core/java/com/android/server/BatteryService.java
@@ -437,6 +437,10 @@ public final class BatteryService extends SystemService {
info.legacy.legacy.batteryChargeCounter);
Trace.traceCounter(Trace.TRACE_TAG_POWER, "BatteryCurrent",
info.legacy.legacy.batteryCurrent);
+ Trace.traceCounter(Trace.TRACE_TAG_POWER, "PlugType",
+ plugType(info.legacy.legacy));
+ Trace.traceCounter(Trace.TRACE_TAG_POWER, "BatteryStatus",
+ info.legacy.legacy.batteryStatus);
synchronized (mLock) {
if (!mUpdatesStopped) {
@@ -471,6 +475,18 @@ public final class BatteryService extends SystemService {
dst.batteryTechnology = src.batteryTechnology;
}
+ private static int plugType(HealthInfo healthInfo) {
+ if (healthInfo.chargerAcOnline) {
+ return BatteryManager.BATTERY_PLUGGED_AC;
+ } else if (healthInfo.chargerUsbOnline) {
+ return BatteryManager.BATTERY_PLUGGED_USB;
+ } else if (healthInfo.chargerWirelessOnline) {
+ return BatteryManager.BATTERY_PLUGGED_WIRELESS;
+ } else {
+ return BATTERY_PLUGGED_NONE;
+ }
+ }
+
private void processValuesLocked(boolean force) {
boolean logOutlier = false;
long dischargeDuration = 0;
@@ -478,15 +494,7 @@ public final class BatteryService extends SystemService {
mBatteryLevelCritical =
mHealthInfo.batteryStatus != BatteryManager.BATTERY_STATUS_UNKNOWN
&& mHealthInfo.batteryLevel <= mCriticalBatteryLevel;
- if (mHealthInfo.chargerAcOnline) {
- mPlugType = BatteryManager.BATTERY_PLUGGED_AC;
- } else if (mHealthInfo.chargerUsbOnline) {
- mPlugType = BatteryManager.BATTERY_PLUGGED_USB;
- } else if (mHealthInfo.chargerWirelessOnline) {
- mPlugType = BatteryManager.BATTERY_PLUGGED_WIRELESS;
- } else {
- mPlugType = BATTERY_PLUGGED_NONE;
- }
+ mPlugType = plugType(mHealthInfo);
if (DEBUG) {
Slog.d(TAG, "Processing new values: "
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index 1eba37d8b02d..2fe37d48379b 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -2697,10 +2697,16 @@ public class ConnectivityService extends IConnectivityManager.Stub
/**
* Return an array of all current NetworkRequest sorted by request id.
*/
- private NetworkRequestInfo[] requestsSortedById() {
+ @VisibleForTesting
+ protected NetworkRequestInfo[] requestsSortedById() {
NetworkRequestInfo[] requests = new NetworkRequestInfo[0];
requests = mNetworkRequests.values().toArray(requests);
- Arrays.sort(requests, Comparator.comparingInt(nri -> nri.request.requestId));
+ // Sort the array based off the NRI containing the min requestId in its requests.
+ Arrays.sort(requests,
+ Comparator.comparingInt(nri -> Collections.min(nri.mRequests,
+ Comparator.comparingInt(req -> req.requestId)).requestId
+ )
+ );
return requests;
}
@@ -5350,6 +5356,12 @@ public class ConnectivityService extends IConnectivityManager.Stub
}
}
+ private void ensureAllNetworkRequestsHaveType(List<NetworkRequest> requests) {
+ for (int i = 0; i < requests.size(); i++) {
+ ensureNetworkRequestHasType(requests.get(i));
+ }
+ }
+
private void ensureNetworkRequestHasType(NetworkRequest request) {
if (request.type == NetworkRequest.Type.NONE) {
throw new IllegalArgumentException(
@@ -5361,7 +5373,8 @@ public class ConnectivityService extends IConnectivityManager.Stub
* Tracks info about the requester.
* Also used to notice when the calling process dies so we can self-expire
*/
- private class NetworkRequestInfo implements IBinder.DeathRecipient {
+ @VisibleForTesting
+ protected class NetworkRequestInfo implements IBinder.DeathRecipient {
final List<NetworkRequest> mRequests;
final NetworkRequest request;
@@ -5380,7 +5393,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
NetworkRequestInfo(NetworkRequest r, PendingIntent pi) {
request = r;
mRequests = initializeRequests(r);
- ensureNetworkRequestHasType(request);
+ ensureAllNetworkRequestsHaveType(mRequests);
mPendingIntent = pi;
messenger = null;
mBinder = null;
@@ -5394,7 +5407,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
messenger = m;
request = r;
mRequests = initializeRequests(r);
- ensureNetworkRequestHasType(request);
+ ensureAllNetworkRequestsHaveType(mRequests);
mBinder = binder;
mPid = getCallingPid();
mUid = getCallingUid();
@@ -5418,6 +5431,19 @@ public class ConnectivityService extends IConnectivityManager.Stub
return Collections.unmodifiableList(tempRequests);
}
+ private NetworkRequest getSatisfiedRequest() {
+ if (mSatisfier == null) {
+ return null;
+ }
+
+ for (NetworkRequest req : mRequests) {
+ if (mSatisfier.isSatisfyingRequest(req.requestId)) {
+ return req;
+ }
+ }
+
+ return null;
+ }
private void enforceRequestCountLimit() {
synchronized (mUidToNetworkRequestCount) {
@@ -5436,14 +5462,16 @@ public class ConnectivityService extends IConnectivityManager.Stub
}
}
+ @Override
public void binderDied() {
log("ConnectivityService NetworkRequestInfo binderDied(" +
- request + ", " + mBinder + ")");
- releaseNetworkRequest(request);
+ mRequests + ", " + mBinder + ")");
+ releaseNetworkRequest(mRequests);
}
+ @Override
public String toString() {
- return "uid/pid:" + mUid + "/" + mPid + " " + request
+ return "uid/pid:" + mUid + "/" + mPid + " " + mRequests
+ (mPendingIntent == null ? "" : " to trigger " + mPendingIntent);
}
}
@@ -5763,6 +5791,12 @@ public class ConnectivityService extends IConnectivityManager.Stub
return mNextNetworkProviderId.getAndIncrement();
}
+ private void releaseNetworkRequest(List<NetworkRequest> networkRequests) {
+ for (int i = 0; i < networkRequests.size(); i++) {
+ releaseNetworkRequest(networkRequests.get(i));
+ }
+ }
+
@Override
public void releaseNetworkRequest(NetworkRequest networkRequest) {
ensureNetworkRequestHasType(networkRequest);
@@ -5854,7 +5888,6 @@ public class ConnectivityService extends IConnectivityManager.Stub
@GuardedBy("mBlockedAppUids")
private final HashSet<Integer> mBlockedAppUids = new HashSet<>();
- // Note: if mDefaultRequest is changed, NetworkMonitor needs to be updated.
@NonNull
private final NetworkRequest mDefaultRequest;
// The NetworkAgentInfo currently satisfying the default request, if any.
@@ -6780,7 +6813,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
}
public String toString() {
- return mRequest.request.requestId + " : "
+ return mRequest.mRequests.get(0).requestId + " : "
+ (null != mOldNetwork ? mOldNetwork.network.netId : "null")
+ " → " + (null != mNewNetwork ? mNewNetwork.network.netId : "null");
}
diff --git a/services/core/java/com/android/server/GestureLauncherService.java b/services/core/java/com/android/server/GestureLauncherService.java
index d4e912b65e17..8ed23f900d73 100644
--- a/services/core/java/com/android/server/GestureLauncherService.java
+++ b/services/core/java/com/android/server/GestureLauncherService.java
@@ -44,6 +44,9 @@ import android.view.KeyEvent;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.logging.MetricsLogger;
+import com.android.internal.logging.UiEvent;
+import com.android.internal.logging.UiEventLogger;
+import com.android.internal.logging.UiEventLoggerImpl;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.server.statusbar.StatusBarManagerInternal;
import com.android.server.wm.WindowManagerInternal;
@@ -145,16 +148,44 @@ public class GestureLauncherService extends SystemService {
private long mLastPowerDown;
private int mPowerButtonConsecutiveTaps;
private int mPowerButtonSlowConsecutiveTaps;
+ private final UiEventLogger mUiEventLogger;
+ @VisibleForTesting
+ public enum GestureLauncherEvent implements UiEventLogger.UiEventEnum {
+ @UiEvent(doc = "The user lifted the device just the right way to launch the camera.")
+ GESTURE_CAMERA_LIFT(658),
+
+ @UiEvent(doc = "The user wiggled the device just the right way to launch the camera.")
+ GESTURE_CAMERA_WIGGLE(659),
+
+ @UiEvent(doc = "The user double-tapped power quickly enough to launch the camera.")
+ GESTURE_CAMERA_DOUBLE_TAP_POWER(660),
+
+ @UiEvent(doc = "The user multi-tapped power quickly enough to signal an emergency.")
+ GESTURE_PANIC_TAP_POWER(661);
+
+ private final int mId;
+
+ GestureLauncherEvent(int id) {
+ mId = id;
+ }
+
+ @Override
+ public int getId() {
+ return mId;
+ }
+ }
public GestureLauncherService(Context context) {
- this(context, new MetricsLogger());
+ this(context, new MetricsLogger(), new UiEventLoggerImpl());
}
@VisibleForTesting
- GestureLauncherService(Context context, MetricsLogger metricsLogger) {
+ GestureLauncherService(Context context, MetricsLogger metricsLogger,
+ UiEventLogger uiEventLogger) {
super(context);
mContext = context;
mMetricsLogger = metricsLogger;
+ mUiEventLogger = uiEventLogger;
}
@Override
@@ -460,11 +491,12 @@ public class GestureLauncherService extends SystemService {
if (launchCamera) {
mMetricsLogger.action(MetricsEvent.ACTION_DOUBLE_TAP_POWER_CAMERA_GESTURE,
(int) powerTapInterval);
+ mUiEventLogger.log(GestureLauncherEvent.GESTURE_CAMERA_DOUBLE_TAP_POWER);
}
} else if (launchEmergencyGesture) {
Slog.i(TAG, "Emergency gesture detected, launching.");
launchEmergencyGesture = handleEmergencyGesture();
- // TODO(b/160006048): Add logging
+ mUiEventLogger.log(GestureLauncherEvent.GESTURE_PANIC_TAP_POWER);
}
mMetricsLogger.histogram("power_consecutive_short_tap_count",
mPowerButtonSlowConsecutiveTaps);
@@ -587,6 +619,7 @@ public class GestureLauncherService extends SystemService {
if (handleCameraGesture(true /* useWakelock */,
StatusBarManager.CAMERA_LAUNCH_SOURCE_WIGGLE)) {
mMetricsLogger.action(MetricsEvent.ACTION_WIGGLE_CAMERA_GESTURE);
+ mUiEventLogger.log(GestureLauncherEvent.GESTURE_CAMERA_WIGGLE);
trackCameraLaunchEvent(event);
}
return;
@@ -671,6 +704,7 @@ public class GestureLauncherService extends SystemService {
if (handleCameraGesture(true /* useWakelock */,
StatusBarManager.CAMERA_LAUNCH_SOURCE_LIFT_TRIGGER)) {
MetricsLogger.action(mContext, MetricsEvent.ACTION_CAMERA_LIFT_TRIGGER);
+ mUiEventLogger.log(GestureLauncherEvent.GESTURE_CAMERA_LIFT);
}
} else {
if (DBG_CAMERA_LIFT) Slog.d(TAG, "Ignoring lift event");
diff --git a/services/core/java/com/android/server/SystemServiceManager.java b/services/core/java/com/android/server/SystemServiceManager.java
index 5556e48a2018..9d60b8438153 100644
--- a/services/core/java/com/android/server/SystemServiceManager.java
+++ b/services/core/java/com/android/server/SystemServiceManager.java
@@ -21,6 +21,7 @@ import android.annotation.Nullable;
import android.annotation.UserIdInt;
import android.content.Context;
import android.content.pm.UserInfo;
+import android.os.Build;
import android.os.Environment;
import android.os.SystemClock;
import android.os.Trace;
@@ -31,6 +32,7 @@ import android.util.Slog;
import android.util.SparseArray;
import com.android.internal.annotations.GuardedBy;
+import com.android.internal.os.ClassLoaderFactory;
import com.android.internal.util.Preconditions;
import com.android.server.SystemService.TargetUser;
import com.android.server.am.EventLogTags;
@@ -121,7 +123,10 @@ public final class SystemServiceManager implements Dumpable {
if (pathClassLoader == null) {
// NB: the parent class loader should always be the system server class loader.
// Changing it has implications that require discussion with the mainline team.
- pathClassLoader = new PathClassLoader(path, this.getClass().getClassLoader());
+ pathClassLoader = (PathClassLoader) ClassLoaderFactory.createClassLoader(
+ path, null /* librarySearchPath */, null /* libraryPermittedPath */,
+ this.getClass().getClassLoader(), Build.VERSION.SDK_INT,
+ true /* isNamespaceShared */, null /* classLoaderName */);
mLoadedPaths.put(path, pathClassLoader);
}
final Class<SystemService> serviceClass = loadClassFromLoader(className, pathClassLoader);
diff --git a/services/core/java/com/android/server/TelephonyRegistry.java b/services/core/java/com/android/server/TelephonyRegistry.java
index ba52aee24dc2..eb55512b4d83 100644
--- a/services/core/java/com/android/server/TelephonyRegistry.java
+++ b/services/core/java/com/android/server/TelephonyRegistry.java
@@ -80,7 +80,6 @@ import android.telephony.emergency.EmergencyNumber;
import android.telephony.ims.ImsReasonInfo;
import android.text.TextUtils;
import android.util.ArrayMap;
-import android.util.ArraySet;
import android.util.LocalLog;
import android.util.Pair;
@@ -102,13 +101,10 @@ import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
-import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.Objects;
-import java.util.Set;
-import java.util.stream.Collectors;
/**
* Since phone process can be restarted, this class provides a centralized place
@@ -148,14 +144,14 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
int callerUid;
int callerPid;
- Set<Integer> eventList;
+ long events;
int subId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
int phoneId = SubscriptionManager.INVALID_SIM_SLOT_INDEX;
- boolean matchPhoneStateListenerEvent(int event) {
- return (callback != null) && (this.eventList.contains(event));
+ boolean matchPhoneStateListenerEvent(long events) {
+ return (callback != null) && ((events & this.events) != 0);
}
boolean matchOnSubscriptionsChangedListener() {
@@ -183,7 +179,7 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
+ onSubscriptionsChangedListenerCallback
+ " onOpportunisticSubscriptionsChangedListenererCallback="
+ onOpportunisticSubscriptionsChangedListenerCallback + " subId=" + subId
- + " phoneId=" + phoneId + " events=" + eventList + "}";
+ + " phoneId=" + phoneId + " events=" + Long.toHexString(events) + "}";
}
}
@@ -314,10 +310,6 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
private List<PhysicalChannelConfig> mPhysicalChannelConfigs;
- private boolean mIsDataEnabled = false;
-
- private int mDataEnabledReason;
-
/**
* Per-phone map of precise data connection state. The key of the map is the pair of transport
* type and APN setting. This is the cache to prevent redundant callbacks to the listeners.
@@ -327,62 +319,40 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
private List<Map<Pair<Integer, ApnSetting>, PreciseDataConnectionState>>
mPreciseDataConnectionStates;
- private static final Set<Integer> REQUIRE_PRECISE_PHONE_STATE_PERMISSION;
- static {
- REQUIRE_PRECISE_PHONE_STATE_PERMISSION = new HashSet<Integer>();
- REQUIRE_PRECISE_PHONE_STATE_PERMISSION.add(
- PhoneStateListener.EVENT_PRECISE_DATA_CONNECTION_STATE_CHANGED);
- REQUIRE_PRECISE_PHONE_STATE_PERMISSION.add(
- PhoneStateListener.EVENT_DATA_CONNECTION_REAL_TIME_INFO_CHANGED);
- REQUIRE_PRECISE_PHONE_STATE_PERMISSION.add(
- PhoneStateListener.EVENT_PRECISE_CALL_STATE_CHANGED);
- REQUIRE_PRECISE_PHONE_STATE_PERMISSION.add(
- PhoneStateListener.EVENT_CALL_DISCONNECT_CAUSE_CHANGED);
- REQUIRE_PRECISE_PHONE_STATE_PERMISSION.add(
- PhoneStateListener.EVENT_CALL_ATTRIBUTES_CHANGED);
- REQUIRE_PRECISE_PHONE_STATE_PERMISSION.add(
- PhoneStateListener.EVENT_IMS_CALL_DISCONNECT_CAUSE_CHANGED);
- REQUIRE_PRECISE_PHONE_STATE_PERMISSION.add(PhoneStateListener.EVENT_REGISTRATION_FAILURE);
- REQUIRE_PRECISE_PHONE_STATE_PERMISSION.add(PhoneStateListener.EVENT_BARRING_INFO_CHANGED);
- REQUIRE_PRECISE_PHONE_STATE_PERMISSION.add(
- PhoneStateListener.EVENT_PHYSICAL_CHANNEL_CONFIG_CHANGED);
- REQUIRE_PRECISE_PHONE_STATE_PERMISSION.add(
- PhoneStateListener.EVENT_DATA_ENABLED_CHANGED);
- }
-
- private boolean isLocationPermissionRequired(Set<Integer> events) {
- return events.contains(PhoneStateListener.EVENT_CELL_LOCATION_CHANGED)
- || events.contains(PhoneStateListener.EVENT_CELL_INFO_CHANGED)
- || events.contains(PhoneStateListener.EVENT_REGISTRATION_FAILURE)
- || events.contains(PhoneStateListener.EVENT_BARRING_INFO_CHANGED);
- }
-
- private boolean isPhoneStatePermissionRequired(Set<Integer> events) {
- return events.contains(PhoneStateListener.EVENT_CALL_FORWARDING_INDICATOR_CHANGED)
- || events.contains(PhoneStateListener.EVENT_MESSAGE_WAITING_INDICATOR_CHANGED)
- || events.contains(PhoneStateListener.EVENT_EMERGENCY_NUMBER_LIST_CHANGED)
- || events.contains(PhoneStateListener.EVENT_ACTIVE_DATA_SUBSCRIPTION_ID_CHANGED);
- }
-
- private boolean isPrecisePhoneStatePermissionRequired(Set<Integer> events) {
- for (Integer requireEvent : REQUIRE_PRECISE_PHONE_STATE_PERMISSION) {
- if (events.contains(requireEvent)) {
- return true;
- }
- }
- return false;
- }
-
- private boolean isActiveEmergencySessionPermissionRequired(Set<Integer> events) {
- return events.contains(PhoneStateListener.EVENT_OUTGOING_EMERGENCY_CALL)
- || events.contains(PhoneStateListener.EVENT_OUTGOING_EMERGENCY_SMS);
- }
-
- private boolean isPrivilegedPhoneStatePermissionRequired(Set<Integer> events) {
- return events.contains(PhoneStateListener.EVENT_SRVCC_STATE_CHANGED)
- || events.contains(PhoneStateListener.EVENT_VOICE_ACTIVATION_STATE_CHANGED)
- || events.contains(PhoneStateListener.EVENT_RADIO_POWER_STATE_CHANGED);
- }
+ // Starting in Q, almost all cellular location requires FINE location enforcement.
+ // Prior to Q, cellular was available with COARSE location enforcement. Bits in this
+ // list will be checked for COARSE on apps targeting P or earlier and FINE on Q or later.
+ static final long ENFORCE_LOCATION_PERMISSION_MASK =
+ PhoneStateListener.LISTEN_CELL_LOCATION
+ | PhoneStateListener.LISTEN_CELL_INFO
+ | PhoneStateListener.LISTEN_REGISTRATION_FAILURE
+ | PhoneStateListener.LISTEN_BARRING_INFO;
+
+ static final long ENFORCE_PHONE_STATE_PERMISSION_MASK =
+ PhoneStateListener.LISTEN_CALL_FORWARDING_INDICATOR
+ | PhoneStateListener.LISTEN_MESSAGE_WAITING_INDICATOR
+ | PhoneStateListener.LISTEN_EMERGENCY_NUMBER_LIST
+ | PhoneStateListener.LISTEN_DISPLAY_INFO_CHANGED;
+
+ static final long ENFORCE_PRECISE_PHONE_STATE_PERMISSION_MASK =
+ PhoneStateListener.LISTEN_PRECISE_CALL_STATE
+ | PhoneStateListener.LISTEN_PRECISE_DATA_CONNECTION_STATE
+ | PhoneStateListener.LISTEN_CALL_DISCONNECT_CAUSES
+ | PhoneStateListener.LISTEN_CALL_ATTRIBUTES_CHANGED
+ | PhoneStateListener.LISTEN_IMS_CALL_DISCONNECT_CAUSES
+ | PhoneStateListener.LISTEN_REGISTRATION_FAILURE
+ | PhoneStateListener.LISTEN_BARRING_INFO
+ | PhoneStateListener.LISTEN_PHYSICAL_CHANNEL_CONFIGURATION;
+
+ static final long READ_ACTIVE_EMERGENCY_SESSION_PERMISSION_MASK =
+ PhoneStateListener.LISTEN_OUTGOING_EMERGENCY_CALL
+ | PhoneStateListener.LISTEN_OUTGOING_EMERGENCY_SMS;
+
+ static final long READ_PRIVILEGED_PHONE_STATE_PERMISSION_MASK =
+ PhoneStateListener.LISTEN_OEM_HOOK_RAW_EVENT
+ | PhoneStateListener.LISTEN_SRVCC_STATE_CHANGED
+ | PhoneStateListener.LISTEN_RADIO_POWER_STATE_CHANGED
+ | PhoneStateListener.LISTEN_VOICE_ACTIVATION_STATE;
private static final int MSG_USER_SWITCHED = 1;
private static final int MSG_UPDATE_DEFAULT_SUB = 2;
@@ -700,7 +670,7 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
r.callingFeatureId = callingFeatureId;
r.callerUid = Binder.getCallingUid();
r.callerPid = Binder.getCallingPid();
- r.eventList = new ArraySet<>();
+ r.events = 0;
if (DBG) {
log("listen oscl: Register r=" + r);
}
@@ -754,7 +724,7 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
r.callingFeatureId = callingFeatureId;
r.callerUid = Binder.getCallingUid();
r.callerPid = Binder.getCallingPid();
- r.eventList = new ArraySet<>();
+ r.events = 0;
if (DBG) {
log("listen ooscl: Register r=" + r);
}
@@ -827,338 +797,331 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
}
}
+ @Deprecated
+ @Override
+ public void listen(String callingPackage, IPhoneStateListener callback, int events,
+ boolean notifyNow) {
+ listenWithFeature(callingPackage, null, callback, events, notifyNow);
+ }
+
+ @Override
+ public void listenWithFeature(String callingPackage, String callingFeatureId,
+ IPhoneStateListener callback, long events, boolean notifyNow) {
+ listenForSubscriber(SubscriptionManager.DEFAULT_SUBSCRIPTION_ID, callingPackage,
+ callingFeatureId, callback, events, notifyNow);
+ }
+
@Override
- public void listenWithEventList(int subId, String callingPackage, String callingFeatureId,
- IPhoneStateListener callback, int[] events, boolean notifyNow) {
- Set<Integer> eventList = Arrays.stream(events).boxed().collect(Collectors.toSet());
- listen(callingPackage, callingFeatureId, callback, eventList, notifyNow, subId);
+ public void listenForSubscriber(int subId, String callingPackage, String callingFeatureId,
+ IPhoneStateListener callback, long events, boolean notifyNow) {
+ listen(callingPackage, callingFeatureId, callback, events, notifyNow, subId);
}
private void listen(String callingPackage, @Nullable String callingFeatureId,
- IPhoneStateListener callback, Set<Integer> events, boolean notifyNow, int subId) {
+ IPhoneStateListener callback, long events, boolean notifyNow, int subId) {
int callerUserId = UserHandle.getCallingUserId();
-
mAppOps.checkPackage(Binder.getCallingUid(), callingPackage);
String str = "listen: E pkg=" + pii(callingPackage) + " uid=" + Binder.getCallingUid()
- + " events=" + events + " notifyNow=" + notifyNow
- + " subId=" + subId + " myUserId=" + UserHandle.myUserId()
- + " callerUserId=" + callerUserId;
+ + " events=0x" + Long.toHexString(events) + " notifyNow=" + notifyNow + " subId="
+ + subId + " myUserId=" + UserHandle.myUserId() + " callerUserId=" + callerUserId;
mListenLog.log(str);
if (VDBG) {
log(str);
}
- if (events.isEmpty()) {
- if (DBG) {
- log("listen: Unregister");
+ if (events != PhoneStateListener.LISTEN_NONE) {
+ // Checks permission and throws SecurityException for disallowed operations. For pre-M
+ // apps whose runtime permission has been revoked, we return immediately to skip sending
+ // events to the app without crashing it.
+ if (!checkListenerPermission(events, subId, callingPackage, callingFeatureId,
+ "listen")) {
+ return;
}
- events.clear();
- remove(callback.asBinder());
- return;
- }
- // Checks permission and throws SecurityException for disallowed operations. For pre-M
- // apps whose runtime permission has been revoked, we return immediately to skip sending
- // events to the app without crashing it.
- if (!checkListenerPermission(events, subId, callingPackage, callingFeatureId,
- "listen")) {
- return;
- }
+ int phoneId = getPhoneIdFromSubId(subId);
+ synchronized (mRecords) {
+ // register
+ IBinder b = callback.asBinder();
+ boolean doesLimitApply =
+ Binder.getCallingUid() != Process.SYSTEM_UID
+ && Binder.getCallingUid() != Process.PHONE_UID
+ && Binder.getCallingUid() != Process.myUid();
+ Record r = add(b, Binder.getCallingUid(), Binder.getCallingPid(), doesLimitApply);
- int phoneId = getPhoneIdFromSubId(subId);
- synchronized (mRecords) {
- // register
- IBinder b = callback.asBinder();
- boolean doesLimitApply =
- Binder.getCallingUid() != Process.SYSTEM_UID
- && Binder.getCallingUid() != Process.PHONE_UID
- && Binder.getCallingUid() != Process.myUid();
- Record r = add(b, Binder.getCallingUid(), Binder.getCallingPid(), doesLimitApply);
-
- if (r == null) {
- return;
- }
+ if (r == null) {
+ return;
+ }
- r.context = mContext;
- r.callback = callback;
- r.callingPackage = callingPackage;
- r.callingFeatureId = callingFeatureId;
- r.callerUid = Binder.getCallingUid();
- r.callerPid = Binder.getCallingPid();
- // Legacy applications pass SubscriptionManager.DEFAULT_SUB_ID,
- // force all illegal subId to SubscriptionManager.DEFAULT_SUB_ID
- if (!SubscriptionManager.isValidSubscriptionId(subId)) {
- r.subId = SubscriptionManager.DEFAULT_SUBSCRIPTION_ID;
- } else {//APP specify subID
- r.subId = subId;
- }
- r.phoneId = phoneId;
- r.eventList = events;
- if (DBG) {
- log("listen: Register r=" + r + " r.subId=" + r.subId + " phoneId=" + phoneId);
- }
- if (notifyNow && validatePhoneId(phoneId)) {
- if (events.contains(PhoneStateListener.EVENT_SERVICE_STATE_CHANGED)) {
- try {
- if (VDBG) log("listen: call onSSC state=" + mServiceState[phoneId]);
- ServiceState rawSs = new ServiceState(mServiceState[phoneId]);
- if (checkFineLocationAccess(r, Build.VERSION_CODES.Q)) {
- r.callback.onServiceStateChanged(rawSs);
- } else if (checkCoarseLocationAccess(r, Build.VERSION_CODES.Q)) {
- r.callback.onServiceStateChanged(
- rawSs.createLocationInfoSanitizedCopy(false));
- } else {
- r.callback.onServiceStateChanged(
- rawSs.createLocationInfoSanitizedCopy(true));
+ r.context = mContext;
+ r.callback = callback;
+ r.callingPackage = callingPackage;
+ r.callingFeatureId = callingFeatureId;
+ r.callerUid = Binder.getCallingUid();
+ r.callerPid = Binder.getCallingPid();
+ // Legacy applications pass SubscriptionManager.DEFAULT_SUB_ID,
+ // force all illegal subId to SubscriptionManager.DEFAULT_SUB_ID
+ if (!SubscriptionManager.isValidSubscriptionId(subId)) {
+ r.subId = SubscriptionManager.DEFAULT_SUBSCRIPTION_ID;
+ } else {//APP specify subID
+ r.subId = subId;
+ }
+ r.phoneId = phoneId;
+ r.events = events;
+ if (DBG) {
+ log("listen: Register r=" + r + " r.subId=" + r.subId + " phoneId=" + phoneId);
+ }
+ if (notifyNow && validatePhoneId(phoneId)) {
+ if ((events & PhoneStateListener.LISTEN_SERVICE_STATE) != 0) {
+ try {
+ if (VDBG) log("listen: call onSSC state=" + mServiceState[phoneId]);
+ ServiceState rawSs = new ServiceState(mServiceState[phoneId]);
+ if (checkFineLocationAccess(r, Build.VERSION_CODES.Q)) {
+ r.callback.onServiceStateChanged(rawSs);
+ } else if (checkCoarseLocationAccess(r, Build.VERSION_CODES.Q)) {
+ r.callback.onServiceStateChanged(
+ rawSs.createLocationInfoSanitizedCopy(false));
+ } else {
+ r.callback.onServiceStateChanged(
+ rawSs.createLocationInfoSanitizedCopy(true));
+ }
+ } catch (RemoteException ex) {
+ remove(r.binder);
}
- } catch (RemoteException ex) {
- remove(r.binder);
}
- }
- if (events.contains(PhoneStateListener.EVENT_SIGNAL_STRENGTH_CHANGED)) {
- try {
- if (mSignalStrength[phoneId] != null) {
- int gsmSignalStrength = mSignalStrength[phoneId]
- .getGsmSignalStrength();
- r.callback.onSignalStrengthChanged((gsmSignalStrength == 99 ? -1
- : gsmSignalStrength));
+ if ((events & PhoneStateListener.LISTEN_SIGNAL_STRENGTH) != 0) {
+ try {
+ if (mSignalStrength[phoneId] != null) {
+ int gsmSignalStrength = mSignalStrength[phoneId]
+ .getGsmSignalStrength();
+ r.callback.onSignalStrengthChanged((gsmSignalStrength == 99 ? -1
+ : gsmSignalStrength));
+ }
+ } catch (RemoteException ex) {
+ remove(r.binder);
}
- } catch (RemoteException ex) {
- remove(r.binder);
}
- }
- if (events.contains(
- PhoneStateListener.EVENT_MESSAGE_WAITING_INDICATOR_CHANGED)) {
- try {
- r.callback.onMessageWaitingIndicatorChanged(
- mMessageWaiting[phoneId]);
- } catch (RemoteException ex) {
- remove(r.binder);
+ if ((events & PhoneStateListener.LISTEN_MESSAGE_WAITING_INDICATOR) != 0) {
+ try {
+ r.callback.onMessageWaitingIndicatorChanged(
+ mMessageWaiting[phoneId]);
+ } catch (RemoteException ex) {
+ remove(r.binder);
+ }
}
- }
- if (events.contains(
- PhoneStateListener.EVENT_CALL_FORWARDING_INDICATOR_CHANGED)) {
- try {
- r.callback.onCallForwardingIndicatorChanged(
- mCallForwarding[phoneId]);
- } catch (RemoteException ex) {
- remove(r.binder);
+ if ((events & PhoneStateListener.LISTEN_CALL_FORWARDING_INDICATOR) != 0) {
+ try {
+ r.callback.onCallForwardingIndicatorChanged(
+ mCallForwarding[phoneId]);
+ } catch (RemoteException ex) {
+ remove(r.binder);
+ }
}
- }
- if (validateEventAndUserLocked(
- r, PhoneStateListener.EVENT_CELL_LOCATION_CHANGED)) {
- try {
- if (DBG_LOC) log("listen: mCellIdentity = " + mCellIdentity[phoneId]);
- if (checkCoarseLocationAccess(r, Build.VERSION_CODES.BASE)
- && checkFineLocationAccess(r, Build.VERSION_CODES.Q)) {
- // null will be translated to empty CellLocation object in client.
- r.callback.onCellLocationChanged(mCellIdentity[phoneId]);
+ if (validateEventsAndUserLocked(r, PhoneStateListener.LISTEN_CELL_LOCATION)) {
+ try {
+ if (DBG_LOC) log("listen: mCellIdentity = " + mCellIdentity[phoneId]);
+ if (checkCoarseLocationAccess(r, Build.VERSION_CODES.BASE)
+ && checkFineLocationAccess(r, Build.VERSION_CODES.Q)) {
+ // null will be translated to empty CellLocation object in client.
+ r.callback.onCellLocationChanged(mCellIdentity[phoneId]);
+ }
+ } catch (RemoteException ex) {
+ remove(r.binder);
}
- } catch (RemoteException ex) {
- remove(r.binder);
}
- }
- if (events.contains(PhoneStateListener.EVENT_CALL_STATE_CHANGED)) {
- try {
- r.callback.onCallStateChanged(mCallState[phoneId],
- getCallIncomingNumber(r, phoneId));
- } catch (RemoteException ex) {
- remove(r.binder);
+ if ((events & PhoneStateListener.LISTEN_CALL_STATE) != 0) {
+ try {
+ r.callback.onCallStateChanged(mCallState[phoneId],
+ getCallIncomingNumber(r, phoneId));
+ } catch (RemoteException ex) {
+ remove(r.binder);
+ }
}
- }
- if (events.contains(PhoneStateListener.EVENT_DATA_CONNECTION_STATE_CHANGED)) {
- try {
- r.callback.onDataConnectionStateChanged(mDataConnectionState[phoneId],
+ if ((events & PhoneStateListener.LISTEN_DATA_CONNECTION_STATE) != 0) {
+ try {
+ r.callback.onDataConnectionStateChanged(mDataConnectionState[phoneId],
mDataConnectionNetworkType[phoneId]);
- } catch (RemoteException ex) {
- remove(r.binder);
- }
- }
- if (events.contains(PhoneStateListener.EVENT_DATA_ACTIVITY_CHANGED)) {
- try {
- r.callback.onDataActivity(mDataActivity[phoneId]);
- } catch (RemoteException ex) {
- remove(r.binder);
+ } catch (RemoteException ex) {
+ remove(r.binder);
+ }
}
- }
- if (events.contains(PhoneStateListener.EVENT_SIGNAL_STRENGTHS_CHANGED)) {
- try {
- if (mSignalStrength[phoneId] != null) {
- r.callback.onSignalStrengthsChanged(mSignalStrength[phoneId]);
+ if ((events & PhoneStateListener.LISTEN_DATA_ACTIVITY) != 0) {
+ try {
+ r.callback.onDataActivity(mDataActivity[phoneId]);
+ } catch (RemoteException ex) {
+ remove(r.binder);
}
- } catch (RemoteException ex) {
- remove(r.binder);
}
- }
- if (events.contains(
- PhoneStateListener.EVENT_ALWAYS_REPORTED_SIGNAL_STRENGTH_CHANGED)) {
- updateReportSignalStrengthDecision(r.subId);
- try {
- if (mSignalStrength[phoneId] != null) {
- r.callback.onSignalStrengthsChanged(mSignalStrength[phoneId]);
+ if ((events & PhoneStateListener.LISTEN_SIGNAL_STRENGTHS) != 0) {
+ try {
+ if (mSignalStrength[phoneId] != null) {
+ r.callback.onSignalStrengthsChanged(mSignalStrength[phoneId]);
+ }
+ } catch (RemoteException ex) {
+ remove(r.binder);
}
- } catch (RemoteException ex) {
- remove(r.binder);
}
- }
- if (validateEventAndUserLocked(
- r, PhoneStateListener.EVENT_CELL_INFO_CHANGED)) {
- try {
- if (DBG_LOC) log("listen: mCellInfo[" + phoneId + "] = "
- + mCellInfo.get(phoneId));
- if (checkCoarseLocationAccess(r, Build.VERSION_CODES.BASE)
- && checkFineLocationAccess(r, Build.VERSION_CODES.Q)) {
- r.callback.onCellInfoChanged(mCellInfo.get(phoneId));
+ if ((events & PhoneStateListener.LISTEN_ALWAYS_REPORTED_SIGNAL_STRENGTH)
+ != 0) {
+ updateReportSignalStrengthDecision(r.subId);
+ try {
+ if (mSignalStrength[phoneId] != null) {
+ r.callback.onSignalStrengthsChanged(mSignalStrength[phoneId]);
+ }
+ } catch (RemoteException ex) {
+ remove(r.binder);
}
- } catch (RemoteException ex) {
- remove(r.binder);
}
- }
- if (events.contains(PhoneStateListener.EVENT_PRECISE_CALL_STATE_CHANGED)) {
- try {
- r.callback.onPreciseCallStateChanged(mPreciseCallState[phoneId]);
- } catch (RemoteException ex) {
- remove(r.binder);
+ if (validateEventsAndUserLocked(r, PhoneStateListener.LISTEN_CELL_INFO)) {
+ try {
+ if (DBG_LOC) log("listen: mCellInfo[" + phoneId + "] = "
+ + mCellInfo.get(phoneId));
+ if (checkCoarseLocationAccess(r, Build.VERSION_CODES.BASE)
+ && checkFineLocationAccess(r, Build.VERSION_CODES.Q)) {
+ r.callback.onCellInfoChanged(mCellInfo.get(phoneId));
+ }
+ } catch (RemoteException ex) {
+ remove(r.binder);
+ }
}
- }
- if (events.contains(PhoneStateListener.EVENT_CALL_DISCONNECT_CAUSE_CHANGED)) {
- try {
- r.callback.onCallDisconnectCauseChanged(mCallDisconnectCause[phoneId],
- mCallPreciseDisconnectCause[phoneId]);
- } catch (RemoteException ex) {
- remove(r.binder);
+ if ((events & PhoneStateListener.LISTEN_PRECISE_CALL_STATE) != 0) {
+ try {
+ r.callback.onPreciseCallStateChanged(mPreciseCallState[phoneId]);
+ } catch (RemoteException ex) {
+ remove(r.binder);
+ }
}
- }
- if (events.contains(PhoneStateListener.EVENT_IMS_CALL_DISCONNECT_CAUSE_CHANGED)) {
- try {
- r.callback.onImsCallDisconnectCauseChanged(mImsReasonInfo.get(phoneId));
- } catch (RemoteException ex) {
- remove(r.binder);
+ if ((events & PhoneStateListener.LISTEN_CALL_DISCONNECT_CAUSES) != 0) {
+ try {
+ r.callback.onCallDisconnectCauseChanged(mCallDisconnectCause[phoneId],
+ mCallPreciseDisconnectCause[phoneId]);
+ } catch (RemoteException ex) {
+ remove(r.binder);
+ }
}
- }
- if (events.contains(
- PhoneStateListener.EVENT_PRECISE_DATA_CONNECTION_STATE_CHANGED)) {
- try {
- for (PreciseDataConnectionState pdcs
- : mPreciseDataConnectionStates.get(phoneId).values()) {
- r.callback.onPreciseDataConnectionStateChanged(pdcs);
+ if ((events & PhoneStateListener.LISTEN_IMS_CALL_DISCONNECT_CAUSES) != 0) {
+ try {
+ r.callback.onImsCallDisconnectCauseChanged(mImsReasonInfo.get(phoneId));
+ } catch (RemoteException ex) {
+ remove(r.binder);
}
- } catch (RemoteException ex) {
- remove(r.binder);
}
- }
- if (events.contains(PhoneStateListener.EVENT_CARRIER_NETWORK_CHANGED)) {
- try {
- r.callback.onCarrierNetworkChange(mCarrierNetworkChangeState);
- } catch (RemoteException ex) {
- remove(r.binder);
+ if ((events & PhoneStateListener.LISTEN_PRECISE_DATA_CONNECTION_STATE) != 0) {
+ try {
+ for (PreciseDataConnectionState pdcs
+ : mPreciseDataConnectionStates.get(phoneId).values()) {
+ r.callback.onPreciseDataConnectionStateChanged(pdcs);
+ }
+ } catch (RemoteException ex) {
+ remove(r.binder);
+ }
}
- }
- if (events.contains(PhoneStateListener.EVENT_VOICE_ACTIVATION_STATE_CHANGED)) {
- try {
- r.callback.onVoiceActivationStateChanged(
- mVoiceActivationState[phoneId]);
- } catch (RemoteException ex) {
- remove(r.binder);
+ if ((events & PhoneStateListener.LISTEN_CARRIER_NETWORK_CHANGE) != 0) {
+ try {
+ r.callback.onCarrierNetworkChange(mCarrierNetworkChangeState);
+ } catch (RemoteException ex) {
+ remove(r.binder);
+ }
}
- }
- if (events.contains(PhoneStateListener.EVENT_DATA_ACTIVATION_STATE_CHANGED)) {
- try {
- r.callback.onDataActivationStateChanged(mDataActivationState[phoneId]);
- } catch (RemoteException ex) {
- remove(r.binder);
+ if ((events & PhoneStateListener.LISTEN_VOICE_ACTIVATION_STATE) !=0) {
+ try {
+ r.callback.onVoiceActivationStateChanged(
+ mVoiceActivationState[phoneId]);
+ } catch (RemoteException ex) {
+ remove(r.binder);
+ }
}
- }
- if (events.contains(PhoneStateListener.EVENT_USER_MOBILE_DATA_STATE_CHANGED)) {
- try {
- r.callback.onUserMobileDataStateChanged(mUserMobileDataState[phoneId]);
- } catch (RemoteException ex) {
- remove(r.binder);
+ if ((events & PhoneStateListener.LISTEN_DATA_ACTIVATION_STATE) !=0) {
+ try {
+ r.callback.onDataActivationStateChanged(mDataActivationState[phoneId]);
+ } catch (RemoteException ex) {
+ remove(r.binder);
+ }
}
- }
- if (events.contains(PhoneStateListener.EVENT_DISPLAY_INFO_CHANGED)) {
- try {
- if (mTelephonyDisplayInfos[phoneId] != null) {
- r.callback.onDisplayInfoChanged(mTelephonyDisplayInfos[phoneId]);
+ if ((events & PhoneStateListener.LISTEN_USER_MOBILE_DATA_STATE) != 0) {
+ try {
+ r.callback.onUserMobileDataStateChanged(mUserMobileDataState[phoneId]);
+ } catch (RemoteException ex) {
+ remove(r.binder);
}
- } catch (RemoteException ex) {
- remove(r.binder);
}
- }
- if (events.contains(PhoneStateListener.EVENT_EMERGENCY_NUMBER_LIST_CHANGED)) {
- try {
- r.callback.onEmergencyNumberListChanged(mEmergencyNumberList);
- } catch (RemoteException ex) {
- remove(r.binder);
+ if ((events & PhoneStateListener.LISTEN_DISPLAY_INFO_CHANGED) != 0) {
+ try {
+ if (mTelephonyDisplayInfos[phoneId] != null) {
+ r.callback.onDisplayInfoChanged(mTelephonyDisplayInfos[phoneId]);
+ }
+ } catch (RemoteException ex) {
+ remove(r.binder);
+ }
}
- }
- if (events.contains(PhoneStateListener.EVENT_PHONE_CAPABILITY_CHANGED)) {
- try {
- r.callback.onPhoneCapabilityChanged(mPhoneCapability);
- } catch (RemoteException ex) {
- remove(r.binder);
+ if ((events & PhoneStateListener.LISTEN_EMERGENCY_NUMBER_LIST) != 0) {
+ try {
+ r.callback.onEmergencyNumberListChanged(mEmergencyNumberList);
+ } catch (RemoteException ex) {
+ remove(r.binder);
+ }
}
- }
- if (events.contains(
- PhoneStateListener.EVENT_ACTIVE_DATA_SUBSCRIPTION_ID_CHANGED)) {
- try {
- r.callback.onActiveDataSubIdChanged(mActiveDataSubId);
- } catch (RemoteException ex) {
- remove(r.binder);
+ if ((events & PhoneStateListener.LISTEN_PHONE_CAPABILITY_CHANGE) != 0) {
+ try {
+ r.callback.onPhoneCapabilityChanged(mPhoneCapability);
+ } catch (RemoteException ex) {
+ remove(r.binder);
+ }
}
- }
- if (events.contains(PhoneStateListener.EVENT_RADIO_POWER_STATE_CHANGED)) {
- try {
- r.callback.onRadioPowerStateChanged(mRadioPowerState);
- } catch (RemoteException ex) {
- remove(r.binder);
+ if ((events & PhoneStateListener
+ .LISTEN_ACTIVE_DATA_SUBSCRIPTION_ID_CHANGE) != 0) {
+ try {
+ r.callback.onActiveDataSubIdChanged(mActiveDataSubId);
+ } catch (RemoteException ex) {
+ remove(r.binder);
+ }
}
- }
- if (events.contains(PhoneStateListener.EVENT_SRVCC_STATE_CHANGED)) {
- try {
- r.callback.onSrvccStateChanged(mSrvccState[phoneId]);
- } catch (RemoteException ex) {
- remove(r.binder);
+ if ((events & PhoneStateListener.LISTEN_RADIO_POWER_STATE_CHANGED) != 0) {
+ try {
+ r.callback.onRadioPowerStateChanged(mRadioPowerState);
+ } catch (RemoteException ex) {
+ remove(r.binder);
+ }
}
- }
- if (events.contains(PhoneStateListener.EVENT_CALL_ATTRIBUTES_CHANGED)) {
- try {
- r.callback.onCallAttributesChanged(mCallAttributes[phoneId]);
- } catch (RemoteException ex) {
- remove(r.binder);
+ if ((events & PhoneStateListener.LISTEN_SRVCC_STATE_CHANGED) != 0) {
+ try {
+ r.callback.onSrvccStateChanged(mSrvccState[phoneId]);
+ } catch (RemoteException ex) {
+ remove(r.binder);
+ }
}
- }
- if (events.contains(PhoneStateListener.EVENT_BARRING_INFO_CHANGED)) {
- BarringInfo barringInfo = mBarringInfo.get(phoneId);
- BarringInfo biNoLocation = barringInfo != null
- ? barringInfo.createLocationInfoSanitizedCopy() : null;
- if (VDBG) log("listen: call onBarringInfoChanged=" + barringInfo);
- try {
- r.callback.onBarringInfoChanged(
- checkFineLocationAccess(r, Build.VERSION_CODES.BASE)
- ? barringInfo : biNoLocation);
- } catch (RemoteException ex) {
- remove(r.binder);
+ if ((events & PhoneStateListener.LISTEN_CALL_ATTRIBUTES_CHANGED) != 0) {
+ try {
+ r.callback.onCallAttributesChanged(mCallAttributes[phoneId]);
+ } catch (RemoteException ex) {
+ remove(r.binder);
+ }
}
- }
- if (events.contains(
- PhoneStateListener.EVENT_PHYSICAL_CHANNEL_CONFIG_CHANGED)) {
- try {
- r.callback.onPhysicalChannelConfigChanged(
- mPhysicalChannelConfigs);
- } catch (RemoteException ex) {
- remove(r.binder);
+ if ((events & PhoneStateListener.LISTEN_BARRING_INFO) != 0) {
+ BarringInfo barringInfo = mBarringInfo.get(phoneId);
+ BarringInfo biNoLocation = barringInfo != null
+ ? barringInfo.createLocationInfoSanitizedCopy() : null;
+ if (VDBG) log("listen: call onBarringInfoChanged=" + barringInfo);
+ try {
+ r.callback.onBarringInfoChanged(
+ checkFineLocationAccess(r, Build.VERSION_CODES.BASE)
+ ? barringInfo : biNoLocation);
+ } catch (RemoteException ex) {
+ remove(r.binder);
+ }
}
- }
- if (events.contains(
- PhoneStateListener.EVENT_DATA_ENABLED_CHANGED)) {
- try {
- r.callback.onDataEnabledChanged(mIsDataEnabled, mDataEnabledReason);
- } catch (RemoteException ex) {
- remove(r.binder);
+ if ((events & PhoneStateListener.LISTEN_PHYSICAL_CHANNEL_CONFIGURATION) != 0) {
+ try {
+ r.callback.onPhysicalChannelConfigurationChanged(
+ mPhysicalChannelConfigs);
+ } catch (RemoteException ex) {
+ remove(r.binder);
+ }
}
}
}
+ } else {
+ if(DBG) log("listen: Unregister");
+ remove(callback.asBinder());
}
}
@@ -1170,7 +1133,7 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
// If any of the system clients wants to always listen to signal strength,
// we need to set it on.
if (r.matchPhoneStateListenerEvent(
- PhoneStateListener.EVENT_ALWAYS_REPORTED_SIGNAL_STRENGTH_CHANGED)) {
+ PhoneStateListener.LISTEN_ALWAYS_REPORTED_SIGNAL_STRENGTH)) {
telephonyManager.createForSubscriptionId(subscriptionId)
.setAlwaysReportSignalStrength(true);
return;
@@ -1271,7 +1234,7 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
// strength is removed from registry records, we need to check if
// the signal strength decision needs to update on its slot.
if (r.matchPhoneStateListenerEvent(
- PhoneStateListener.EVENT_ALWAYS_REPORTED_SIGNAL_STRENGTH_CHANGED)) {
+ PhoneStateListener.LISTEN_ALWAYS_REPORTED_SIGNAL_STRENGTH)) {
updateReportSignalStrengthDecision(r.subId);
}
return;
@@ -1291,8 +1254,8 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
synchronized (mRecords) {
for (Record r : mRecords) {
- if (r.matchPhoneStateListenerEvent(PhoneStateListener.EVENT_CALL_STATE_CHANGED)
- && (r.subId == SubscriptionManager.DEFAULT_SUBSCRIPTION_ID)) {
+ if (r.matchPhoneStateListenerEvent(PhoneStateListener.LISTEN_CALL_STATE) &&
+ (r.subId == SubscriptionManager.DEFAULT_SUBSCRIPTION_ID)) {
try {
// Ensure the listener has read call log permission; if they do not return
// an empty phone number.
@@ -1326,9 +1289,9 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
mCallState[phoneId] = state;
mCallIncomingNumber[phoneId] = incomingNumber;
for (Record r : mRecords) {
- if (r.matchPhoneStateListenerEvent(PhoneStateListener.EVENT_CALL_STATE_CHANGED)
- && (r.subId == subId)
- && (r.subId != SubscriptionManager.DEFAULT_SUBSCRIPTION_ID)) {
+ if (r.matchPhoneStateListenerEvent(PhoneStateListener.LISTEN_CALL_STATE) &&
+ (r.subId == subId) &&
+ (r.subId != SubscriptionManager.DEFAULT_SUBSCRIPTION_ID)) {
try {
String incomingNumberOrEmpty = getCallIncomingNumber(r, phoneId);
r.callback.onCallStateChanged(state, incomingNumberOrEmpty);
@@ -1368,9 +1331,8 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
log("notifyServiceStateForSubscriber: r=" + r + " subId=" + subId
+ " phoneId=" + phoneId + " state=" + state);
}
- if (r.matchPhoneStateListenerEvent(
- PhoneStateListener.EVENT_SERVICE_STATE_CHANGED)
- && idMatch(r.subId, subId, phoneId)) {
+ if (r.matchPhoneStateListenerEvent(PhoneStateListener.LISTEN_SERVICE_STATE) &&
+ idMatch(r.subId, subId, phoneId)) {
try {
ServiceState stateToSend;
@@ -1431,7 +1393,7 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
try {
if ((activationType == SIM_ACTIVATION_TYPE_VOICE)
&& r.matchPhoneStateListenerEvent(
- PhoneStateListener.EVENT_VOICE_ACTIVATION_STATE_CHANGED)
+ PhoneStateListener.LISTEN_VOICE_ACTIVATION_STATE)
&& idMatch(r.subId, subId, phoneId)) {
if (DBG) {
log("notifyVoiceActivationStateForPhoneId: callback.onVASC r=" + r
@@ -1442,7 +1404,7 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
}
if ((activationType == SIM_ACTIVATION_TYPE_DATA)
&& r.matchPhoneStateListenerEvent(
- PhoneStateListener.EVENT_DATA_ACTIVATION_STATE_CHANGED)
+ PhoneStateListener.LISTEN_DATA_ACTIVATION_STATE)
&& idMatch(r.subId, subId, phoneId)) {
if (DBG) {
log("notifyDataActivationStateForPhoneId: callback.onDASC r=" + r
@@ -1481,11 +1443,9 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
log("notifySignalStrengthForPhoneId: r=" + r + " subId=" + subId
+ " phoneId=" + phoneId + " ss=" + signalStrength);
}
- if ((r.matchPhoneStateListenerEvent(
- PhoneStateListener.EVENT_SIGNAL_STRENGTHS_CHANGED)
+ if ((r.matchPhoneStateListenerEvent(PhoneStateListener.LISTEN_SIGNAL_STRENGTHS)
|| r.matchPhoneStateListenerEvent(
- PhoneStateListener.
- EVENT_ALWAYS_REPORTED_SIGNAL_STRENGTH_CHANGED))
+ PhoneStateListener.LISTEN_ALWAYS_REPORTED_SIGNAL_STRENGTH))
&& idMatch(r.subId, subId, phoneId)) {
try {
if (DBG) {
@@ -1498,9 +1458,8 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
mRemoveList.add(r.binder);
}
}
- if (r.matchPhoneStateListenerEvent(
- PhoneStateListener.EVENT_SIGNAL_STRENGTH_CHANGED)
- && idMatch(r.subId, subId, phoneId)) {
+ if (r.matchPhoneStateListenerEvent(PhoneStateListener.LISTEN_SIGNAL_STRENGTH) &&
+ idMatch(r.subId, subId, phoneId)) {
try {
int gsmSignalStrength = signalStrength.getGsmSignalStrength();
int ss = (gsmSignalStrength == 99 ? -1 : gsmSignalStrength);
@@ -1546,8 +1505,8 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
}
for (Record r : mRecords) {
if (r.matchPhoneStateListenerEvent(
- PhoneStateListener.EVENT_CARRIER_NETWORK_CHANGED)
- && idMatch(r.subId, subId, phoneId)) {
+ PhoneStateListener.LISTEN_CARRIER_NETWORK_CHANGE) &&
+ idMatch(r.subId, subId, phoneId)) {
try {
r.callback.onCarrierNetworkChange(active);
} catch (RemoteException ex) {
@@ -1577,10 +1536,9 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
if (validatePhoneId(phoneId)) {
mCellInfo.set(phoneId, cellInfo);
for (Record r : mRecords) {
- if (validateEventAndUserLocked(
- r, PhoneStateListener.EVENT_CELL_INFO_CHANGED)
- && idMatch(r.subId, subId, phoneId)
- && (checkCoarseLocationAccess(r, Build.VERSION_CODES.BASE)
+ if (validateEventsAndUserLocked(r, PhoneStateListener.LISTEN_CELL_INFO) &&
+ idMatch(r.subId, subId, phoneId) &&
+ (checkCoarseLocationAccess(r, Build.VERSION_CODES.BASE)
&& checkFineLocationAccess(r, Build.VERSION_CODES.Q))) {
try {
if (DBG_LOC) {
@@ -1612,8 +1570,8 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
mMessageWaiting[phoneId] = mwi;
for (Record r : mRecords) {
if (r.matchPhoneStateListenerEvent(
- PhoneStateListener.EVENT_MESSAGE_WAITING_INDICATOR_CHANGED)
- && idMatch(r.subId, subId, phoneId)) {
+ PhoneStateListener.LISTEN_MESSAGE_WAITING_INDICATOR) &&
+ idMatch(r.subId, subId, phoneId)) {
try {
r.callback.onMessageWaitingIndicatorChanged(mwi);
} catch (RemoteException ex) {
@@ -1639,8 +1597,8 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
mUserMobileDataState[phoneId] = state;
for (Record r : mRecords) {
if (r.matchPhoneStateListenerEvent(
- PhoneStateListener.EVENT_USER_MOBILE_DATA_STATE_CHANGED)
- && idMatch(r.subId, subId, phoneId)) {
+ PhoneStateListener.LISTEN_USER_MOBILE_DATA_STATE) &&
+ idMatch(r.subId, subId, phoneId)) {
try {
r.callback.onUserMobileDataStateChanged(state);
} catch (RemoteException ex) {
@@ -1678,7 +1636,7 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
mTelephonyDisplayInfos[phoneId] = telephonyDisplayInfo;
for (Record r : mRecords) {
if (r.matchPhoneStateListenerEvent(
- PhoneStateListener.EVENT_DISPLAY_INFO_CHANGED)
+ PhoneStateListener.LISTEN_DISPLAY_INFO_CHANGED)
&& idMatchWithoutDefaultPhoneCheck(r.subId, subId)) {
try {
r.callback.onDisplayInfoChanged(telephonyDisplayInfo);
@@ -1710,8 +1668,8 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
mCallForwarding[phoneId] = cfi;
for (Record r : mRecords) {
if (r.matchPhoneStateListenerEvent(
- PhoneStateListener.EVENT_CALL_FORWARDING_INDICATOR_CHANGED)
- && idMatch(r.subId, subId, phoneId)) {
+ PhoneStateListener.LISTEN_CALL_FORWARDING_INDICATOR) &&
+ idMatch(r.subId, subId, phoneId)) {
try {
r.callback.onCallForwardingIndicatorChanged(cfi);
} catch (RemoteException ex) {
@@ -1738,9 +1696,8 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
mDataActivity[phoneId] = state;
for (Record r : mRecords) {
// Notify by correct subId.
- if (r.matchPhoneStateListenerEvent(
- PhoneStateListener.EVENT_DATA_ACTIVITY_CHANGED)
- && idMatch(r.subId, subId, phoneId)) {
+ if (r.matchPhoneStateListenerEvent(PhoneStateListener.LISTEN_DATA_ACTIVITY) &&
+ idMatch(r.subId, subId, phoneId)) {
try {
r.callback.onDataActivity(state);
} catch (RemoteException ex) {
@@ -1787,7 +1744,7 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
mLocalLog.log(str);
for (Record r : mRecords) {
if (r.matchPhoneStateListenerEvent(
- PhoneStateListener.EVENT_DATA_CONNECTION_STATE_CHANGED)
+ PhoneStateListener.LISTEN_DATA_CONNECTION_STATE)
&& idMatch(r.subId, subId, phoneId)) {
try {
if (DBG) {
@@ -1812,7 +1769,7 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
if (!Objects.equals(oldState, preciseState)) {
for (Record r : mRecords) {
if (r.matchPhoneStateListenerEvent(
- PhoneStateListener.EVENT_PRECISE_DATA_CONNECTION_STATE_CHANGED)
+ PhoneStateListener.LISTEN_PRECISE_DATA_CONNECTION_STATE)
&& idMatch(r.subId, subId, phoneId)) {
try {
r.callback.onPreciseDataConnectionStateChanged(preciseState);
@@ -1857,10 +1814,9 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
if (validatePhoneId(phoneId) && !Objects.equals(cellIdentity, mCellIdentity[phoneId])) {
mCellIdentity[phoneId] = cellIdentity;
for (Record r : mRecords) {
- if (validateEventAndUserLocked(
- r, PhoneStateListener.EVENT_CELL_LOCATION_CHANGED)
- && idMatch(r.subId, subId, phoneId)
- && (checkCoarseLocationAccess(r, Build.VERSION_CODES.BASE)
+ if (validateEventsAndUserLocked(r, PhoneStateListener.LISTEN_CELL_LOCATION) &&
+ idMatch(r.subId, subId, phoneId) &&
+ (checkCoarseLocationAccess(r, Build.VERSION_CODES.BASE)
&& checkFineLocationAccess(r, Build.VERSION_CODES.Q))) {
try {
if (DBG_LOC) {
@@ -1911,8 +1867,7 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
}
for (Record r : mRecords) {
- if (r.matchPhoneStateListenerEvent(
- PhoneStateListener.EVENT_PRECISE_CALL_STATE_CHANGED)
+ if (r.matchPhoneStateListenerEvent(PhoneStateListener.LISTEN_PRECISE_CALL_STATE)
&& idMatch(r.subId, subId, phoneId)) {
try {
r.callback.onPreciseCallStateChanged(mPreciseCallState[phoneId]);
@@ -1921,7 +1876,7 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
}
}
if (notifyCallAttributes && r.matchPhoneStateListenerEvent(
- PhoneStateListener.EVENT_CALL_ATTRIBUTES_CHANGED)
+ PhoneStateListener.LISTEN_CALL_ATTRIBUTES_CHANGED)
&& idMatch(r.subId, subId, phoneId)) {
try {
r.callback.onCallAttributesChanged(mCallAttributes[phoneId]);
@@ -1970,7 +1925,7 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
mImsReasonInfo.set(phoneId, imsReasonInfo);
for (Record r : mRecords) {
if (r.matchPhoneStateListenerEvent(
- PhoneStateListener.EVENT_IMS_CALL_DISCONNECT_CAUSE_CHANGED)
+ PhoneStateListener.LISTEN_IMS_CALL_DISCONNECT_CAUSES)
&& idMatch(r.subId, subId, phoneId)) {
try {
if (DBG_LOC) {
@@ -2002,8 +1957,8 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
mSrvccState[phoneId] = state;
for (Record r : mRecords) {
if (r.matchPhoneStateListenerEvent(
- PhoneStateListener.EVENT_SRVCC_STATE_CHANGED)
- && idMatch(r.subId, subId, phoneId)) {
+ PhoneStateListener.LISTEN_SRVCC_STATE_CHANGED) &&
+ idMatch(r.subId, subId, phoneId)) {
try {
if (DBG_LOC) {
log("notifySrvccStateChanged: mSrvccState=" + state + " r=" + r);
@@ -2031,7 +1986,7 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
log("notifyOemHookRawEventForSubscriber: r=" + r + " subId=" + subId);
}
if ((r.matchPhoneStateListenerEvent(
- PhoneStateListener.EVENT_OEM_HOOK_RAW))
+ PhoneStateListener.LISTEN_OEM_HOOK_RAW_EVENT))
&& idMatch(r.subId, subId, phoneId)) {
try {
r.callback.onOemHookRawEvent(rawData);
@@ -2059,7 +2014,7 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
for (Record r : mRecords) {
if (r.matchPhoneStateListenerEvent(
- PhoneStateListener.EVENT_PHONE_CAPABILITY_CHANGED)) {
+ PhoneStateListener.LISTEN_PHONE_CAPABILITY_CHANGE)) {
try {
r.callback.onPhoneCapabilityChanged(capability);
} catch (RemoteException ex) {
@@ -2084,7 +2039,7 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
synchronized (mRecords) {
for (Record r : mRecords) {
if (r.matchPhoneStateListenerEvent(
- PhoneStateListener.EVENT_ACTIVE_DATA_SUBSCRIPTION_ID_CHANGED)) {
+ PhoneStateListener.LISTEN_ACTIVE_DATA_SUBSCRIPTION_ID_CHANGE)) {
try {
r.callback.onActiveDataSubIdChanged(activeDataSubId);
} catch (RemoteException ex) {
@@ -2111,7 +2066,7 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
for (Record r : mRecords) {
if (r.matchPhoneStateListenerEvent(
- PhoneStateListener.EVENT_RADIO_POWER_STATE_CHANGED)
+ PhoneStateListener.LISTEN_RADIO_POWER_STATE_CHANGED)
&& idMatch(r.subId, subId, phoneId)) {
try {
r.callback.onRadioPowerStateChanged(state);
@@ -2140,7 +2095,7 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
for (Record r : mRecords) {
if (r.matchPhoneStateListenerEvent(
- PhoneStateListener.EVENT_EMERGENCY_NUMBER_LIST_CHANGED)
+ PhoneStateListener.LISTEN_EMERGENCY_NUMBER_LIST)
&& idMatch(r.subId, subId, phoneId)) {
try {
r.callback.onEmergencyNumberListChanged(mEmergencyNumberList);
@@ -2172,7 +2127,7 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
for (Record r : mRecords) {
// Send to all listeners regardless of subscription
if (r.matchPhoneStateListenerEvent(
- PhoneStateListener.EVENT_OUTGOING_EMERGENCY_CALL)) {
+ PhoneStateListener.LISTEN_OUTGOING_EMERGENCY_CALL)) {
try {
r.callback.onOutgoingEmergencyCall(emergencyNumber, subId);
} catch (RemoteException ex) {
@@ -2196,7 +2151,7 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
for (Record r : mRecords) {
// Send to all listeners regardless of subscription
if (r.matchPhoneStateListenerEvent(
- PhoneStateListener.EVENT_OUTGOING_EMERGENCY_SMS)) {
+ PhoneStateListener.LISTEN_OUTGOING_EMERGENCY_SMS)) {
try {
r.callback.onOutgoingEmergencySms(emergencyNumber, subId);
} catch (RemoteException ex) {
@@ -2226,7 +2181,7 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
for (Record r : mRecords) {
if (r.matchPhoneStateListenerEvent(
- PhoneStateListener.EVENT_CALL_ATTRIBUTES_CHANGED)
+ PhoneStateListener.LISTEN_CALL_ATTRIBUTES_CHANGED)
&& idMatch(r.subId, subId, phoneId)) {
try {
r.callback.onCallAttributesChanged(mCallAttributes[phoneId]);
@@ -2257,7 +2212,7 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
if (validatePhoneId(phoneId)) {
for (Record r : mRecords) {
if (r.matchPhoneStateListenerEvent(
- PhoneStateListener.EVENT_REGISTRATION_FAILURE)
+ PhoneStateListener.LISTEN_REGISTRATION_FAILURE)
&& idMatch(r.subId, subId, phoneId)) {
try {
r.callback.onRegistrationFailed(
@@ -2300,7 +2255,7 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
if (VDBG) log("listen: call onBarringInfoChanged=" + barringInfo);
for (Record r : mRecords) {
if (r.matchPhoneStateListenerEvent(
- PhoneStateListener.EVENT_BARRING_INFO_CHANGED)
+ PhoneStateListener.LISTEN_BARRING_INFO)
&& idMatch(r.subId, subId, phoneId)) {
try {
if (DBG_LOC) {
@@ -2327,14 +2282,14 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
* @param subId the subId
* @param configs a list of {@link PhysicalChannelConfig}, the configs of physical channel.
*/
- public void notifyPhysicalChannelConfigForSubscriber(
+ public void notifyPhysicalChannelConfigurationForSubscriber(
int subId, List<PhysicalChannelConfig> configs) {
- if (!checkNotifyPermission("notifyPhysicalChannelConfig()")) {
+ if (!checkNotifyPermission("notifyPhysicalChannelConfiguration()")) {
return;
}
if (VDBG) {
- log("notifyPhysicalChannelConfig: subId=" + subId + " configs=" + configs);
+ log("notifyPhysicalChannelConfiguration: subId=" + subId + " configs=" + configs);
}
synchronized (mRecords) {
@@ -2343,15 +2298,15 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
mPhysicalChannelConfigs.set(phoneId, configs.get(phoneId));
for (Record r : mRecords) {
if (r.matchPhoneStateListenerEvent(
- PhoneStateListener.EVENT_PHYSICAL_CHANNEL_CONFIG_CHANGED)
+ PhoneStateListener.LISTEN_PHYSICAL_CHANNEL_CONFIGURATION)
&& idMatch(r.subId, subId, phoneId)) {
try {
if (DBG_LOC) {
- log("notifyPhysicalChannelConfig: "
+ log("notifyPhysicalChannelConfiguration: "
+ "mPhysicalChannelConfigs="
+ configs + " r=" + r);
}
- r.callback.onPhysicalChannelConfigChanged(configs);
+ r.callback.onPhysicalChannelConfigurationChanged(configs);
} catch (RemoteException ex) {
mRemoveList.add(r.binder);
}
@@ -2661,18 +2616,18 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
== PackageManager.PERMISSION_GRANTED;
}
- private boolean checkListenerPermission(Set<Integer> events, int subId, String callingPackage,
- @Nullable String callingFeatureId, String message) {
+ private boolean checkListenerPermission(long events, int subId, String callingPackage,
+ @Nullable String callingFeatureId, String message) {
LocationAccessPolicy.LocationPermissionQuery.Builder locationQueryBuilder =
new LocationAccessPolicy.LocationPermissionQuery.Builder()
- .setCallingPackage(callingPackage)
- .setMethod(message + " events: " + events)
- .setCallingPid(Binder.getCallingPid())
- .setCallingUid(Binder.getCallingUid());
+ .setCallingPackage(callingPackage)
+ .setMethod(message + " events: " + events)
+ .setCallingPid(Binder.getCallingPid())
+ .setCallingUid(Binder.getCallingUid());
boolean shouldCheckLocationPermissions = false;
- if (isLocationPermissionRequired(events)) {
+ if ((events & ENFORCE_LOCATION_PERMISSION_MASK) != 0) {
// Everything that requires fine location started in Q. So far...
locationQueryBuilder.setMinSdkVersionForFine(Build.VERSION_CODES.Q);
// If we're enforcing fine starting in Q, we also want to enforce coarse even for
@@ -2697,14 +2652,14 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
}
}
- if (isPhoneStatePermissionRequired(events)) {
+ if ((events & ENFORCE_PHONE_STATE_PERMISSION_MASK) != 0) {
if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(
mContext, subId, callingPackage, callingFeatureId, message)) {
isPermissionCheckSuccessful = false;
}
}
- if (isPrecisePhoneStatePermissionRequired(events)) {
+ if ((events & ENFORCE_PRECISE_PHONE_STATE_PERMISSION_MASK) != 0) {
// check if calling app has either permission READ_PRECISE_PHONE_STATE
// or with carrier privileges
try {
@@ -2715,20 +2670,21 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
}
}
- if (isActiveEmergencySessionPermissionRequired(events)) {
+ if ((events & READ_ACTIVE_EMERGENCY_SESSION_PERMISSION_MASK) != 0) {
mContext.enforceCallingOrSelfPermission(
android.Manifest.permission.READ_ACTIVE_EMERGENCY_SESSION, null);
}
- if ((events.contains(PhoneStateListener.EVENT_ALWAYS_REPORTED_SIGNAL_STRENGTH_CHANGED))) {
+ if ((events & PhoneStateListener.LISTEN_ALWAYS_REPORTED_SIGNAL_STRENGTH) != 0) {
mContext.enforceCallingOrSelfPermission(
android.Manifest.permission.LISTEN_ALWAYS_REPORTED_SIGNAL_STRENGTH, null);
}
- if (isPrivilegedPhoneStatePermissionRequired(events)) {
+ if ((events & READ_PRIVILEGED_PHONE_STATE_PERMISSION_MASK) != 0) {
mContext.enforceCallingOrSelfPermission(
android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, null);
}
+
return isPermissionCheckSuccessful;
}
@@ -2736,25 +2692,25 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
int size = mRemoveList.size();
if (VDBG) log("handleRemoveListLocked: mRemoveList.size()=" + size);
if (size > 0) {
- for (IBinder b : mRemoveList) {
+ for (IBinder b: mRemoveList) {
remove(b);
}
mRemoveList.clear();
}
}
- private boolean validateEventAndUserLocked(Record r, int event) {
+ private boolean validateEventsAndUserLocked(Record r, int events) {
int foregroundUser;
final long callingIdentity = Binder.clearCallingIdentity();
boolean valid = false;
try {
foregroundUser = ActivityManager.getCurrentUser();
valid = UserHandle.getUserId(r.callerUid) == foregroundUser
- && r.matchPhoneStateListenerEvent(event);
+ && r.matchPhoneStateListenerEvent(events);
if (DBG | DBG_LOC) {
- log("validateEventAndUserLocked: valid=" + valid
+ log("validateEventsAndUserLocked: valid=" + valid
+ " r.callerUid=" + r.callerUid + " foregroundUser=" + foregroundUser
- + " r.eventList=" + r.eventList + " event=" + event);
+ + " r.events=" + r.events + " events=" + events);
}
} finally {
Binder.restoreCallingIdentity(callingIdentity);
@@ -2866,14 +2822,9 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
}
private void checkPossibleMissNotify(Record r, int phoneId) {
- Set<Integer> events = r.eventList;
-
- if (events == null || events.isEmpty()) {
- log("checkPossibleMissNotify: events = null.");
- return;
- }
+ long events = r.events;
- if ((events.contains(PhoneStateListener.EVENT_SERVICE_STATE_CHANGED))) {
+ if ((events & PhoneStateListener.LISTEN_SERVICE_STATE) != 0) {
try {
if (VDBG) log("checkPossibleMissNotify: onServiceStateChanged state=" +
mServiceState[phoneId]);
@@ -2892,9 +2843,8 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
}
}
- if (events.contains(PhoneStateListener.EVENT_SIGNAL_STRENGTHS_CHANGED)
- || events.contains(
- PhoneStateListener.EVENT_ALWAYS_REPORTED_SIGNAL_STRENGTH_CHANGED)) {
+ if ((events & PhoneStateListener.LISTEN_SIGNAL_STRENGTHS) != 0
+ || (events & PhoneStateListener.LISTEN_ALWAYS_REPORTED_SIGNAL_STRENGTH) != 0) {
try {
if (mSignalStrength[phoneId] != null) {
SignalStrength signalStrength = mSignalStrength[phoneId];
@@ -2909,7 +2859,7 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
}
}
- if (events.contains(PhoneStateListener.EVENT_SIGNAL_STRENGTH_CHANGED)) {
+ if ((events & PhoneStateListener.LISTEN_SIGNAL_STRENGTH) != 0) {
try {
if (mSignalStrength[phoneId] != null) {
int gsmSignalStrength = mSignalStrength[phoneId]
@@ -2926,7 +2876,7 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
}
}
- if (validateEventAndUserLocked(r, PhoneStateListener.EVENT_CELL_INFO_CHANGED)) {
+ if (validateEventsAndUserLocked(r, PhoneStateListener.LISTEN_CELL_INFO)) {
try {
if (DBG_LOC) {
log("checkPossibleMissNotify: onCellInfoChanged[" + phoneId + "] = "
@@ -2941,7 +2891,7 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
}
}
- if (events.contains(PhoneStateListener.EVENT_USER_MOBILE_DATA_STATE_CHANGED)) {
+ if ((events & PhoneStateListener.LISTEN_USER_MOBILE_DATA_STATE) != 0) {
try {
if (VDBG) {
log("checkPossibleMissNotify: onUserMobileDataStateChanged phoneId="
@@ -2953,7 +2903,7 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
}
}
- if (events.contains(PhoneStateListener.EVENT_DISPLAY_INFO_CHANGED)) {
+ if ((events & PhoneStateListener.LISTEN_DISPLAY_INFO_CHANGED) != 0) {
try {
if (VDBG) {
log("checkPossibleMissNotify: onDisplayInfoChanged phoneId="
@@ -2967,7 +2917,7 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
}
}
- if (events.contains(PhoneStateListener.EVENT_MESSAGE_WAITING_INDICATOR_CHANGED)) {
+ if ((events & PhoneStateListener.LISTEN_MESSAGE_WAITING_INDICATOR) != 0) {
try {
if (VDBG) {
log("checkPossibleMissNotify: onMessageWaitingIndicatorChanged phoneId="
@@ -2980,7 +2930,7 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
}
}
- if (events.contains(PhoneStateListener.EVENT_CALL_FORWARDING_INDICATOR_CHANGED)) {
+ if ((events & PhoneStateListener.LISTEN_CALL_FORWARDING_INDICATOR) != 0) {
try {
if (VDBG) {
log("checkPossibleMissNotify: onCallForwardingIndicatorChanged phoneId="
@@ -2993,7 +2943,7 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
}
}
- if (validateEventAndUserLocked(r, PhoneStateListener.EVENT_CELL_LOCATION_CHANGED)) {
+ if (validateEventsAndUserLocked(r, PhoneStateListener.LISTEN_CELL_LOCATION)) {
try {
if (DBG_LOC) {
log("checkPossibleMissNotify: onCellLocationChanged mCellIdentity = "
@@ -3009,7 +2959,7 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
}
}
- if (events.contains(PhoneStateListener.EVENT_DATA_CONNECTION_STATE_CHANGED)) {
+ if ((events & PhoneStateListener.LISTEN_DATA_CONNECTION_STATE) != 0) {
try {
if (DBG) {
log("checkPossibleMissNotify: onDataConnectionStateChanged(mDataConnectionState"
diff --git a/services/core/java/com/android/server/VcnManagementService.java b/services/core/java/com/android/server/VcnManagementService.java
index f376473bb2a1..165b6a1b08f1 100644
--- a/services/core/java/com/android/server/VcnManagementService.java
+++ b/services/core/java/com/android/server/VcnManagementService.java
@@ -165,9 +165,13 @@ public class VcnManagementService extends IVcnManagementService.Stub {
// TODO: Clear VCN configuration, trigger teardown as necessary
}
- @VisibleForTesting(visibility = Visibility.PRIVATE)
- class VcnNetworkProvider extends NetworkProvider {
- VcnNetworkProvider(@NonNull Context context, @NonNull Looper looper) {
+ /**
+ * Network provider for VCN networks.
+ *
+ * @hide
+ */
+ public class VcnNetworkProvider extends NetworkProvider {
+ VcnNetworkProvider(Context context, Looper looper) {
super(context, looper, VcnNetworkProvider.class.getSimpleName());
}
diff --git a/services/core/java/com/android/server/am/ActiveUids.java b/services/core/java/com/android/server/am/ActiveUids.java
index c86c29f8ac2a..27be53a5faf4 100644
--- a/services/core/java/com/android/server/am/ActiveUids.java
+++ b/services/core/java/com/android/server/am/ActiveUids.java
@@ -52,9 +52,8 @@ final class ActiveUids {
void clear() {
mActiveUids.clear();
- if (mPostChangesToAtm) {
- mService.mAtmInternal.onActiveUidsCleared();
- }
+ // It is only called for a temporal container with mPostChangesToAtm == false or test case.
+ // So there is no need to notify activity task manager.
}
UidRecord get(int uid) {
diff --git a/services/core/java/com/android/server/am/BatteryStatsService.java b/services/core/java/com/android/server/am/BatteryStatsService.java
index c3ba15024a78..ed2faf992e0e 100644
--- a/services/core/java/com/android/server/am/BatteryStatsService.java
+++ b/services/core/java/com/android/server/am/BatteryStatsService.java
@@ -519,16 +519,24 @@ public final class BatteryStatsService extends IBatteryStats.Stub
return data;
}
- public ParcelFileDescriptor getStatisticsStream() {
+ /**
+ * Returns parceled BatteryStats as a MemoryFile.
+ *
+ * @param forceUpdate If true, runs a sync to get fresh battery stats. Otherwise,
+ * returns the current values.
+ */
+ public ParcelFileDescriptor getStatisticsStream(boolean forceUpdate) {
mContext.enforceCallingOrSelfPermission(
android.Manifest.permission.BATTERY_STATS, null);
//Slog.i("foo", "SENDING BATTERY INFO:");
//mStats.dumpLocked(new LogPrinter(Log.INFO, "foo", Log.LOG_ID_SYSTEM));
Parcel out = Parcel.obtain();
- // Drain the handler queue to make sure we've handled all pending works, so we'll get
- // an accurate stats.
- awaitCompletion();
- syncStats("get-stats", BatteryExternalStatsWorker.UPDATE_ALL);
+ if (forceUpdate) {
+ // Drain the handler queue to make sure we've handled all pending works, so we'll get
+ // an accurate stats.
+ awaitCompletion();
+ syncStats("get-stats", BatteryExternalStatsWorker.UPDATE_ALL);
+ }
synchronized (mStats) {
mStats.writeToParcel(out, 0);
}
diff --git a/services/core/java/com/android/server/appop/AppOpsService.java b/services/core/java/com/android/server/appop/AppOpsService.java
index 09937e3a74c1..da4704097ad0 100644
--- a/services/core/java/com/android/server/appop/AppOpsService.java
+++ b/services/core/java/com/android/server/appop/AppOpsService.java
@@ -94,7 +94,6 @@ import android.app.AsyncNotedAppOp;
import android.app.RuntimeAppOpAccessMessage;
import android.app.SyncNotedAppOp;
import android.content.BroadcastReceiver;
-import android.content.ComponentName;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
@@ -3018,28 +3017,6 @@ public class AppOpsService extends IAppOpsService.Stub {
}
}
- private boolean isTrustedVoiceServiceProxy(String packageName, int code) {
- if (code != OP_RECORD_AUDIO) {
- return false;
- }
- final String voiceRecognitionComponent = Settings.Secure.getString(
- mContext.getContentResolver(), Settings.Secure.VOICE_RECOGNITION_SERVICE);
- final String voiceInteractionComponent = Settings.Secure.getString(
- mContext.getContentResolver(), Settings.Secure.VOICE_INTERACTION_SERVICE);
-
- final String voiceRecognitionServicePackageName =
- getComponentPackageNameFromString(voiceRecognitionComponent);
- final String voiceInteractionServicePackageName =
- getComponentPackageNameFromString(voiceInteractionComponent);
- return Objects.equals(packageName, voiceRecognitionServicePackageName) && Objects.equals(
- voiceRecognitionServicePackageName, voiceInteractionServicePackageName);
- }
-
- private String getComponentPackageNameFromString(String from) {
- ComponentName componentName = from != null ? ComponentName.unflattenFromString(from) : null;
- return componentName != null ? componentName.getPackageName() : "";
- }
-
@Override
public int noteProxyOperation(int code, int proxiedUid, String proxiedPackageName,
String proxiedAttributionTag, int proxyUid, String proxyPackageName,
@@ -3057,10 +3034,12 @@ public class AppOpsService extends IAppOpsService.Stub {
// This is a workaround for R QPR, new API change is not allowed. We only allow the current
// voice recognizer is also the voice interactor to noteproxy op.
- final boolean isTrustVoiceServiceProxy = isTrustedVoiceServiceProxy(proxyPackageName, code);
+ final boolean isTrustVoiceServiceProxy =
+ AppOpsManager.isTrustedVoiceServiceProxy(mContext, proxyPackageName, code);
+ final boolean isSelfBlame = Binder.getCallingUid() == proxiedUid;
final boolean isProxyTrusted = mContext.checkPermission(
Manifest.permission.UPDATE_APP_OPS_STATS, -1, proxyUid)
- == PackageManager.PERMISSION_GRANTED || isTrustVoiceServiceProxy;
+ == PackageManager.PERMISSION_GRANTED || isTrustVoiceServiceProxy || isSelfBlame;
final int proxyFlags = isProxyTrusted ? AppOpsManager.OP_FLAG_TRUSTED_PROXY
: AppOpsManager.OP_FLAG_UNTRUSTED_PROXY;
@@ -3524,10 +3503,12 @@ public class AppOpsService extends IAppOpsService.Stub {
// This is a workaround for R QPR, new API change is not allowed. We only allow the current
// voice recognizer is also the voice interactor to noteproxy op.
- final boolean isTrustVoiceServiceProxy = isTrustedVoiceServiceProxy(proxyPackageName, code);
+ final boolean isTrustVoiceServiceProxy =
+ AppOpsManager.isTrustedVoiceServiceProxy(mContext, proxyPackageName, code);
+ final boolean isSelfBlame = Binder.getCallingUid() == proxiedUid;
final boolean isProxyTrusted = mContext.checkPermission(
Manifest.permission.UPDATE_APP_OPS_STATS, -1, proxyUid)
- == PackageManager.PERMISSION_GRANTED || isTrustVoiceServiceProxy;
+ == PackageManager.PERMISSION_GRANTED || isTrustVoiceServiceProxy || isSelfBlame;
final int proxyFlags = isProxyTrusted ? AppOpsManager.OP_FLAG_TRUSTED_PROXY
: AppOpsManager.OP_FLAG_UNTRUSTED_PROXY;
diff --git a/services/core/java/com/android/server/appop/TEST_MAPPING b/services/core/java/com/android/server/appop/TEST_MAPPING
index 84de25c06ebf..72d3835efc26 100644
--- a/services/core/java/com/android/server/appop/TEST_MAPPING
+++ b/services/core/java/com/android/server/appop/TEST_MAPPING
@@ -48,10 +48,10 @@
]
},
{
- "name": "CtsStatsdHostTestCases",
+ "name": "CtsStatsdAtomHostTestCases",
"options": [
{
- "include-filter": "android.cts.statsd.atom.UidAtomTests#testAppOps"
+ "include-filter": "android.cts.statsdatom.appops.AppOpsTests#testAppOps"
}
]
}
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/aidl/AidlNativeHandleUtils.java b/services/core/java/com/android/server/biometrics/sensors/face/aidl/AidlNativeHandleUtils.java
new file mode 100644
index 000000000000..77e6cebed789
--- /dev/null
+++ b/services/core/java/com/android/server/biometrics/sensors/face/aidl/AidlNativeHandleUtils.java
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.biometrics.sensors.face.aidl;
+
+import android.annotation.Nullable;
+import android.os.ParcelFileDescriptor;
+
+import java.io.FileDescriptor;
+import java.io.IOException;
+
+/**
+ * A utility class for the AIDL implementation of NativeHandle - {@link
+ * android.hardware.common.NativeHandle}.
+ */
+public final class AidlNativeHandleUtils {
+
+ /**
+ * Converts a {@link android.os.NativeHandle} to a {@link android.hardware.common.NativeHandle}
+ * by duplicating the underlying file descriptors.
+ *
+ * Both the original and new handle must be closed after use.
+ *
+ * @param handle {@link android.os.NativeHandle}. Can be null.
+ * @return a {@link android.hardware.common.NativeHandle} representation of {@code handle}.
+ * Returns null if {@code handle} is null.
+ * @throws IOException if any of the underlying calls to {@code dup} fail.
+ */
+ public static @Nullable android.hardware.common.NativeHandle dup(
+ @Nullable android.os.NativeHandle handle) throws IOException {
+ if (handle == null) {
+ return null;
+ }
+ android.hardware.common.NativeHandle res = new android.hardware.common.NativeHandle();
+ final FileDescriptor[] fds = handle.getFileDescriptors();
+ res.ints = handle.getInts().clone();
+ res.fds = new ParcelFileDescriptor[fds.length];
+ for (int i = 0; i < fds.length; ++i) {
+ res.fds[i] = ParcelFileDescriptor.dup(fds[i]);
+ }
+ return res;
+ }
+
+ /**
+ * Closes the file descriptors contained within a {@link android.hardware.common.NativeHandle}.
+ * This is a no-op if the handle is null.
+ *
+ * This should only be used for handles that own their file descriptors, for example handles
+ * obtained using {@link #dup(android.os.NativeHandle)}.
+ *
+ * @param handle {@link android.hardware.common.NativeHandle}. Can be null.
+ * @throws IOException if any of the underlying calls to {@code close} fail.
+ */
+ public static void close(@Nullable android.hardware.common.NativeHandle handle)
+ throws IOException {
+ if (handle != null) {
+ for (ParcelFileDescriptor fd : handle.fds) {
+ if (fd != null) {
+ fd.close();
+ }
+ }
+ }
+ }
+}
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceEnrollClient.java b/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceEnrollClient.java
index f950862bacd9..f09df1e1812e 100644
--- a/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceEnrollClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceEnrollClient.java
@@ -39,6 +39,7 @@ import com.android.server.biometrics.sensors.ClientMonitorCallbackConverter;
import com.android.server.biometrics.sensors.EnrollClient;
import com.android.server.biometrics.sensors.face.FaceUtils;
+import java.io.IOException;
import java.util.ArrayList;
/**
@@ -51,6 +52,7 @@ public class FaceEnrollClient extends EnrollClient<ISession> {
@NonNull private final int[] mEnrollIgnoreList;
@NonNull private final int[] mEnrollIgnoreListVendor;
@Nullable private ICancellationSignal mCancellationSignal;
+ @Nullable private android.hardware.common.NativeHandle mPreviewSurface;
private final int mMaxTemplatesPerUser;
FaceEnrollClient(@NonNull Context context, @NonNull LazyDaemon<ISession> lazyDaemon,
@@ -66,6 +68,24 @@ public class FaceEnrollClient extends EnrollClient<ISession> {
mEnrollIgnoreListVendor = getContext().getResources()
.getIntArray(R.array.config_face_acquire_vendor_enroll_ignorelist);
mMaxTemplatesPerUser = maxTemplatesPerUser;
+ try {
+ // We must manually close the duplicate handle after it's no longer needed.
+ // The caller is responsible for closing the original handle.
+ mPreviewSurface = AidlNativeHandleUtils.dup(previewSurface);
+ } catch (IOException e) {
+ mPreviewSurface = null;
+ Slog.e(TAG, "Failed to dup previewSurface", e);
+ }
+ }
+
+ @Override
+ public void destroy() {
+ try {
+ AidlNativeHandleUtils.close(mPreviewSurface);
+ } catch (IOException e) {
+ Slog.e(TAG, "Failed to close mPreviewSurface", e);
+ }
+ super.destroy();
}
@Override
@@ -94,10 +114,9 @@ public class FaceEnrollClient extends EnrollClient<ISession> {
try {
// TODO(b/172593978): Pass features.
- // TODO(b/172593521): Pass mPreviewSurface as android.hardware.common.NativeHandle.
mCancellationSignal = getFreshDaemon().enroll(mSequentialId,
HardwareAuthTokenUtils.toHardwareAuthToken(mHardwareAuthToken),
- null /* mPreviewSurface */);
+ mPreviewSurface);
} catch (RemoteException e) {
Slog.e(TAG, "Remote exception when requesting enroll", e);
onError(BiometricFaceConstants.FACE_ERROR_UNABLE_TO_PROCESS, 0 /* vendorCode */);
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceProvider.java b/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceProvider.java
index 26f62644e38b..36796b842410 100644
--- a/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceProvider.java
+++ b/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceProvider.java
@@ -205,7 +205,7 @@ public class FaceProvider implements IBinder.DeathRecipient, ServiceProvider {
private void createNewSessionWithoutHandler(@NonNull IFace daemon, int sensorId,
int userId) throws RemoteException {
- // Note that per IFingerprint createSession contract, this method will block until all
+ // Note that per IFace createSession contract, this method will block until all
// existing operations are canceled/finished. However, also note that this is fine, since
// this method "withoutHandler" means it should only ever be invoked from the worker thread,
// so callers will never be blocked.
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/hidl/Face10.java b/services/core/java/com/android/server/biometrics/sensors/face/hidl/Face10.java
index 3555bbe629ae..c57ab505ca2a 100644
--- a/services/core/java/com/android/server/biometrics/sensors/face/hidl/Face10.java
+++ b/services/core/java/com/android/server/biometrics/sensors/face/hidl/Face10.java
@@ -71,7 +71,6 @@ import com.android.server.biometrics.sensors.face.FaceUtils;
import com.android.server.biometrics.sensors.face.LockoutHalImpl;
import com.android.server.biometrics.sensors.face.ServiceProvider;
import com.android.server.biometrics.sensors.face.UsageStats;
-import com.android.server.biometrics.sensors.fingerprint.FingerprintUtils;
import org.json.JSONArray;
import org.json.JSONException;
@@ -259,8 +258,7 @@ public class Face10 implements IHwBinder.DeathRecipient, ServiceProvider {
if (!removed.isEmpty()) {
// Convert to old fingerprint-like behavior, where remove() receives
- // one removal
- // at a time. This way, remove can share some more common code.
+ // one removal at a time. This way, remove can share some more common code.
for (int i = 0; i < removed.size(); i++) {
final int id = removed.get(i);
final Face face = new Face("", id, deviceId);
@@ -290,21 +288,16 @@ public class Face10 implements IHwBinder.DeathRecipient, ServiceProvider {
final EnumerateConsumer enumerateConsumer = (EnumerateConsumer) client;
if (!faceIds.isEmpty()) {
- // Convert to old fingerprint-like behavior, where enumerate()
- // receives one
- // template at a time. This way, enumerate can share some more common
- // code.
+ // Convert to old fingerprint-like behavior, where enumerate() receives one
+ // template at a time. This way, enumerate can share some more common code.
for (int i = 0; i < faceIds.size(); i++) {
final Face face = new Face("", faceIds.get(i), deviceId);
enumerateConsumer.onEnumerationResult(face, faceIds.size() - i - 1);
}
} else {
- // For face, the HIDL contract is to receive an empty list when there
- // are no
- // templates enrolled. Send a null identifier since we don't consume
- // them
- // anywhere, and send remaining == 0 so this code can be shared with
- // Fingerprint@2.1
+ // For face, the HIDL contract is to receive an empty list when there are no
+ // templates enrolled. Send a null identifier since we don't consume them
+ // anywhere, and send remaining == 0 so this code can be shared with Face@1.1
enumerateConsumer.onEnumerationResult(null /* identifier */, 0);
}
});
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintEnrollClient.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintEnrollClient.java
index 437ecd7a0f8d..fd1181b616c7 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintEnrollClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintEnrollClient.java
@@ -19,7 +19,6 @@ package com.android.server.biometrics.sensors.fingerprint.aidl;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.Context;
-import android.hardware.biometrics.BiometricFaceConstants;
import android.hardware.biometrics.BiometricFingerprintConstants;
import android.hardware.biometrics.BiometricsProtoEnums;
import android.hardware.biometrics.common.ICancellationSignal;
@@ -89,7 +88,8 @@ class FingerprintEnrollClient extends EnrollClient<ISession> implements Udfps {
HardwareAuthTokenUtils.toHardwareAuthToken(mHardwareAuthToken));
} catch (RemoteException e) {
Slog.e(TAG, "Remote exception when requesting enroll", e);
- onError(BiometricFaceConstants.FACE_ERROR_UNABLE_TO_PROCESS, 0 /* vendorCode */);
+ onError(BiometricFingerprintConstants.FINGERPRINT_ERROR_UNABLE_TO_PROCESS,
+ 0 /* vendorCode */);
mCallback.onClientFinished(this, false /* success */);
}
}
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintEnrollClient.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintEnrollClient.java
index c750b906c9b6..2a89a880b680 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintEnrollClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintEnrollClient.java
@@ -65,7 +65,7 @@ public class FingerprintEnrollClient extends EnrollClient<IBiometricsFingerprint
final int enrolled = mBiometricUtils.getBiometricsForUser(getContext(), getTargetUserId())
.size();
if (enrolled >= limit) {
- Slog.w(TAG, "Too many faces registered, user: " + getTargetUserId());
+ Slog.w(TAG, "Too many fingerprints registered, user: " + getTargetUserId());
return true;
}
return false;
diff --git a/services/core/java/com/android/server/camera/CameraServiceProxy.java b/services/core/java/com/android/server/camera/CameraServiceProxy.java
index a4ae9c87c694..2a814268da25 100644
--- a/services/core/java/com/android/server/camera/CameraServiceProxy.java
+++ b/services/core/java/com/android/server/camera/CameraServiceProxy.java
@@ -22,6 +22,8 @@ import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
+import android.hardware.CameraSessionStats;
+import android.hardware.CameraStreamStats;
import android.hardware.ICameraService;
import android.hardware.ICameraServiceProxy;
import android.media.AudioManager;
@@ -36,11 +38,13 @@ import android.os.RemoteException;
import android.os.SystemClock;
import android.os.SystemProperties;
import android.os.UserManager;
+import android.stats.camera.nano.CameraStreamProto;
import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.Slog;
import com.android.internal.annotations.GuardedBy;
+import com.android.framework.protobuf.nano.MessageNano;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.internal.util.FrameworkStatsLog;
@@ -97,7 +101,10 @@ public class CameraServiceProxy extends SystemService
@interface DeviceStateFlags {}
// Maximum entries to keep in usage history before dumping out
- private static final int MAX_USAGE_HISTORY = 100;
+ private static final int MAX_USAGE_HISTORY = 20;
+ // Number of stream statistics being dumped for each camera session
+ // Must be equal to number of CameraStreamProto in CameraActionEvent
+ private static final int MAX_STREAM_STATISTICS = 5;
private final Context mContext;
private final ServiceThread mHandlerThread;
@@ -123,7 +130,6 @@ public class CameraServiceProxy extends SystemService
private final ArrayMap<String, CameraUsageEvent> mActiveCameraUsage = new ArrayMap<>();
private final List<CameraUsageEvent> mCameraUsageHistory = new ArrayList<>();
- private final MetricsLogger mLogger = new MetricsLogger();
private static final String NFC_NOTIFICATION_PROP = "ro.camera.notify_nfc";
private static final String NFC_SERVICE_BINDER_NAME = "nfc";
private static final IBinder nfcInterfaceToken = new Binder();
@@ -137,27 +143,50 @@ public class CameraServiceProxy extends SystemService
* Structure to track camera usage
*/
private static class CameraUsageEvent {
+ public final String mCameraId;
public final int mCameraFacing;
public final String mClientName;
public final int mAPILevel;
+ public final boolean mIsNdk;
+ public final int mAction;
+ public final int mLatencyMs;
+ public final int mOperatingMode;
private boolean mCompleted;
+ public int mInternalReconfigure;
+ public long mRequestCount;
+ public long mResultErrorCount;
+ public boolean mDeviceError;
+ public List<CameraStreamStats> mStreamStats;
private long mDurationOrStartTimeMs; // Either start time, or duration once completed
- public CameraUsageEvent(int facing, String clientName, int apiLevel) {
+ CameraUsageEvent(String cameraId, int facing, String clientName, int apiLevel,
+ boolean isNdk, int action, int latencyMs, int operatingMode) {
+ mCameraId = cameraId;
mCameraFacing = facing;
mClientName = clientName;
mAPILevel = apiLevel;
mDurationOrStartTimeMs = SystemClock.elapsedRealtime();
mCompleted = false;
+ mIsNdk = isNdk;
+ mAction = action;
+ mLatencyMs = latencyMs;
+ mOperatingMode = operatingMode;
}
- public void markCompleted() {
+ public void markCompleted(int internalReconfigure, long requestCount,
+ long resultErrorCount, boolean deviceError,
+ List<CameraStreamStats> streamStats) {
if (mCompleted) {
return;
}
mCompleted = true;
mDurationOrStartTimeMs = SystemClock.elapsedRealtime() - mDurationOrStartTimeMs;
+ mInternalReconfigure = internalReconfigure;
+ mRequestCount = requestCount;
+ mResultErrorCount = resultErrorCount;
+ mDeviceError = deviceError;
+ mStreamStats = streamStats;
if (CameraServiceProxy.DEBUG) {
Slog.v(TAG, "A camera facing " + cameraFacingToString(mCameraFacing) +
" was in use by " + mClientName + " for " +
@@ -211,19 +240,22 @@ public class CameraServiceProxy extends SystemService
}
@Override
- public void notifyCameraState(String cameraId, int newCameraState, int facing,
- String clientName, int apiLevel) {
+ public void notifyCameraState(CameraSessionStats cameraState) {
if (Binder.getCallingUid() != Process.CAMERASERVER_UID) {
Slog.e(TAG, "Calling UID: " + Binder.getCallingUid() + " doesn't match expected " +
" camera service UID!");
return;
}
- String state = cameraStateToString(newCameraState);
- String facingStr = cameraFacingToString(facing);
- if (DEBUG) Slog.v(TAG, "Camera " + cameraId + " facing " + facingStr + " state now " +
- state + " for client " + clientName + " API Level " + apiLevel);
+ String state = cameraStateToString(cameraState.getNewCameraState());
+ String facingStr = cameraFacingToString(cameraState.getFacing());
+ if (DEBUG) {
+ Slog.v(TAG, "Camera " + cameraState.getCameraId()
+ + " facing " + facingStr + " state now " + state
+ + " for client " + cameraState.getClientName()
+ + " API Level " + cameraState.getApiLevel());
+ }
- updateActivityCount(cameraId, newCameraState, facing, clientName, apiLevel);
+ updateActivityCount(cameraState);
}
};
@@ -385,20 +417,80 @@ public class CameraServiceProxy extends SystemService
private void logCameraUsageEvent(CameraUsageEvent e) {
int facing = FrameworkStatsLog.CAMERA_ACTION_EVENT__FACING__UNKNOWN;
switch(e.mCameraFacing) {
- case ICameraServiceProxy.CAMERA_FACING_BACK:
+ case CameraSessionStats.CAMERA_FACING_BACK:
facing = FrameworkStatsLog.CAMERA_ACTION_EVENT__FACING__BACK;
break;
- case ICameraServiceProxy.CAMERA_FACING_FRONT:
+ case CameraSessionStats.CAMERA_FACING_FRONT:
facing = FrameworkStatsLog.CAMERA_ACTION_EVENT__FACING__FRONT;
break;
- case ICameraServiceProxy.CAMERA_FACING_EXTERNAL:
+ case CameraSessionStats.CAMERA_FACING_EXTERNAL:
facing = FrameworkStatsLog.CAMERA_ACTION_EVENT__FACING__EXTERNAL;
break;
default:
Slog.w(TAG, "Unknown camera facing: " + e.mCameraFacing);
}
+
+ int streamCount = 0;
+ if (e.mStreamStats != null) {
+ streamCount = e.mStreamStats.size();
+ }
+ if (CameraServiceProxy.DEBUG) {
+ Slog.v(TAG, "CAMERA_ACTION_EVENT: action " + e.mAction
+ + " clientName " + e.mClientName
+ + ", duration " + e.getDuration()
+ + ", APILevel " + e.mAPILevel
+ + ", cameraId " + e.mCameraId
+ + ", facing " + facing
+ + ", isNdk " + e.mIsNdk
+ + ", latencyMs " + e.mLatencyMs
+ + ", operatingMode " + e.mOperatingMode
+ + ", internalReconfigure " + e.mInternalReconfigure
+ + ", requestCount " + e.mRequestCount
+ + ", resultErrorCount " + e.mResultErrorCount
+ + ", deviceError " + e.mDeviceError
+ + ", streamCount is " + streamCount);
+ }
+ // Convert from CameraStreamStats to CameraStreamProto
+ CameraStreamProto[] streamProtos = new CameraStreamProto[MAX_STREAM_STATISTICS];
+ for (int i = 0; i < MAX_STREAM_STATISTICS; i++) {
+ streamProtos[i] = new CameraStreamProto();
+ if (i < streamCount) {
+ CameraStreamStats streamStats = e.mStreamStats.get(i);
+ streamProtos[i].width = streamStats.getWidth();
+ streamProtos[i].height = streamStats.getHeight();
+ streamProtos[i].format = streamStats.getFormat();
+ streamProtos[i].dataSpace = streamStats.getDataSpace();
+ streamProtos[i].usage = streamStats.getUsage();
+ streamProtos[i].requestCount = streamStats.getRequestCount();
+ streamProtos[i].errorCount = streamStats.getErrorCount();
+ streamProtos[i].firstCaptureLatencyMillis = streamStats.getStartLatencyMs();
+ streamProtos[i].maxHalBuffers = streamStats.getMaxHalBuffers();
+ streamProtos[i].maxAppBuffers = streamStats.getMaxAppBuffers();
+
+ if (CameraServiceProxy.DEBUG) {
+ Slog.v(TAG, "Stream " + i + ": width " + streamProtos[i].width
+ + ", height " + streamProtos[i].height
+ + ", format " + streamProtos[i].format
+ + ", dataSpace " + streamProtos[i].dataSpace
+ + ", usage " + streamProtos[i].usage
+ + ", requestCount " + streamProtos[i].requestCount
+ + ", errorCount " + streamProtos[i].errorCount
+ + ", firstCaptureLatencyMillis "
+ + streamProtos[i].firstCaptureLatencyMillis
+ + ", maxHalBuffers " + streamProtos[i].maxHalBuffers
+ + ", maxAppBuffers " + streamProtos[i].maxAppBuffers);
+ }
+ }
+ }
FrameworkStatsLog.write(FrameworkStatsLog.CAMERA_ACTION_EVENT, e.getDuration(),
- e.mAPILevel, e.mClientName, facing);
+ e.mAPILevel, e.mClientName, facing, e.mCameraId, e.mAction, e.mIsNdk,
+ e.mLatencyMs, e.mOperatingMode, e.mInternalReconfigure,
+ e.mRequestCount, e.mResultErrorCount, e.mDeviceError,
+ streamCount, MessageNano.toByteArray(streamProtos[0]),
+ MessageNano.toByteArray(streamProtos[1]),
+ MessageNano.toByteArray(streamProtos[2]),
+ MessageNano.toByteArray(streamProtos[3]),
+ MessageNano.toByteArray(streamProtos[4]));
}
}
@@ -410,35 +502,6 @@ public class CameraServiceProxy extends SystemService
synchronized(mLock) {
// Randomize order of events so that it's not meaningful
Collections.shuffle(mCameraUsageHistory);
- for (CameraUsageEvent e : mCameraUsageHistory) {
- if (DEBUG) {
- Slog.v(TAG, "Camera: " + e.mClientName + " used a camera facing " +
- cameraFacingToString(e.mCameraFacing) + " for " +
- e.getDuration() + " ms");
- }
- int subtype = 0;
- switch(e.mCameraFacing) {
- case ICameraServiceProxy.CAMERA_FACING_BACK:
- subtype = MetricsEvent.CAMERA_BACK_USED;
- break;
- case ICameraServiceProxy.CAMERA_FACING_FRONT:
- subtype = MetricsEvent.CAMERA_FRONT_USED;
- break;
- case ICameraServiceProxy.CAMERA_FACING_EXTERNAL:
- subtype = MetricsEvent.CAMERA_EXTERNAL_USED;
- break;
- default:
- continue;
- }
- LogMaker l = new LogMaker(MetricsEvent.ACTION_CAMERA_EVENT)
- .setType(MetricsEvent.TYPE_ACTION)
- .setSubtype(subtype)
- .setLatency(e.getDuration())
- .addTaggedData(MetricsEvent.FIELD_CAMERA_API_LEVEL, e.mAPILevel)
- .setPackageName(e.mClientName);
- mLogger.write(l);
- }
-
mLogWriterService.execute(new EventWriterTask(
new ArrayList<CameraUsageEvent>(mCameraUsageHistory)));
@@ -569,13 +632,25 @@ public class CameraServiceProxy extends SystemService
return true;
}
- private void updateActivityCount(String cameraId, int newCameraState, int facing,
- String clientName, int apiLevel) {
+ private void updateActivityCount(CameraSessionStats cameraState) {
+ String cameraId = cameraState.getCameraId();
+ int newCameraState = cameraState.getNewCameraState();
+ int facing = cameraState.getFacing();
+ String clientName = cameraState.getClientName();
+ int apiLevel = cameraState.getApiLevel();
+ boolean isNdk = cameraState.isNdk();
+ int sessionType = cameraState.getSessionType();
+ int internalReconfigureCount = cameraState.getInternalReconfigureCount();
+ int latencyMs = cameraState.getLatencyMs();
+ long requestCount = cameraState.getRequestCount();
+ long resultErrorCount = cameraState.getResultErrorCount();
+ boolean deviceError = cameraState.getDeviceErrorFlag();
+ List<CameraStreamStats> streamStats = cameraState.getStreamStats();
synchronized(mLock) {
// Update active camera list and notify NFC if necessary
boolean wasEmpty = mActiveCameraUsage.isEmpty();
switch (newCameraState) {
- case ICameraServiceProxy.CAMERA_STATE_OPEN:
+ case CameraSessionStats.CAMERA_STATE_OPEN:
// Notify the audio subsystem about the facing of the most-recently opened
// camera This can be used to select the best audio tuning in case video
// recording with that camera will happen. Since only open events are used, if
@@ -584,13 +659,18 @@ public class CameraServiceProxy extends SystemService
AudioManager audioManager = getContext().getSystemService(AudioManager.class);
if (audioManager != null) {
// Map external to front for audio tuning purposes
- String facingStr = (facing == ICameraServiceProxy.CAMERA_FACING_BACK) ?
+ String facingStr = (facing == CameraSessionStats.CAMERA_FACING_BACK) ?
"back" : "front";
String facingParameter = "cameraFacing=" + facingStr;
audioManager.setParameters(facingParameter);
}
+ CameraUsageEvent openEvent = new CameraUsageEvent(
+ cameraId, facing, clientName, apiLevel, isNdk,
+ FrameworkStatsLog.CAMERA_ACTION_EVENT__ACTION__OPEN,
+ latencyMs, sessionType);
+ mCameraUsageHistory.add(openEvent);
break;
- case ICameraServiceProxy.CAMERA_STATE_ACTIVE:
+ case CameraSessionStats.CAMERA_STATE_ACTIVE:
// Check current active camera IDs to see if this package is already talking to
// some camera
boolean alreadyActivePackage = false;
@@ -609,40 +689,55 @@ public class CameraServiceProxy extends SystemService
}
// Update activity events
- CameraUsageEvent newEvent = new CameraUsageEvent(facing, clientName, apiLevel);
+ CameraUsageEvent newEvent = new CameraUsageEvent(
+ cameraId, facing, clientName, apiLevel, isNdk,
+ FrameworkStatsLog.CAMERA_ACTION_EVENT__ACTION__SESSION,
+ latencyMs, sessionType);
CameraUsageEvent oldEvent = mActiveCameraUsage.put(cameraId, newEvent);
if (oldEvent != null) {
Slog.w(TAG, "Camera " + cameraId + " was already marked as active");
- oldEvent.markCompleted();
+ oldEvent.markCompleted(/*internalReconfigure*/0, /*requestCount*/0,
+ /*resultErrorCount*/0, /*deviceError*/false, streamStats);
mCameraUsageHistory.add(oldEvent);
}
break;
- case ICameraServiceProxy.CAMERA_STATE_IDLE:
- case ICameraServiceProxy.CAMERA_STATE_CLOSED:
+ case CameraSessionStats.CAMERA_STATE_IDLE:
+ case CameraSessionStats.CAMERA_STATE_CLOSED:
CameraUsageEvent doneEvent = mActiveCameraUsage.remove(cameraId);
- if (doneEvent == null) break;
-
- doneEvent.markCompleted();
- mCameraUsageHistory.add(doneEvent);
- if (mCameraUsageHistory.size() > MAX_USAGE_HISTORY) {
- dumpUsageEvents();
+ if (doneEvent != null) {
+
+ doneEvent.markCompleted(internalReconfigureCount, requestCount,
+ resultErrorCount, deviceError, streamStats);
+ mCameraUsageHistory.add(doneEvent);
+
+ // Check current active camera IDs to see if this package is still
+ // talking to some camera
+ boolean stillActivePackage = false;
+ for (int i = 0; i < mActiveCameraUsage.size(); i++) {
+ if (mActiveCameraUsage.valueAt(i).mClientName.equals(clientName)) {
+ stillActivePackage = true;
+ break;
+ }
+ }
+ // If not longer active, notify window manager about this package being done
+ // with camera
+ if (!stillActivePackage) {
+ WindowManagerInternal wmi =
+ LocalServices.getService(WindowManagerInternal.class);
+ wmi.removeNonHighRefreshRatePackage(clientName);
+ }
}
- // Check current active camera IDs to see if this package is still talking to
- // some camera
- boolean stillActivePackage = false;
- for (int i = 0; i < mActiveCameraUsage.size(); i++) {
- if (mActiveCameraUsage.valueAt(i).mClientName.equals(clientName)) {
- stillActivePackage = true;
- break;
- }
+ if (newCameraState == CameraSessionStats.CAMERA_STATE_CLOSED) {
+ CameraUsageEvent closeEvent = new CameraUsageEvent(
+ cameraId, facing, clientName, apiLevel, isNdk,
+ FrameworkStatsLog.CAMERA_ACTION_EVENT__ACTION__CLOSE,
+ latencyMs, sessionType);
+ mCameraUsageHistory.add(closeEvent);
}
- // If not longer active, notify window manager about this package being done
- // with camera
- if (!stillActivePackage) {
- WindowManagerInternal wmi =
- LocalServices.getService(WindowManagerInternal.class);
- wmi.removeNonHighRefreshRatePackage(clientName);
+
+ if (mCameraUsageHistory.size() > MAX_USAGE_HISTORY) {
+ dumpUsageEvents();
}
break;
@@ -683,10 +778,10 @@ public class CameraServiceProxy extends SystemService
private static String cameraStateToString(int newCameraState) {
switch (newCameraState) {
- case ICameraServiceProxy.CAMERA_STATE_OPEN: return "CAMERA_STATE_OPEN";
- case ICameraServiceProxy.CAMERA_STATE_ACTIVE: return "CAMERA_STATE_ACTIVE";
- case ICameraServiceProxy.CAMERA_STATE_IDLE: return "CAMERA_STATE_IDLE";
- case ICameraServiceProxy.CAMERA_STATE_CLOSED: return "CAMERA_STATE_CLOSED";
+ case CameraSessionStats.CAMERA_STATE_OPEN: return "CAMERA_STATE_OPEN";
+ case CameraSessionStats.CAMERA_STATE_ACTIVE: return "CAMERA_STATE_ACTIVE";
+ case CameraSessionStats.CAMERA_STATE_IDLE: return "CAMERA_STATE_IDLE";
+ case CameraSessionStats.CAMERA_STATE_CLOSED: return "CAMERA_STATE_CLOSED";
default: break;
}
return "CAMERA_STATE_UNKNOWN";
@@ -694,9 +789,9 @@ public class CameraServiceProxy extends SystemService
private static String cameraFacingToString(int cameraFacing) {
switch (cameraFacing) {
- case ICameraServiceProxy.CAMERA_FACING_BACK: return "CAMERA_FACING_BACK";
- case ICameraServiceProxy.CAMERA_FACING_FRONT: return "CAMERA_FACING_FRONT";
- case ICameraServiceProxy.CAMERA_FACING_EXTERNAL: return "CAMERA_FACING_EXTERNAL";
+ case CameraSessionStats.CAMERA_FACING_BACK: return "CAMERA_FACING_BACK";
+ case CameraSessionStats.CAMERA_FACING_FRONT: return "CAMERA_FACING_FRONT";
+ case CameraSessionStats.CAMERA_FACING_EXTERNAL: return "CAMERA_FACING_EXTERNAL";
default: break;
}
return "CAMERA_FACING_UNKNOWN";
diff --git a/services/core/java/com/android/server/connectivity/Vpn.java b/services/core/java/com/android/server/connectivity/Vpn.java
index 4d959d08d3ef..bdd315de32b1 100644
--- a/services/core/java/com/android/server/connectivity/Vpn.java
+++ b/services/core/java/com/android/server/connectivity/Vpn.java
@@ -207,7 +207,8 @@ public class Vpn {
@VisibleForTesting protected String mPackage;
private int mOwnerUID;
private boolean mIsPackageTargetingAtLeastQ;
- private String mInterface;
+ @VisibleForTesting
+ protected String mInterface;
private Connection mConnection;
/** Tracks the runners for all VPN types managed by the platform (eg. LegacyVpn, PlatformVpn) */
diff --git a/services/core/java/com/android/server/devicestate/DeviceStateManagerService.java b/services/core/java/com/android/server/devicestate/DeviceStateManagerService.java
index 3172a04e9a3d..d7dcbde5692d 100644
--- a/services/core/java/com/android/server/devicestate/DeviceStateManagerService.java
+++ b/services/core/java/com/android/server/devicestate/DeviceStateManagerService.java
@@ -100,7 +100,7 @@ public final class DeviceStateManagerService extends SystemService {
private final SparseArray<CallbackRecord> mCallbacks = new SparseArray<>();
public DeviceStateManagerService(@NonNull Context context) {
- this(context, new DeviceStatePolicyImpl());
+ this(context, new DeviceStatePolicyImpl(context));
}
@VisibleForTesting
diff --git a/services/core/java/com/android/server/display/DisplayGroup.java b/services/core/java/com/android/server/display/DisplayGroup.java
index f2413edd1a3a..2ba875813734 100644
--- a/services/core/java/com/android/server/display/DisplayGroup.java
+++ b/services/core/java/com/android/server/display/DisplayGroup.java
@@ -22,10 +22,22 @@ import java.util.List;
/**
* Represents a collection of {@link LogicalDisplay}s which act in unison for certain behaviors and
* operations.
+ * @hide
*/
public class DisplayGroup {
- final List<LogicalDisplay> mDisplays = new ArrayList<>();
+ public static final int DEFAULT = 0;
+
+ private final List<LogicalDisplay> mDisplays = new ArrayList<>();
+ private final int mGroupId;
+
+ DisplayGroup(int groupId) {
+ mGroupId = groupId;
+ }
+
+ int getGroupId() {
+ return mGroupId;
+ }
void addDisplay(LogicalDisplay display) {
if (!mDisplays.contains(display)) {
diff --git a/services/core/java/com/android/server/display/DisplayManagerService.java b/services/core/java/com/android/server/display/DisplayManagerService.java
index 004e481354ec..4e60f1ff929e 100644
--- a/services/core/java/com/android/server/display/DisplayManagerService.java
+++ b/services/core/java/com/android/server/display/DisplayManagerService.java
@@ -2536,6 +2536,13 @@ public final class DisplayManagerService extends SystemService {
}
@Override
+ public int getDisplayGroupId(int displayId) {
+ synchronized (mSyncRoot) {
+ return mLogicalDisplayMapper.getDisplayGroupIdLocked(displayId);
+ }
+ }
+
+ @Override
public SurfaceControl.ScreenshotHardwareBuffer systemScreenshot(int displayId) {
return systemScreenshotInternal(displayId);
}
diff --git a/services/core/java/com/android/server/display/LogicalDisplayMapper.java b/services/core/java/com/android/server/display/LogicalDisplayMapper.java
index 45c38b456b0a..6b741709321c 100644
--- a/services/core/java/com/android/server/display/LogicalDisplayMapper.java
+++ b/services/core/java/com/android/server/display/LogicalDisplayMapper.java
@@ -94,6 +94,7 @@ class LogicalDisplayMapper implements DisplayDeviceRepository.Listener {
private final SparseArray<LogicalDisplay> mLogicalDisplays =
new SparseArray<LogicalDisplay>();
private int mNextNonDefaultDisplayId = Display.DEFAULT_DISPLAY + 1;
+ private int mNextNonDefaultGroupId = DisplayGroup.DEFAULT + 1;
/** A mapping from logical display id to display group. */
private final SparseArray<DisplayGroup> mDisplayGroups = new SparseArray<>();
@@ -178,6 +179,15 @@ class LogicalDisplayMapper implements DisplayDeviceRepository.Listener {
}
}
+ public int getDisplayGroupIdLocked(int displayId) {
+ final DisplayGroup displayGroup = mDisplayGroups.get(displayId);
+ if (displayGroup != null) {
+ return displayGroup.getGroupId();
+ }
+
+ return -1;
+ }
+
public void dumpLocked(PrintWriter pw) {
pw.println("LogicalDisplayMapper:");
IndentingPrintWriter ipw = new IndentingPrintWriter(pw, " ");
@@ -309,7 +319,8 @@ class LogicalDisplayMapper implements DisplayDeviceRepository.Listener {
final DisplayGroup displayGroup;
if (isDefault || (deviceInfo.flags & DisplayDeviceInfo.FLAG_OWN_DISPLAY_GROUP) != 0) {
- displayGroup = new DisplayGroup();
+ final int groupId = assignDisplayGroupIdLocked(isDefault);
+ displayGroup = new DisplayGroup(groupId);
} else {
displayGroup = mDisplayGroups.get(Display.DEFAULT_DISPLAY);
}
@@ -345,7 +356,8 @@ class LogicalDisplayMapper implements DisplayDeviceRepository.Listener {
if ((flags & Display.FLAG_OWN_DISPLAY_GROUP) != 0) {
// The display should have its own DisplayGroup.
if (defaultDisplayGroup.removeDisplay(display)) {
- final DisplayGroup displayGroup = new DisplayGroup();
+ final int groupId = assignDisplayGroupIdLocked(false);
+ final DisplayGroup displayGroup = new DisplayGroup(groupId);
displayGroup.addDisplay(display);
mDisplayGroups.append(display.getDisplayIdLocked(), displayGroup);
}
@@ -381,6 +393,10 @@ class LogicalDisplayMapper implements DisplayDeviceRepository.Listener {
return isDefault ? Display.DEFAULT_DISPLAY : mNextNonDefaultDisplayId++;
}
+ private int assignDisplayGroupIdLocked(boolean isDefault) {
+ return isDefault ? DisplayGroup.DEFAULT : mNextNonDefaultGroupId++;
+ }
+
private int assignLayerStackLocked(int displayId) {
// Currently layer stacks and display ids are the same.
// This need not be the case.
diff --git a/services/core/java/com/android/server/hdmi/Constants.java b/services/core/java/com/android/server/hdmi/Constants.java
index d0cc8e71dbfa..42dcbeb73fff 100644
--- a/services/core/java/com/android/server/hdmi/Constants.java
+++ b/services/core/java/com/android/server/hdmi/Constants.java
@@ -501,15 +501,6 @@ final class Constants {
static final int DISABLED = 0;
static final int ENABLED = 1;
- @IntDef({
- VERSION_1_4,
- VERSION_2_0
- })
- @interface CecVersion {}
- static final int VERSION_1_3 = 0x04;
- static final int VERSION_1_4 = 0x05;
- static final int VERSION_2_0 = 0x06;
-
static final int ALL_DEVICE_TYPES_TV = 7;
static final int ALL_DEVICE_TYPES_RECORDER = 6;
static final int ALL_DEVICE_TYPES_TUNER = 5;
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java b/services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java
index e7f302c1977a..fb71d9510627 100755
--- a/services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java
@@ -18,6 +18,7 @@ package com.android.server.hdmi;
import android.annotation.CallSuper;
import android.annotation.Nullable;
+import android.hardware.hdmi.HdmiControlManager;
import android.hardware.hdmi.HdmiDeviceInfo;
import android.hardware.hdmi.IHdmiControlCallback;
import android.hardware.input.InputManager;
@@ -560,7 +561,7 @@ abstract class HdmiCecLocalDevice {
protected abstract List<Integer> getDeviceFeatures();
protected boolean handleGiveFeatures(HdmiCecMessage message) {
- if (mService.getCecVersion() < Constants.VERSION_2_0) {
+ if (mService.getCecVersion() < HdmiControlManager.HDMI_CEC_VERSION_2_0) {
return false;
}
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecLocalDevicePlayback.java b/services/core/java/com/android/server/hdmi/HdmiCecLocalDevicePlayback.java
index 109f6a7f56fe..9ca1f913f5ce 100644
--- a/services/core/java/com/android/server/hdmi/HdmiCecLocalDevicePlayback.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecLocalDevicePlayback.java
@@ -128,25 +128,6 @@ public class HdmiCecLocalDevicePlayback extends HdmiCecLocalDeviceSource {
String.valueOf(addr));
}
- @ServiceThreadOnly
- void queryDisplayStatus(IHdmiControlCallback callback) {
- assertRunOnServiceThread();
- List<DevicePowerStatusAction> actions = getActions(DevicePowerStatusAction.class);
- if (!actions.isEmpty()) {
- Slog.i(TAG, "queryDisplayStatus already in progress");
- actions.get(0).addCallback(callback);
- return;
- }
- DevicePowerStatusAction action = DevicePowerStatusAction.create(this, Constants.ADDR_TV,
- callback);
- if (action == null) {
- Slog.w(TAG, "Cannot initiate queryDisplayStatus");
- invokeCallback(callback, HdmiControlManager.RESULT_EXCEPTION);
- return;
- }
- addAndStartAction(action);
- }
-
@Override
@ServiceThreadOnly
void onHotplug(int portId, boolean connected) {
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceSource.java b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceSource.java
index 62b7d8f95f5a..3b3ac747db6c 100644
--- a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceSource.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceSource.java
@@ -70,6 +70,25 @@ abstract class HdmiCecLocalDeviceSource extends HdmiCecLocalDevice {
super(service, deviceType);
}
+ @ServiceThreadOnly
+ void queryDisplayStatus(IHdmiControlCallback callback) {
+ assertRunOnServiceThread();
+ List<DevicePowerStatusAction> actions = getActions(DevicePowerStatusAction.class);
+ if (!actions.isEmpty()) {
+ Slog.i(TAG, "queryDisplayStatus already in progress");
+ actions.get(0).addCallback(callback);
+ return;
+ }
+ DevicePowerStatusAction action = DevicePowerStatusAction.create(this, Constants.ADDR_TV,
+ callback);
+ if (action == null) {
+ Slog.w(TAG, "Cannot initiate queryDisplayStatus");
+ invokeCallback(callback, HdmiControlManager.RESULT_EXCEPTION);
+ return;
+ }
+ addAndStartAction(action);
+ }
+
@Override
@ServiceThreadOnly
void onHotplug(int portId, boolean connected) {
@@ -87,10 +106,14 @@ abstract class HdmiCecLocalDeviceSource extends HdmiCecLocalDevice {
@ServiceThreadOnly
protected void sendStandby(int deviceId) {
assertRunOnServiceThread();
-
- // Send standby to TV only for now
- int targetAddress = Constants.ADDR_TV;
- mService.sendCecCommand(HdmiCecMessageBuilder.buildStandby(mAddress, targetAddress));
+ String sendStandbyOnSleep = mService.getHdmiCecConfig().getStringValue(
+ HdmiControlManager.CEC_SETTING_NAME_SEND_STANDBY_ON_SLEEP);
+ if (sendStandbyOnSleep.equals(HdmiControlManager.SEND_STANDBY_ON_SLEEP_BROADCAST)) {
+ mService.sendCecCommand(
+ HdmiCecMessageBuilder.buildStandby(mAddress, Constants.ADDR_BROADCAST));
+ return;
+ }
+ mService.sendCecCommand(HdmiCecMessageBuilder.buildStandby(mAddress, Constants.ADDR_TV));
}
@ServiceThreadOnly
@@ -113,6 +136,44 @@ abstract class HdmiCecLocalDeviceSource extends HdmiCecLocalDevice {
}
@ServiceThreadOnly
+ void toggleAndFollowTvPower() {
+ assertRunOnServiceThread();
+ // Wake up Android framework to take over CEC control from the microprocessor.
+ mService.wakeUp();
+ mService.queryDisplayStatus(new IHdmiControlCallback.Stub() {
+ @Override
+ public void onComplete(int status) {
+ if (status == HdmiControlManager.POWER_STATUS_UNKNOWN) {
+ Slog.i(TAG, "TV power toggle: TV power status unknown");
+ sendUserControlPressedAndReleased(Constants.ADDR_TV,
+ HdmiCecKeycode.CEC_KEYCODE_POWER_TOGGLE_FUNCTION);
+ // Source device remains awake.
+ } else if (status == HdmiControlManager.POWER_STATUS_ON
+ || status == HdmiControlManager.POWER_STATUS_TRANSIENT_TO_ON) {
+ Slog.i(TAG, "TV power toggle: turning off TV");
+ sendStandby(0 /*unused */);
+ // Source device goes to standby, to follow the toggled TV power state.
+ mService.standby();
+ } else if (status == HdmiControlManager.POWER_STATUS_STANDBY
+ || status == HdmiControlManager.POWER_STATUS_TRANSIENT_TO_STANDBY) {
+ Slog.i(TAG, "TV power toggle: turning on TV");
+ oneTouchPlay(new IHdmiControlCallback.Stub() {
+ @Override
+ public void onComplete(int result) {
+ if (result != HdmiControlManager.RESULT_SUCCESS) {
+ Slog.w(TAG, "Failed to complete One Touch Play. result=" + result);
+ sendUserControlPressedAndReleased(Constants.ADDR_TV,
+ HdmiCecKeycode.CEC_KEYCODE_POWER_TOGGLE_FUNCTION);
+ }
+ }
+ });
+ // Source device remains awake, to follow the toggled TV power state.
+ }
+ }
+ });
+ }
+
+ @ServiceThreadOnly
protected void onActiveSourceLost() {
// Nothing to do.
}
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecMessageBuilder.java b/services/core/java/com/android/server/hdmi/HdmiCecMessageBuilder.java
index 1a481b632606..96303ce9a76c 100644
--- a/services/core/java/com/android/server/hdmi/HdmiCecMessageBuilder.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecMessageBuilder.java
@@ -16,10 +16,10 @@
package com.android.server.hdmi;
+import android.hardware.hdmi.HdmiControlManager;
import android.hardware.hdmi.HdmiDeviceInfo;
import com.android.server.hdmi.Constants.AudioCodec;
-import com.android.server.hdmi.Constants.CecVersion;
import java.io.UnsupportedEncodingException;
import java.util.Arrays;
@@ -696,9 +696,9 @@ public class HdmiCecMessageBuilder {
return buildCommand(src, dest, Constants.MESSAGE_GIVE_FEATURES);
}
- static HdmiCecMessage buildReportFeatures(int src, @CecVersion int cecVersion,
- List<Integer> allDeviceTypes, int rcProfile, List<Integer> rcFeatures,
- List<Integer> deviceFeatures) {
+ static HdmiCecMessage buildReportFeatures(int src,
+ @HdmiControlManager.HdmiCecVersion int cecVersion, List<Integer> allDeviceTypes,
+ int rcProfile, List<Integer> rcFeatures, List<Integer> deviceFeatures) {
byte cecVersionByte = (byte) (cecVersion & 0xFF);
byte deviceTypes = 0;
for (Integer deviceType : allDeviceTypes) {
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecMessageValidator.java b/services/core/java/com/android/server/hdmi/HdmiCecMessageValidator.java
index baed9cc1b71d..d2a2d727b654 100644
--- a/services/core/java/com/android/server/hdmi/HdmiCecMessageValidator.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecMessageValidator.java
@@ -201,7 +201,7 @@ public class HdmiCecMessageValidator {
addValidationInfo(
Constants.MESSAGE_REPORT_POWER_STATUS,
new OneByteRangeValidator(0x00, 0x03),
- DEST_DIRECT);
+ DEST_DIRECT | DEST_BROADCAST);
// Messages for the General Protocol.
addValidationInfo(Constants.MESSAGE_FEATURE_ABORT,
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecPowerStatusController.java b/services/core/java/com/android/server/hdmi/HdmiCecPowerStatusController.java
new file mode 100644
index 000000000000..c4dadaa19bd4
--- /dev/null
+++ b/services/core/java/com/android/server/hdmi/HdmiCecPowerStatusController.java
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.hdmi;
+
+import static com.android.server.hdmi.HdmiAnnotations.ServiceThreadOnly;
+
+import android.hardware.hdmi.HdmiControlManager;
+
+/**
+ * Storage of HDMI-CEC power status and controls possible cases where power status changes must also
+ * broadcast {@code <Report Power Status>} messages.
+ *
+ * All HDMI-CEC related power status changes should be done through this class.
+ */
+class HdmiCecPowerStatusController {
+
+ private final HdmiControlService mHdmiControlService;
+
+ private int mPowerStatus = HdmiControlManager.POWER_STATUS_STANDBY;
+
+ HdmiCecPowerStatusController(HdmiControlService hdmiControlService) {
+ mHdmiControlService = hdmiControlService;
+ }
+
+ int getPowerStatus() {
+ return mPowerStatus;
+ }
+
+ boolean isPowerStatusOn() {
+ return mPowerStatus == HdmiControlManager.POWER_STATUS_ON;
+ }
+
+ boolean isPowerStatusStandby() {
+ return mPowerStatus == HdmiControlManager.POWER_STATUS_STANDBY;
+ }
+
+ boolean isPowerStatusTransientToOn() {
+ return mPowerStatus == HdmiControlManager.POWER_STATUS_TRANSIENT_TO_ON;
+ }
+
+ boolean isPowerStatusTransientToStandby() {
+ return mPowerStatus == HdmiControlManager.POWER_STATUS_TRANSIENT_TO_STANDBY;
+ }
+
+ @ServiceThreadOnly
+ void setPowerStatus(int powerStatus) {
+ setPowerStatus(powerStatus, true);
+ }
+
+ @ServiceThreadOnly
+ void setPowerStatus(int powerStatus, boolean sendPowerStatusUpdate) {
+ if (powerStatus == mPowerStatus) {
+ return;
+ }
+
+ mPowerStatus = powerStatus;
+ if (sendPowerStatusUpdate
+ && mHdmiControlService.getCecVersion() >= HdmiControlManager.HDMI_CEC_VERSION_2_0) {
+ sendReportPowerStatus(mPowerStatus);
+ }
+ }
+
+ private void sendReportPowerStatus(int powerStatus) {
+ for (HdmiCecLocalDevice localDevice : mHdmiControlService.getAllLocalDevices()) {
+ mHdmiControlService.sendCecCommand(
+ HdmiCecMessageBuilder.buildReportPowerStatus(localDevice.mAddress,
+ Constants.ADDR_BROADCAST, powerStatus));
+ }
+ }
+}
diff --git a/services/core/java/com/android/server/hdmi/HdmiControlService.java b/services/core/java/com/android/server/hdmi/HdmiControlService.java
index dcd6c0260cff..01ec3b4cd823 100644
--- a/services/core/java/com/android/server/hdmi/HdmiControlService.java
+++ b/services/core/java/com/android/server/hdmi/HdmiControlService.java
@@ -350,8 +350,8 @@ public class HdmiControlService extends SystemService {
private HdmiCecMessageValidator mMessageValidator;
- @ServiceThreadOnly
- private int mPowerStatus = HdmiControlManager.POWER_STATUS_STANDBY;
+ private final HdmiCecPowerStatusController mPowerStatusController =
+ new HdmiCecPowerStatusController(this);
@ServiceThreadOnly
private String mMenuLanguage = localeToMenuLanguage(Locale.getDefault());
@@ -530,7 +530,8 @@ public class HdmiControlService extends SystemService {
mIoThread.start();
mIoLooper = mIoThread.getLooper();
}
- mPowerStatus = getInitialPowerStatus();
+
+ mPowerStatusController.setPowerStatus(getInitialPowerStatus());
mProhibitMode = false;
mHdmiControlEnabled = readBooleanSetting(Global.HDMI_CONTROL_ENABLED, true);
mHdmiCecVolumeControlEnabled = readBooleanSetting(
@@ -673,10 +674,12 @@ public class HdmiControlService extends SystemService {
* Updates the power status once the initialization of local devices is complete.
*/
private void updatePowerStatusOnInitializeCecComplete() {
- if (mPowerStatus == HdmiControlManager.POWER_STATUS_TRANSIENT_TO_ON) {
- mPowerStatus = HdmiControlManager.POWER_STATUS_ON;
- } else if (mPowerStatus == HdmiControlManager.POWER_STATUS_TRANSIENT_TO_STANDBY) {
- mPowerStatus = HdmiControlManager.POWER_STATUS_STANDBY;
+ if (mPowerStatusController.isPowerStatusTransientToOn()) {
+ mHandler.post(() -> mPowerStatusController.setPowerStatus(
+ HdmiControlManager.POWER_STATUS_ON));
+ } else if (mPowerStatusController.isPowerStatusTransientToStandby()) {
+ mHandler.post(() -> mPowerStatusController.setPowerStatus(
+ HdmiControlManager.POWER_STATUS_STANDBY));
}
}
@@ -1686,7 +1689,7 @@ public class HdmiControlService extends SystemService {
public void oneTouchPlay(final IHdmiControlCallback callback) {
enforceAccessPermission();
int pid = Binder.getCallingPid();
- Slog.d(TAG, "Proccess pid: " + pid + " is calling oneTouchPlay.");
+ Slog.d(TAG, "Process pid: " + pid + " is calling oneTouchPlay.");
runOnServiceThread(new Runnable() {
@Override
public void run() {
@@ -1696,6 +1699,19 @@ public class HdmiControlService extends SystemService {
}
@Override
+ public void toggleAndFollowTvPower() {
+ enforceAccessPermission();
+ int pid = Binder.getCallingPid();
+ Slog.d(TAG, "Process pid: " + pid + " is calling toggleAndFollowTvPower.");
+ runOnServiceThread(new Runnable() {
+ @Override
+ public void run() {
+ HdmiControlService.this.toggleAndFollowTvPower();
+ }
+ });
+ }
+
+ @Override
public void queryDisplayStatus(final IHdmiControlCallback callback) {
enforceAccessPermission();
runOnServiceThread(new Runnable() {
@@ -2191,7 +2207,7 @@ public class HdmiControlService extends SystemService {
final IndentingPrintWriter pw = new IndentingPrintWriter(writer, " ");
pw.println("mProhibitMode: " + mProhibitMode);
- pw.println("mPowerStatus: " + mPowerStatus);
+ pw.println("mPowerStatus: " + mPowerStatusController.getPowerStatus());
// System settings
pw.println("System_settings:");
@@ -2362,7 +2378,23 @@ public class HdmiControlService extends SystemService {
}
@ServiceThreadOnly
- private void queryDisplayStatus(final IHdmiControlCallback callback) {
+ @VisibleForTesting
+ protected void toggleAndFollowTvPower() {
+ assertRunOnServiceThread();
+ HdmiCecLocalDeviceSource source = playback();
+ if (source == null) {
+ source = audioSystem();
+ }
+
+ if (source == null) {
+ Slog.w(TAG, "Local source device not available");
+ return;
+ }
+ source.toggleAndFollowTvPower();
+ }
+
+ @ServiceThreadOnly
+ protected void queryDisplayStatus(final IHdmiControlCallback callback) {
assertRunOnServiceThread();
if (!mAddressAllocated) {
mDisplayStatusCallback = callback;
@@ -2371,9 +2403,13 @@ public class HdmiControlService extends SystemService {
return;
}
- HdmiCecLocalDevicePlayback source = playback();
+ HdmiCecLocalDeviceSource source = playback();
+ if (source == null) {
+ source = audioSystem();
+ }
+
if (source == null) {
- Slog.w(TAG, "Local playback device not available");
+ Slog.w(TAG, "Local source device not available");
invokeCallback(callback, HdmiControlManager.RESULT_SOURCE_NOT_AVAILABLE);
return;
}
@@ -2831,34 +2867,34 @@ public class HdmiControlService extends SystemService {
@ServiceThreadOnly
int getPowerStatus() {
assertRunOnServiceThread();
- return mPowerStatus;
+ return mPowerStatusController.getPowerStatus();
}
@ServiceThreadOnly
@VisibleForTesting
void setPowerStatus(int powerStatus) {
assertRunOnServiceThread();
- mPowerStatus = powerStatus;
+ mPowerStatusController.setPowerStatus(powerStatus);
}
@ServiceThreadOnly
boolean isPowerOnOrTransient() {
assertRunOnServiceThread();
- return mPowerStatus == HdmiControlManager.POWER_STATUS_ON
- || mPowerStatus == HdmiControlManager.POWER_STATUS_TRANSIENT_TO_ON;
+ return mPowerStatusController.isPowerStatusOn()
+ || mPowerStatusController.isPowerStatusTransientToOn();
}
@ServiceThreadOnly
boolean isPowerStandbyOrTransient() {
assertRunOnServiceThread();
- return mPowerStatus == HdmiControlManager.POWER_STATUS_STANDBY
- || mPowerStatus == HdmiControlManager.POWER_STATUS_TRANSIENT_TO_STANDBY;
+ return mPowerStatusController.isPowerStatusStandby()
+ || mPowerStatusController.isPowerStatusTransientToStandby();
}
@ServiceThreadOnly
boolean isPowerStandby() {
assertRunOnServiceThread();
- return mPowerStatus == HdmiControlManager.POWER_STATUS_STANDBY;
+ return mPowerStatusController.isPowerStatusStandby();
}
@ServiceThreadOnly
@@ -2895,7 +2931,8 @@ public class HdmiControlService extends SystemService {
@ServiceThreadOnly
private void onWakeUp(@WakeReason final int wakeUpAction) {
assertRunOnServiceThread();
- mPowerStatus = HdmiControlManager.POWER_STATUS_TRANSIENT_TO_ON;
+ mPowerStatusController.setPowerStatus(HdmiControlManager.POWER_STATUS_TRANSIENT_TO_ON,
+ false);
if (mCecController != null) {
if (mHdmiControlEnabled) {
int startReason = -1;
@@ -2926,14 +2963,15 @@ public class HdmiControlService extends SystemService {
@VisibleForTesting
protected void onStandby(final int standbyAction) {
assertRunOnServiceThread();
- mPowerStatus = HdmiControlManager.POWER_STATUS_TRANSIENT_TO_STANDBY;
+ mPowerStatusController.setPowerStatus(HdmiControlManager.POWER_STATUS_TRANSIENT_TO_STANDBY,
+ false);
invokeVendorCommandListenersOnControlStateChanged(false,
HdmiControlManager.CONTROL_STATE_CHANGED_REASON_STANDBY);
final List<HdmiCecLocalDevice> devices = getAllLocalDevices();
if (!isStandbyMessageReceived() && !canGoToStandby()) {
- mPowerStatus = HdmiControlManager.POWER_STATUS_STANDBY;
+ mPowerStatusController.setPowerStatus(HdmiControlManager.POWER_STATUS_STANDBY);
for (HdmiCecLocalDevice device : devices) {
device.onStandby(mStandbyMessageReceived, standbyAction);
}
@@ -3013,10 +3051,10 @@ public class HdmiControlService extends SystemService {
assertRunOnServiceThread();
Slog.v(TAG, "onStandbyCompleted");
- if (mPowerStatus != HdmiControlManager.POWER_STATUS_TRANSIENT_TO_STANDBY) {
+ if (!mPowerStatusController.isPowerStatusTransientToStandby()) {
return;
}
- mPowerStatus = HdmiControlManager.POWER_STATUS_STANDBY;
+ mPowerStatusController.setPowerStatus(HdmiControlManager.POWER_STATUS_STANDBY);
for (HdmiCecLocalDevice device : mHdmiCecNetwork.getLocalDeviceList()) {
device.onStandby(mStandbyMessageReceived, standbyAction);
}
diff --git a/services/core/java/com/android/server/hdmi/cec_key_handling.md b/services/core/java/com/android/server/hdmi/cec_key_handling.md
index d150dd3fceb9..1b41a6740869 100644
--- a/services/core/java/com/android/server/hdmi/cec_key_handling.md
+++ b/services/core/java/com/android/server/hdmi/cec_key_handling.md
@@ -9,13 +9,13 @@ Android TV requires special handling of some keys.
The general action for key handling is described in the table
-| Android Key | TV Panel | OTT | Soundbar |
-| ----------- | ----------------- | ------------------- | ------------------- |
-| general | Send to active source | handle on device | handle on device |
-| POWER | Toggle the device power state | Toggle the TV power state | Toggle the TV power state |
-| TV_POWER | Toggle the device power state | Toggle the TV power state | Toggle the TV power state |
-| HOME | Turn on TV, Set active Source to TV, go to home screen | OTP, and go to home screen | OTP, and go to home screen |
-| volume keys | Handle on device or send to soundbar | Send to TV or soundbar | Handle on device or send to TV |
+| Android Key | TV Panel | OTT | Soundbar |
+| ----------- | ----------------- | ------------------- | ------------------- |
+| general | Send to active source | handle on device | handle on device |
+| POWER | Toggle the device power state | Toggle the OTT power state, TV power state follows | Toggle the soundbar power state, TV power state follows|
+| TV_POWER | Toggle the device power state | Toggle the TV power state, OTT power state follows | Toggle the TV power state, soundbar power state follows|
+| HOME | Turn on TV, Set active Source to TV, go to home screen | OTP, and go to home screen | OTP, and go to home screen |
+| volume keys | Handle on device or send to soundbar | Send to TV or soundbar | Handle on device or send to TV |
Special cases and flags for each key are described below
diff --git a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
index a4844f6931ed..cfb5116c47f3 100644
--- a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
+++ b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
@@ -474,6 +474,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
}
}
+ @GuardedBy("mMethodMap")
final ArrayMap<IBinder, ClientState> mClients = new ArrayMap<>();
private static final class ActivityViewInfo {
@@ -5322,20 +5323,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
case "reset":
return mService.handleShellCommandResetInputMethod(this);
case "tracing":
- int result = ImeTracing.getInstance().onShellCommand(this);
- boolean isImeTraceEnabled = ImeTracing.getInstance().isEnabled();
- for (ClientState state : mService.mClients.values()) {
- if (state != null) {
- try {
- state.client.setImeTraceEnabled(isImeTraceEnabled);
- } catch (RemoteException e) {
- Log.e(TAG,
- "Error while trying to enable/disable ime "
- + "trace on client window", e);
- }
- }
- }
- return result;
+ return mService.handleShellCommandTraceInputMethod(this);
default:
getOutPrintWriter().println("Unknown command: " + imeCommand);
return ShellCommandResult.FAILURE;
@@ -5716,6 +5704,34 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
}
/**
+ * Handles {@code adb shell ime tracing start/stop}.
+ * @param shellCommand {@link ShellCommand} object that is handling this command.
+ * @return Exit code of the command.
+ */
+ @BinderThread
+ @ShellCommandResult
+ private int handleShellCommandTraceInputMethod(@NonNull ShellCommand shellCommand) {
+ int result = ImeTracing.getInstance().onShellCommand(shellCommand);
+ boolean isImeTraceEnabled = ImeTracing.getInstance().isEnabled();
+ ArrayMap<IBinder, ClientState> clients;
+ synchronized (mMethodMap) {
+ clients = new ArrayMap<>(mClients);
+ }
+ for (ClientState state : clients.values()) {
+ if (state != null) {
+ try {
+ state.client.setImeTraceEnabled(isImeTraceEnabled);
+ } catch (RemoteException e) {
+ Log.e(TAG,
+ "Error while trying to enable/disable ime "
+ + "trace on client window", e);
+ }
+ }
+ }
+ return result;
+ }
+
+ /**
* @param userId the actual user handle obtained by {@link UserHandle#getIdentifier()}
* and *not* pseudo ids like {@link UserHandle#USER_ALL etc}.
* @return {@code true} if userId has debugging privileges.
diff --git a/services/core/java/com/android/server/location/geofence/GeofenceManager.java b/services/core/java/com/android/server/location/geofence/GeofenceManager.java
index 4a8534292eaf..5a90fa7a271c 100644
--- a/services/core/java/com/android/server/location/geofence/GeofenceManager.java
+++ b/services/core/java/com/android/server/location/geofence/GeofenceManager.java
@@ -322,12 +322,28 @@ public class GeofenceManager extends
@Override
protected boolean isActive(GeofenceRegistration registration) {
- CallerIdentity identity = registration.getIdentity();
- return registration.isPermitted()
- && (identity.isSystem() || mUserInfoHelper.isCurrentUserId(identity.getUserId()))
- && mSettingsHelper.isLocationEnabled(identity.getUserId())
- && !mSettingsHelper.isLocationPackageBlacklisted(identity.getUserId(),
- identity.getPackageName());
+ return registration.isPermitted() && isActive(registration.getIdentity());
+ }
+
+ private boolean isActive(CallerIdentity identity) {
+ if (identity.isSystemServer()) {
+ if (!mSettingsHelper.isLocationEnabled(mUserInfoHelper.getCurrentUserId())) {
+ return false;
+ }
+ } else {
+ if (!mSettingsHelper.isLocationEnabled(identity.getUserId())) {
+ return false;
+ }
+ if (!mUserInfoHelper.isCurrentUserId(identity.getUserId())) {
+ return false;
+ }
+ if (mSettingsHelper.isLocationPackageBlacklisted(identity.getUserId(),
+ identity.getPackageName())) {
+ return false;
+ }
+ }
+
+ return true;
}
@Override
diff --git a/services/core/java/com/android/server/location/gnss/GnssListenerMultiplexer.java b/services/core/java/com/android/server/location/gnss/GnssListenerMultiplexer.java
index e68f595c3c43..7e848e03c3a0 100644
--- a/services/core/java/com/android/server/location/gnss/GnssListenerMultiplexer.java
+++ b/services/core/java/com/android/server/location/gnss/GnssListenerMultiplexer.java
@@ -266,11 +266,30 @@ public abstract class GnssListenerMultiplexer<TRequest, TListener extends IInter
CallerIdentity identity = registration.getIdentity();
return registration.isPermitted()
&& (registration.isForeground() || isBackgroundRestrictionExempt(identity))
- && (identity.isSystem() || mUserInfoHelper.isCurrentUserId(identity.getUserId()))
- && mLocationManagerInternal.isProviderEnabledForUser(GPS_PROVIDER,
- identity.getUserId())
- && !mSettingsHelper.isLocationPackageBlacklisted(identity.getUserId(),
- identity.getPackageName());
+ && isActive(identity);
+ }
+
+ private boolean isActive(CallerIdentity identity) {
+ if (identity.isSystemServer()) {
+ if (!mLocationManagerInternal.isProviderEnabledForUser(GPS_PROVIDER,
+ mUserInfoHelper.getCurrentUserId())) {
+ return false;
+ }
+ } else {
+ if (!mLocationManagerInternal.isProviderEnabledForUser(GPS_PROVIDER,
+ identity.getUserId())) {
+ return false;
+ }
+ if (!mUserInfoHelper.isCurrentUserId(identity.getUserId())) {
+ return false;
+ }
+ if (mSettingsHelper.isLocationPackageBlacklisted(identity.getUserId(),
+ identity.getPackageName())) {
+ return false;
+ }
+ }
+
+ return true;
}
private boolean isBackgroundRestrictionExempt(CallerIdentity identity) {
diff --git a/services/core/java/com/android/server/location/gnss/GnssLocationProvider.java b/services/core/java/com/android/server/location/gnss/GnssLocationProvider.java
index ceac10d717e4..a8889fd6b454 100644
--- a/services/core/java/com/android/server/location/gnss/GnssLocationProvider.java
+++ b/services/core/java/com/android/server/location/gnss/GnssLocationProvider.java
@@ -709,8 +709,10 @@ public class GnssLocationProvider extends AbstractLocationProvider implements
"GNSS HAL Requesting location updates from %s provider for %d millis.",
provider, durationMillis));
- locationManager.requestLocationUpdates(provider, locationRequest.build(),
- DIRECT_EXECUTOR, locationListener);
+ if (locationManager.getProvider(provider) != null) {
+ locationManager.requestLocationUpdates(provider, locationRequest.build(),
+ DIRECT_EXECUTOR, locationListener);
+ }
}
private void injectBestLocation(Location location) {
diff --git a/services/core/java/com/android/server/location/injector/SystemUserInfoHelper.java b/services/core/java/com/android/server/location/injector/SystemUserInfoHelper.java
index 56dd92ab1829..d4a8fbd0ceb0 100644
--- a/services/core/java/com/android/server/location/injector/SystemUserInfoHelper.java
+++ b/services/core/java/com/android/server/location/injector/SystemUserInfoHelper.java
@@ -88,11 +88,6 @@ public class SystemUserInfoHelper extends UserInfoHelper {
return mUserManager;
}
- /**
- * Returns an array of running user ids. This will include all running users, and will also
- * include any profiles of the running users. The caller must never mutate the returned
- * array.
- */
@Override
public int[] getRunningUserIds() {
IActivityManager activityManager = getActivityManager();
@@ -110,10 +105,6 @@ public class SystemUserInfoHelper extends UserInfoHelper {
}
}
- /**
- * Returns true if the given user id is either the current user or a profile of the current
- * user.
- */
@Override
public boolean isCurrentUserId(@UserIdInt int userId) {
ActivityManagerInternal activityManagerInternal = getActivityManagerInternal();
@@ -130,6 +121,21 @@ public class SystemUserInfoHelper extends UserInfoHelper {
}
@Override
+ public @UserIdInt int getCurrentUserId() {
+ ActivityManagerInternal activityManagerInternal = getActivityManagerInternal();
+ if (activityManagerInternal != null) {
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ return activityManagerInternal.getCurrentUserId();
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ } else {
+ return UserHandle.USER_NULL;
+ }
+ }
+
+ @Override
protected int[] getProfileIds(@UserIdInt int userId) {
UserManager userManager = getUserManager();
diff --git a/services/core/java/com/android/server/location/injector/UserInfoHelper.java b/services/core/java/com/android/server/location/injector/UserInfoHelper.java
index 3b7e3b40324e..0fcc1ecc4c1a 100644
--- a/services/core/java/com/android/server/location/injector/UserInfoHelper.java
+++ b/services/core/java/com/android/server/location/injector/UserInfoHelper.java
@@ -132,6 +132,12 @@ public abstract class UserInfoHelper {
*/
public abstract boolean isCurrentUserId(@UserIdInt int userId);
+ /**
+ * Returns the current user id. Where possible, prefer to use {@link #isCurrentUserId(int)}
+ * instead, as that method has more flexibility.
+ */
+ public abstract @UserIdInt int getCurrentUserId();
+
protected abstract int[] getProfileIds(@UserIdInt int userId);
/**
diff --git a/services/core/java/com/android/server/location/provider/LocationProviderManager.java b/services/core/java/com/android/server/location/provider/LocationProviderManager.java
index eca607030444..c5d7f2c033dd 100644
--- a/services/core/java/com/android/server/location/provider/LocationProviderManager.java
+++ b/services/core/java/com/android/server/location/provider/LocationProviderManager.java
@@ -1469,18 +1469,9 @@ public class LocationProviderManager extends
public @Nullable Location getLastLocation(CallerIdentity identity,
@PermissionLevel int permissionLevel, boolean ignoreLocationSettings) {
- if (mSettingsHelper.isLocationPackageBlacklisted(identity.getUserId(),
- identity.getPackageName())) {
+ if (!isActive(ignoreLocationSettings, identity)) {
return null;
}
- if (!ignoreLocationSettings) {
- if (!isEnabled(identity.getUserId())) {
- return null;
- }
- if (!identity.isSystem() && !mUserHelper.isCurrentUserId(identity.getUserId())) {
- return null;
- }
- }
// lastly - note app ops
if (!mAppOpsHelper.noteOpNoThrow(LocationPermissions.asAppOp(permissionLevel),
@@ -1905,20 +1896,16 @@ public class LocationProviderManager extends
Preconditions.checkState(Thread.holdsLock(mLock));
}
- CallerIdentity identity = registration.getIdentity();
-
if (!registration.isPermitted()) {
return false;
}
- if (!registration.getRequest().isLocationSettingsIgnored()) {
- if (!isEnabled(identity.getUserId())) {
- return false;
- }
- if (!identity.isSystem() && !mUserHelper.isCurrentUserId(identity.getUserId())) {
- return false;
- }
+ boolean locationSettingsIgnored = registration.getRequest().isLocationSettingsIgnored();
+ if (!isActive(locationSettingsIgnored, registration.getIdentity())) {
+ return false;
+ }
+ if (!locationSettingsIgnored) {
switch (mLocationPowerSaveModeHelper.getLocationPowerSaveMode()) {
case LOCATION_MODE_FOREGROUND_ONLY:
if (!registration.isForeground()) {
@@ -1944,8 +1931,32 @@ public class LocationProviderManager extends
}
}
- return !mSettingsHelper.isLocationPackageBlacklisted(identity.getUserId(),
- identity.getPackageName());
+ return true;
+ }
+
+ private boolean isActive(boolean locationSettingsIgnored, CallerIdentity identity) {
+ if (identity.isSystemServer()) {
+ if (!locationSettingsIgnored) {
+ if (!isEnabled(mUserHelper.getCurrentUserId())) {
+ return false;
+ }
+ }
+ } else {
+ if (!locationSettingsIgnored) {
+ if (!isEnabled(identity.getUserId())) {
+ return false;
+ }
+ if (!mUserHelper.isCurrentUserId(identity.getUserId())) {
+ return false;
+ }
+ }
+ if (mSettingsHelper.isLocationPackageBlacklisted(identity.getUserId(),
+ identity.getPackageName())) {
+ return false;
+ }
+ }
+
+ return true;
}
@GuardedBy("mLock")
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index dfeb6822c8e8..b1289dd0e39f 100755
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -7164,6 +7164,16 @@ public class NotificationManagerService extends SystemService {
return true;
}
+ // Suppressed since it's a non-interruptive update to a bubble-suppressed notification
+ final boolean isBubbleOrOverflowed = record.canBubble() && (record.isFlagBubbleRemoved()
+ || record.getNotification().isBubbleNotification());
+ if (record.isUpdate && !record.isInterruptive() && isBubbleOrOverflowed
+ && record.getNotification().getBubbleMetadata() != null) {
+ if (record.getNotification().getBubbleMetadata().isNotificationSuppressed()) {
+ return true;
+ }
+ }
+
return false;
}
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index ad686f2cab89..55f9feec10d3 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -94,6 +94,11 @@ import static android.content.pm.PackageManager.MOVE_FAILED_OPERATION_PENDING;
import static android.content.pm.PackageManager.MOVE_FAILED_SYSTEM_PACKAGE;
import static android.content.pm.PackageManager.PERMISSION_GRANTED;
import static android.content.pm.PackageManager.RESTRICTION_NONE;
+import static android.content.pm.PackageManager.TYPE_ACTIVITY;
+import static android.content.pm.PackageManager.TYPE_PROVIDER;
+import static android.content.pm.PackageManager.TYPE_RECEIVER;
+import static android.content.pm.PackageManager.TYPE_SERVICE;
+import static android.content.pm.PackageManager.TYPE_UNKNOWN;
import static android.content.pm.PackageManager.UNINSTALL_REASON_UNKNOWN;
import static android.content.pm.PackageManagerInternal.LAST_KNOWN_PACKAGE;
import static android.content.pm.PackageParser.SigningDetails.SignatureSchemeVersion.SIGNING_BLOCK_V4;
@@ -103,7 +108,6 @@ import static android.os.incremental.IncrementalManager.isIncrementalPath;
import static android.os.storage.StorageManager.FLAG_STORAGE_CE;
import static android.os.storage.StorageManager.FLAG_STORAGE_DE;
import static android.os.storage.StorageManager.FLAG_STORAGE_EXTERNAL;
-import static android.permission.PermissionManager.KILL_APP_REASON_GIDS_CHANGED;
import static com.android.internal.annotations.VisibleForTesting.Visibility;
import static com.android.internal.app.IntentForwarderActivity.FORWARD_INTENT_TO_MANAGED_PROFILE;
@@ -137,6 +141,7 @@ import android.annotation.AppIdInt;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.StringRes;
import android.annotation.UserIdInt;
import android.annotation.WorkerThread;
import android.app.ActivityManager;
@@ -196,8 +201,11 @@ import android.content.pm.PackageInfo;
import android.content.pm.PackageInfoLite;
import android.content.pm.PackageInstaller;
import android.content.pm.PackageManager;
+import android.content.pm.PackageManager.ComponentType;
import android.content.pm.PackageManager.LegacyPackageDeleteObserver;
import android.content.pm.PackageManager.ModuleInfoFlags;
+import android.content.pm.PackageManager.Property;
+import android.content.pm.PackageManager.PropertyLocation;
import android.content.pm.PackageManagerInternal;
import android.content.pm.PackageManagerInternal.PackageListObserver;
import android.content.pm.PackageManagerInternal.PrivateResolveFlags;
@@ -246,7 +254,6 @@ import android.database.ContentObserver;
import android.graphics.Bitmap;
import android.hardware.display.DisplayManager;
import android.net.Uri;
-import android.os.AsyncTask;
import android.os.Binder;
import android.os.Build;
import android.os.Bundle;
@@ -339,10 +346,8 @@ import com.android.internal.os.SomeArgs;
import com.android.internal.os.Zygote;
import com.android.internal.telephony.CarrierAppUtils;
import com.android.internal.util.ArrayUtils;
-import com.android.internal.util.CollectionUtils;
import com.android.internal.util.ConcurrentUtils;
import com.android.internal.util.DumpUtils;
-import com.android.internal.util.FastXmlSerializer;
import com.android.internal.util.FrameworkStatsLog;
import com.android.internal.util.IndentingPrintWriter;
import com.android.internal.util.Preconditions;
@@ -397,7 +402,6 @@ import libcore.util.HexEncoding;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
-import org.xmlpull.v1.XmlSerializer;
import java.io.BufferedOutputStream;
import java.io.ByteArrayInputStream;
@@ -575,21 +579,6 @@ public class PackageManagerService extends IPackageManager.Stub
private static final int[] EMPTY_INT_ARRAY = new int[0];
- private static final int TYPE_UNKNOWN = 0;
- private static final int TYPE_ACTIVITY = 1;
- private static final int TYPE_RECEIVER = 2;
- private static final int TYPE_SERVICE = 3;
- private static final int TYPE_PROVIDER = 4;
- @IntDef(prefix = { "TYPE_" }, value = {
- TYPE_UNKNOWN,
- TYPE_ACTIVITY,
- TYPE_RECEIVER,
- TYPE_SERVICE,
- TYPE_PROVIDER,
- })
- @Retention(RetentionPolicy.SOURCE)
- public @interface ComponentType {}
-
/**
* Timeout (in milliseconds) after which the watchdog should declare that
* our handler thread is wedged. The usual default for such things is one
@@ -1215,6 +1204,7 @@ public class PackageManagerService extends IPackageManager.Stub
public ViewCompiler viewCompiler;
public @Nullable String wellbeingPackage;
public @Nullable String retailDemoPackage;
+ public @Nullable String recentsPackage;
public ComponentName resolveComponentName;
public ArrayMap<String, AndroidPackage> packages;
public boolean enableFreeCacheV2;
@@ -1320,6 +1310,8 @@ public class PackageManagerService extends IPackageManager.Stub
private final IncrementalManager mIncrementalManager;
+ private final PackageProperty mPackageProperty = new PackageProperty();
+
private static class IFVerificationParams {
String packageName;
boolean hasDomainUrls;
@@ -1747,6 +1739,7 @@ public class PackageManagerService extends IPackageManager.Stub
final @Nullable String mSharedSystemSharedLibraryPackageName;
final @Nullable String mRetailDemoPackage;
final @Nullable String mOverlayConfigSignaturePackage;
+ final @Nullable String mRecentsPackage;
private final PackageUsage mPackageUsage = new PackageUsage();
private final CompilerStats mCompilerStats = new CompilerStats();
@@ -2990,6 +2983,7 @@ public class PackageManagerService extends IPackageManager.Stub
mSystemTextClassifierPackageName = testParams.systemTextClassifierPackage;
mWellbeingPackage = testParams.wellbeingPackage;
mRetailDemoPackage = testParams.retailDemoPackage;
+ mRecentsPackage = testParams.recentsPackage;
mDocumenterPackage = testParams.documenterPackage;
mConfiguratorPackage = testParams.configuratorPackage;
mAppPredictionServicePackage = testParams.appPredictionServicePackage;
@@ -3574,6 +3568,7 @@ public class PackageManagerService extends IPackageManager.Stub
mIncidentReportApproverPackage = getIncidentReportApproverPackageName();
mRetailDemoPackage = getRetailDemoPackageName();
mOverlayConfigSignaturePackage = getOverlayConfigSignaturePackageName();
+ mRecentsPackage = getRecentsPackageName();
// Now that we know all of the shared libraries, update all clients to have
// the correct library paths.
@@ -3842,7 +3837,7 @@ public class PackageManagerService extends IPackageManager.Stub
// are all flushed. Not really needed, but keeps things nice and
// tidy.
t.traceBegin("GC");
- Runtime.getRuntime().gc();
+ VMRuntime.getRuntime().requestConcurrentGC();
t.traceEnd();
// The initial scanning above does many calls into installd while
@@ -11592,22 +11587,6 @@ public class PackageManagerService extends IPackageManager.Stub
}
pkgSetting.signatures.mSigningDetails = reconciledPkg.signingDetails;
- if (!pkg.getAdoptPermissions().isEmpty()) {
- // This package wants to adopt ownership of permissions from
- // another package.
- for (int i = pkg.getAdoptPermissions().size() - 1; i >= 0; i--) {
- final String origName = pkg.getAdoptPermissions().get(i);
- final PackageSetting orig = mSettings.getPackageLPr(origName);
- if (orig != null) {
- if (verifyPackageUpdateLPr(orig, pkg)) {
- Slog.i(TAG, "Adopting permissions from " + origName + " to "
- + pkg.getPackageName());
- mPermissionManager.transferPermissions(origName, pkg.getPackageName());
- }
- }
- }
- }
-
if (changedAbiCodePath != null && changedAbiCodePath.size() > 0) {
for (int i = changedAbiCodePath.size() - 1; i >= 0; --i) {
final String codePathString = changedAbiCodePath.get(i);
@@ -12727,6 +12706,37 @@ public class PackageManagerService extends IPackageManager.Stub
return true;
}
+ @Override
+ public Property getProperty(String propertyName, String packageName, String className) {
+ Objects.requireNonNull(propertyName);
+ Objects.requireNonNull(packageName);
+ synchronized (mLock) {
+ final PackageSetting ps = getPackageSetting(packageName);
+ if (shouldFilterApplicationLocked(ps, Binder.getCallingUid(),
+ UserHandle.getCallingUserId())) {
+ return null;
+ }
+ return mPackageProperty.getProperty(propertyName, packageName, className);
+ }
+ }
+
+ @Override
+ public ParceledListSlice<Property> queryProperty(
+ String propertyName, @PropertyLocation int componentType) {
+ Objects.requireNonNull(propertyName);
+ final int callingUid = Binder.getCallingUid();
+ final int callingUserId = UserHandle.getCallingUserId();
+ final List<Property> result =
+ mPackageProperty.queryProperty(propertyName, componentType, packageName -> {
+ final PackageSetting ps = getPackageSetting(packageName);
+ return shouldFilterApplicationLocked(ps, callingUid, callingUserId);
+ });
+ if (result == null) {
+ return ParceledListSlice.emptyList();
+ }
+ return new ParceledListSlice<>(result);
+ }
+
/**
* Adds a scanned package to the system. When this method is finished, the package will
* be available for query, resolution, etc...
@@ -12853,27 +12863,7 @@ public class PackageManagerService extends IPackageManager.Stub
final boolean isReplace =
reconciledPkg.prepareResult != null && reconciledPkg.prepareResult.replace;
mAppsFilter.addPackage(pkgSetting, isReplace);
-
- // Don't allow ephemeral applications to define new permissions groups.
- if ((scanFlags & SCAN_AS_INSTANT_APP) != 0) {
- Slog.w(TAG, "Permission groups from package " + pkg.getPackageName()
- + " ignored: instant apps cannot define new permission groups.");
- } else {
- mPermissionManager.addAllPermissionGroups(pkg, chatty);
- }
-
- // If a permission has had its defining app changed, or it has had its protection
- // upgraded, we need to revoke apps that hold it
- final List<String> permissionsWithChangedDefinition;
- // Don't allow ephemeral applications to define new permissions.
- if ((scanFlags & SCAN_AS_INSTANT_APP) != 0) {
- permissionsWithChangedDefinition = null;
- Slog.w(TAG, "Permissions from package " + pkg.getPackageName()
- + " ignored: instant apps cannot define new permissions.");
- } else {
- permissionsWithChangedDefinition =
- mPermissionManager.addAllPermissions(pkg, chatty);
- }
+ mPackageProperty.addAllProperties(pkg);
int collectionSize = ArrayUtils.size(pkg.getInstrumentations());
StringBuilder r = null;
@@ -12901,31 +12891,7 @@ public class PackageManagerService extends IPackageManager.Stub
}
}
- boolean hasOldPkg = oldPkg != null;
- boolean hasPermissionDefinitionChanges =
- !CollectionUtils.isEmpty(permissionsWithChangedDefinition);
- if (hasOldPkg || hasPermissionDefinitionChanges) {
- // We need to call revokeRuntimePermissionsIfGroupChanged async as permission
- // revoke callbacks from this method might need to kill apps which need the
- // mPackages lock on a different thread. This would dead lock.
- //
- // Hence create a copy of all package names and pass it into
- // revokeRuntimePermissionsIfGroupChanged. Only for those permissions might get
- // revoked. If a new package is added before the async code runs the permission
- // won't be granted yet, hence new packages are no problem.
- final ArrayList<String> allPackageNames = new ArrayList<>(mPackages.keySet());
-
- AsyncTask.execute(() -> {
- if (hasOldPkg) {
- mPermissionManager.revokeRuntimePermissionsIfGroupChanged(pkg, oldPkg,
- allPackageNames);
- }
- if (hasPermissionDefinitionChanges) {
- mPermissionManager.revokeRuntimePermissionsIfPermissionDefinitionChanged(
- permissionsWithChangedDefinition, allPackageNames);
- }
- });
- }
+ mPermissionManager.onPackageAdded(pkg, (scanFlags & SCAN_AS_INSTANT_APP) != 0, oldPkg);
}
Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
@@ -13024,7 +12990,7 @@ public class PackageManagerService extends IPackageManager.Stub
}
}
- void removePackageLI(String packageName, boolean chatty) {
+ private void removePackageLI(String packageName, boolean chatty) {
if (DEBUG_INSTALL) {
if (chatty)
Log.d(TAG, "Removing package " + packageName);
@@ -13039,9 +13005,10 @@ public class PackageManagerService extends IPackageManager.Stub
}
}
- void cleanPackageDataStructuresLILPw(AndroidPackage pkg, boolean chatty) {
+ private void cleanPackageDataStructuresLILPw(AndroidPackage pkg, boolean chatty) {
mComponentResolver.removeAllComponents(pkg, chatty);
- mPermissionManager.removeAllPermissions(pkg, chatty);
+ mPermissionManager.onPackageRemoved(pkg);
+ mPackageProperty.removeAllProperties(pkg);
final int instrumentationSize = ArrayUtils.size(pkg.getInstrumentations());
StringBuilder r = null;
@@ -19539,33 +19506,13 @@ public class PackageManagerService extends IPackageManager.Stub
if (outInfo != null) {
outInfo.removedAppId = removedAppId;
}
- if ((deletedPs.sharedUser == null || deletedPs.sharedUser.packages.size() == 0)
- && !isUpdatedSystemApp(deletedPs)) {
- mPermissionManager.removeAppIdStateTEMP(removedAppId);
- }
- mPermissionManager.updatePermissions(deletedPs.name, null);
- if (deletedPs.sharedUser != null) {
- // Remove permissions associated with package. Since runtime
- // permissions are per user we have to kill the removed package
- // or packages running under the shared user of the removed
- // package if revoking the permissions requested only by the removed
- // package is successful and this causes a change in gids.
- boolean shouldKill = false;
- for (int userId : UserManagerService.getInstance().getUserIds()) {
- final int userIdToKill = mPermissionManager
- .revokeSharedUserPermissionsForDeletedPackageTEMP(deletedPs,
- userId);
- shouldKill |= userIdToKill != UserHandle.USER_NULL;
- }
- // If gids changed, kill all affected packages.
- if (shouldKill) {
- mHandler.post(() -> {
- // This has to happen with no lock held.
- killApplication(deletedPs.name, deletedPs.appId,
- KILL_APP_REASON_GIDS_CHANGED);
- });
- }
+ final SharedUserSetting sus = deletedPs.getSharedUser();
+ List<AndroidPackage> sharedUserPkgs = sus != null ? sus.getPackages() : null;
+ if (sharedUserPkgs == null) {
+ sharedUserPkgs = Collections.emptyList();
}
+ mPermissionManager.onPackageStateRemoved(packageName, deletedPs.appId,
+ deletedPs.pkg, sharedUserPkgs);
clearPackagePreferredActivitiesLPw(
deletedPs.name, changedUsers, UserHandle.USER_ALL);
}
@@ -21387,15 +21334,8 @@ public class PackageManagerService extends IPackageManager.Stub
@Override
public @Nullable String getAttentionServicePackageName() {
- final String flattenedComponentName =
- mContext.getString(R.string.config_defaultAttentionService);
- if (flattenedComponentName != null) {
- ComponentName componentName = ComponentName.unflattenFromString(flattenedComponentName);
- if (componentName != null && componentName.getPackageName() != null) {
- return ensureSystemPackageName(componentName.getPackageName());
- }
- }
- return null;
+ return ensureSystemPackageName(
+ getPackageFromComponentString(R.string.config_defaultAttentionService));
}
private @Nullable String getDocumenterPackageName() {
@@ -21430,17 +21370,8 @@ public class PackageManagerService extends IPackageManager.Stub
@Override
public String getAppPredictionServicePackageName() {
- String flattenedAppPredictionServiceComponentName =
- mContext.getString(R.string.config_defaultAppPredictionService);
- if (flattenedAppPredictionServiceComponentName == null) {
- return null;
- }
- ComponentName appPredictionServiceComponentName =
- ComponentName.unflattenFromString(flattenedAppPredictionServiceComponentName);
- if (appPredictionServiceComponentName == null) {
- return null;
- }
- return ensureSystemPackageName(appPredictionServiceComponentName.getPackageName());
+ return ensureSystemPackageName(
+ getPackageFromComponentString(R.string.config_defaultAppPredictionService));
}
private @NonNull String[] dropNonSystemPackages(@NonNull String[] pkgNames) {
@@ -21457,19 +21388,8 @@ public class PackageManagerService extends IPackageManager.Stub
@Override
public String getSystemCaptionsServicePackageName() {
- String flattenedSystemCaptionsServiceComponentName =
- mContext.getString(R.string.config_defaultSystemCaptionsService);
-
- if (TextUtils.isEmpty(flattenedSystemCaptionsServiceComponentName)) {
- return null;
- }
-
- ComponentName systemCaptionsServiceComponentName =
- ComponentName.unflattenFromString(flattenedSystemCaptionsServiceComponentName);
- if (systemCaptionsServiceComponentName == null) {
- return null;
- }
- return ensureSystemPackageName(systemCaptionsServiceComponentName.getPackageName());
+ return ensureSystemPackageName(
+ getPackageFromComponentString(R.string.config_defaultSystemCaptionsService));
}
@Override
@@ -21487,19 +21407,8 @@ public class PackageManagerService extends IPackageManager.Stub
@Override
public String getContentCaptureServicePackageName() {
- final String flattenedContentCaptureService =
- mContext.getString(R.string.config_defaultContentCaptureService);
-
- if (TextUtils.isEmpty(flattenedContentCaptureService)) {
- return null;
- }
-
- final ComponentName contentCaptureServiceComponentName =
- ComponentName.unflattenFromString(flattenedContentCaptureService);
- if (contentCaptureServiceComponentName == null) {
- return null;
- }
- return ensureSystemPackageName(contentCaptureServiceComponentName.getPackageName());
+ return ensureSystemPackageName(
+ getPackageFromComponentString(R.string.config_defaultContentCaptureService));
}
public String getOverlayConfigSignaturePackageName() {
@@ -21543,6 +21452,26 @@ public class PackageManagerService extends IPackageManager.Stub
}
@Nullable
+ private String getRecentsPackageName() {
+ return ensureSystemPackageName(
+ getPackageFromComponentString(R.string.config_recentsComponentName));
+
+ }
+
+ @Nullable
+ private String getPackageFromComponentString(@StringRes int stringResId) {
+ final String componentString = mContext.getString(stringResId);
+ if (TextUtils.isEmpty(componentString)) {
+ return null;
+ }
+ final ComponentName component = ComponentName.unflattenFromString(componentString);
+ if (component == null) {
+ return null;
+ }
+ return component.getPackageName();
+ }
+
+ @Nullable
private String ensureSystemPackageName(@Nullable String packageName) {
if (packageName == null) {
return null;
@@ -25150,6 +25079,8 @@ public class PackageManagerService extends IPackageManager.Stub
: new String[] {mRetailDemoPackage};
case PackageManagerInternal.PACKAGE_OVERLAY_CONFIG_SIGNATURE:
return filterOnlySystemPackages(getOverlayConfigSignaturePackageName());
+ case PackageManagerInternal.PACKAGE_RECENTS:
+ return filterOnlySystemPackages(mRecentsPackage);
default:
return ArrayUtils.emptyArray(String.class);
}
diff --git a/services/core/java/com/android/server/pm/PackageProperty.java b/services/core/java/com/android/server/pm/PackageProperty.java
new file mode 100644
index 000000000000..d18a02d9f315
--- /dev/null
+++ b/services/core/java/com/android/server/pm/PackageProperty.java
@@ -0,0 +1,287 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.pm;
+
+import static android.content.pm.PackageManager.TYPE_ACTIVITY;
+import static android.content.pm.PackageManager.TYPE_APPLICATION;
+import static android.content.pm.PackageManager.TYPE_PROVIDER;
+import static android.content.pm.PackageManager.TYPE_RECEIVER;
+import static android.content.pm.PackageManager.TYPE_SERVICE;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.content.pm.PackageManager;
+import android.content.pm.PackageManager.Property;
+import android.content.pm.PackageManager.PropertyLocation;
+import android.content.pm.parsing.component.ParsedComponent;
+import android.os.Binder;
+import android.os.UserHandle;
+import android.util.ArrayMap;
+
+import com.android.server.pm.parsing.pkg.AndroidPackage;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.function.Predicate;
+
+/**
+ * Manages properties defined within a package using the &lt;property&gt; tag.
+ */
+public class PackageProperty {
+ /**
+ * Mapping of property name to all defined defined properties.
+ * <p>This is a mapping of property name --> package map. The package
+ * map is a mapping of package name -> list of properties.
+ */
+ private ArrayMap<String, ArrayMap<String, ArrayList<Property>>> mApplicationProperties;
+ private ArrayMap<String, ArrayMap<String, ArrayList<Property>>> mActivityProperties;
+ private ArrayMap<String, ArrayMap<String, ArrayList<Property>>> mProviderProperties;
+ private ArrayMap<String, ArrayMap<String, ArrayList<Property>>> mReceiverProperties;
+ private ArrayMap<String, ArrayMap<String, ArrayList<Property>>> mServiceProperties;
+
+ /**
+ * If the provided component is {@code null}, returns the property defined on the
+ * application. Otherwise, returns the property defined on the component.
+ */
+ public Property getProperty(@NonNull String propertyName, @NonNull String packageName,
+ @Nullable String className) {
+ if (className == null) {
+ return getApplicationProperty(propertyName, packageName);
+ }
+ return getComponentProperty(propertyName, packageName, className);
+ }
+
+ /**
+ * Returns all properties defined at the given location.
+ * <p>Valid locations are {@link PackageManager#TYPE_APPLICATION},
+ * {@link PackageManager#TYPE_ACTIVITY}, {@link PackageManager#TYPE_PROVIDER},
+ * {@link PackageManager#TYPE_RECEIVER}, or {@link PackageManager#TYPE_SERVICE}.
+ */
+ public List<Property> queryProperty(@NonNull String propertyName,
+ @PropertyLocation int componentType, Predicate<String> filter) {
+ final ArrayMap<String, ArrayMap<String, ArrayList<Property>>> propertyMap;
+ if (componentType == TYPE_APPLICATION) {
+ propertyMap = mApplicationProperties;
+ } else if (componentType == TYPE_ACTIVITY) {
+ propertyMap = mActivityProperties;
+ } else if (componentType == TYPE_PROVIDER) {
+ propertyMap = mProviderProperties;
+ } else if (componentType == TYPE_RECEIVER) {
+ propertyMap = mReceiverProperties;
+ } else if (componentType == TYPE_SERVICE) {
+ propertyMap = mServiceProperties;
+ } else {
+ propertyMap = null;
+ }
+ if (propertyMap == null) {
+ return null;
+ }
+ final ArrayMap<String, ArrayList<Property>> packagePropertyMap =
+ propertyMap.get(propertyName);
+ if (packagePropertyMap == null) {
+ return null;
+ }
+ final int callingUid = Binder.getCallingUid();
+ final int callingUserId = UserHandle.getCallingUserId();
+ final int mapSize = packagePropertyMap.size();
+ final List<Property> result = new ArrayList<>(mapSize);
+ for (int i = 0; i < mapSize; i++) {
+ final String packageName = packagePropertyMap.keyAt(i);
+ if (filter.test(packageName)) {
+ continue;
+ }
+ result.addAll(packagePropertyMap.valueAt(i));
+ }
+ return result;
+ }
+
+ /** Adds all properties defined for the given package */
+ void addAllProperties(AndroidPackage pkg) {
+ mApplicationProperties = addProperties(pkg.getProperties(), mApplicationProperties);
+ mActivityProperties = addComponentProperties(pkg.getActivities(), mActivityProperties);
+ mProviderProperties = addComponentProperties(pkg.getProviders(), mProviderProperties);
+ mReceiverProperties = addComponentProperties(pkg.getReceivers(), mReceiverProperties);
+ mServiceProperties = addComponentProperties(pkg.getServices(), mServiceProperties);
+ }
+
+ /** Adds all properties defined for the given package */
+ void removeAllProperties(AndroidPackage pkg) {
+ mApplicationProperties = removeProperties(pkg.getProperties(), mApplicationProperties);
+ mActivityProperties = removeComponentProperties(pkg.getActivities(), mActivityProperties);
+ mProviderProperties = removeComponentProperties(pkg.getProviders(), mProviderProperties);
+ mReceiverProperties = removeComponentProperties(pkg.getReceivers(), mReceiverProperties);
+ mServiceProperties = removeComponentProperties(pkg.getServices(), mServiceProperties);
+ }
+
+ /** Add the properties defined on the given components to the property collection */
+ private static <T extends ParsedComponent>
+ ArrayMap<String, ArrayMap<String, ArrayList<Property>>> addComponentProperties(
+ @NonNull List<T> components,
+ @Nullable ArrayMap<String, ArrayMap<String, ArrayList<Property>>> propertyCollection) {
+ ArrayMap<String, ArrayMap<String, ArrayList<Property>>> returnCollection =
+ propertyCollection;
+ final int componentsSize = components.size();
+ for (int i = 0; i < componentsSize; i++) {
+ final Map<String, Property> properties = components.get(i).getProperties();
+ if (properties.size() == 0) {
+ continue;
+ }
+ returnCollection = addProperties(properties, returnCollection);
+ }
+ return returnCollection;
+ }
+
+ /** Add the given properties to the property collection */
+ private static ArrayMap<String, ArrayMap<String, ArrayList<Property>>> addProperties(
+ @NonNull Map<String, Property> properties,
+ @Nullable ArrayMap<String, ArrayMap<String, ArrayList<Property>>> propertyCollection) {
+ if (properties.size() == 0) {
+ return propertyCollection;
+ }
+ final ArrayMap<String, ArrayMap<String, ArrayList<Property>>> returnCollection =
+ propertyCollection == null ? new ArrayMap<>(10) : propertyCollection;
+ final Iterator<Property> iter = properties.values().iterator();
+ while (iter.hasNext()) {
+ final Property property = iter.next();
+ final String propertyName = property.getName();
+ final String packageName = property.getPackageName();
+ ArrayMap<String, ArrayList<Property>> propertyMap = returnCollection.get(propertyName);
+ if (propertyMap == null) {
+ propertyMap = new ArrayMap<>();
+ returnCollection.put(propertyName, propertyMap);
+ }
+ ArrayList<Property> packageProperties = propertyMap.get(packageName);
+ if (packageProperties == null) {
+ packageProperties = new ArrayList<>(properties.size());
+ propertyMap.put(packageName, packageProperties);
+ }
+ packageProperties.add(property);
+ }
+ return returnCollection;
+ }
+
+ /** Removes the properties defined on the given components from the property collection */
+ private static <T extends ParsedComponent>
+ ArrayMap<String, ArrayMap<String, ArrayList<Property>>> removeComponentProperties(
+ @NonNull List<T> components,
+ @Nullable ArrayMap<String, ArrayMap<String, ArrayList<Property>>> propertyCollection) {
+ ArrayMap<String, ArrayMap<String, ArrayList<Property>>> returnCollection =
+ propertyCollection;
+ final int componentsSize = components.size();
+ for (int i = 0; returnCollection != null && i < componentsSize; i++) {
+ final Map<String, Property> properties = components.get(i).getProperties();
+ if (properties.size() == 0) {
+ continue;
+ }
+ returnCollection = removeProperties(properties, returnCollection);
+ }
+ return returnCollection;
+ }
+
+ /** Removes the given properties from the property collection */
+ private static ArrayMap<String, ArrayMap<String, ArrayList<Property>>> removeProperties(
+ @NonNull Map<String, Property> properties,
+ @Nullable ArrayMap<String, ArrayMap<String, ArrayList<Property>>> propertyCollection) {
+ if (propertyCollection == null) {
+ return null;
+ }
+ final Iterator<Property> iter = properties.values().iterator();
+ while (iter.hasNext()) {
+ final Property property = iter.next();
+ final String propertyName = property.getName();
+ final String packageName = property.getPackageName();
+ ArrayMap<String, ArrayList<Property>> propertyMap =
+ propertyCollection.get(propertyName);
+ if (propertyMap == null) {
+ // error
+ continue;
+ }
+ ArrayList<Property> packageProperties = propertyMap.get(packageName);
+ if (packageProperties == null) {
+ //error
+ continue;
+ }
+ packageProperties.remove(property);
+
+ // clean up empty structures
+ if (packageProperties.size() == 0) {
+ propertyMap.remove(packageName);
+ }
+ if (propertyMap.size() == 0) {
+ propertyCollection.remove(propertyName);
+ }
+ }
+ if (propertyCollection.size() == 0) {
+ return null;
+ }
+ return propertyCollection;
+ }
+
+ private static Property getProperty(String propertyName, String packageName, String className,
+ ArrayMap<String, ArrayMap<String, ArrayList<Property>>> propertyMap) {
+ final ArrayMap<String, ArrayList<Property>> packagePropertyMap =
+ propertyMap.get(propertyName);
+ if (packagePropertyMap == null) {
+ return null;
+ }
+ final List<Property> propertyList = packagePropertyMap.get(packageName);
+ if (propertyList == null) {
+ return null;
+ }
+ for (int i = propertyList.size() - 1; i >= 0; i--) {
+ final Property property = propertyList.get(i);
+ if (Objects.equals(className, property.getClassName())) {
+ return property;
+ }
+ }
+ return null;
+ }
+
+ private Property getComponentProperty(
+ String propertyName, String packageName, String className) {
+ Property property = null;
+ if (property == null && mActivityProperties != null) {
+ property = getProperty(propertyName, packageName, className, mActivityProperties);
+ }
+ if (property == null && mProviderProperties != null) {
+ property = getProperty(propertyName, packageName, className, mProviderProperties);
+ }
+ if (property == null && mReceiverProperties != null) {
+ property = getProperty(propertyName, packageName, className, mReceiverProperties);
+ }
+ if (property == null && mServiceProperties != null) {
+ property = getProperty(propertyName, packageName, className, mServiceProperties);
+ }
+ return property;
+ }
+
+ private Property getApplicationProperty(String propertyName, String packageName) {
+ final ArrayMap<String, ArrayList<Property>> packagePropertyMap =
+ mApplicationProperties.get(propertyName);
+ if (packagePropertyMap == null) {
+ return null;
+ }
+ final List<Property> propertyList = packagePropertyMap.get(packageName);
+ if (propertyList == null) {
+ return null;
+ }
+ return propertyList.get(0);
+ }
+}
diff --git a/services/core/java/com/android/server/pm/permission/Permission.java b/services/core/java/com/android/server/pm/permission/Permission.java
index 0245b28884ea..995b59e97e91 100644
--- a/services/core/java/com/android/server/pm/permission/Permission.java
+++ b/services/core/java/com/android/server/pm/permission/Permission.java
@@ -331,6 +331,10 @@ public final class Permission {
return (mPermissionInfo.protectionLevel & PermissionInfo.PROTECTION_FLAG_RETAIL_DEMO) != 0;
}
+ public boolean isRecents() {
+ return (mPermissionInfo.protectionLevel & PermissionInfo.PROTECTION_FLAG_RECENTS) != 0;
+ }
+
public void transfer(@NonNull String oldPackageName, @NonNull String newPackageName) {
if (!oldPackageName.equals(mPermissionInfo.packageName)) {
return;
@@ -399,8 +403,7 @@ public final class Permission {
@NonNull
public static Permission createOrUpdate(@Nullable Permission permission,
@NonNull PermissionInfo permissionInfo, @NonNull AndroidPackage pkg,
- @NonNull Collection<Permission> permissionTrees, boolean isOverridingSystemPermission,
- boolean chatty) {
+ @NonNull Collection<Permission> permissionTrees, boolean isOverridingSystemPermission) {
// Allow system apps to redefine non-system permissions
boolean ownerChanged = false;
if (permission != null && !Objects.equals(permission.mPermissionInfo.packageName,
@@ -437,7 +440,7 @@ public final class Permission {
permission.mPermissionInfo = permissionInfo;
permission.mReconciled = true;
permission.mUid = pkg.getUid();
- if (chatty) {
+ if (PackageManagerService.DEBUG_PACKAGE_SCANNING) {
if (r == null) {
r = new StringBuilder(256);
} else {
@@ -456,7 +459,7 @@ public final class Permission {
+ permissionInfo.packageName + " ignored: original from "
+ permission.mPermissionInfo.packageName);
}
- } else if (chatty) {
+ } else if (PackageManagerService.DEBUG_PACKAGE_SCANNING) {
if (r == null) {
r = new StringBuilder(256);
} else {
diff --git a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
index 6c03a28d03c7..fb1ed2f6b58b 100644
--- a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
+++ b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
@@ -93,6 +93,7 @@ import android.content.pm.parsing.component.ParsedPermission;
import android.content.pm.parsing.component.ParsedPermissionGroup;
import android.content.pm.permission.SplitPermissionInfoParcelable;
import android.metrics.LogMaker;
+import android.os.AsyncTask;
import android.os.Binder;
import android.os.Build;
import android.os.Debug;
@@ -133,6 +134,7 @@ import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.internal.os.RoSystemProperties;
import com.android.internal.util.ArrayUtils;
+import com.android.internal.util.CollectionUtils;
import com.android.internal.util.DumpUtils;
import com.android.internal.util.IntPair;
import com.android.internal.util.Preconditions;
@@ -145,7 +147,6 @@ import com.android.server.Watchdog;
import com.android.server.pm.ApexManager;
import com.android.server.pm.PackageManagerServiceUtils;
import com.android.server.pm.PackageSetting;
-import com.android.server.pm.SharedUserSetting;
import com.android.server.pm.UserManagerInternal;
import com.android.server.pm.UserManagerService;
import com.android.server.pm.parsing.PackageInfoUtils;
@@ -2363,14 +2364,9 @@ public class PermissionManagerService extends IPermissionManager.Stub {
*
* @param newPackage The new package that was installed
* @param oldPackage The old package that was updated
- * @param allPackageNames All package names
- * @param permissionCallback Callback for permission changed
*/
- private void revokeRuntimePermissionsIfGroupChanged(
- @NonNull AndroidPackage newPackage,
- @NonNull AndroidPackage oldPackage,
- @NonNull ArrayList<String> allPackageNames,
- @NonNull PermissionCallback permissionCallback) {
+ private void revokeRuntimePermissionsIfGroupChangedInternal(@NonNull AndroidPackage newPackage,
+ @NonNull AndroidPackage oldPackage) {
final int numOldPackagePermissions = ArrayUtils.size(oldPackage.getPermissions());
final ArrayMap<String, String> oldPermissionNameToGroupName
= new ArrayMap<>(numOldPackagePermissions);
@@ -2403,13 +2399,9 @@ public class PermissionManagerService extends IPermissionManager.Stub {
if (newPermissionGroupName != null
&& !newPermissionGroupName.equals(oldPermissionGroupName)) {
final int[] userIds = mUserManagerInt.getUserIds();
- final int numUserIds = userIds.length;
- for (int userIdNum = 0; userIdNum < numUserIds; userIdNum++) {
- final int userId = userIds[userIdNum];
-
- final int numPackages = allPackageNames.size();
- for (int packageNum = 0; packageNum < numPackages; packageNum++) {
- final String packageName = allPackageNames.get(packageNum);
+ mPackageManagerInt.forEachPackage(pkg -> {
+ final String packageName = pkg.getPackageName();
+ for (final int userId : userIds) {
final int permissionState = checkPermission(permissionName, packageName,
userId);
if (permissionState == PackageManager.PERMISSION_GRANTED) {
@@ -2422,14 +2414,15 @@ public class PermissionManagerService extends IPermissionManager.Stub {
try {
revokeRuntimePermissionInternal(permissionName, packageName,
- false, callingUid, userId, null, permissionCallback);
+ false, callingUid, userId, null,
+ mDefaultPermissionCallback);
} catch (IllegalArgumentException e) {
Slog.e(TAG, "Could not revoke " + permissionName + " from "
+ packageName, e);
}
}
}
- }
+ });
}
}
}
@@ -2440,18 +2433,11 @@ public class PermissionManagerService extends IPermissionManager.Stub {
* granted permissions must be revoked.
*
* @param permissionsToRevoke A list of permission names to revoke
- * @param allPackageNames All package names
- * @param permissionCallback Callback for permission changed
*/
- private void revokeRuntimePermissionsIfPermissionDefinitionChanged(
- @NonNull List<String> permissionsToRevoke,
- @NonNull ArrayList<String> allPackageNames,
- @NonNull PermissionCallback permissionCallback) {
-
+ private void revokeRuntimePermissionsIfPermissionDefinitionChangedInternal(
+ @NonNull List<String> permissionsToRevoke) {
final int[] userIds = mUserManagerInt.getUserIds();
final int numPermissions = permissionsToRevoke.size();
- final int numUserIds = userIds.length;
- final int numPackages = allPackageNames.size();
final int callingUid = Binder.getCallingUid();
for (int permNum = 0; permNum < numPermissions; permNum++) {
@@ -2462,15 +2448,14 @@ public class PermissionManagerService extends IPermissionManager.Stub {
continue;
}
}
- for (int userIdNum = 0; userIdNum < numUserIds; userIdNum++) {
- final int userId = userIds[userIdNum];
- for (int packageNum = 0; packageNum < numPackages; packageNum++) {
- final String packageName = allPackageNames.get(packageNum);
- final int uid = mPackageManagerInt.getPackageUid(packageName, 0, userId);
- if (uid < Process.FIRST_APPLICATION_UID) {
- // do not revoke from system apps
- continue;
- }
+ mPackageManagerInt.forEachPackage(pkg -> {
+ final String packageName = pkg.getPackageName();
+ final int appId = pkg.getUid();
+ if (appId < Process.FIRST_APPLICATION_UID) {
+ // do not revoke from system apps
+ return;
+ }
+ for (final int userId : userIds) {
final int permissionState = checkPermissionImpl(permName, packageName,
userId);
final int flags = getPermissionFlags(permName, packageName, userId);
@@ -2480,6 +2465,7 @@ public class PermissionManagerService extends IPermissionManager.Stub {
| FLAG_PERMISSION_GRANTED_BY_ROLE;
if (permissionState == PackageManager.PERMISSION_GRANTED
&& (flags & flagMask) == 0) {
+ final int uid = UserHandle.getUid(userId, appId);
EventLog.writeEvent(0x534e4554, "154505240", uid,
"Revoking permission " + permName + " from package "
+ packageName + " due to definition change");
@@ -2490,18 +2476,18 @@ public class PermissionManagerService extends IPermissionManager.Stub {
+ packageName + " due to definition change");
try {
revokeRuntimePermissionInternal(permName, packageName,
- false, callingUid, userId, null, permissionCallback);
+ false, callingUid, userId, null, mDefaultPermissionCallback);
} catch (Exception e) {
Slog.e(TAG, "Could not revoke " + permName + " from "
+ packageName, e);
}
}
}
- }
+ });
}
}
- private List<String> addAllPermissions(AndroidPackage pkg, boolean chatty) {
+ private List<String> addAllPermissionsInternal(@NonNull AndroidPackage pkg) {
final int N = ArrayUtils.size(pkg.getPermissions());
ArrayList<String> definitionChangedPermissions = new ArrayList<>();
for (int i=0; i<N; i++) {
@@ -2539,7 +2525,7 @@ public class PermissionManagerService extends IPermissionManager.Stub {
synchronized (mLock) {
final Permission permission = Permission.createOrUpdate(oldPermission,
permissionInfo, pkg, mRegistry.getPermissionTrees(),
- isOverridingSystemPermission, chatty);
+ isOverridingSystemPermission);
if (p.isTree()) {
mRegistry.addPermissionTree(permission);
} else {
@@ -2557,7 +2543,7 @@ public class PermissionManagerService extends IPermissionManager.Stub {
return definitionChangedPermissions;
}
- private void addAllPermissionGroups(AndroidPackage pkg, boolean chatty) {
+ private void addAllPermissionGroupsInternal(@NonNull AndroidPackage pkg) {
synchronized (mLock) {
final int N = ArrayUtils.size(pkg.getPermissionGroups());
StringBuilder r = null;
@@ -2568,7 +2554,7 @@ public class PermissionManagerService extends IPermissionManager.Stub {
final boolean isPackageUpdate = pg.getPackageName().equals(curPackageName);
if (cur == null || isPackageUpdate) {
mRegistry.addPermissionGroup(pg);
- if (chatty && DEBUG_PACKAGE_SCANNING) {
+ if (DEBUG_PACKAGE_SCANNING) {
if (r == null) {
r = new StringBuilder(256);
} else {
@@ -2583,7 +2569,7 @@ public class PermissionManagerService extends IPermissionManager.Stub {
Slog.w(TAG, "Permission group " + pg.getName() + " from package "
+ pg.getPackageName() + " ignored: original from "
+ cur.getPackageName());
- if (chatty && DEBUG_PACKAGE_SCANNING) {
+ if (DEBUG_PACKAGE_SCANNING) {
if (r == null) {
r = new StringBuilder(256);
} else {
@@ -2600,7 +2586,7 @@ public class PermissionManagerService extends IPermissionManager.Stub {
}
}
- private void removeAllPermissions(AndroidPackage pkg, boolean chatty) {
+ private void removeAllPermissionsInternal(@NonNull AndroidPackage pkg) {
synchronized (mLock) {
int N = ArrayUtils.size(pkg.getPermissions());
StringBuilder r = null;
@@ -2612,7 +2598,7 @@ public class PermissionManagerService extends IPermissionManager.Stub {
}
if (bp != null && bp.isPermission(p)) {
bp.setPermissionInfo(null);
- if (DEBUG_REMOVE && chatty) {
+ if (DEBUG_REMOVE) {
if (r == null) {
r = new StringBuilder(256);
} else {
@@ -3630,6 +3616,13 @@ public class PermissionManagerService extends IPermissionManager.Stub {
// Special permission granted only to the OEM specified retail demo app
allowed = true;
}
+ if (!allowed && bp.isRecents()
+ && ArrayUtils.contains(mPackageManagerInt.getKnownPackageNames(
+ PackageManagerInternal.PACKAGE_RECENTS, UserHandle.USER_SYSTEM),
+ pkg.getPackageName())) {
+ // Special permission for the recents app.
+ allowed = true;
+ }
return allowed;
}
@@ -3990,34 +3983,30 @@ public class PermissionManagerService extends IPermissionManager.Stub {
}
@UserIdInt
- private int revokeSharedUserPermissionsForDeletedPackage(@NonNull PackageSetting deletedPs,
+ private int revokeSharedUserPermissionsForDeletedPackageInternal(
+ @Nullable AndroidPackage pkg, @NonNull List<AndroidPackage> sharedUserPkgs,
@UserIdInt int userId) {
- if ((deletedPs == null) || (deletedPs.pkg == null)) {
+ if (pkg == null) {
Slog.i(TAG, "Trying to update info for null package. Just ignoring");
return UserHandle.USER_NULL;
}
- SharedUserSetting sus = deletedPs.getSharedUser();
-
- // No sharedUserId
- if (sus == null) {
+ // No shared user packages
+ if (sharedUserPkgs.isEmpty()) {
return UserHandle.USER_NULL;
}
int affectedUserId = UserHandle.USER_NULL;
// Update permissions
- for (String eachPerm : deletedPs.pkg.getRequestedPermissions()) {
+ for (String eachPerm : pkg.getRequestedPermissions()) {
// Check if another package in the shared user needs the permission.
boolean used = false;
- final List<AndroidPackage> pkgs = sus.getPackages();
- if (pkgs != null) {
- for (AndroidPackage pkg : pkgs) {
- if (pkg != null
- && !pkg.getPackageName().equals(deletedPs.pkg.getPackageName())
- && pkg.getRequestedPermissions().contains(eachPerm)) {
- used = true;
- break;
- }
+ for (AndroidPackage sharedUserpkg : sharedUserPkgs) {
+ if (sharedUserpkg != null
+ && !sharedUserpkg.getPackageName().equals(pkg.getPackageName())
+ && sharedUserpkg.getRequestedPermissions().contains(eachPerm)) {
+ used = true;
+ break;
}
}
if (used) {
@@ -4025,7 +4014,7 @@ public class PermissionManagerService extends IPermissionManager.Stub {
}
PackageSetting disabledPs = mPackageManagerInt.getDisabledSystemPackage(
- deletedPs.pkg.getPackageName());
+ pkg.getPackageName());
// If the package is shadowing is a disabled system package,
// do not drop permissions that the shadowed package requests.
@@ -4043,9 +4032,9 @@ public class PermissionManagerService extends IPermissionManager.Stub {
}
synchronized (mLock) {
- UidPermissionState uidState = getUidStateLocked(deletedPs.pkg, userId);
+ UidPermissionState uidState = getUidStateLocked(pkg, userId);
if (uidState == null) {
- Slog.e(TAG, "Missing permissions state for " + deletedPs.pkg.getPackageName()
+ Slog.e(TAG, "Missing permissions state for " + pkg.getPackageName()
+ " and user " + userId);
continue;
}
@@ -4848,10 +4837,113 @@ public class PermissionManagerService extends IPermissionManager.Stub {
}
}
- private void transferPermissions(@NonNull String oldPackageName,
- @NonNull String newPackageName) {
- synchronized (mLock) {
- mRegistry.transferPermissions(oldPackageName, newPackageName);
+ private void onPackageAddedInternal(@NonNull AndroidPackage pkg, boolean isInstantApp,
+ @Nullable AndroidPackage oldPkg) {
+ if (!pkg.getAdoptPermissions().isEmpty()) {
+ // This package wants to adopt ownership of permissions from
+ // another package.
+ for (int i = pkg.getAdoptPermissions().size() - 1; i >= 0; i--) {
+ final String origName = pkg.getAdoptPermissions().get(i);
+ if (canAdoptPermissionsInternal(origName, pkg)) {
+ Slog.i(TAG, "Adopting permissions from " + origName + " to "
+ + pkg.getPackageName());
+ synchronized (mLock) {
+ mRegistry.transferPermissions(origName, pkg.getPackageName());
+ }
+ }
+ }
+ }
+
+ // Don't allow ephemeral applications to define new permissions groups.
+ if (isInstantApp) {
+ Slog.w(TAG, "Permission groups from package " + pkg.getPackageName()
+ + " ignored: instant apps cannot define new permission groups.");
+ } else {
+ addAllPermissionGroupsInternal(pkg);
+ }
+
+ // If a permission has had its defining app changed, or it has had its protection
+ // upgraded, we need to revoke apps that hold it
+ final List<String> permissionsWithChangedDefinition;
+ // Don't allow ephemeral applications to define new permissions.
+ if (isInstantApp) {
+ permissionsWithChangedDefinition = null;
+ Slog.w(TAG, "Permissions from package " + pkg.getPackageName()
+ + " ignored: instant apps cannot define new permissions.");
+ } else {
+ permissionsWithChangedDefinition = addAllPermissionsInternal(pkg);
+ }
+
+ boolean hasOldPkg = oldPkg != null;
+ boolean hasPermissionDefinitionChanges =
+ !CollectionUtils.isEmpty(permissionsWithChangedDefinition);
+ if (hasOldPkg || hasPermissionDefinitionChanges) {
+ // We need to call revokeRuntimePermissionsIfGroupChanged async as permission
+ // revoke callbacks from this method might need to kill apps which need the
+ // mPackages lock on a different thread. This would dead lock.
+ AsyncTask.execute(() -> {
+ if (hasOldPkg) {
+ revokeRuntimePermissionsIfGroupChangedInternal(pkg, oldPkg);
+ }
+ if (hasPermissionDefinitionChanges) {
+ revokeRuntimePermissionsIfPermissionDefinitionChangedInternal(
+ permissionsWithChangedDefinition);
+ }
+ });
+ }
+ }
+
+ private boolean canAdoptPermissionsInternal(@NonNull String oldPackageName,
+ @NonNull AndroidPackage newPkg) {
+ final PackageSetting oldPs = mPackageManagerInt.getPackageSetting(oldPackageName);
+ if (oldPs == null) {
+ return false;
+ }
+ if (!oldPs.isSystem()) {
+ Slog.w(TAG, "Unable to update from " + oldPs.name
+ + " to " + newPkg.getPackageName()
+ + ": old package not in system partition");
+ return false;
+ }
+ if (mPackageManagerInt.getPackage(oldPs.name) != null) {
+ Slog.w(TAG, "Unable to update from " + oldPs.name
+ + " to " + newPkg.getPackageName()
+ + ": old package still exists");
+ return false;
+ }
+ return true;
+ }
+
+ private void onPackageRemovedInternal(@NonNull AndroidPackage pkg) {
+ removeAllPermissionsInternal(pkg);
+ }
+
+ private void onPackageStateRemovedInternal(@NonNull String packageName, int appId,
+ @Nullable AndroidPackage pkg, @NonNull List<AndroidPackage> sharedUserPkgs) {
+ if (sharedUserPkgs.isEmpty()
+ && mPackageManagerInt.getDisabledSystemPackage(packageName) == null) {
+ removeAppIdState(appId);
+ }
+ updatePermissions(packageName, null, mDefaultPermissionCallback);
+ if (!sharedUserPkgs.isEmpty()) {
+ // Remove permissions associated with package. Since runtime
+ // permissions are per user we have to kill the removed package
+ // or packages running under the shared user of the removed
+ // package if revoking the permissions requested only by the removed
+ // package is successful and this causes a change in gids.
+ boolean shouldKill = false;
+ for (int userId : UserManagerService.getInstance().getUserIds()) {
+ final int userIdToKill = revokeSharedUserPermissionsForDeletedPackageInternal(pkg,
+ sharedUserPkgs, userId);
+ shouldKill |= userIdToKill != UserHandle.USER_NULL;
+ }
+ // If gids changed, kill all affected packages.
+ if (shouldKill) {
+ mHandler.post(() -> {
+ // This has to happen with no lock held.
+ killUid(appId, UserHandle.USER_ALL, KILL_APP_REASON_GIDS_CHANGED);
+ });
+ }
}
}
@@ -4955,35 +5047,6 @@ public class PermissionManagerService extends IPermissionManager.Stub {
}
@Override
- public void revokeRuntimePermissionsIfGroupChanged(
- @NonNull AndroidPackage newPackage,
- @NonNull AndroidPackage oldPackage,
- @NonNull ArrayList<String> allPackageNames) {
- PermissionManagerService.this.revokeRuntimePermissionsIfGroupChanged(newPackage,
- oldPackage, allPackageNames, mDefaultPermissionCallback);
- }
-
- @Override
- public void revokeRuntimePermissionsIfPermissionDefinitionChanged(
- @NonNull List<String> permissionsToRevoke,
- @NonNull ArrayList<String> allPackageNames) {
- PermissionManagerService.this.revokeRuntimePermissionsIfPermissionDefinitionChanged(
- permissionsToRevoke, allPackageNames, mDefaultPermissionCallback);
- }
-
- @Override
- public List<String> addAllPermissions(AndroidPackage pkg, boolean chatty) {
- return PermissionManagerService.this.addAllPermissions(pkg, chatty);
- }
- @Override
- public void addAllPermissionGroups(AndroidPackage pkg, boolean chatty) {
- PermissionManagerService.this.addAllPermissionGroups(pkg, chatty);
- }
- @Override
- public void removeAllPermissions(AndroidPackage pkg, boolean chatty) {
- PermissionManagerService.this.removeAllPermissions(pkg, chatty);
- }
- @Override
public void readLegacyPermissionStateTEMP() {
PermissionManagerService.this.readLegacyPermissionState();
}
@@ -4995,17 +5058,6 @@ public class PermissionManagerService extends IPermissionManager.Stub {
public void onUserRemoved(@UserIdInt int userId) {
PermissionManagerService.this.onUserRemoved(userId);
}
- @Override
- public void removeAppIdStateTEMP(@AppIdInt int appId) {
- PermissionManagerService.this.removeAppIdState(appId);
- }
- @Override
- @UserIdInt
- public int revokeSharedUserPermissionsForDeletedPackageTEMP(
- @NonNull PackageSetting deletedPs, @UserIdInt int userId) {
- return PermissionManagerService.this.revokeSharedUserPermissionsForDeletedPackage(
- deletedPs, userId);
- }
@NonNull
@Override
public Set<String> getGrantedPermissions(@NonNull String packageName,
@@ -5313,9 +5365,24 @@ public class PermissionManagerService extends IPermissionManager.Stub {
}
@Override
- public void transferPermissions(@NonNull String oldPackageName,
- @NonNull String newPackageName) {
- PermissionManagerService.this.transferPermissions(oldPackageName, newPackageName);
+ public void onPackageAdded(@NonNull AndroidPackage pkg, boolean isInstantApp,
+ @Nullable AndroidPackage oldPkg) {
+ Objects.requireNonNull(pkg);
+ onPackageAddedInternal(pkg, isInstantApp, oldPkg);
+ }
+
+ @Override
+ public void onPackageRemoved(@NonNull AndroidPackage pkg) {
+ Objects.requireNonNull(pkg);
+ onPackageRemovedInternal(pkg);
+ }
+
+ @Override
+ public void onPackageStateRemoved(@NonNull String packageName, int appId,
+ @Nullable AndroidPackage pkg, @NonNull List<AndroidPackage> sharedUserPkgs) {
+ Objects.requireNonNull(packageName);
+ Objects.requireNonNull(sharedUserPkgs);
+ onPackageStateRemovedInternal(packageName, appId, pkg, sharedUserPkgs);
}
@Override
diff --git a/services/core/java/com/android/server/pm/permission/PermissionManagerServiceInternal.java b/services/core/java/com/android/server/pm/permission/PermissionManagerServiceInternal.java
index df9d0d397c56..1becbedc29fb 100644
--- a/services/core/java/com/android/server/pm/permission/PermissionManagerServiceInternal.java
+++ b/services/core/java/com/android/server/pm/permission/PermissionManagerServiceInternal.java
@@ -24,7 +24,6 @@ import android.content.pm.PackageManager;
import android.content.pm.PermissionInfo;
import android.permission.PermissionManagerInternal;
-import com.android.server.pm.PackageSetting;
import com.android.server.pm.parsing.pkg.AndroidPackage;
import java.util.ArrayList;
@@ -277,44 +276,6 @@ public abstract class PermissionManagerServiceInternal extends PermissionManager
public abstract void resetAllRuntimePermissions(@UserIdInt int userId);
/**
- * We might auto-grant permissions if any permission of the group is already granted. Hence if
- * the group of a granted permission changes we need to revoke it to avoid having permissions of
- * the new group auto-granted.
- *
- * @param newPackage The new package that was installed
- * @param oldPackage The old package that was updated
- * @param allPackageNames All packages
- */
- public abstract void revokeRuntimePermissionsIfGroupChanged(
- @NonNull AndroidPackage newPackage,
- @NonNull AndroidPackage oldPackage,
- @NonNull ArrayList<String> allPackageNames);
-
- /**
- * Some permissions might have been owned by a non-system package, and the system then defined
- * said permission. Some other permissions may one have been install permissions, but are now
- * runtime or higher. These permissions should be revoked.
- *
- * @param permissionsToRevoke A list of permission names to revoke
- * @param allPackageNames All packages
- */
- public abstract void revokeRuntimePermissionsIfPermissionDefinitionChanged(
- @NonNull List<String> permissionsToRevoke,
- @NonNull ArrayList<String> allPackageNames);
-
- /**
- * Add all permissions in the given package.
- * <p>
- * NOTE: argument {@code groupTEMP} is temporary until mPermissionGroups is moved to
- * the permission settings.
- *
- * @return A list of BasePermissions that were updated, and need to be revoked from packages
- */
- public abstract List<String> addAllPermissions(@NonNull AndroidPackage pkg, boolean chatty);
- public abstract void addAllPermissionGroups(@NonNull AndroidPackage pkg, boolean chatty);
- public abstract void removeAllPermissions(@NonNull AndroidPackage pkg, boolean chatty);
-
- /**
* Read legacy permission state from package settings.
*
* TODO(zhanghai): This is a temporary method because we should not expose
@@ -337,30 +298,6 @@ public abstract class PermissionManagerServiceInternal extends PermissionManager
public abstract void onUserRemoved(@UserIdInt int userId);
/**
- * Remove the permission state associated with an app ID, called the same time as the
- * removal of a {@code PackageSetitng}.
- *
- * TODO(zhanghai): This is a temporary method before we figure out a way to get notified of app
- * ID removal via API.
- */
- public abstract void removeAppIdStateTEMP(@AppIdInt int appId);
-
- /**
- * Update the shared user setting when a package with a shared user id is removed. The gids
- * associated with each permission of the deleted package are removed from the shared user'
- * gid list only if its not in use by other permissions of packages in the shared user setting.
- *
- * TODO(zhanghai): We should not need this when permission no longer sees an incomplete package
- * state where the updated system package is uninstalled but the disabled system package is yet
- * to be installed. Then we should handle this in restorePermissionState().
- *
- * @return the affected user id, may be a real user ID, USER_ALL, or USER_NULL when none.
- */
- @UserIdInt
- public abstract int revokeSharedUserPermissionsForDeletedPackageTEMP(
- @NonNull PackageSetting deletedPs, @UserIdInt int userId);
-
- /**
* Get all the permissions granted to a package.
*
* @param packageName the name of the package
@@ -578,10 +515,35 @@ public abstract class PermissionManagerServiceInternal extends PermissionManager
@NonNull LegacyPermissionSettings legacyPermissionSettings);
/**
- * Transfers ownership of permissions from one package to another.
+ * Callback when a package has been added.
+ *
+ * @param pkg the added package
+ * @param isInstantApp whether the added package is an instant app
+ * @param oldPkg the old package, or {@code null} if none
*/
- public abstract void transferPermissions(@NonNull String oldPackageName,
- @NonNull String newPackageName);
+ //@SystemApi(client = SystemApi.Client.SYSTEM_SERVER)
+ public abstract void onPackageAdded(@NonNull AndroidPackage pkg, boolean isInstantApp,
+ @Nullable AndroidPackage oldPkg);
+
+ /**
+ * Callback when a package has been removed.
+ *
+ * @param pkg the removed package
+ */
+ //@SystemApi(client = SystemApi.Client.SYSTEM_SERVER)
+ public abstract void onPackageRemoved(@NonNull AndroidPackage pkg);
+
+ /**
+ * Callback when the state for a package has been removed.
+ *
+ * @param packageName the name of the removed package
+ * @param appId the app ID of the removed package
+ * @param pkg the removed package, or {@code null} if unavailable
+ * @param sharedUserPkgs the packages that are in the same shared user
+ */
+ //@SystemApi(client = SystemApi.Client.SYSTEM_SERVER)
+ public abstract void onPackageStateRemoved(@NonNull String packageName, int appId,
+ @Nullable AndroidPackage pkg, @NonNull List<AndroidPackage> sharedUserPkgs);
/**
* Check whether a permission can be propagated to instant app.
diff --git a/services/core/java/com/android/server/policy/DeviceStatePolicyImpl.java b/services/core/java/com/android/server/policy/DeviceStatePolicyImpl.java
index 54f618327da8..154f9a455a1a 100644
--- a/services/core/java/com/android/server/policy/DeviceStatePolicyImpl.java
+++ b/services/core/java/com/android/server/policy/DeviceStatePolicyImpl.java
@@ -17,6 +17,7 @@
package com.android.server.policy;
import android.annotation.NonNull;
+import android.content.Context;
import com.android.server.devicestate.DeviceStatePolicy;
import com.android.server.devicestate.DeviceStateProvider;
@@ -27,10 +28,12 @@ import com.android.server.devicestate.DeviceStateProvider;
* @see DeviceStateProviderImpl
*/
public final class DeviceStatePolicyImpl implements DeviceStatePolicy {
+ private final Context mContext;
private final DeviceStateProvider mProvider;
- public DeviceStatePolicyImpl() {
- mProvider = new DeviceStateProviderImpl();
+ public DeviceStatePolicyImpl(Context context) {
+ mContext = context;
+ mProvider = DeviceStateProviderImpl.create(mContext);
}
public DeviceStateProvider getDeviceStateProvider() {
diff --git a/services/core/java/com/android/server/policy/DeviceStateProviderImpl.java b/services/core/java/com/android/server/policy/DeviceStateProviderImpl.java
index 85ab0bc12cae..321bb8c0251d 100644
--- a/services/core/java/com/android/server/policy/DeviceStateProviderImpl.java
+++ b/services/core/java/com/android/server/policy/DeviceStateProviderImpl.java
@@ -16,30 +16,464 @@
package com.android.server.policy;
+import static android.hardware.devicestate.DeviceStateManager.INVALID_DEVICE_STATE;
+
+import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.content.Context;
+import android.hardware.Sensor;
+import android.hardware.SensorEvent;
+import android.hardware.SensorEventListener;
+import android.hardware.SensorManager;
+import android.hardware.input.InputManagerInternal;
+import android.os.Environment;
+import android.util.ArrayMap;
+import android.util.ArraySet;
+import android.util.Slog;
+import android.util.SparseArray;
+import com.android.internal.annotations.GuardedBy;
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.server.LocalServices;
import com.android.server.devicestate.DeviceStateProvider;
+import com.android.server.policy.devicestate.config.Conditions;
+import com.android.server.policy.devicestate.config.DeviceState;
+import com.android.server.policy.devicestate.config.DeviceStateConfig;
+import com.android.server.policy.devicestate.config.LidSwitchCondition;
+import com.android.server.policy.devicestate.config.NumericRange;
+import com.android.server.policy.devicestate.config.SensorCondition;
+import com.android.server.policy.devicestate.config.XmlParser;
+
+import org.xmlpull.v1.XmlPullParserException;
+
+import java.io.BufferedInputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.math.BigDecimal;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+import java.util.function.BooleanSupplier;
+
+import javax.xml.datatype.DatatypeConfigurationException;
/**
- * Default implementation of {@link DeviceStateProvider}. Currently only supports
- * {@link #DEFAULT_DEVICE_STATE}.
- *
- * @see DeviceStatePolicyImpl
+ * Implementation of {@link DeviceStateProvider} that reads the set of supported device states
+ * from a configuration file provided at either /vendor/etc/devicestate or
+ * /data/system/devicestate/. By default, the provider supports {@link #DEFAULT_DEVICE_STATE} when
+ * no configuration is provided.
*/
-final class DeviceStateProviderImpl implements DeviceStateProvider {
- private static final int DEFAULT_DEVICE_STATE = 0;
+public final class DeviceStateProviderImpl implements DeviceStateProvider,
+ InputManagerInternal.LidSwitchCallback, SensorEventListener {
+ private static final String TAG = "DeviceStateProviderImpl";
+
+ private static final BooleanSupplier TRUE_BOOLEAN_SUPPLIER = () -> true;
+
+ @VisibleForTesting
+ static final int DEFAULT_DEVICE_STATE = 0;
+
+ private static final String VENDOR_CONFIG_FILE_PATH = "etc/devicestate/";
+ private static final String DATA_CONFIG_FILE_PATH = "system/devicestate/";
+ private static final String CONFIG_FILE_NAME = "device_state_configuration.xml";
+
+ /** Interface that allows reading the device state configuration. */
+ interface ReadableConfig {
+ @NonNull
+ InputStream openRead() throws IOException;
+ }
+
+ /**
+ * Returns a new {@link DeviceStateProviderImpl} instance.
+ *
+ * @param context the {@link Context} that should be used to access system services.
+ */
+ public static DeviceStateProviderImpl create(@NonNull Context context) {
+ File configFile = getConfigurationFile();
+ if (configFile == null) {
+ return createFromConfig(context, null);
+ }
+ return createFromConfig(context, new ReadableFileConfig(configFile));
+ }
+
+ /**
+ * Returns a new {@link DeviceStateProviderImpl} instance.
+ *
+ * @param context the {@link Context} that should be used to access system services.
+ * @param readableConfig the config the provider instance should read supported states from.
+ */
+ @VisibleForTesting
+ static DeviceStateProviderImpl createFromConfig(@NonNull Context context,
+ @Nullable ReadableConfig readableConfig) {
+ SparseArray<Conditions> conditionsForState = new SparseArray<>();
+ if (readableConfig != null) {
+ DeviceStateConfig config = parseConfig(readableConfig);
+ if (config != null) {
+ for (DeviceState stateConfig : config.getDeviceState()) {
+ int state = stateConfig.getIdentifier().intValue();
+ Conditions conditions = stateConfig.getConditions();
+ conditionsForState.put(state, conditions);
+ }
+ }
+ }
+
+ if (conditionsForState.size() == 0) {
+ conditionsForState.put(DEFAULT_DEVICE_STATE, null);
+ }
+ return new DeviceStateProviderImpl(context, conditionsForState);
+ }
+
+ // Lock for internal state.
+ private final Object mLock = new Object();
+ private final Context mContext;
+ // List of supported states in ascending order.
+ private final int[] mOrderedStates;
+ // Map of state to a boolean supplier that returns true when all required conditions are met for
+ // the device to be in the state.
+ private final SparseArray<BooleanSupplier> mStateConditions;
@Nullable
+ @GuardedBy("mLock")
private Listener mListener = null;
+ @GuardedBy("mLock")
+ private int mLastReportedState = INVALID_DEVICE_STATE;
+
+ @GuardedBy("mLock")
+ private boolean mIsLidOpen;
+ @GuardedBy("mLock")
+ private final Map<Sensor, SensorEvent> mLatestSensorEvent = new ArrayMap<>();
+
+ private DeviceStateProviderImpl(@NonNull Context context,
+ @NonNull SparseArray<Conditions> conditionsForState) {
+ mContext = context;
+ mOrderedStates = new int[conditionsForState.size()];
+ for (int i = 0; i < conditionsForState.size(); i++) {
+ mOrderedStates[i] = conditionsForState.keyAt(i);
+ }
+
+ // Whether or not this instance should register to receive lid switch notifications from
+ // InputManagerInternal. If there are no device state conditions that are based on the lid
+ // switch there is no need to register for a callback.
+ boolean shouldListenToLidSwitch = false;
+
+ final SensorManager sensorManager = mContext.getSystemService(SensorManager.class);
+ // The set of Sensor(s) that this instance should register to receive SensorEvent(s) from.
+ final ArraySet<Sensor> sensorsToListenTo = new ArraySet<>();
+
+ mStateConditions = new SparseArray<>();
+ for (int i = 0; i < mOrderedStates.length; i++) {
+ int state = mOrderedStates[i];
+ Conditions conditions = conditionsForState.get(state);
+ if (conditions == null) {
+ mStateConditions.put(state, TRUE_BOOLEAN_SUPPLIER);
+ continue;
+ }
+
+ List<BooleanSupplier> suppliers = new ArrayList<>();
+
+ LidSwitchCondition lidSwitchCondition = conditions.getLidSwitch();
+ if (lidSwitchCondition != null) {
+ suppliers.add(new LidSwitchBooleanSupplier(lidSwitchCondition.getOpen()));
+ shouldListenToLidSwitch = true;
+ }
+
+ List<SensorCondition> sensorConditions = conditions.getSensor();
+ for (int j = 0; j < sensorConditions.size(); j++) {
+ SensorCondition sensorCondition = sensorConditions.get(j);
+ final int expectedSensorType = sensorCondition.getType().intValue();
+ final String expectedSensorName = sensorCondition.getName();
+
+ List<Sensor> sensors = sensorManager.getSensorList(expectedSensorType);
+ Sensor foundSensor = null;
+ for (int sensorIndex = 0; sensorIndex < sensors.size(); sensorIndex++) {
+ Sensor sensor = sensors.get(sensorIndex);
+ if (sensor.getName().equals(expectedSensorName)) {
+ foundSensor = sensor;
+ break;
+ }
+ }
+
+ if (foundSensor == null) {
+ throw new IllegalStateException("Failed to find Sensor with type: "
+ + expectedSensorType + " and name: " + expectedSensorName);
+ }
+
+ suppliers.add(new SensorBooleanSupplier(foundSensor, sensorCondition.getValue()));
+ sensorsToListenTo.add(foundSensor);
+ }
+
+ if (suppliers.size() > 1) {
+ mStateConditions.put(state, new AndBooleanSupplier(suppliers));
+ } else if (suppliers.size() > 0) {
+ // No need to wrap with an AND supplier if there is only 1.
+ mStateConditions.put(state, suppliers.get(0));
+ } else {
+ // There are no conditions for this state. Default to always true.
+ mStateConditions.put(state, TRUE_BOOLEAN_SUPPLIER);
+ }
+ }
+
+ if (shouldListenToLidSwitch) {
+ InputManagerInternal inputManager = LocalServices.getService(
+ InputManagerInternal.class);
+ inputManager.registerLidSwitchCallback(this);
+ }
+
+ for (int i = 0; i < sensorsToListenTo.size(); i++) {
+ Sensor sensor = sensorsToListenTo.valueAt(i);
+ sensorManager.registerListener(this, sensor, SensorManager.SENSOR_DELAY_FASTEST);
+ }
+ }
@Override
public void setListener(Listener listener) {
- if (mListener != null) {
- throw new RuntimeException("Provider already has a listener set.");
+ synchronized (mLock) {
+ if (mListener != null) {
+ throw new RuntimeException("Provider already has a listener set.");
+ }
+ mListener = listener;
+ }
+ notifySupportedStatesChanged();
+ notifyDeviceStateChangedIfNeeded();
+ }
+
+ /** Notifies the listener that the set of supported device states has changed. */
+ private void notifySupportedStatesChanged() {
+ int[] supportedStates;
+ synchronized (mLock) {
+ if (mListener == null) {
+ return;
+ }
+
+ supportedStates = Arrays.copyOf(mOrderedStates, mOrderedStates.length);
}
- mListener = listener;
- mListener.onSupportedDeviceStatesChanged(new int[]{ DEFAULT_DEVICE_STATE });
- mListener.onStateChanged(DEFAULT_DEVICE_STATE);
+ mListener.onSupportedDeviceStatesChanged(supportedStates);
+ }
+
+ /** Computes the current device state and notifies the listener of a change, if needed. */
+ void notifyDeviceStateChangedIfNeeded() {
+ int stateToReport = INVALID_DEVICE_STATE;
+ synchronized (mLock) {
+ if (mListener == null) {
+ return;
+ }
+
+ int newState = mOrderedStates[0];
+ for (int i = 1; i < mOrderedStates.length; i++) {
+ int state = mOrderedStates[i];
+ if (mStateConditions.get(state).getAsBoolean()) {
+ newState = state;
+ break;
+ }
+ }
+
+ if (newState != mLastReportedState) {
+ mLastReportedState = newState;
+ stateToReport = newState;
+ }
+ }
+
+ if (stateToReport != INVALID_DEVICE_STATE) {
+ mListener.onStateChanged(stateToReport);
+ }
+ }
+
+ @Override
+ public void notifyLidSwitchChanged(long whenNanos, boolean lidOpen) {
+ synchronized (mLock) {
+ mIsLidOpen = lidOpen;
+ }
+ notifyDeviceStateChangedIfNeeded();
+ }
+
+ @Override
+ public void onSensorChanged(SensorEvent event) {
+ synchronized (mLock) {
+ mLatestSensorEvent.put(event.sensor, event);
+ }
+ notifyDeviceStateChangedIfNeeded();
+ }
+
+ @Override
+ public void onAccuracyChanged(Sensor sensor, int accuracy) {
+ // Do nothing.
+ }
+
+ /**
+ * Implementation of {@link BooleanSupplier} that returns {@code true} if the expected lid
+ * switch open state matches {@link #mIsLidOpen}.
+ */
+ private final class LidSwitchBooleanSupplier implements BooleanSupplier {
+ private final boolean mExpectedOpen;
+
+ LidSwitchBooleanSupplier(boolean expectedOpen) {
+ mExpectedOpen = expectedOpen;
+ }
+
+ @Override
+ public boolean getAsBoolean() {
+ synchronized (mLock) {
+ return mIsLidOpen == mExpectedOpen;
+ }
+ }
+ }
+
+ /**
+ * Implementation of {@link BooleanSupplier} that returns {@code true} if the latest
+ * {@link SensorEvent#values sensor event values} for the specified {@link Sensor} adhere to
+ * the supplied {@link NumericRange ranges}.
+ */
+ private final class SensorBooleanSupplier implements BooleanSupplier {
+ @NonNull
+ private final Sensor mSensor;
+ @NonNull
+ private final List<NumericRange> mExpectedValues;
+
+ SensorBooleanSupplier(@NonNull Sensor sensor, @NonNull List<NumericRange> expectedValues) {
+ mSensor = sensor;
+ mExpectedValues = expectedValues;
+ }
+
+ @Override
+ public boolean getAsBoolean() {
+ synchronized (mLock) {
+ SensorEvent latestEvent = mLatestSensorEvent.get(mSensor);
+ if (latestEvent == null) {
+ // Default to returning false if we have not yet received a sensor event for the
+ // sensor.
+ return false;
+ }
+
+ if (latestEvent.values.length != mExpectedValues.size()) {
+ throw new IllegalStateException("Number of supplied numeric range(s) does not "
+ + "match the number of values in the latest sensor event for sensor: "
+ + mSensor);
+ }
+
+ for (int i = 0; i < latestEvent.values.length; i++) {
+ if (!adheresToRange(latestEvent.values[i], mExpectedValues.get(i))) {
+ return false;
+ }
+ }
+ return true;
+ }
+ }
+
+ /**
+ * Returns {@code true} if the supplied {@code value} adheres to the constraints specified
+ * in {@code range}.
+ */
+ private boolean adheresToRange(float value, @NonNull NumericRange range) {
+ final BigDecimal min = range.getMin_optional();
+ if (min != null) {
+ if (value <= min.floatValue()) {
+ return false;
+ }
+ }
+
+ final BigDecimal minInclusive = range.getMinInclusive_optional();
+ if (minInclusive != null) {
+ if (value < minInclusive.floatValue()) {
+ return false;
+ }
+ }
+
+ final BigDecimal max = range.getMax_optional();
+ if (max != null) {
+ if (value >= max.floatValue()) {
+ return false;
+ }
+ }
+
+ final BigDecimal maxInclusive = range.getMaxInclusive_optional();
+ if (maxInclusive != null) {
+ if (value > maxInclusive.floatValue()) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+ }
+
+ /**
+ * Implementation of {@link BooleanSupplier} whose result is the product of an AND operation
+ * applied to the result of all child suppliers.
+ */
+ private static final class AndBooleanSupplier implements BooleanSupplier {
+ @NonNull
+ List<BooleanSupplier> mBooleanSuppliers;
+
+ AndBooleanSupplier(@NonNull List<BooleanSupplier> booleanSuppliers) {
+ mBooleanSuppliers = booleanSuppliers;
+ }
+
+ @Override
+ public boolean getAsBoolean() {
+ for (int i = 0; i < mBooleanSuppliers.size(); i++) {
+ if (!mBooleanSuppliers.get(i).getAsBoolean()) {
+ return false;
+ }
+ }
+ return true;
+ }
+ }
+
+ /**
+ * Returns the device state configuration file that should be used, or {@code null} if no file
+ * is present on the device.
+ * <p>
+ * Defaults to returning a config file present in the data/ dir at
+ * {@link #DATA_CONFIG_FILE_PATH}, and then falls back to the config file in the vendor/ dir
+ * at {@link #VENDOR_CONFIG_FILE_PATH} if no config file is found in the data/ dir.
+ */
+ @Nullable
+ private static File getConfigurationFile() {
+ final File configFileFromDataDir = Environment.buildPath(Environment.getDataDirectory(),
+ DATA_CONFIG_FILE_PATH, CONFIG_FILE_NAME);
+ if (configFileFromDataDir.exists()) {
+ return configFileFromDataDir;
+ }
+
+ final File configFileFromVendorDir = Environment.buildPath(Environment.getVendorDirectory(),
+ VENDOR_CONFIG_FILE_PATH, CONFIG_FILE_NAME);
+ if (configFileFromVendorDir.exists()) {
+ return configFileFromVendorDir;
+ }
+
+ return null;
+ }
+
+ /**
+ * Tries to parse the provided file into a {@link DeviceStateConfig} object. Returns
+ * {@code null} if the file could not be successfully parsed.
+ */
+ @Nullable
+ private static DeviceStateConfig parseConfig(@NonNull ReadableConfig readableConfig) {
+ try (InputStream in = readableConfig.openRead();
+ InputStream bin = new BufferedInputStream(in)) {
+ return XmlParser.read(bin);
+ } catch (IOException | DatatypeConfigurationException | XmlPullParserException e) {
+ Slog.e(TAG, "Encountered an error while reading device state config", e);
+ }
+ return null;
+ }
+
+ /** Implementation of {@link ReadableConfig} that reads config data from a file. */
+ private static final class ReadableFileConfig implements ReadableConfig {
+ @NonNull
+ private final File mFile;
+
+ private ReadableFileConfig(@NonNull File file) {
+ mFile = file;
+ }
+
+ @Override
+ public InputStream openRead() throws IOException {
+ return new FileInputStream(mFile);
+ }
}
}
diff --git a/services/core/java/com/android/server/power/DisplayPowerRequestMapper.java b/services/core/java/com/android/server/power/DisplayPowerRequestMapper.java
new file mode 100644
index 000000000000..6477552eb550
--- /dev/null
+++ b/services/core/java/com/android/server/power/DisplayPowerRequestMapper.java
@@ -0,0 +1,122 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.power;
+
+import android.hardware.display.DisplayManager;
+import android.hardware.display.DisplayManagerInternal;
+import android.hardware.display.DisplayManagerInternal.DisplayPowerRequest;
+import android.os.Handler;
+import android.util.SparseArray;
+import android.util.SparseIntArray;
+import android.view.Display;
+
+import com.android.internal.annotations.GuardedBy;
+import com.android.server.display.DisplayGroup;
+
+/**
+ * Responsible for creating {@link DisplayPowerRequest}s and associating them with
+ * {@link com.android.server.display.DisplayGroup}s.
+ *
+ * Each {@link com.android.server.display.DisplayGroup} has a single {@link DisplayPowerRequest}
+ * which is used to request power state changes to every display in the group.
+ */
+class DisplayPowerRequestMapper {
+
+ private final Object mLock = new Object();
+
+ /** A mapping from LogicalDisplay Id to DisplayGroup Id. */
+ @GuardedBy("mLock")
+ private final SparseIntArray mDisplayGroupIds = new SparseIntArray();
+
+ /** A mapping from DisplayGroup Id to DisplayPowerRequest. */
+ @GuardedBy("mLock")
+ private final SparseArray<DisplayPowerRequest> mDisplayPowerRequests = new SparseArray<>();
+
+ private final DisplayManagerInternal mDisplayManagerInternal;
+
+ private final DisplayManager.DisplayListener mDisplayListener =
+ new DisplayManager.DisplayListener() {
+
+ @Override
+ public void onDisplayAdded(int displayId) {
+ synchronized (mLock) {
+ if (mDisplayGroupIds.indexOfKey(displayId) >= 0) {
+ return;
+ }
+ final int displayGroupId = mDisplayManagerInternal.getDisplayGroupId(
+ displayId);
+ if (!mDisplayPowerRequests.contains(displayGroupId)) {
+ // A new DisplayGroup was created; create a new DisplayPowerRequest.
+ mDisplayPowerRequests.append(displayGroupId, new DisplayPowerRequest());
+ }
+ mDisplayGroupIds.append(displayId, displayGroupId);
+ }
+ }
+
+ @Override
+ public void onDisplayRemoved(int displayId) {
+ synchronized (mLock) {
+ final int index = mDisplayGroupIds.indexOfKey(displayId);
+ if (index < 0) {
+ return;
+ }
+ final int displayGroupId = mDisplayGroupIds.valueAt(index);
+ mDisplayGroupIds.removeAt(index);
+
+ if (mDisplayGroupIds.indexOfValue(displayGroupId) < 0) {
+ // The DisplayGroup no longer exists; delete the DisplayPowerRequest.
+ mDisplayPowerRequests.delete(displayGroupId);
+ }
+ }
+ }
+
+ @Override
+ public void onDisplayChanged(int displayId) {
+ synchronized (mLock) {
+ final int newDisplayGroupId = mDisplayManagerInternal.getDisplayGroupId(
+ displayId);
+ final int oldDisplayGroupId = mDisplayGroupIds.get(displayId);
+
+ if (!mDisplayPowerRequests.contains(newDisplayGroupId)) {
+ // A new DisplayGroup was created; create a new DisplayPowerRequest.
+ mDisplayPowerRequests.append(newDisplayGroupId,
+ new DisplayPowerRequest());
+ }
+ mDisplayGroupIds.put(displayId, newDisplayGroupId);
+
+ if (mDisplayGroupIds.indexOfValue(oldDisplayGroupId) < 0) {
+ // The DisplayGroup no longer exists; delete the DisplayPowerRequest.
+ mDisplayPowerRequests.delete(oldDisplayGroupId);
+ }
+ }
+ }
+ };
+
+ DisplayPowerRequestMapper(DisplayManager displayManager,
+ DisplayManagerInternal displayManagerInternal, Handler handler) {
+ mDisplayManagerInternal = displayManagerInternal;
+ displayManager.registerDisplayListener(mDisplayListener, handler);
+ mDisplayPowerRequests.append(DisplayGroup.DEFAULT, new DisplayPowerRequest());
+ mDisplayGroupIds.append(Display.DEFAULT_DISPLAY, DisplayGroup.DEFAULT);
+ }
+
+ DisplayPowerRequest get(int displayId) {
+ synchronized (mLock) {
+ return mDisplayPowerRequests.get(mDisplayGroupIds.get(displayId));
+ }
+ }
+}
diff --git a/services/core/java/com/android/server/power/PowerManagerService.java b/services/core/java/com/android/server/power/PowerManagerService.java
index ccd659dcf5a4..955e1cdfeaaa 100644
--- a/services/core/java/com/android/server/power/PowerManagerService.java
+++ b/services/core/java/com/android/server/power/PowerManagerService.java
@@ -42,6 +42,7 @@ import android.database.ContentObserver;
import android.hardware.SensorManager;
import android.hardware.SystemSensorManager;
import android.hardware.display.AmbientDisplayConfiguration;
+import android.hardware.display.DisplayManager;
import android.hardware.display.DisplayManagerInternal;
import android.hardware.display.DisplayManagerInternal.DisplayPowerRequest;
import android.hardware.power.Boost;
@@ -348,9 +349,9 @@ public final class PowerManagerService extends SystemService
// A bitfield that summarizes the effect of the user activity timer.
private int mUserActivitySummary;
- // The desired display power state. The actual state may lag behind the
+ // Manages the desired power state of displays. The actual state may lag behind the
// requested because it is updated asynchronously by the display power controller.
- private final DisplayPowerRequest mDisplayPowerRequest = new DisplayPowerRequest();
+ private DisplayPowerRequestMapper mDisplayPowerRequestMapper;
// True if the display power state has been fully applied, which means the display
// is actually on or actually off or whatever was requested.
@@ -1054,6 +1055,8 @@ public final class PowerManagerService extends SystemService
mPolicy = getLocalService(WindowManagerPolicy.class);
mBatteryManagerInternal = getLocalService(BatteryManagerInternal.class);
mAttentionDetector.systemReady(mContext);
+ mDisplayPowerRequestMapper = new DisplayPowerRequestMapper(mContext.getSystemService(
+ DisplayManager.class), mDisplayManagerInternal, mHandler);
SensorManager sensorManager = new SystemSensorManager(mContext, mHandler.getLooper());
@@ -2296,10 +2299,12 @@ public final class PowerManagerService extends SystemService
&& mLastUserActivityTimeNoChangeLights >= mLastWakeTime) {
nextTimeout = mLastUserActivityTimeNoChangeLights + screenOffTimeout;
if (now < nextTimeout) {
- if (mDisplayPowerRequest.policy == DisplayPowerRequest.POLICY_BRIGHT
- || mDisplayPowerRequest.policy == DisplayPowerRequest.POLICY_VR) {
+ final DisplayPowerRequest displayPowerRequest =
+ mDisplayPowerRequestMapper.get(Display.DEFAULT_DISPLAY);
+ if (displayPowerRequest.policy == DisplayPowerRequest.POLICY_BRIGHT
+ || displayPowerRequest.policy == DisplayPowerRequest.POLICY_VR) {
mUserActivitySummary = USER_ACTIVITY_SCREEN_BRIGHT;
- } else if (mDisplayPowerRequest.policy == DisplayPowerRequest.POLICY_DIM) {
+ } else if (displayPowerRequest.policy == DisplayPowerRequest.POLICY_DIM) {
mUserActivitySummary = USER_ACTIVITY_SCREEN_DIM;
}
}
@@ -2771,11 +2776,13 @@ public final class PowerManagerService extends SystemService
* Returns true if the device is allowed to dream in its current state.
*/
private boolean canDreamLocked() {
+ final DisplayPowerRequest displayPowerRequest =
+ mDisplayPowerRequestMapper.get(Display.DEFAULT_DISPLAY);
if (getWakefulnessLocked() != WAKEFULNESS_DREAMING
|| !mDreamsSupportedConfig
|| !mDreamsEnabledSetting
- || !mDisplayPowerRequest.isBrightOrDim()
- || mDisplayPowerRequest.isVr()
+ || !displayPowerRequest.isBrightOrDim()
+ || displayPowerRequest.isVr()
|| (mUserActivitySummary & (USER_ACTIVITY_SCREEN_BRIGHT
| USER_ACTIVITY_SCREEN_DIM | USER_ACTIVITY_SCREEN_DREAM)) == 0
|| !mBootCompleted) {
@@ -2826,7 +2833,9 @@ public final class PowerManagerService extends SystemService
sQuiescent = false;
}
- mDisplayPowerRequest.policy = getDesiredScreenPolicyLocked();
+ final DisplayPowerRequest displayPowerRequest = mDisplayPowerRequestMapper.get(
+ Display.DEFAULT_DISPLAY);
+ displayPowerRequest.policy = getDesiredScreenPolicyLocked();
// Determine appropriate screen brightness and auto-brightness adjustments.
final boolean autoBrightness;
@@ -2846,39 +2855,39 @@ public final class PowerManagerService extends SystemService
}
// Update display power request.
- mDisplayPowerRequest.screenBrightnessOverride = screenBrightnessOverride;
- mDisplayPowerRequest.useAutoBrightness = autoBrightness;
- mDisplayPowerRequest.useProximitySensor = shouldUseProximitySensorLocked();
- mDisplayPowerRequest.boostScreenBrightness = shouldBoostScreenBrightness();
+ displayPowerRequest.screenBrightnessOverride = screenBrightnessOverride;
+ displayPowerRequest.useAutoBrightness = autoBrightness;
+ displayPowerRequest.useProximitySensor = shouldUseProximitySensorLocked();
+ displayPowerRequest.boostScreenBrightness = shouldBoostScreenBrightness();
- updatePowerRequestFromBatterySaverPolicy(mDisplayPowerRequest);
+ updatePowerRequestFromBatterySaverPolicy(displayPowerRequest);
- if (mDisplayPowerRequest.policy == DisplayPowerRequest.POLICY_DOZE) {
- mDisplayPowerRequest.dozeScreenState = mDozeScreenStateOverrideFromDreamManager;
+ if (displayPowerRequest.policy == DisplayPowerRequest.POLICY_DOZE) {
+ displayPowerRequest.dozeScreenState = mDozeScreenStateOverrideFromDreamManager;
if ((mWakeLockSummary & WAKE_LOCK_DRAW) != 0
&& !mDrawWakeLockOverrideFromSidekick) {
- if (mDisplayPowerRequest.dozeScreenState == Display.STATE_DOZE_SUSPEND) {
- mDisplayPowerRequest.dozeScreenState = Display.STATE_DOZE;
+ if (displayPowerRequest.dozeScreenState == Display.STATE_DOZE_SUSPEND) {
+ displayPowerRequest.dozeScreenState = Display.STATE_DOZE;
}
- if (mDisplayPowerRequest.dozeScreenState == Display.STATE_ON_SUSPEND) {
- mDisplayPowerRequest.dozeScreenState = Display.STATE_ON;
+ if (displayPowerRequest.dozeScreenState == Display.STATE_ON_SUSPEND) {
+ displayPowerRequest.dozeScreenState = Display.STATE_ON;
}
}
- mDisplayPowerRequest.dozeScreenBrightness =
+ displayPowerRequest.dozeScreenBrightness =
mDozeScreenBrightnessOverrideFromDreamManagerFloat;
} else {
- mDisplayPowerRequest.dozeScreenState = Display.STATE_UNKNOWN;
- mDisplayPowerRequest.dozeScreenBrightness =
+ displayPowerRequest.dozeScreenState = Display.STATE_UNKNOWN;
+ displayPowerRequest.dozeScreenBrightness =
PowerManager.BRIGHTNESS_INVALID_FLOAT;
}
- mDisplayReady = mDisplayManagerInternal.requestPowerState(mDisplayPowerRequest,
+ mDisplayReady = mDisplayManagerInternal.requestPowerState(displayPowerRequest,
mRequestWaitForNegativeProximity);
mRequestWaitForNegativeProximity = false;
if (DEBUG_SPEW) {
Slog.d(TAG, "updateDisplayPowerStateLocked: mDisplayReady=" + mDisplayReady
- + ", policy=" + mDisplayPowerRequest.policy
+ + ", policy=" + displayPowerRequest.policy
+ ", mWakefulness=" + getWakefulnessLocked()
+ ", mWakeLockSummary=0x" + Integer.toHexString(mWakeLockSummary)
+ ", mUserActivitySummary=0x" + Integer.toHexString(mUserActivitySummary)
@@ -3049,7 +3058,9 @@ public final class PowerManagerService extends SystemService
final boolean needWakeLockSuspendBlocker = ((mWakeLockSummary & WAKE_LOCK_CPU) != 0);
final boolean needDisplaySuspendBlocker = needDisplaySuspendBlockerLocked();
final boolean autoSuspend = !needDisplaySuspendBlocker;
- final boolean interactive = mDisplayPowerRequest.isBrightOrDim();
+ final DisplayPowerRequest displayPowerRequest = mDisplayPowerRequestMapper.get(
+ Display.DEFAULT_DISPLAY);
+ final boolean interactive = displayPowerRequest.isBrightOrDim();
// Disable auto-suspend if needed.
// FIXME We should consider just leaving auto-suspend enabled forever since
@@ -3108,19 +3119,21 @@ public final class PowerManagerService extends SystemService
if (!mDisplayReady) {
return true;
}
- if (mDisplayPowerRequest.isBrightOrDim()) {
+ final DisplayPowerRequest displayPowerRequest = mDisplayPowerRequestMapper.get(
+ Display.DEFAULT_DISPLAY);
+ if (displayPowerRequest.isBrightOrDim()) {
// If we asked for the screen to be on but it is off due to the proximity
// sensor then we may suspend but only if the configuration allows it.
// On some hardware it may not be safe to suspend because the proximity
// sensor may not be correctly configured as a wake-up source.
- if (!mDisplayPowerRequest.useProximitySensor || !mProximityPositive
+ if (!displayPowerRequest.useProximitySensor || !mProximityPositive
|| !mSuspendWhenScreenOffDueToProximityConfig) {
return true;
}
}
- if (mDisplayPowerRequest.policy == DisplayPowerRequest.POLICY_DOZE
- && mDisplayPowerRequest.dozeScreenState == Display.STATE_ON) {
+ if (displayPowerRequest.policy == DisplayPowerRequest.POLICY_DOZE
+ && displayPowerRequest.dozeScreenState == Display.STATE_ON) {
// Although we are in DOZE and would normally allow the device to suspend,
// the doze service has explicitly requested the display to remain in the ON
// state which means we should hold the display suspend blocker.
@@ -5575,7 +5588,10 @@ public final class PowerManagerService extends SystemService
// DisplayPowerController only reports proximity positive (near) if it's
// positive and the proximity wasn't already being ignored. So it reliably
// also tells us that we're not already ignoring the proximity sensor.
- if (mDisplayPowerRequest.useProximitySensor && mProximityPositive) {
+
+ final DisplayPowerRequest displayPowerRequest =
+ mDisplayPowerRequestMapper.get(Display.DEFAULT_DISPLAY);
+ if (displayPowerRequest.useProximitySensor && mProximityPositive) {
mDisplayManagerInternal.ignoreProximitySensorUntilChanged();
return true;
}
diff --git a/services/core/java/com/android/server/vcn/UnderlyingNetworkTracker.java b/services/core/java/com/android/server/vcn/UnderlyingNetworkTracker.java
new file mode 100644
index 000000000000..e1feb5aab869
--- /dev/null
+++ b/services/core/java/com/android/server/vcn/UnderlyingNetworkTracker.java
@@ -0,0 +1,100 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.vcn;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.net.LinkProperties;
+import android.net.Network;
+import android.net.NetworkCapabilities;
+import android.os.Handler;
+import android.os.ParcelUuid;
+
+import java.util.Objects;
+
+/**
+ * Tracks a set of Networks underpinning a VcnGatewayConnection.
+ *
+ * <p>A single UnderlyingNetworkTracker is built to serve a SINGLE VCN Gateway Connection, and MUST
+ * be torn down with the VcnGatewayConnection in order to ensure underlying networks are allowed to
+ * be reaped.
+ *
+ * @hide
+ */
+public class UnderlyingNetworkTracker extends Handler {
+ @NonNull private static final String TAG = UnderlyingNetworkTracker.class.getSimpleName();
+
+ @NonNull private final VcnContext mVcnContext;
+ @NonNull private final ParcelUuid mSubscriptionGroup;
+ @NonNull private final UnderlyingNetworkTrackerCallback mCb;
+ @NonNull private final Dependencies mDeps;
+
+ public UnderlyingNetworkTracker(
+ @NonNull VcnContext vcnContext,
+ @NonNull ParcelUuid subscriptionGroup,
+ @NonNull UnderlyingNetworkTrackerCallback cb) {
+ this(vcnContext, subscriptionGroup, cb, new Dependencies());
+ }
+
+ private UnderlyingNetworkTracker(
+ @NonNull VcnContext vcnContext,
+ @NonNull ParcelUuid subscriptionGroup,
+ @NonNull UnderlyingNetworkTrackerCallback cb,
+ @NonNull Dependencies deps) {
+ super(Objects.requireNonNull(vcnContext, "Missing vcnContext").getLooper());
+ mVcnContext = vcnContext;
+ mSubscriptionGroup = Objects.requireNonNull(subscriptionGroup, "Missing subscriptionGroup");
+ mCb = Objects.requireNonNull(cb, "Missing cb");
+ mDeps = Objects.requireNonNull(deps, "Missing deps");
+ }
+
+ /** Tears down this Tracker, and releases all underlying network requests. */
+ public void teardown() {}
+
+ /** An record of a single underlying network, caching relevant fields. */
+ public static class UnderlyingNetworkRecord {
+ @NonNull public final Network network;
+ @NonNull public final NetworkCapabilities networkCapabilities;
+ @NonNull public final LinkProperties linkProperties;
+ public final boolean blocked;
+
+ private UnderlyingNetworkRecord(
+ @NonNull Network network,
+ @NonNull NetworkCapabilities networkCapabilities,
+ @NonNull LinkProperties linkProperties,
+ boolean blocked) {
+ this.network = network;
+ this.networkCapabilities = networkCapabilities;
+ this.linkProperties = linkProperties;
+ this.blocked = blocked;
+ }
+ }
+
+ /** Callbacks for being notified of the changes in, or to the selected underlying network. */
+ public interface UnderlyingNetworkTrackerCallback {
+ /**
+ * Fired when a new underlying network is selected, or properties have changed.
+ *
+ * <p>This callback does NOT signal a mobility event.
+ *
+ * @param underlying The details of the new underlying network
+ */
+ void onSelectedUnderlyingNetworkChanged(@Nullable UnderlyingNetworkRecord underlying);
+ }
+
+ private static class Dependencies {}
+}
diff --git a/services/core/java/com/android/server/vcn/Vcn.java b/services/core/java/com/android/server/vcn/Vcn.java
new file mode 100644
index 000000000000..d51d16b1b4df
--- /dev/null
+++ b/services/core/java/com/android/server/vcn/Vcn.java
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.vcn;
+
+import android.annotation.NonNull;
+import android.net.NetworkRequest;
+import android.net.vcn.VcnConfig;
+import android.os.Handler;
+import android.os.Message;
+import android.os.ParcelUuid;
+
+import java.util.Objects;
+
+/**
+ * Represents an single instance of a VCN.
+ *
+ * <p>Each Vcn instance manages all tunnels for a given subscription group, including per-capability
+ * networks, network selection, and multi-homing.
+ *
+ * @hide
+ */
+public class Vcn extends Handler {
+ private static final String TAG = Vcn.class.getSimpleName();
+
+ @NonNull private final VcnContext mVcnContext;
+ @NonNull private final ParcelUuid mSubscriptionGroup;
+ @NonNull private final Dependencies mDeps;
+
+ @NonNull private VcnConfig mConfig;
+
+ public Vcn(
+ @NonNull VcnContext vcnContext,
+ @NonNull ParcelUuid subscriptionGroup,
+ @NonNull VcnConfig config) {
+ this(vcnContext, subscriptionGroup, config, new Dependencies());
+ }
+
+ private Vcn(
+ @NonNull VcnContext vcnContext,
+ @NonNull ParcelUuid subscriptionGroup,
+ @NonNull VcnConfig config,
+ @NonNull Dependencies deps) {
+ super(Objects.requireNonNull(vcnContext, "Missing vcnContext").getLooper());
+ mVcnContext = vcnContext;
+ mSubscriptionGroup = Objects.requireNonNull(subscriptionGroup, "Missing subscriptionGroup");
+ mDeps = Objects.requireNonNull(deps, "Missing deps");
+
+ mConfig = Objects.requireNonNull(config, "Missing config");
+ }
+
+ /** Asynchronously updates the configuration and triggers a re-evaluation of Networks */
+ public void updateConfig(@NonNull VcnConfig config) {
+ Objects.requireNonNull(config, "Missing config");
+ // TODO: Proxy to handler, and make config there.
+ }
+
+ /** Asynchronously tears down this Vcn instance, along with all tunnels and Networks */
+ public void teardown() {
+ // TODO: Proxy to handler, and teardown there.
+ }
+
+ /** Notifies this Vcn instance of a new NetworkRequest */
+ public void onNetworkRequested(@NonNull NetworkRequest request, int score, int providerId) {
+ Objects.requireNonNull(request, "Missing request");
+
+ // TODO: Proxy to handler, and handle there.
+ }
+
+ @Override
+ public void handleMessage(@NonNull Message msg) {
+ // TODO: Do something
+ }
+
+ /** Retrieves the network score for a VCN Network */
+ private int getNetworkScore() {
+ // TODO: STOPSHIP (b/173549607): Make this use new NetworkSelection, or some magic "max in
+ // subGrp" value
+ return 52;
+ }
+
+ private static class Dependencies {}
+}
diff --git a/services/core/java/com/android/server/vcn/VcnContext.java b/services/core/java/com/android/server/vcn/VcnContext.java
new file mode 100644
index 000000000000..8ab52931cae3
--- /dev/null
+++ b/services/core/java/com/android/server/vcn/VcnContext.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.vcn;
+
+import android.annotation.NonNull;
+import android.content.Context;
+import android.os.Looper;
+
+import com.android.server.VcnManagementService.VcnNetworkProvider;
+
+import java.util.Objects;
+
+/**
+ * A simple class to pass around context information.
+ *
+ * @hide
+ */
+public class VcnContext {
+ @NonNull private final Context mContext;
+ @NonNull private final Looper mLooper;
+ @NonNull private final VcnNetworkProvider mVcnNetworkProvider;
+
+ public VcnContext(
+ @NonNull Context context,
+ @NonNull Looper looper,
+ @NonNull VcnNetworkProvider vcnNetworkProvider) {
+ mContext = Objects.requireNonNull(context, "Missing context");
+ mLooper = Objects.requireNonNull(looper, "Missing looper");
+ mVcnNetworkProvider = Objects.requireNonNull(vcnNetworkProvider, "Missing networkProvider");
+ }
+
+ @NonNull
+ public Context getContext() {
+ return mContext;
+ }
+
+ @NonNull
+ public Looper getLooper() {
+ return mLooper;
+ }
+
+ @NonNull
+ public VcnNetworkProvider getVcnNetworkProvider() {
+ return mVcnNetworkProvider;
+ }
+}
diff --git a/services/core/java/com/android/server/vcn/VcnGatewayConnection.java b/services/core/java/com/android/server/vcn/VcnGatewayConnection.java
new file mode 100644
index 000000000000..49c9b3297c77
--- /dev/null
+++ b/services/core/java/com/android/server/vcn/VcnGatewayConnection.java
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.vcn;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.net.vcn.VcnGatewayConnectionConfig;
+import android.os.Handler;
+import android.os.ParcelUuid;
+
+import com.android.server.vcn.UnderlyingNetworkTracker.UnderlyingNetworkRecord;
+import com.android.server.vcn.UnderlyingNetworkTracker.UnderlyingNetworkTrackerCallback;
+
+import java.util.Objects;
+
+/**
+ * A single VCN Gateway Connection, providing a single public-facing VCN network.
+ *
+ * <p>This class handles mobility events, performs retries, and tracks safe-mode conditions.
+ *
+ * @hide
+ */
+public class VcnGatewayConnection extends Handler implements UnderlyingNetworkTrackerCallback {
+ private static final String TAG = VcnGatewayConnection.class.getSimpleName();
+
+ @NonNull private final VcnContext mVcnContext;
+ @NonNull private final ParcelUuid mSubscriptionGroup;
+ @NonNull private final UnderlyingNetworkTracker mUnderlyingNetworkTracker;
+ @NonNull private final VcnGatewayConnectionConfig mConnectionConfig;
+ @NonNull private final Dependencies mDeps;
+
+ public VcnGatewayConnection(
+ @NonNull VcnContext vcnContext,
+ @NonNull ParcelUuid subscriptionGroup,
+ @NonNull VcnGatewayConnectionConfig connectionConfig) {
+ this(vcnContext, subscriptionGroup, connectionConfig, new Dependencies());
+ }
+
+ private VcnGatewayConnection(
+ @NonNull VcnContext vcnContext,
+ @NonNull ParcelUuid subscriptionGroup,
+ @NonNull VcnGatewayConnectionConfig connectionConfig,
+ @NonNull Dependencies deps) {
+ super(Objects.requireNonNull(vcnContext, "Missing vcnContext").getLooper());
+ mVcnContext = vcnContext;
+ mSubscriptionGroup = Objects.requireNonNull(subscriptionGroup, "Missing subscriptionGroup");
+ mConnectionConfig = Objects.requireNonNull(connectionConfig, "Missing connectionConfig");
+ mDeps = Objects.requireNonNull(deps, "Missing deps");
+
+ mUnderlyingNetworkTracker =
+ mDeps.newUnderlyingNetworkTracker(mVcnContext, subscriptionGroup, this);
+ }
+
+ /** Tears down this GatewayConnection, and any resources used */
+ public void teardown() {
+ mUnderlyingNetworkTracker.teardown();
+ }
+
+ private static class Dependencies {
+ public UnderlyingNetworkTracker newUnderlyingNetworkTracker(
+ VcnContext vcnContext,
+ ParcelUuid subscriptionGroup,
+ UnderlyingNetworkTrackerCallback callback) {
+ return new UnderlyingNetworkTracker(vcnContext, subscriptionGroup, callback);
+ }
+ }
+
+ @Override
+ public void onSelectedUnderlyingNetworkChanged(@Nullable UnderlyingNetworkRecord underlying) {}
+}
diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java
index 8cc02e58b30f..c2016decdbe9 100644
--- a/services/core/java/com/android/server/wm/ActivityRecord.java
+++ b/services/core/java/com/android/server/wm/ActivityRecord.java
@@ -1558,10 +1558,6 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
}
}
- // Application tokens start out hidden.
- setVisible(false);
- mVisibleRequested = false;
-
ColorDisplayService.ColorDisplayServiceInternal cds = LocalServices.getService(
ColorDisplayService.ColorDisplayServiceInternal.class);
cds.attachColorTransformController(packageName, mUserId,
@@ -3507,7 +3503,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
}
if (fromActivity.isVisible()) {
setVisible(true);
- mVisibleRequested = true;
+ setVisibleRequested(true);
mVisibleSetFromTransferredStartingWindow = true;
}
setClientVisible(fromActivity.mClientVisible);
@@ -4123,11 +4119,28 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
void setVisible(boolean visible) {
if (visible != mVisible) {
mVisible = visible;
+ if (app != null) {
+ mTaskSupervisor.onProcessActivityStateChanged(app, false /* forceBatch */);
+ }
scheduleAnimation();
}
}
/**
+ * This is the only place that writes {@link #mVisibleRequested} (except unit test). The caller
+ * outside of this class should use {@link #setVisibility}.
+ */
+ private void setVisibleRequested(boolean visible) {
+ if (visible == mVisibleRequested) {
+ return;
+ }
+ mVisibleRequested = visible;
+ if (app != null) {
+ mTaskSupervisor.onProcessActivityStateChanged(app, false /* forceBatch */);
+ }
+ }
+
+ /**
* Set visibility on this {@link ActivityRecord}
*
* <p class="note"><strong>Note: </strong>This function might not update the visibility of
@@ -4190,7 +4203,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
displayContent.mOpeningApps.remove(this);
displayContent.mClosingApps.remove(this);
waitingToShow = false;
- mVisibleRequested = visible;
+ setVisibleRequested(visible);
mLastDeferHidingClient = deferHidingClient;
if (!visible) {
@@ -4332,7 +4345,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
ANIMATION_TYPE_APP_TRANSITION));
}
setVisible(visible);
- mVisibleRequested = visible;
+ setVisibleRequested(visible);
if (!visible) {
stopFreezingScreen(true, true);
} else {
@@ -4520,7 +4533,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
detachChildren();
}
if (app != null) {
- app.computeProcessActivityState();
+ mTaskSupervisor.onProcessActivityStateChanged(app, false /* forceBatch */);
}
switch (state) {
@@ -6395,13 +6408,10 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
// The app is just becoming visible, and the parent Task has updated with the
// orientation request. Update the size compat mode.
updateSizeCompatMode();
- if (task.isOrganized()) {
- // WM Shell can override WM Core positioning (e.g. for letterboxing) so ensure
- // that WM Shell is called when an activity becomes visible. Without this, WM Core
- // will handle positioning instead of WM Shell when an app is reopened.
- mAtmService.mTaskOrganizerController.dispatchTaskInfoChanged(
- task, /* force= */ true);
- }
+ // WM Shell can override WM Core positioning (e.g. for letterboxing) so ensure
+ // that WM Shell is called when an activity becomes visible. Without this, WM Core
+ // will handle positioning instead of WM Shell when an app is reopened.
+ task.dispatchTaskInfoChangedIfNeeded(/* force= */ true);
}
}
diff --git a/services/core/java/com/android/server/wm/ActivityStarter.java b/services/core/java/com/android/server/wm/ActivityStarter.java
index 5208fd5dac3a..acee7b26725e 100644
--- a/services/core/java/com/android/server/wm/ActivityStarter.java
+++ b/services/core/java/com/android/server/wm/ActivityStarter.java
@@ -1281,6 +1281,15 @@ class ActivityStarter {
return false;
}
+ // IME should always be allowed to start activity, like IME settings.
+ final WindowState imeWindow = mRootWindowContainer.getCurrentInputMethodWindow();
+ if (imeWindow != null && callingAppId == imeWindow.mOwnerUid) {
+ if (DEBUG_ACTIVITY_STARTS) {
+ Slog.d(TAG, "Activity start allowed for active ime (" + callingUid + ")");
+ }
+ return false;
+ }
+
// App switching will be allowed if BAL app switching flag is not enabled, or if
// its app switching rule allows it.
// This is used to block background activity launch even if the app is still
@@ -1288,9 +1297,8 @@ class ActivityStarter {
final boolean appSwitchAllowed = mService.getBalAppSwitchesAllowed();
// don't abort if the callingUid has a visible window or is a persistent system process
- final int callingUidProcState = mService.getUidState(callingUid);
- final boolean callingUidHasAnyVisibleWindow =
- mService.mWindowManager.mRoot.isAnyNonToastWindowVisibleForUid(callingUid);
+ final int callingUidProcState = mService.mActiveUids.getUidState(callingUid);
+ final boolean callingUidHasAnyVisibleWindow = mService.hasActiveVisibleWindow(callingUid);
final boolean isCallingUidForeground = callingUidHasAnyVisibleWindow
|| callingUidProcState == ActivityManager.PROCESS_STATE_TOP
|| callingUidProcState == ActivityManager.PROCESS_STATE_BOUND_TOP;
@@ -1308,10 +1316,10 @@ class ActivityStarter {
// take realCallingUid into consideration
final int realCallingUidProcState = (callingUid == realCallingUid)
? callingUidProcState
- : mService.getUidState(realCallingUid);
+ : mService.mActiveUids.getUidState(realCallingUid);
final boolean realCallingUidHasAnyVisibleWindow = (callingUid == realCallingUid)
? callingUidHasAnyVisibleWindow
- : mService.mWindowManager.mRoot.isAnyNonToastWindowVisibleForUid(realCallingUid);
+ : mService.hasActiveVisibleWindow(realCallingUid);
final boolean isRealCallingUidForeground = (callingUid == realCallingUid)
? isCallingUidForeground
: realCallingUidHasAnyVisibleWindow
diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java b/services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java
index f649a2f9f5a6..a5df2a604808 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java
@@ -514,7 +514,6 @@ public abstract class ActivityTaskManagerInternal {
public abstract void onUidActive(int uid, int procState);
public abstract void onUidInactive(int uid);
- public abstract void onActiveUidsCleared();
public abstract void onUidProcStateChanged(int uid, int procState);
public abstract void onUidAddedToPendingTempAllowlist(int uid, String tag);
diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
index e4c607dd8cdd..27faf13e2999 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
@@ -390,7 +390,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
private UserManagerService mUserManager;
private AppOpsManager mAppOpsManager;
/** All active uids in the system. */
- private final MirrorActiveUids mActiveUids = new MirrorActiveUids();
+ final MirrorActiveUids mActiveUids = new MirrorActiveUids();
private final SparseArray<String> mPendingTempAllowlist = new SparseArray<>();
/** All processes currently running that might have a window organized by name. */
final ProcessMap<WindowProcessController> mProcessNames = new ProcessMap<>();
@@ -3646,7 +3646,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
*/
private static int checkCallingPermission(String permission) {
return checkPermission(
- permission, Binder.getCallingPid(), UserHandle.getAppId(Binder.getCallingUid()));
+ permission, Binder.getCallingPid(), Binder.getCallingUid());
}
/** This can be called with or without the global lock held. */
@@ -4956,6 +4956,8 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
printedAnything = true;
mTaskSupervisor.dump(pw, " ");
mTaskOrganizerController.dump(pw, " ");
+ mVisibleActivityProcessTracker.dump(pw, " ");
+ mActiveUids.dump(pw, " ");
}
if (!printedAnything) {
@@ -5986,13 +5988,12 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
return null;
}
- int getUidState(int uid) {
- return mActiveUids.getUidState(uid);
- }
-
- boolean isUidForeground(int uid) {
- // A uid is considered to be foreground if it has a visible non-toast window.
- return mWindowManager.mRoot.isAnyNonToastWindowVisibleForUid(uid);
+ /** A uid is considered to be foreground if it has a visible non-toast window. */
+ boolean hasActiveVisibleWindow(int uid) {
+ if (mVisibleActivityProcessTracker.hasVisibleActivity(uid)) {
+ return true;
+ }
+ return mActiveUids.hasNonAppVisibleWindow(uid);
}
boolean isDeviceOwner(int uid) {
@@ -7283,12 +7284,6 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
@HotPath(caller = HotPath.OOM_ADJUSTMENT)
@Override
- public void onActiveUidsCleared() {
- mActiveUids.onActiveUidsCleared();
- }
-
- @HotPath(caller = HotPath.OOM_ADJUSTMENT)
- @Override
public void onUidProcStateChanged(int uid, int procState) {
mActiveUids.onUidProcStateChanged(uid, procState);
}
@@ -7432,9 +7427,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
@Override
public boolean isUidForeground(int uid) {
- synchronized (mGlobalLock) {
- return ActivityTaskManagerService.this.isUidForeground(uid);
- }
+ return ActivityTaskManagerService.this.hasActiveVisibleWindow(uid);
}
@Override
diff --git a/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java b/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java
index 01d77d5b6cc8..37f04cec071b 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java
@@ -254,6 +254,12 @@ public class ActivityTaskSupervisor implements RecentTasks.Callbacks {
private LaunchParamsController mLaunchParamsController;
/**
+ * The processes with changed states that should eventually call
+ * {@link WindowProcessController#computeProcessActivityState}.
+ */
+ private final ArrayList<WindowProcessController> mActivityStateChangedProcs = new ArrayList<>();
+
+ /**
* Maps the task identifier that activities are currently being started in to the userId of the
* task. Each time a new task is created, the entry for the userId of the task is incremented
*/
@@ -2310,6 +2316,9 @@ public class ActivityTaskSupervisor implements RecentTasks.Callbacks {
/** Ends a batch of visibility updates. */
void endActivityVisibilityUpdate() {
mVisibilityTransactionDepth--;
+ if (mVisibilityTransactionDepth == 0) {
+ computeProcessActivityStateBatch();
+ }
}
/** Returns {@code true} if the caller is on the path to update visibility. */
@@ -2318,6 +2327,34 @@ public class ActivityTaskSupervisor implements RecentTasks.Callbacks {
}
/**
+ * Called when the state or visibility of an attached activity is changed.
+ *
+ * @param wpc The process who owns the activity.
+ * @param forceBatch Whether to put the changed record to a pending list. If the caller is not
+ * in the path of visibility update ({@link #inActivityVisibilityUpdate}), it
+ * must call {@link #computeProcessActivityStateBatch} manually.
+ */
+ void onProcessActivityStateChanged(WindowProcessController wpc, boolean forceBatch) {
+ if (forceBatch || inActivityVisibilityUpdate()) {
+ if (!mActivityStateChangedProcs.contains(wpc)) {
+ mActivityStateChangedProcs.add(wpc);
+ }
+ return;
+ }
+ wpc.computeProcessActivityState();
+ }
+
+ void computeProcessActivityStateBatch() {
+ if (mActivityStateChangedProcs.isEmpty()) {
+ return;
+ }
+ for (int i = mActivityStateChangedProcs.size() - 1; i >= 0; i--) {
+ mActivityStateChangedProcs.get(i).computeProcessActivityState();
+ }
+ mActivityStateChangedProcs.clear();
+ }
+
+ /**
* Begin deferring resume to avoid duplicate resumes in one pass.
*/
void beginDeferResume() {
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index 097f4ed97e15..4133ea2b2a7b 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -5378,20 +5378,6 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
forAllTasks((t) -> { t.getRootTask().removeChild(t, "removeAllTasks"); });
}
- /**
- * Similar to {@link RootWindowContainer#isAnyNonToastWindowVisibleForUid(int)}, but
- * used for pid.
- */
- boolean isAnyNonToastWindowVisibleForPid(int pid) {
- final PooledPredicate p = PooledLambda.obtainPredicate(
- WindowState::isNonToastWindowVisibleForPid,
- PooledLambda.__(WindowState.class), pid);
-
- final WindowState w = getWindow(p);
- p.recycle();
- return w != null;
- }
-
Context getDisplayUiContext() {
return mDisplayPolicy.getSystemUiContext();
}
diff --git a/services/core/java/com/android/server/wm/ImpressionAttestationController.java b/services/core/java/com/android/server/wm/ImpressionAttestationController.java
index d00faef1c147..4793e1b6fb9f 100644
--- a/services/core/java/com/android/server/wm/ImpressionAttestationController.java
+++ b/services/core/java/com/android/server/wm/ImpressionAttestationController.java
@@ -47,6 +47,7 @@ import android.util.Slog;
import com.android.internal.annotations.GuardedBy;
import java.util.ArrayList;
+import java.util.UUID;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import java.util.function.BiConsumer;
@@ -78,6 +79,8 @@ public class ImpressionAttestationController {
private final Handler mHandler;
+ private final String mSalt;
+
private interface Command {
void run(IImpressionAttestationService service) throws RemoteException;
}
@@ -85,6 +88,7 @@ public class ImpressionAttestationController {
ImpressionAttestationController(Context context) {
mContext = context;
mHandler = new Handler(Looper.getMainLooper());
+ mSalt = UUID.randomUUID().toString();
}
String[] getSupportedImpressionAlgorithms() {
@@ -118,17 +122,17 @@ public class ImpressionAttestationController {
}
}
- int verifyImpressionToken(ImpressionToken impressionToken) {
+ boolean verifyImpressionToken(ImpressionToken impressionToken) {
final SyncCommand syncCommand = new SyncCommand();
Bundle results = syncCommand.run((service, remoteCallback) -> {
try {
- service.verifyImpressionToken(impressionToken, remoteCallback);
+ service.verifyImpressionToken(mSalt, impressionToken, remoteCallback);
} catch (RemoteException e) {
Slog.e(TAG, "Failed to invoke verifyImpressionToken command");
}
});
- return results.getInt(ImpressionAttestationService.EXTRA_VERIFICATION_STATUS);
+ return results.getBoolean(ImpressionAttestationService.EXTRA_VERIFICATION_STATUS);
}
ImpressionToken generateImpressionToken(HardwareBuffer screenshot, Rect bounds,
@@ -136,7 +140,8 @@ public class ImpressionAttestationController {
final SyncCommand syncCommand = new SyncCommand();
Bundle results = syncCommand.run((service, remoteCallback) -> {
try {
- service.generateImpressionToken(screenshot, bounds, hashAlgorithm, remoteCallback);
+ service.generateImpressionToken(mSalt, screenshot, bounds, hashAlgorithm,
+ remoteCallback);
} catch (RemoteException e) {
Slog.e(TAG, "Failed to invoke generateImpressionToken command", e);
}
diff --git a/services/core/java/com/android/server/wm/MirrorActiveUids.java b/services/core/java/com/android/server/wm/MirrorActiveUids.java
index 00479428525a..4e7f1d4cca18 100644
--- a/services/core/java/com/android/server/wm/MirrorActiveUids.java
+++ b/services/core/java/com/android/server/wm/MirrorActiveUids.java
@@ -18,7 +18,10 @@ package com.android.server.wm;
import static android.app.ActivityManager.PROCESS_STATE_NONEXISTENT;
-import android.util.SparseIntArray;
+import android.app.ActivityManager.ProcessState;
+import android.util.SparseArray;
+
+import java.io.PrintWriter;
/**
* This is a partial mirror of {@link @com.android.server.am.ActiveUids}. It is already thread
@@ -26,28 +29,64 @@ import android.util.SparseIntArray;
* adjustment) or getting state from window manager (background start check).
*/
class MirrorActiveUids {
- private SparseIntArray mUidStates = new SparseIntArray();
+ private final SparseArray<UidRecord> mUidStates = new SparseArray<>();
synchronized void onUidActive(int uid, int procState) {
- mUidStates.put(uid, procState);
+ UidRecord r = mUidStates.get(uid);
+ if (r == null) {
+ r = new UidRecord();
+ mUidStates.put(uid, r);
+ }
+ r.mProcState = procState;
}
synchronized void onUidInactive(int uid) {
mUidStates.delete(uid);
}
- synchronized void onActiveUidsCleared() {
- mUidStates.clear();
+ synchronized void onUidProcStateChanged(int uid, int procState) {
+ final UidRecord r = mUidStates.get(uid);
+ if (r != null) {
+ r.mProcState = procState;
+ }
}
- synchronized void onUidProcStateChanged(int uid, int procState) {
- final int index = mUidStates.indexOfKey(uid);
- if (index >= 0) {
- mUidStates.setValueAt(index, procState);
+ synchronized @ProcessState int getUidState(int uid) {
+ final UidRecord r = mUidStates.get(uid);
+ return r != null ? r.mProcState : PROCESS_STATE_NONEXISTENT;
+ }
+
+ /** Called when the surface of non-application (exclude toast) window is shown or hidden. */
+ synchronized void onNonAppSurfaceVisibilityChanged(int uid, boolean visible) {
+ final UidRecord r = mUidStates.get(uid);
+ if (r != null) {
+ r.mNumNonAppVisibleWindow += visible ? 1 : -1;
+ }
+ }
+
+ /**
+ * Returns {@code true} if the uid has any non-application (exclude toast) window currently
+ * visible to the user. The application window visibility of a uid can be found from
+ * {@link VisibleActivityProcessTracker}.
+ */
+ synchronized boolean hasNonAppVisibleWindow(int uid) {
+ final UidRecord r = mUidStates.get(uid);
+ return r != null && r.mNumNonAppVisibleWindow > 0;
+ }
+
+ synchronized void dump(PrintWriter pw, String prefix) {
+ pw.print(prefix + "NumNonAppVisibleWindowByUid:[");
+ for (int i = mUidStates.size() - 1; i >= 0; i--) {
+ final UidRecord r = mUidStates.valueAt(i);
+ if (r.mNumNonAppVisibleWindow > 0) {
+ pw.print(" " + mUidStates.keyAt(i) + ":" + r.mNumNonAppVisibleWindow);
+ }
}
+ pw.println("]");
}
- synchronized int getUidState(int uid) {
- return mUidStates.get(uid, PROCESS_STATE_NONEXISTENT);
+ private static final class UidRecord {
+ @ProcessState int mProcState;
+ int mNumNonAppVisibleWindow;
}
}
diff --git a/services/core/java/com/android/server/wm/RecentsAnimation.java b/services/core/java/com/android/server/wm/RecentsAnimation.java
index b117699a67bd..823dc51e939f 100644
--- a/services/core/java/com/android/server/wm/RecentsAnimation.java
+++ b/services/core/java/com/android/server/wm/RecentsAnimation.java
@@ -385,12 +385,9 @@ class RecentsAnimation implements RecentsAnimationCallbacks,
mWindowManager.executeAppTransition();
final Task rootTask = targetStack.getRootTask();
- if (rootTask.isOrganized()) {
- // Client state may have changed during the recents animation, so force
- // send task info so the client can synchronize its state.
- mService.mTaskOrganizerController.dispatchTaskInfoChanged(
- rootTask, true /* force */);
- }
+ // Client state may have changed during the recents animation, so force
+ // send task info so the client can synchronize its state.
+ rootTask.dispatchTaskInfoChangedIfNeeded(true /* force */);
} catch (Exception e) {
Slog.e(TAG, "Failed to clean up recents activity", e);
throw e;
diff --git a/services/core/java/com/android/server/wm/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java
index a550e150a7a0..707354823817 100644
--- a/services/core/java/com/android/server/wm/RootWindowContainer.java
+++ b/services/core/java/com/android/server/wm/RootWindowContainer.java
@@ -276,7 +276,6 @@ class RootWindowContainer extends WindowContainer<DisplayContent>
// Whether tasks have moved and we need to rank the tasks before next OOM scoring
private boolean mTaskLayersChanged = true;
private int mTmpTaskLayerRank;
- private final ArraySet<WindowProcessController> mTmpTaskLayerChangedProcs = new ArraySet<>();
private final LockedScheduler mRankTaskLayersScheduler;
private boolean mTmpBoolean;
@@ -578,23 +577,6 @@ class RootWindowContainer extends WindowContainer<DisplayContent>
}
/**
- * Returns {@code true} if the callingUid has any non-toast window currently visible to the
- * user. Also ignores {@link android.view.WindowManager.LayoutParams#TYPE_APPLICATION_STARTING},
- * since those windows don't belong to apps.
- *
- * @see WindowState#isNonToastOrStarting()
- */
- boolean isAnyNonToastWindowVisibleForUid(int callingUid) {
- final PooledPredicate p = PooledLambda.obtainPredicate(
- WindowState::isNonToastWindowVisibleForUid,
- PooledLambda.__(WindowState.class), callingUid);
-
- final WindowState w = getWindow(p);
- p.recycle();
- return w != null;
- }
-
- /**
* Returns the app window token for the input binder if it exist in the system.
* NOTE: Only one AppWindowToken is allowed to exist in the system for a binder token, since
* AppWindowToken represents an activity which can only exist on one display.
@@ -1016,9 +998,6 @@ class RootWindowContainer extends WindowContainer<DisplayContent>
}
}
- // Remove all deferred displays stacks, tasks, and activities.
- handleCompleteDeferredRemoval();
-
forAllDisplays(dc -> {
dc.getInputMonitor().updateInputWindowsLw(true /*force*/);
dc.updateSystemGestureExclusion();
@@ -1367,7 +1346,8 @@ class RootWindowContainer extends WindowContainer<DisplayContent>
}
for (int i = mChildren.size() - 1; i >= 0; --i) {
DisplayContent dc = mChildren.get(i);
- if (dc.isAnyNonToastWindowVisibleForPid(pid)) {
+ if (dc.getWindow(w -> pid == w.mSession.mPid && w.isVisibleNow()
+ && w.mAttrs.type != WindowManager.LayoutParams.TYPE_TOAST) != null) {
outContexts.add(dc.getDisplayUiContext());
}
}
@@ -2720,16 +2700,16 @@ class RootWindowContainer extends WindowContainer<DisplayContent>
if (task.mLayerRank != oldRank) {
task.forAllActivities(activity -> {
if (activity.hasProcess()) {
- mTmpTaskLayerChangedProcs.add(activity.app);
+ mTaskSupervisor.onProcessActivityStateChanged(activity.app,
+ true /* forceBatch */);
}
});
}
}, true /* traverseTopToBottom */);
- for (int i = mTmpTaskLayerChangedProcs.size() - 1; i >= 0; i--) {
- mTmpTaskLayerChangedProcs.valueAt(i).computeProcessActivityState();
+ if (!mTaskSupervisor.inActivityVisibilityUpdate()) {
+ mTaskSupervisor.computeProcessActivityStateBatch();
}
- mTmpTaskLayerChangedProcs.clear();
}
void clearOtherAppTimeTrackers(AppTimeTracker except) {
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index 3caf86c24380..ebf5989d6b55 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -2041,9 +2041,7 @@ class Task extends WindowContainer<WindowContainer> {
}
}
- if (isOrganized()) {
- mAtmService.mTaskOrganizerController.dispatchTaskInfoChanged(this, false /* force */);
- }
+ dispatchTaskInfoChangedIfNeeded(false /* force */);
}
private static boolean setTaskDescriptionFromActivityAboveRoot(
@@ -2272,8 +2270,8 @@ class Task extends WindowContainer<WindowContainer> {
}
// If the task organizer has changed, then it will already be receiving taskAppeared with
// the latest task-info thus the task-info won't have changed.
- if (!taskOrgChanged && isOrganized()) {
- mAtmService.mTaskOrganizerController.dispatchTaskInfoChanged(this, false /* force */);
+ if (!taskOrgChanged) {
+ dispatchTaskInfoChangedIfNeeded(false /* force */);
}
}
@@ -4100,6 +4098,7 @@ class Task extends WindowContainer<WindowContainer> {
info.parentTaskId = rootTask == getParent() && rootTask.mCreatedByOrganizer
? rootTask.mTaskId
: INVALID_TASK_ID;
+ info.isFocused = isFocused();
}
@Nullable PictureInPictureParams getPictureInPictureParams() {
@@ -4120,8 +4119,7 @@ class Task extends WindowContainer<WindowContainer> {
letterboxActivityBounds)) {
mLetterboxActivityBounds = Rect.copyOrNull(letterboxActivityBounds);
// Forcing update to reduce visual jank during the transition.
- mAtmService.mTaskOrganizerController.dispatchTaskInfoChanged(
- this, /* force= */ true);
+ dispatchTaskInfoChangedIfNeeded(true /* force */);
}
}
@@ -5067,12 +5065,11 @@ class Task extends WindowContainer<WindowContainer> {
*/
void onWindowFocusChanged(boolean hasFocus) {
updateShadowsRadius(hasFocus, getSyncTransaction());
+ dispatchTaskInfoChangedIfNeeded(false /* force */);
}
void onPictureInPictureParamsChanged() {
- if (isOrganized()) {
- mAtmService.mTaskOrganizerController.dispatchTaskInfoChanged(this, true /* force */);
- }
+ dispatchTaskInfoChangedIfNeeded(true /* force */);
}
/**
@@ -7447,9 +7444,7 @@ class Task extends WindowContainer<WindowContainer> {
@Override
void onChildPositionChanged(WindowContainer child) {
- if (isOrganized()) {
- mAtmService.mTaskOrganizerController.dispatchTaskInfoChanged(this, false /* force */);
- }
+ dispatchTaskInfoChangedIfNeeded(false /* force */);
if (!mChildren.contains(child)) {
return;
@@ -7604,6 +7599,12 @@ class Task extends WindowContainer<WindowContainer> {
return super.getBounds();
}
+ void dispatchTaskInfoChangedIfNeeded(boolean force) {
+ if (isOrganized()) {
+ mAtmService.mTaskOrganizerController.dispatchTaskInfoChanged(this, force);
+ }
+ }
+
@Override
public void dumpDebug(ProtoOutputStream proto, long fieldId,
@WindowTraceLogLevel int logLevel) {
diff --git a/services/core/java/com/android/server/wm/VisibleActivityProcessTracker.java b/services/core/java/com/android/server/wm/VisibleActivityProcessTracker.java
index 7f626308976b..0e2b71c02637 100644
--- a/services/core/java/com/android/server/wm/VisibleActivityProcessTracker.java
+++ b/services/core/java/com/android/server/wm/VisibleActivityProcessTracker.java
@@ -21,7 +21,9 @@ import android.util.ArrayMap;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.os.BackgroundThread;
+import java.io.PrintWriter;
import java.util.concurrent.Executor;
+import java.util.function.Predicate;
/**
* A quick lookup for all processes with visible activities. It also tracks the CPU usage of
@@ -70,10 +72,22 @@ class VisibleActivityProcessTracker {
}
boolean hasResumedActivity(int uid) {
+ return match(uid, WindowProcessController::hasResumedActivity);
+ }
+
+ /**
+ * Returns {@code true} if the uid has a process that contains an activity with
+ * {@link ActivityRecord#mVisibleRequested} or {@link ActivityRecord#isVisible()} is true.
+ */
+ boolean hasVisibleActivity(int uid) {
+ return match(uid, null /* predicate */);
+ }
+
+ private boolean match(int uid, Predicate<WindowProcessController> predicate) {
synchronized (mProcMap) {
for (int i = mProcMap.size() - 1; i >= 0; i--) {
final WindowProcessController wpc = mProcMap.keyAt(i);
- if (wpc.mUid == uid && wpc.hasResumedActivity()) {
+ if (wpc.mUid == uid && (predicate == null || predicate.test(wpc))) {
return true;
}
}
@@ -87,6 +101,16 @@ class VisibleActivityProcessTracker {
}
}
+ void dump(PrintWriter pw, String prefix) {
+ pw.print(prefix + "VisibleActivityProcess:[");
+ synchronized (mProcMap) {
+ for (int i = mProcMap.size() - 1; i >= 0; i--) {
+ pw.print(" " + mProcMap.keyAt(i));
+ }
+ }
+ pw.println("]");
+ }
+
/**
* Get CPU time in background thread because it will access proc files or the lock of cpu
* tracker is held by a background thread.
diff --git a/services/core/java/com/android/server/wm/WindowAnimator.java b/services/core/java/com/android/server/wm/WindowAnimator.java
index ff5c17487413..f627ca620bc3 100644
--- a/services/core/java/com/android/server/wm/WindowAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowAnimator.java
@@ -145,6 +145,9 @@ public class WindowAnimator {
ProtoLog.i(WM_SHOW_TRANSACTIONS, ">>> OPEN TRANSACTION animate");
mService.openSurfaceTransaction();
try {
+ // Remove all deferred displays, tasks, and activities.
+ mService.mRoot.handleCompleteDeferredRemoval();
+
final AccessibilityController accessibilityController =
mService.mAccessibilityController;
final int numDisplays = mDisplayContentsAnimators.size();
diff --git a/services/core/java/com/android/server/wm/WindowContainer.java b/services/core/java/com/android/server/wm/WindowContainer.java
index b25fbc0e18a3..4574be70674f 100644
--- a/services/core/java/com/android/server/wm/WindowContainer.java
+++ b/services/core/java/com/android/server/wm/WindowContainer.java
@@ -1112,7 +1112,7 @@ class WindowContainer<E extends WindowContainer> extends ConfigurationContainer<
// descendant. E.g. if a display is pending to be removed because it contains an
// activity with {@link ActivityRecord#mIsExiting} is true, the display may be
// removed when completing the removal of the last activity from
- // {@link ActivityRecord#checkCompleteDeferredRemoval}.
+ // {@link ActivityRecord#handleCompleteDeferredRemoval}.
return false;
}
}
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 7c7dd6ff268c..580c088ec133 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -2978,7 +2978,7 @@ public class WindowManagerService extends IWindowManager.Stub
displayContent, true /* includingParents */);
}
}
- syncInputTransactions();
+ syncInputTransactions(true /* waitForAnimations */);
}
/**
@@ -7979,7 +7979,8 @@ public class WindowManagerService extends IWindowManager.Stub
}
@Override
- public boolean injectInputAfterTransactionsApplied(InputEvent ev, int mode) {
+ public boolean injectInputAfterTransactionsApplied(InputEvent ev, int mode,
+ boolean waitForAnimations) {
boolean isDown;
boolean isUp;
@@ -7998,21 +7999,23 @@ public class WindowManagerService extends IWindowManager.Stub
// For all mouse events, also sync before injecting.
// For ACTION_UP, sync after injecting.
if (isDown || isMouseEvent) {
- syncInputTransactions();
+ syncInputTransactions(waitForAnimations);
}
final boolean result =
LocalServices.getService(InputManagerInternal.class).injectInputEvent(ev, mode);
if (isUp) {
- syncInputTransactions();
+ syncInputTransactions(waitForAnimations);
}
return result;
}
@Override
- public void syncInputTransactions() {
+ public void syncInputTransactions(boolean waitForAnimations) {
final long token = Binder.clearCallingIdentity();
try {
- waitForAnimationsToComplete();
+ if (waitForAnimations) {
+ waitForAnimationsToComplete();
+ }
// Collect all input transactions from all displays to make sure we could sync all input
// windows at same time.
diff --git a/services/core/java/com/android/server/wm/WindowProcessController.java b/services/core/java/com/android/server/wm/WindowProcessController.java
index 88fd36114ed3..c55f059cae16 100644
--- a/services/core/java/com/android/server/wm/WindowProcessController.java
+++ b/services/core/java/com/android/server/wm/WindowProcessController.java
@@ -607,7 +607,7 @@ public class WindowProcessController extends ConfigurationContainer<Configuratio
private boolean isBoundByForegroundUid() {
for (int i = mBoundClientUids.size() - 1; i >= 0; --i) {
- if (mAtm.isUidForeground(mBoundClientUids.valueAt(i))) {
+ if (mAtm.hasActiveVisibleWindow(mBoundClientUids.valueAt(i))) {
return true;
}
}
@@ -1049,16 +1049,6 @@ public class WindowProcessController extends ConfigurationContainer<Configuratio
& (ACTIVITY_STATE_FLAG_IS_VISIBLE | ACTIVITY_STATE_FLAG_IS_WINDOW_VISIBLE)) != 0;
for (int i = mActivities.size() - 1; i >= 0; i--) {
final ActivityRecord r = mActivities.get(i);
- if (r.app != this) {
- Slog.e(TAG, "Found activity " + r + " in proc activity list using " + r.app
- + " instead of expected " + this);
- if (r.app == null || (r.app.mUid == mUid)) {
- // Only fix things up when they look valid.
- r.setProcess(this);
- } else {
- continue;
- }
- }
if (r.isVisible()) {
stateFlags |= ACTIVITY_STATE_FLAG_IS_WINDOW_VISIBLE;
}
@@ -1115,6 +1105,7 @@ public class WindowProcessController extends ConfigurationContainer<Configuratio
/** Called when the process has some oom related changes and it is going to update oom-adj. */
private void prepareOomAdjustment() {
mAtm.mRootWindowContainer.rankTaskLayersIfNeeded();
+ mAtm.mTaskSupervisor.computeProcessActivityStateBatch();
}
public int computeRelaunchReason() {
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index b5509f62f92a..0a8ff4dc71f5 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -3286,6 +3286,11 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
logExclusionRestrictions(EXCLUSION_LEFT);
logExclusionRestrictions(EXCLUSION_RIGHT);
}
+ // Exclude toast because legacy apps may show toast window by themselves, so the misused
+ // apps won't always be considered as foreground state.
+ if (mAttrs.type >= FIRST_SYSTEM_WINDOW && mAttrs.type != TYPE_TOAST) {
+ mWmService.mAtmService.mActiveUids.onNonAppSurfaceVisibilityChanged(mOwnerUid, shown);
+ }
}
private void logExclusionRestrictions(int side) {
@@ -5624,23 +5629,6 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
true /* ignoreVisibility */));
}
- /**
- * Returns {@code true} if this window is not {@link WindowManager.LayoutParams#TYPE_TOAST}
- * or {@link WindowManager.LayoutParams#TYPE_APPLICATION_STARTING},
- * since this window doesn't belong to apps.
- */
- boolean isNonToastOrStarting() {
- return mAttrs.type != TYPE_TOAST && mAttrs.type != TYPE_APPLICATION_STARTING;
- }
-
- boolean isNonToastWindowVisibleForUid(int callingUid) {
- return getOwningUid() == callingUid && isNonToastOrStarting() && isVisibleNow();
- }
-
- boolean isNonToastWindowVisibleForPid(int pid) {
- return mSession.mPid == pid && isNonToastOrStarting() && isVisibleNow();
- }
-
void setViewVisibility(int viewVisibility) {
mViewVisibility = viewVisibility;
}
diff --git a/services/core/xsd/Android.bp b/services/core/xsd/Android.bp
index fb55e75b9ac4..d1918d8dbe14 100644
--- a/services/core/xsd/Android.bp
+++ b/services/core/xsd/Android.bp
@@ -28,3 +28,10 @@ xsd_config {
api_dir: "cec-config/schema",
package_name: "com.android.server.hdmi.cec.config",
}
+
+xsd_config {
+ name: "device-state-config",
+ srcs: ["device-state-config/device-state-config.xsd"],
+ api_dir: "device-state-config/schema",
+ package_name: "com.android.server.policy.devicestate.config",
+}
diff --git a/services/core/xsd/device-state-config/device-state-config.xsd b/services/core/xsd/device-state-config/device-state-config.xsd
new file mode 100644
index 000000000000..0d8c08c93ff2
--- /dev/null
+++ b/services/core/xsd/device-state-config/device-state-config.xsd
@@ -0,0 +1,78 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright (C) 2020 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<xs:schema version="2.0"
+ elementFormDefault="qualified"
+ xmlns:xs="http://www.w3.org/2001/XMLSchema">
+
+ <xs:element name="device-state-config">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="device-state" type="deviceState" maxOccurs="256" />
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+
+ <xs:complexType name="deviceState">
+ <xs:sequence>
+ <xs:element name="identifier">
+ <xs:simpleType>
+ <xs:restriction base="xs:integer">
+ <xs:minInclusive value="0" />
+ <xs:maxInclusive value="255" />
+ </xs:restriction>
+ </xs:simpleType>
+ </xs:element>
+ <xs:element name="name" type="xs:string" minOccurs="0" />
+ <xs:element name="conditions" type="conditions" />
+ </xs:sequence>
+ </xs:complexType>
+
+ <xs:complexType name="conditions">
+ <xs:sequence>
+ <xs:element name="lid-switch" type="lidSwitchCondition" minOccurs="0" />
+ <xs:element name="sensor" type="sensorCondition" minOccurs="0" maxOccurs="unbounded" />
+ </xs:sequence>
+ </xs:complexType>
+
+ <xs:complexType name="lidSwitchCondition">
+ <xs:sequence>
+ <xs:element name="open" type="xs:boolean" />
+ </xs:sequence>
+ </xs:complexType>
+
+ <xs:complexType name="sensorCondition">
+ <xs:sequence>
+ <xs:element name="name" type="xs:string" />
+ <xs:element name="type" type="xs:positiveInteger" />
+ <xs:element name="value" type="numericRange" maxOccurs="unbounded" />
+ </xs:sequence>
+ </xs:complexType>
+
+ <xs:complexType name="numericRange">
+ <xs:sequence>
+ <xs:choice minOccurs="0">
+ <xs:element name="min" type="xs:decimal" />
+ <xs:element name="min-inclusive" type="xs:decimal" />
+ </xs:choice>
+ <xs:choice minOccurs="0">
+ <xs:element name="max" type="xs:decimal" />
+ <xs:element name="max-inclusive" type="xs:decimal"/>
+ </xs:choice>
+ </xs:sequence>
+ </xs:complexType>
+</xs:schema>
diff --git a/services/core/xsd/device-state-config/schema/current.txt b/services/core/xsd/device-state-config/schema/current.txt
new file mode 100644
index 000000000000..667d1add5a98
--- /dev/null
+++ b/services/core/xsd/device-state-config/schema/current.txt
@@ -0,0 +1,61 @@
+// Signature format: 2.0
+package com.android.server.policy.devicestate.config {
+
+ public class Conditions {
+ ctor public Conditions();
+ method public com.android.server.policy.devicestate.config.LidSwitchCondition getLidSwitch();
+ method public java.util.List<com.android.server.policy.devicestate.config.SensorCondition> getSensor();
+ method public void setLidSwitch(com.android.server.policy.devicestate.config.LidSwitchCondition);
+ }
+
+ public class DeviceState {
+ ctor public DeviceState();
+ method public com.android.server.policy.devicestate.config.Conditions getConditions();
+ method public java.math.BigInteger getIdentifier();
+ method public String getName();
+ method public void setConditions(com.android.server.policy.devicestate.config.Conditions);
+ method public void setIdentifier(java.math.BigInteger);
+ method public void setName(String);
+ }
+
+ public class DeviceStateConfig {
+ ctor public DeviceStateConfig();
+ method public java.util.List<com.android.server.policy.devicestate.config.DeviceState> getDeviceState();
+ }
+
+ public class LidSwitchCondition {
+ ctor public LidSwitchCondition();
+ method public boolean getOpen();
+ method public void setOpen(boolean);
+ }
+
+ public class NumericRange {
+ ctor public NumericRange();
+ method public java.math.BigDecimal getMaxInclusive_optional();
+ method public java.math.BigDecimal getMax_optional();
+ method public java.math.BigDecimal getMinInclusive_optional();
+ method public java.math.BigDecimal getMin_optional();
+ method public void setMaxInclusive_optional(java.math.BigDecimal);
+ method public void setMax_optional(java.math.BigDecimal);
+ method public void setMinInclusive_optional(java.math.BigDecimal);
+ method public void setMin_optional(java.math.BigDecimal);
+ }
+
+ public class SensorCondition {
+ ctor public SensorCondition();
+ method public String getName();
+ method public java.math.BigInteger getType();
+ method public java.util.List<com.android.server.policy.devicestate.config.NumericRange> getValue();
+ method public void setName(String);
+ method public void setType(java.math.BigInteger);
+ }
+
+ public class XmlParser {
+ ctor public XmlParser();
+ method public static com.android.server.policy.devicestate.config.DeviceStateConfig read(java.io.InputStream) throws javax.xml.datatype.DatatypeConfigurationException, java.io.IOException, org.xmlpull.v1.XmlPullParserException;
+ method public static String readText(org.xmlpull.v1.XmlPullParser) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException;
+ method public static void skip(org.xmlpull.v1.XmlPullParser) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException;
+ }
+
+}
+
diff --git a/services/core/xsd/device-state-config/schema/last_current.txt b/services/core/xsd/device-state-config/schema/last_current.txt
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/services/core/xsd/device-state-config/schema/last_current.txt
diff --git a/services/core/xsd/device-state-config/schema/last_removed.txt b/services/core/xsd/device-state-config/schema/last_removed.txt
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/services/core/xsd/device-state-config/schema/last_removed.txt
diff --git a/services/core/xsd/device-state-config/schema/removed.txt b/services/core/xsd/device-state-config/schema/removed.txt
new file mode 100644
index 000000000000..d802177e249b
--- /dev/null
+++ b/services/core/xsd/device-state-config/schema/removed.txt
@@ -0,0 +1 @@
+// Signature format: 2.0
diff --git a/services/incremental/IncrementalService.cpp b/services/incremental/IncrementalService.cpp
index 91478a594ad2..eb6b325050eb 100644
--- a/services/incremental/IncrementalService.cpp
+++ b/services/incremental/IncrementalService.cpp
@@ -481,6 +481,9 @@ StorageId IncrementalService::createStorage(std::string_view mountPoint,
if (!mkdirOrLog(path::join(backing, ".index"), 0777)) {
return kInvalidStorageId;
}
+ if (!mkdirOrLog(path::join(backing, ".incomplete"), 0777)) {
+ return kInvalidStorageId;
+ }
auto status = mVold->mountIncFs(backing, mountTarget, 0, &controlParcel);
if (!status.isOk()) {
LOG(ERROR) << "Vold::mountIncFs() failed: " << status.toString8();
diff --git a/services/tests/mockingservicestests/src/com/android/server/job/controllers/QuotaControllerTest.java b/services/tests/mockingservicestests/src/com/android/server/job/controllers/QuotaControllerTest.java
index 77fef1274415..8795d7711c63 100644
--- a/services/tests/mockingservicestests/src/com/android/server/job/controllers/QuotaControllerTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/job/controllers/QuotaControllerTest.java
@@ -284,6 +284,8 @@ public class QuotaControllerTest {
return UsageStatsManager.STANDBY_BUCKET_FREQUENT;
case RARE_INDEX:
return UsageStatsManager.STANDBY_BUCKET_RARE;
+ case RESTRICTED_INDEX:
+ return UsageStatsManager.STANDBY_BUCKET_RESTRICTED;
default:
return UsageStatsManager.STANDBY_BUCKET_NEVER;
}
@@ -292,6 +294,7 @@ public class QuotaControllerTest {
private void setStandbyBucket(int bucketIndex) {
when(mUsageStatsManager.getAppStandbyBucket(eq(SOURCE_PACKAGE), eq(SOURCE_USER_ID),
anyLong())).thenReturn(bucketIndexToUsageStatsBucket(bucketIndex));
+ mQuotaController.updateStandbyBucket(SOURCE_USER_ID, SOURCE_PACKAGE, bucketIndex);
}
private void setStandbyBucket(int bucketIndex, JobStatus... jobs) {
diff --git a/services/tests/mockingservicestests/src/com/android/server/location/injector/FakeUserInfoHelper.java b/services/tests/mockingservicestests/src/com/android/server/location/injector/FakeUserInfoHelper.java
index be6bc9958140..ac23d4e427c4 100644
--- a/services/tests/mockingservicestests/src/com/android/server/location/injector/FakeUserInfoHelper.java
+++ b/services/tests/mockingservicestests/src/com/android/server/location/injector/FakeUserInfoHelper.java
@@ -100,6 +100,11 @@ public class FakeUserInfoHelper extends UserInfoHelper {
}
@Override
+ public int getCurrentUserId() {
+ return mCurrentUserId;
+ }
+
+ @Override
protected int[] getProfileIds(int userId) {
IntArray profiles = mProfiles.get(userId);
if (profiles != null) {
diff --git a/services/tests/servicestests/Android.bp b/services/tests/servicestests/Android.bp
index 1f723749856f..f2bb91c66ac3 100644
--- a/services/tests/servicestests/Android.bp
+++ b/services/tests/servicestests/Android.bp
@@ -103,6 +103,7 @@ android_test {
":PackageParserTestApp1",
":PackageParserTestApp2",
":PackageParserTestApp3",
+ ":PackageParserTestApp4",
":apex.test",
],
resource_zips: [":FrameworksServicesTests_apks_as_resources"],
diff --git a/services/tests/servicestests/src/com/android/server/GestureLauncherServiceTest.java b/services/tests/servicestests/src/com/android/server/GestureLauncherServiceTest.java
index e76c5a476c48..a02c53336da0 100644
--- a/services/tests/servicestests/src/com/android/server/GestureLauncherServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/GestureLauncherServiceTest.java
@@ -19,6 +19,7 @@ package com.android.server;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Matchers.anyInt;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.never;
@@ -36,6 +37,7 @@ import android.platform.test.annotations.Presubmit;
import android.provider.Settings;
import android.telecom.TelecomManager;
import android.test.mock.MockContentResolver;
+import android.testing.TestableLooper;
import android.util.MutableBoolean;
import android.view.KeyEvent;
@@ -44,6 +46,7 @@ import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;
import com.android.internal.logging.MetricsLogger;
+import com.android.internal.logging.UiEventLogger;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.internal.util.test.FakeSettingsProvider;
import com.android.server.statusbar.StatusBarManagerInternal;
@@ -65,6 +68,7 @@ import java.util.List;
@Presubmit
@SmallTest
@RunWith(AndroidJUnit4.class)
+@TestableLooper.RunWithLooper(setAsMainLooper = true)
public class GestureLauncherServiceTest {
private static final int FAKE_USER_ID = 1337;
@@ -83,6 +87,7 @@ public class GestureLauncherServiceTest {
private @Mock StatusBarManagerInternal mStatusBarManagerInternal;
private @Mock TelecomManager mTelecomManager;
private @Mock MetricsLogger mMetricsLogger;
+ @Mock private UiEventLogger mUiEventLogger;
private MockContentResolver mContentResolver;
private GestureLauncherService mGestureLauncherService;
@@ -109,7 +114,8 @@ public class GestureLauncherServiceTest {
when(mContext.getSystemService(Context.TELECOM_SERVICE)).thenReturn(mTelecomManager);
when(mTelecomManager.createLaunchEmergencyDialerIntent(null)).thenReturn(new Intent());
- mGestureLauncherService = new GestureLauncherService(mContext, mMetricsLogger);
+ mGestureLauncherService = new GestureLauncherService(mContext, mMetricsLogger,
+ mUiEventLogger);
}
@Test
@@ -268,6 +274,7 @@ public class GestureLauncherServiceTest {
verify(mMetricsLogger, never())
.action(eq(MetricsEvent.ACTION_DOUBLE_TAP_POWER_CAMERA_GESTURE), anyInt());
+ verify(mUiEventLogger, never()).log(any());
final ArgumentCaptor<Integer> intervalCaptor = ArgumentCaptor.forClass(Integer.class);
verify(mMetricsLogger, times(2)).histogram(
@@ -312,6 +319,7 @@ public class GestureLauncherServiceTest {
verify(mMetricsLogger, never())
.action(eq(MetricsEvent.ACTION_DOUBLE_TAP_POWER_CAMERA_GESTURE), anyInt());
+ verify(mUiEventLogger, never()).log(any());
final ArgumentCaptor<Integer> intervalCaptor = ArgumentCaptor.forClass(Integer.class);
verify(mMetricsLogger, times(2)).histogram(
@@ -358,6 +366,7 @@ public class GestureLauncherServiceTest {
verify(mMetricsLogger, never())
.action(eq(MetricsEvent.ACTION_DOUBLE_TAP_POWER_CAMERA_GESTURE), anyInt());
+ verify(mUiEventLogger, never()).log(any());
final ArgumentCaptor<Integer> intervalCaptor = ArgumentCaptor.forClass(Integer.class);
verify(mMetricsLogger, times(2)).histogram(
@@ -406,6 +415,8 @@ public class GestureLauncherServiceTest {
StatusBarManager.CAMERA_LAUNCH_SOURCE_POWER_DOUBLE_TAP);
verify(mMetricsLogger)
.action(MetricsEvent.ACTION_DOUBLE_TAP_POWER_CAMERA_GESTURE, (int) interval);
+ verify(mUiEventLogger, times(1))
+ .log(GestureLauncherService.GestureLauncherEvent.GESTURE_CAMERA_DOUBLE_TAP_POWER);
final ArgumentCaptor<Integer> intervalCaptor = ArgumentCaptor.forClass(Integer.class);
verify(mMetricsLogger, times(2)).histogram(
@@ -460,6 +471,8 @@ public class GestureLauncherServiceTest {
StatusBarManager.CAMERA_LAUNCH_SOURCE_POWER_DOUBLE_TAP);
verify(mMetricsLogger)
.action(MetricsEvent.ACTION_DOUBLE_TAP_POWER_CAMERA_GESTURE, (int) interval);
+ verify(mUiEventLogger, times(1))
+ .log(GestureLauncherService.GestureLauncherEvent.GESTURE_CAMERA_DOUBLE_TAP_POWER);
final ArgumentCaptor<Integer> cameraIntervalCaptor = ArgumentCaptor.forClass(Integer.class);
verify(mMetricsLogger, times(2)).histogram(
@@ -499,7 +512,8 @@ public class GestureLauncherServiceTest {
assertTrue(intercepted);
assertTrue(outLaunched.value);
- // TODO (b/169960245) Verify metric event equiv. to ACTION_DOUBLE_TAP_POWER_CAMERA_GESTURE
+ verify(mUiEventLogger, times(1))
+ .log(GestureLauncherService.GestureLauncherEvent.GESTURE_PANIC_TAP_POWER);
verify(mStatusBarManagerInternal).onEmergencyActionLaunchGestureDetected();
final ArgumentCaptor<Integer> intervalCaptor = ArgumentCaptor.forClass(Integer.class);
@@ -551,7 +565,8 @@ public class GestureLauncherServiceTest {
assertTrue(outLaunched.value);
assertTrue(intercepted);
- // TODO (b/169960245) Verify metric event equiv. to ACTION_DOUBLE_TAP_POWER_CAMERA_GESTURE
+ verify(mUiEventLogger, times(1))
+ .log(GestureLauncherService.GestureLauncherEvent.GESTURE_PANIC_TAP_POWER);
verify(mStatusBarManagerInternal).onEmergencyActionLaunchGestureDetected();
final ArgumentCaptor<Integer> intervalCaptor = ArgumentCaptor.forClass(Integer.class);
@@ -646,6 +661,7 @@ public class GestureLauncherServiceTest {
verify(mMetricsLogger, never())
.action(eq(MetricsEvent.ACTION_DOUBLE_TAP_POWER_CAMERA_GESTURE), anyInt());
+ verify(mUiEventLogger, never()).log(any());
final ArgumentCaptor<Integer> intervalCaptor = ArgumentCaptor.forClass(Integer.class);
verify(mMetricsLogger, times(1)).histogram(
@@ -690,6 +706,7 @@ public class GestureLauncherServiceTest {
verify(mMetricsLogger, never())
.action(eq(MetricsEvent.ACTION_DOUBLE_TAP_POWER_CAMERA_GESTURE), anyInt());
+ verify(mUiEventLogger, never()).log(any());
final ArgumentCaptor<Integer> intervalCaptor = ArgumentCaptor.forClass(Integer.class);
verify(mMetricsLogger, times(2)).histogram(
@@ -736,6 +753,7 @@ public class GestureLauncherServiceTest {
verify(mMetricsLogger, never())
.action(eq(MetricsEvent.ACTION_DOUBLE_TAP_POWER_CAMERA_GESTURE), anyInt());
+ verify(mUiEventLogger, never()).log(any());
final ArgumentCaptor<Integer> intervalCaptor = ArgumentCaptor.forClass(Integer.class);
verify(mMetricsLogger, times(2)).histogram(
@@ -782,6 +800,7 @@ public class GestureLauncherServiceTest {
verify(mMetricsLogger, never())
.action(eq(MetricsEvent.ACTION_DOUBLE_TAP_POWER_CAMERA_GESTURE), anyInt());
+ verify(mUiEventLogger, never()).log(any());
final ArgumentCaptor<Integer> intervalCaptor = ArgumentCaptor.forClass(Integer.class);
verify(mMetricsLogger, times(2)).histogram(
@@ -826,6 +845,7 @@ public class GestureLauncherServiceTest {
verify(mMetricsLogger, never())
.action(eq(MetricsEvent.ACTION_DOUBLE_TAP_POWER_CAMERA_GESTURE), anyInt());
+ verify(mUiEventLogger, never()).log(any());
final ArgumentCaptor<Integer> intervalCaptor = ArgumentCaptor.forClass(Integer.class);
verify(mMetricsLogger, times(2)).histogram(
@@ -869,6 +889,7 @@ public class GestureLauncherServiceTest {
assertFalse(outLaunched.value);
verify(mMetricsLogger, never())
.action(eq(MetricsEvent.ACTION_DOUBLE_TAP_POWER_CAMERA_GESTURE), anyInt());
+ verify(mUiEventLogger, never()).log(any());
final ArgumentCaptor<Integer> intervalCaptor = ArgumentCaptor.forClass(Integer.class);
verify(mMetricsLogger, times(2)).histogram(
@@ -914,6 +935,7 @@ public class GestureLauncherServiceTest {
assertFalse(outLaunched.value);
verify(mMetricsLogger, never())
.action(eq(MetricsEvent.ACTION_DOUBLE_TAP_POWER_CAMERA_GESTURE), anyInt());
+ verify(mUiEventLogger, never()).log(any());
final ArgumentCaptor<Integer> intervalCaptor = ArgumentCaptor.forClass(Integer.class);
verify(mMetricsLogger, times(2)).histogram(
@@ -961,6 +983,8 @@ public class GestureLauncherServiceTest {
StatusBarManager.CAMERA_LAUNCH_SOURCE_POWER_DOUBLE_TAP);
verify(mMetricsLogger)
.action(MetricsEvent.ACTION_DOUBLE_TAP_POWER_CAMERA_GESTURE, (int) interval);
+ verify(mUiEventLogger, times(1))
+ .log(GestureLauncherService.GestureLauncherEvent.GESTURE_CAMERA_DOUBLE_TAP_POWER);
final ArgumentCaptor<Integer> intervalCaptor = ArgumentCaptor.forClass(Integer.class);
verify(mMetricsLogger, times(2)).histogram(
@@ -1007,6 +1031,7 @@ public class GestureLauncherServiceTest {
verify(mMetricsLogger, never())
.action(eq(MetricsEvent.ACTION_DOUBLE_TAP_POWER_CAMERA_GESTURE), anyInt());
+ verify(mUiEventLogger, never()).log(any());
final ArgumentCaptor<Integer> intervalCaptor = ArgumentCaptor.forClass(Integer.class);
verify(mMetricsLogger, times(2)).histogram(
@@ -1051,6 +1076,7 @@ public class GestureLauncherServiceTest {
verify(mMetricsLogger, never())
.action(eq(MetricsEvent.ACTION_DOUBLE_TAP_POWER_CAMERA_GESTURE), anyInt());
+ verify(mUiEventLogger, never()).log(any());
final ArgumentCaptor<Integer> intervalCaptor = ArgumentCaptor.forClass(Integer.class);
verify(mMetricsLogger, times(2)).histogram(
@@ -1097,6 +1123,7 @@ public class GestureLauncherServiceTest {
verify(mMetricsLogger, never())
.action(eq(MetricsEvent.ACTION_DOUBLE_TAP_POWER_CAMERA_GESTURE), anyInt());
+ verify(mUiEventLogger, never()).log(any());
final ArgumentCaptor<Integer> intervalCaptor = ArgumentCaptor.forClass(Integer.class);
verify(mMetricsLogger, times(2)).histogram(
diff --git a/services/tests/servicestests/src/com/android/server/appsearch/external/localstorage/AppSearchImplTest.java b/services/tests/servicestests/src/com/android/server/appsearch/external/localstorage/AppSearchImplTest.java
index 726e48a001d7..b929061a967e 100644
--- a/services/tests/servicestests/src/com/android/server/appsearch/external/localstorage/AppSearchImplTest.java
+++ b/services/tests/servicestests/src/com/android/server/appsearch/external/localstorage/AppSearchImplTest.java
@@ -26,15 +26,17 @@ import android.app.appsearch.SearchResultPage;
import android.app.appsearch.SearchSpec;
import android.app.appsearch.exceptions.AppSearchException;
+import com.android.server.appsearch.external.localstorage.converter.SchemaToProtoConverter;
import com.android.server.appsearch.proto.DocumentProto;
import com.android.server.appsearch.proto.GetOptimizeInfoResultProto;
-import com.android.server.appsearch.proto.IndexingConfig;
import com.android.server.appsearch.proto.PropertyConfigProto;
import com.android.server.appsearch.proto.PropertyProto;
import com.android.server.appsearch.proto.SchemaProto;
import com.android.server.appsearch.proto.SchemaTypeConfigProto;
import com.android.server.appsearch.proto.SearchSpecProto;
+import com.android.server.appsearch.proto.StringIndexingConfig;
import com.android.server.appsearch.proto.TermMatchType;
+
import com.google.common.collect.ImmutableSet;
import org.junit.Before;
@@ -42,18 +44,36 @@ import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
+import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
+import java.util.List;
import java.util.Set;
public class AppSearchImplTest {
- @Rule
- public TemporaryFolder mTemporaryFolder = new TemporaryFolder();
+ @Rule public TemporaryFolder mTemporaryFolder = new TemporaryFolder();
private AppSearchImpl mAppSearchImpl;
+ private SchemaTypeConfigProto mVisibilitySchemaProto;
@Before
public void setUp() throws Exception {
mAppSearchImpl = AppSearchImpl.create(mTemporaryFolder.newFolder());
+
+ AppSearchSchema visibilityAppSearchSchema =
+ new AppSearchSchema.Builder(
+ VisibilityStore.DATABASE_NAME
+ + AppSearchImpl.DATABASE_DELIMITER
+ + VisibilityStore.SCHEMA_TYPE)
+ .addProperty(
+ new AppSearchSchema.PropertyConfig.Builder(
+ VisibilityStore.PLATFORM_HIDDEN_PROPERTY)
+ .setDataType(
+ AppSearchSchema.PropertyConfig.DATA_TYPE_STRING)
+ .setCardinality(
+ AppSearchSchema.PropertyConfig.CARDINALITY_REPEATED)
+ .build())
+ .build();
+ mVisibilitySchemaProto = SchemaToProtoConverter.convert(visibilityAppSearchSchema);
}
/**
@@ -62,91 +82,217 @@ public class AppSearchImplTest {
* schema.
*/
@Test
- public void testRewriteSchema() throws Exception {
- SchemaProto.Builder existingSchemaBuilder = mAppSearchImpl.getSchemaProto().toBuilder();
-
- SchemaProto newSchema = SchemaProto.newBuilder()
- .addTypes(SchemaTypeConfigProto.newBuilder()
- .setSchemaType("Foo").build())
- .addTypes(SchemaTypeConfigProto.newBuilder()
- .setSchemaType("TestType")
- .addProperties(PropertyConfigProto.newBuilder()
- .setPropertyName("subject")
- .setDataType(PropertyConfigProto.DataType.Code.STRING)
- .setCardinality(PropertyConfigProto.Cardinality.Code.OPTIONAL)
- .setIndexingConfig(
- IndexingConfig.newBuilder()
- .setTokenizerType(
- IndexingConfig.TokenizerType.Code.PLAIN)
- .setTermMatchType(TermMatchType.Code.PREFIX)
- .build()
- ).build()
- ).addProperties(PropertyConfigProto.newBuilder()
- .setPropertyName("link")
- .setDataType(PropertyConfigProto.DataType.Code.DOCUMENT)
- .setCardinality(PropertyConfigProto.Cardinality.Code.OPTIONAL)
- .setSchemaType("RefType")
- .build()
- ).build()
- ).build();
-
- Set<String> newTypes = mAppSearchImpl.rewriteSchema("databaseName", existingSchemaBuilder,
- newSchema);
- assertThat(newTypes).containsExactly("databaseName/Foo", "databaseName/TestType");
-
- SchemaProto expectedSchema = SchemaProto.newBuilder()
- .addTypes(SchemaTypeConfigProto.newBuilder()
- .setSchemaType("databaseName/Foo").build())
- .addTypes(SchemaTypeConfigProto.newBuilder()
- .setSchemaType("databaseName/TestType")
- .addProperties(PropertyConfigProto.newBuilder()
- .setPropertyName("subject")
- .setDataType(PropertyConfigProto.DataType.Code.STRING)
- .setCardinality(PropertyConfigProto.Cardinality.Code.OPTIONAL)
- .setIndexingConfig(
- IndexingConfig.newBuilder()
- .setTokenizerType(
- IndexingConfig.TokenizerType.Code.PLAIN)
- .setTermMatchType(TermMatchType.Code.PREFIX)
- .build()
- ).build()
- ).addProperties(PropertyConfigProto.newBuilder()
- .setPropertyName("link")
- .setDataType(PropertyConfigProto.DataType.Code.DOCUMENT)
- .setCardinality(PropertyConfigProto.Cardinality.Code.OPTIONAL)
- .setSchemaType("databaseName/RefType")
- .build()
- ).build())
- .build();
+ public void testRewriteSchema_addType() throws Exception {
+ SchemaProto.Builder existingSchemaBuilder =
+ SchemaProto.newBuilder()
+ .addTypes(
+ SchemaTypeConfigProto.newBuilder()
+ .setSchemaType("existingDatabase/Foo")
+ .build());
+
+ // Create a copy so we can modify it.
+ List<SchemaTypeConfigProto> existingTypes =
+ new ArrayList<>(existingSchemaBuilder.getTypesList());
+
+ SchemaProto newSchema =
+ SchemaProto.newBuilder()
+ .addTypes(SchemaTypeConfigProto.newBuilder().setSchemaType("Foo").build())
+ .addTypes(
+ SchemaTypeConfigProto.newBuilder()
+ .setSchemaType("TestType")
+ .addProperties(
+ PropertyConfigProto.newBuilder()
+ .setPropertyName("subject")
+ .setDataType(
+ PropertyConfigProto.DataType.Code
+ .STRING)
+ .setCardinality(
+ PropertyConfigProto.Cardinality.Code
+ .OPTIONAL)
+ .setStringIndexingConfig(
+ StringIndexingConfig.newBuilder()
+ .setTokenizerType(
+ StringIndexingConfig
+ .TokenizerType
+ .Code.PLAIN)
+ .setTermMatchType(
+ TermMatchType.Code
+ .PREFIX)
+ .build())
+ .build())
+ .addProperties(
+ PropertyConfigProto.newBuilder()
+ .setPropertyName("link")
+ .setDataType(
+ PropertyConfigProto.DataType.Code
+ .DOCUMENT)
+ .setCardinality(
+ PropertyConfigProto.Cardinality.Code
+ .OPTIONAL)
+ .setSchemaType("RefType")
+ .build())
+ .build())
+ .build();
+
+ AppSearchImpl.RewrittenSchemaResults rewrittenSchemaResults =
+ mAppSearchImpl.rewriteSchema("newDatabase", existingSchemaBuilder, newSchema);
+
+ // We rewrote all the new types that were added. And nothing was removed.
+ assertThat(rewrittenSchemaResults.mRewrittenQualifiedTypes)
+ .containsExactly("newDatabase/Foo", "newDatabase/TestType");
+ assertThat(rewrittenSchemaResults.mDeletedQualifiedTypes).isEmpty();
+
+ SchemaProto expectedSchema =
+ SchemaProto.newBuilder()
+ .addTypes(
+ SchemaTypeConfigProto.newBuilder()
+ .setSchemaType("newDatabase/Foo")
+ .build())
+ .addTypes(
+ SchemaTypeConfigProto.newBuilder()
+ .setSchemaType("newDatabase/TestType")
+ .addProperties(
+ PropertyConfigProto.newBuilder()
+ .setPropertyName("subject")
+ .setDataType(
+ PropertyConfigProto.DataType.Code
+ .STRING)
+ .setCardinality(
+ PropertyConfigProto.Cardinality.Code
+ .OPTIONAL)
+ .setStringIndexingConfig(
+ StringIndexingConfig.newBuilder()
+ .setTokenizerType(
+ StringIndexingConfig
+ .TokenizerType
+ .Code.PLAIN)
+ .setTermMatchType(
+ TermMatchType.Code
+ .PREFIX)
+ .build())
+ .build())
+ .addProperties(
+ PropertyConfigProto.newBuilder()
+ .setPropertyName("link")
+ .setDataType(
+ PropertyConfigProto.DataType.Code
+ .DOCUMENT)
+ .setCardinality(
+ PropertyConfigProto.Cardinality.Code
+ .OPTIONAL)
+ .setSchemaType("newDatabase/RefType")
+ .build())
+ .build())
+ .build();
+
+ existingTypes.addAll(expectedSchema.getTypesList());
+ assertThat(existingSchemaBuilder.getTypesList()).containsExactlyElementsIn(existingTypes);
+ }
+
+ /**
+ * Ensure that we track all types that were rewritten in the input schema. Even if they were not
+ * technically "added" to the existing schema.
+ */
+ @Test
+ public void testRewriteSchema_rewriteType() throws Exception {
+ SchemaProto.Builder existingSchemaBuilder =
+ SchemaProto.newBuilder()
+ .addTypes(
+ SchemaTypeConfigProto.newBuilder()
+ .setSchemaType("existingDatabase/Foo")
+ .build());
+
+ SchemaProto newSchema =
+ SchemaProto.newBuilder()
+ .addTypes(SchemaTypeConfigProto.newBuilder().setSchemaType("Foo").build())
+ .build();
+
+ AppSearchImpl.RewrittenSchemaResults rewrittenSchemaResults =
+ mAppSearchImpl.rewriteSchema("existingDatabase", existingSchemaBuilder, newSchema);
+
+ // Nothing was removed, but the method did rewrite the type name.
+ assertThat(rewrittenSchemaResults.mRewrittenQualifiedTypes)
+ .containsExactly("existingDatabase/Foo");
+ assertThat(rewrittenSchemaResults.mDeletedQualifiedTypes).isEmpty();
+
+ // Same schema since nothing was added.
+ SchemaProto expectedSchema = existingSchemaBuilder.build();
+ assertThat(existingSchemaBuilder.getTypesList())
+ .containsExactlyElementsIn(expectedSchema.getTypesList());
+ }
+
+ /**
+ * Ensure that we track which types from the existing schema are deleted when a new schema is
+ * set.
+ */
+ @Test
+ public void testRewriteSchema_deleteType() throws Exception {
+ SchemaProto.Builder existingSchemaBuilder =
+ SchemaProto.newBuilder()
+ .addTypes(
+ SchemaTypeConfigProto.newBuilder()
+ .setSchemaType("existingDatabase/Foo")
+ .build());
+
+ SchemaProto newSchema =
+ SchemaProto.newBuilder()
+ .addTypes(SchemaTypeConfigProto.newBuilder().setSchemaType("Bar").build())
+ .build();
+
+ AppSearchImpl.RewrittenSchemaResults rewrittenSchemaResults =
+ mAppSearchImpl.rewriteSchema("existingDatabase", existingSchemaBuilder, newSchema);
+
+ // Bar type was rewritten, but Foo ended up being deleted since it wasn't included in the
+ // new schema.
+ assertThat(rewrittenSchemaResults.mRewrittenQualifiedTypes)
+ .containsExactly("existingDatabase/Bar");
+ assertThat(rewrittenSchemaResults.mDeletedQualifiedTypes)
+ .containsExactly("existingDatabase/Foo");
+
+ // Same schema since nothing was added.
+ SchemaProto expectedSchema =
+ SchemaProto.newBuilder()
+ .addTypes(
+ SchemaTypeConfigProto.newBuilder()
+ .setSchemaType("existingDatabase/Bar")
+ .build())
+ .build();
+
assertThat(existingSchemaBuilder.getTypesList())
.containsExactlyElementsIn(expectedSchema.getTypesList());
}
@Test
public void testAddDocumentTypePrefix() {
- DocumentProto insideDocument = DocumentProto.newBuilder()
- .setUri("inside-uri")
- .setSchema("type")
- .setNamespace("namespace")
- .build();
- DocumentProto documentProto = DocumentProto.newBuilder()
- .setUri("uri")
- .setSchema("type")
- .setNamespace("namespace")
- .addProperties(PropertyProto.newBuilder().addDocumentValues(insideDocument))
- .build();
-
- DocumentProto expectedInsideDocument = DocumentProto.newBuilder()
- .setUri("inside-uri")
- .setSchema("databaseName/type")
- .setNamespace("databaseName/namespace")
- .build();
- DocumentProto expectedDocumentProto = DocumentProto.newBuilder()
- .setUri("uri")
- .setSchema("databaseName/type")
- .setNamespace("databaseName/namespace")
- .addProperties(PropertyProto.newBuilder().addDocumentValues(expectedInsideDocument))
- .build();
+ DocumentProto insideDocument =
+ DocumentProto.newBuilder()
+ .setUri("inside-uri")
+ .setSchema("type")
+ .setNamespace("namespace")
+ .build();
+ DocumentProto documentProto =
+ DocumentProto.newBuilder()
+ .setUri("uri")
+ .setSchema("type")
+ .setNamespace("namespace")
+ .addProperties(PropertyProto.newBuilder().addDocumentValues(insideDocument))
+ .build();
+
+ DocumentProto expectedInsideDocument =
+ DocumentProto.newBuilder()
+ .setUri("inside-uri")
+ .setSchema("databaseName/type")
+ .setNamespace("databaseName/namespace")
+ .build();
+ DocumentProto expectedDocumentProto =
+ DocumentProto.newBuilder()
+ .setUri("uri")
+ .setSchema("databaseName/type")
+ .setNamespace("databaseName/namespace")
+ .addProperties(
+ PropertyProto.newBuilder()
+ .addDocumentValues(expectedInsideDocument))
+ .build();
DocumentProto.Builder actualDocument = documentProto.toBuilder();
mAppSearchImpl.addPrefixToDocument(actualDocument, "databaseName/");
@@ -154,31 +300,37 @@ public class AppSearchImplTest {
}
@Test
- public void testRemoveDocumentTypePrefixes() {
- DocumentProto insideDocument = DocumentProto.newBuilder()
- .setUri("inside-uri")
- .setSchema("databaseName1/type")
- .setNamespace("databaseName2/namespace")
- .build();
- DocumentProto documentProto = DocumentProto.newBuilder()
- .setUri("uri")
- .setSchema("databaseName2/type")
- .setNamespace("databaseName3/namespace")
- .addProperties(PropertyProto.newBuilder().addDocumentValues(insideDocument))
- .build();
-
- DocumentProto expectedInsideDocument = DocumentProto.newBuilder()
- .setUri("inside-uri")
- .setSchema("type")
- .setNamespace("namespace")
- .build();
+ public void testRemoveDocumentTypePrefixes() throws Exception {
+ DocumentProto insideDocument =
+ DocumentProto.newBuilder()
+ .setUri("inside-uri")
+ .setSchema("databaseName1/type")
+ .setNamespace("databaseName2/namespace")
+ .build();
+ DocumentProto documentProto =
+ DocumentProto.newBuilder()
+ .setUri("uri")
+ .setSchema("databaseName2/type")
+ .setNamespace("databaseName3/namespace")
+ .addProperties(PropertyProto.newBuilder().addDocumentValues(insideDocument))
+ .build();
+
+ DocumentProto expectedInsideDocument =
+ DocumentProto.newBuilder()
+ .setUri("inside-uri")
+ .setSchema("type")
+ .setNamespace("namespace")
+ .build();
// Since we don't pass in "databaseName3/" as a prefix to remove, it stays on the Document.
- DocumentProto expectedDocumentProto = DocumentProto.newBuilder()
- .setUri("uri")
- .setSchema("type")
- .setNamespace("namespace")
- .addProperties(PropertyProto.newBuilder().addDocumentValues(expectedInsideDocument))
- .build();
+ DocumentProto expectedDocumentProto =
+ DocumentProto.newBuilder()
+ .setUri("uri")
+ .setSchema("type")
+ .setNamespace("namespace")
+ .addProperties(
+ PropertyProto.newBuilder()
+ .addDocumentValues(expectedInsideDocument))
+ .build();
DocumentProto.Builder actualDocument = documentProto.toBuilder();
mAppSearchImpl.removeDatabasesFromDocument(actualDocument);
@@ -190,19 +342,23 @@ public class AppSearchImplTest {
// Insert schema
Set<AppSearchSchema> schemas =
Collections.singleton(new AppSearchSchema.Builder("type").build());
- mAppSearchImpl.setSchema("database", schemas, /*forceOverride=*/false);
+ mAppSearchImpl.setSchema("database", schemas, /*forceOverride=*/ false);
// Insert enough documents.
- for (int i = 0; i < AppSearchImpl.OPTIMIZE_THRESHOLD_DOC_COUNT
- + AppSearchImpl.CHECK_OPTIMIZE_INTERVAL; i++) {
+ for (int i = 0;
+ i
+ < AppSearchImpl.OPTIMIZE_THRESHOLD_DOC_COUNT
+ + AppSearchImpl.CHECK_OPTIMIZE_INTERVAL;
+ i++) {
GenericDocument document =
- new GenericDocument.Builder("uri" + i, "type").setNamespace(
- "namespace").build();
+ new GenericDocument.Builder("uri" + i, "type")
+ .setNamespace("namespace")
+ .build();
mAppSearchImpl.putDocument("database", document);
}
// Check optimize() will release 0 docs since there is no deletion.
- GetOptimizeInfoResultProto optimizeInfo = mAppSearchImpl.getOptimizeInfoResult();
+ GetOptimizeInfoResultProto optimizeInfo = mAppSearchImpl.getOptimizeInfoResultLocked();
assertThat(optimizeInfo.getOptimizableDocs()).isEqualTo(0);
// delete 999 documents , we will reach the threshold to trigger optimize() in next
@@ -212,82 +368,82 @@ public class AppSearchImplTest {
}
// optimize() still not be triggered since we are in the interval to call getOptimizeInfo()
- optimizeInfo = mAppSearchImpl.getOptimizeInfoResult();
+ optimizeInfo = mAppSearchImpl.getOptimizeInfoResultLocked();
assertThat(optimizeInfo.getOptimizableDocs())
.isEqualTo(AppSearchImpl.OPTIMIZE_THRESHOLD_DOC_COUNT - 1);
// Keep delete docs, will reach the interval this time and trigger optimize().
for (int i = AppSearchImpl.OPTIMIZE_THRESHOLD_DOC_COUNT;
- i < AppSearchImpl.OPTIMIZE_THRESHOLD_DOC_COUNT
- + AppSearchImpl.CHECK_OPTIMIZE_INTERVAL; i++) {
+ i
+ < AppSearchImpl.OPTIMIZE_THRESHOLD_DOC_COUNT
+ + AppSearchImpl.CHECK_OPTIMIZE_INTERVAL;
+ i++) {
mAppSearchImpl.remove("database", "namespace", "uri" + i);
}
// Verify optimize() is triggered
- optimizeInfo = mAppSearchImpl.getOptimizeInfoResult();
+ optimizeInfo = mAppSearchImpl.getOptimizeInfoResultLocked();
assertThat(optimizeInfo.getOptimizableDocs())
.isLessThan(AppSearchImpl.CHECK_OPTIMIZE_INTERVAL);
}
@Test
- public void testRewriteSearchSpec_OneInstance() throws Exception {
- SearchSpecProto.Builder searchSpecProto =
- SearchSpecProto.newBuilder().setQuery("");
+ public void testRewriteSearchSpec_oneInstance() throws Exception {
+ SearchSpecProto.Builder searchSpecProto = SearchSpecProto.newBuilder().setQuery("");
// Insert schema
Set<AppSearchSchema> schemas =
Collections.singleton(new AppSearchSchema.Builder("type").build());
- mAppSearchImpl.setSchema("database", schemas, /*forceOverride=*/false);
+ mAppSearchImpl.setSchema("database", schemas, /*forceOverride=*/ false);
// Insert document
- GenericDocument document = new GenericDocument.Builder("uri", "type").setNamespace(
- "namespace").build();
+ GenericDocument document =
+ new GenericDocument.Builder("uri", "type").setNamespace("namespace").build();
mAppSearchImpl.putDocument("database", document);
// Rewrite SearchSpec
- mAppSearchImpl.rewriteSearchSpecForDatabases(searchSpecProto, Collections.singleton(
- "database"));
+ mAppSearchImpl.rewriteSearchSpecForDatabasesLocked(
+ searchSpecProto, Collections.singleton("database"));
assertThat(searchSpecProto.getSchemaTypeFiltersList()).containsExactly("database/type");
assertThat(searchSpecProto.getNamespaceFiltersList()).containsExactly("database/namespace");
}
@Test
- public void testRewriteSearchSpec_TwoInstances() throws Exception {
- SearchSpecProto.Builder searchSpecProto =
- SearchSpecProto.newBuilder().setQuery("");
+ public void testRewriteSearchSpec_twoInstances() throws Exception {
+ SearchSpecProto.Builder searchSpecProto = SearchSpecProto.newBuilder().setQuery("");
// Insert schema
- Set<AppSearchSchema> schemas = Set.of(
- new AppSearchSchema.Builder("typeA").build(),
- new AppSearchSchema.Builder("typeB").build());
- mAppSearchImpl.setSchema("database1", schemas, /*forceOverride=*/false);
- mAppSearchImpl.setSchema("database2", schemas, /*forceOverride=*/false);
+ Set<AppSearchSchema> schemas =
+ Set.of(
+ new AppSearchSchema.Builder("typeA").build(),
+ new AppSearchSchema.Builder("typeB").build());
+ mAppSearchImpl.setSchema("database1", schemas, /*forceOverride=*/ false);
+ mAppSearchImpl.setSchema("database2", schemas, /*forceOverride=*/ false);
// Insert documents
- GenericDocument document1 = new GenericDocument.Builder("uri", "typeA").setNamespace(
- "namespace").build();
+ GenericDocument document1 =
+ new GenericDocument.Builder("uri", "typeA").setNamespace("namespace").build();
mAppSearchImpl.putDocument("database1", document1);
- GenericDocument document2 = new GenericDocument.Builder("uri", "typeB").setNamespace(
- "namespace").build();
+ GenericDocument document2 =
+ new GenericDocument.Builder("uri", "typeB").setNamespace("namespace").build();
mAppSearchImpl.putDocument("database2", document2);
// Rewrite SearchSpec
- mAppSearchImpl.rewriteSearchSpecForDatabases(searchSpecProto,
- ImmutableSet.of("database1", "database2"));
- assertThat(searchSpecProto.getSchemaTypeFiltersList()).containsExactly(
- "database1/typeA", "database1/typeB", "database2/typeA", "database2/typeB");
- assertThat(searchSpecProto.getNamespaceFiltersList()).containsExactly(
- "database1/namespace", "database2/namespace");
+ mAppSearchImpl.rewriteSearchSpecForDatabasesLocked(
+ searchSpecProto, ImmutableSet.of("database1", "database2"));
+ assertThat(searchSpecProto.getSchemaTypeFiltersList())
+ .containsExactly(
+ "database1/typeA", "database1/typeB", "database2/typeA", "database2/typeB");
+ assertThat(searchSpecProto.getNamespaceFiltersList())
+ .containsExactly("database1/namespace", "database2/namespace");
}
@Test
public void testQueryEmptyDatabase() throws Exception {
SearchSpec searchSpec =
new SearchSpec.Builder().setTermMatch(TermMatchType.Code.PREFIX_VALUE).build();
- SearchResultPage searchResultPage = mAppSearchImpl.query(
- "EmptyDatabase",
- "", searchSpec);
+ SearchResultPage searchResultPage = mAppSearchImpl.query("EmptyDatabase", "", searchSpec);
assertThat(searchResultPage.getResults()).isEmpty();
}
@@ -295,25 +451,25 @@ public class AppSearchImplTest {
public void testGlobalQueryEmptyDatabase() throws Exception {
SearchSpec searchSpec =
new SearchSpec.Builder().setTermMatch(TermMatchType.Code.PREFIX_VALUE).build();
- SearchResultPage searchResultPage = mAppSearchImpl.query(
- "EmptyDatabase",
- "", searchSpec);
+ SearchResultPage searchResultPage = mAppSearchImpl.query("EmptyDatabase", "", searchSpec);
assertThat(searchResultPage.getResults()).isEmpty();
}
@Test
- public void testRemoveEmptyDatabase_NoExceptionThrown() throws Exception {
+ public void testRemoveEmptyDatabase_noExceptionThrown() throws Exception {
SearchSpec searchSpec =
- new SearchSpec.Builder().addSchema("FakeType").setTermMatch(
- TermMatchType.Code.PREFIX_VALUE).build();
- mAppSearchImpl.removeByQuery("EmptyDatabase",
- "", searchSpec);
+ new SearchSpec.Builder()
+ .addSchemaType("FakeType")
+ .setTermMatch(TermMatchType.Code.PREFIX_VALUE)
+ .build();
+ mAppSearchImpl.removeByQuery("EmptyDatabase", "", searchSpec);
searchSpec =
- new SearchSpec.Builder().addNamespace("FakeNamespace").setTermMatch(
- TermMatchType.Code.PREFIX_VALUE).build();
- mAppSearchImpl.removeByQuery("EmptyDatabase",
- "", searchSpec);
+ new SearchSpec.Builder()
+ .addNamespace("FakeNamespace")
+ .setTermMatch(TermMatchType.Code.PREFIX_VALUE)
+ .build();
+ mAppSearchImpl.removeByQuery("EmptyDatabase", "", searchSpec);
searchSpec = new SearchSpec.Builder().setTermMatch(TermMatchType.Code.PREFIX_VALUE).build();
mAppSearchImpl.removeByQuery("EmptyDatabase", "", searchSpec);
@@ -324,14 +480,46 @@ public class AppSearchImplTest {
Set<AppSearchSchema> schemas =
Collections.singleton(new AppSearchSchema.Builder("Email").build());
// Set schema Email to AppSearch database1
- mAppSearchImpl.setSchema("database1", schemas, /*forceOverride=*/false);
-
- // Create excepted schemaType proto.
- SchemaProto exceptedProto = SchemaProto.newBuilder()
- .addTypes(SchemaTypeConfigProto.newBuilder().setSchemaType("database1/Email"))
- .build();
- assertThat(mAppSearchImpl.getSchemaProto().getTypesList())
- .containsExactlyElementsIn(exceptedProto.getTypesList());
+ mAppSearchImpl.setSchema("database1", schemas, /*forceOverride=*/ false);
+
+ // Create expected schemaType proto.
+ SchemaProto expectedProto =
+ SchemaProto.newBuilder()
+ .addTypes(
+ SchemaTypeConfigProto.newBuilder().setSchemaType("database1/Email"))
+ .build();
+
+ List<SchemaTypeConfigProto> expectedTypes = new ArrayList<>();
+ expectedTypes.add(mVisibilitySchemaProto);
+ expectedTypes.addAll(expectedProto.getTypesList());
+ assertThat(mAppSearchImpl.getSchemaProtoLocked().getTypesList())
+ .containsExactlyElementsIn(expectedTypes);
+ }
+
+ @Test
+ public void testSetSchema_existingSchemaRetainsVisibilitySetting() throws Exception {
+ mAppSearchImpl.setSchema(
+ "database",
+ Collections.singleton(new AppSearchSchema.Builder("schema1").build()),
+ /*forceOverride=*/ false);
+ mAppSearchImpl.setVisibility("database", Set.of("schema1"));
+
+ // "schema1" is platform hidden now
+ assertThat(mAppSearchImpl.getVisibilityStoreLocked().getPlatformHiddenSchemas("database"))
+ .containsExactly("database/schema1");
+
+ // Add a new schema, and include the already-existing "schema1"
+ mAppSearchImpl.setSchema(
+ "database",
+ Set.of(
+ new AppSearchSchema.Builder("schema1").build(),
+ new AppSearchSchema.Builder("schema2").build()),
+ /*forceOverride=*/ false);
+
+ // Check that "schema1" is still platform hidden, but "schema2" is the default platform
+ // visible.
+ assertThat(mAppSearchImpl.getVisibilityStoreLocked().getPlatformHiddenSchemas("database"))
+ .containsExactly("database/schema1");
}
@Test
@@ -340,35 +528,52 @@ public class AppSearchImplTest {
schemas.add(new AppSearchSchema.Builder("Email").build());
schemas.add(new AppSearchSchema.Builder("Document").build());
// Set schema Email and Document to AppSearch database1
- mAppSearchImpl.setSchema("database1", schemas, /*forceOverride=*/false);
-
- // Create excepted schemaType proto.
- SchemaProto exceptedProto = SchemaProto.newBuilder()
- .addTypes(SchemaTypeConfigProto.newBuilder().setSchemaType("database1/Email"))
- .addTypes(SchemaTypeConfigProto.newBuilder().setSchemaType("database1/Document"))
- .build();
+ mAppSearchImpl.setSchema("database1", schemas, /*forceOverride=*/ false);
+
+ // Create expected schemaType proto.
+ SchemaProto expectedProto =
+ SchemaProto.newBuilder()
+ .addTypes(
+ SchemaTypeConfigProto.newBuilder().setSchemaType("database1/Email"))
+ .addTypes(
+ SchemaTypeConfigProto.newBuilder()
+ .setSchemaType("database1/Document"))
+ .build();
// Check both schema Email and Document saved correctly.
- assertThat(mAppSearchImpl.getSchemaProto().getTypesList())
- .containsExactlyElementsIn(exceptedProto.getTypesList());
+ List<SchemaTypeConfigProto> expectedTypes = new ArrayList<>();
+ expectedTypes.add(mVisibilitySchemaProto);
+ expectedTypes.addAll(expectedProto.getTypesList());
+ assertThat(mAppSearchImpl.getSchemaProtoLocked().getTypesList())
+ .containsExactlyElementsIn(expectedTypes);
- final Set<AppSearchSchema> finalSchemas = Collections.singleton(new AppSearchSchema.Builder(
- "Email").build());
+ final Set<AppSearchSchema> finalSchemas =
+ Collections.singleton(new AppSearchSchema.Builder("Email").build());
// Check the incompatible error has been thrown.
- AppSearchException e = expectThrows(AppSearchException.class, () ->
- mAppSearchImpl.setSchema("database1", finalSchemas, /*forceOverride=*/false));
+ AppSearchException e =
+ expectThrows(
+ AppSearchException.class,
+ () ->
+ mAppSearchImpl.setSchema(
+ "database1", finalSchemas, /*forceOverride=*/ false));
assertThat(e).hasMessageThat().contains("Schema is incompatible");
assertThat(e).hasMessageThat().contains("Deleted types: [database1/Document]");
// ForceOverride to delete.
- mAppSearchImpl.setSchema("database1", finalSchemas, /*forceOverride=*/true);
+ mAppSearchImpl.setSchema("database1", finalSchemas, /*forceOverride=*/ true);
// Check Document schema is removed.
- exceptedProto = SchemaProto.newBuilder()
- .addTypes(SchemaTypeConfigProto.newBuilder().setSchemaType("database1/Email"))
- .build();
- assertThat(mAppSearchImpl.getSchemaProto().getTypesList())
- .containsExactlyElementsIn(exceptedProto.getTypesList());
+ expectedProto =
+ SchemaProto.newBuilder()
+ .addTypes(
+ SchemaTypeConfigProto.newBuilder().setSchemaType("database1/Email"))
+ .build();
+
+ expectedTypes = new ArrayList<>();
+ expectedTypes.add(mVisibilitySchemaProto);
+ expectedTypes.addAll(expectedProto.getTypesList());
+ assertThat(mAppSearchImpl.getSchemaProtoLocked().getTypesList())
+ .containsExactlyElementsIn(expectedTypes);
}
@Test
@@ -379,35 +584,156 @@ public class AppSearchImplTest {
schemas.add(new AppSearchSchema.Builder("Document").build());
// Set schema Email and Document to AppSearch database1 and 2
- mAppSearchImpl.setSchema("database1", schemas, /*forceOverride=*/false);
- mAppSearchImpl.setSchema("database2", schemas, /*forceOverride=*/false);
-
- // Create excepted schemaType proto.
- SchemaProto exceptedProto = SchemaProto.newBuilder()
- .addTypes(SchemaTypeConfigProto.newBuilder().setSchemaType("database1/Email"))
- .addTypes(SchemaTypeConfigProto.newBuilder().setSchemaType("database1/Document"))
- .addTypes(SchemaTypeConfigProto.newBuilder().setSchemaType("database2/Email"))
- .addTypes(SchemaTypeConfigProto.newBuilder().setSchemaType("database2/Document"))
- .build();
+ mAppSearchImpl.setSchema("database1", schemas, /*forceOverride=*/ false);
+ mAppSearchImpl.setSchema("database2", schemas, /*forceOverride=*/ false);
+
+ // Create expected schemaType proto.
+ SchemaProto expectedProto =
+ SchemaProto.newBuilder()
+ .addTypes(
+ SchemaTypeConfigProto.newBuilder().setSchemaType("database1/Email"))
+ .addTypes(
+ SchemaTypeConfigProto.newBuilder()
+ .setSchemaType("database1/Document"))
+ .addTypes(
+ SchemaTypeConfigProto.newBuilder().setSchemaType("database2/Email"))
+ .addTypes(
+ SchemaTypeConfigProto.newBuilder()
+ .setSchemaType("database2/Document"))
+ .build();
// Check Email and Document is saved in database 1 and 2 correctly.
- assertThat(mAppSearchImpl.getSchemaProto().getTypesList())
- .containsExactlyElementsIn(exceptedProto.getTypesList());
+ List<SchemaTypeConfigProto> expectedTypes = new ArrayList<>();
+ expectedTypes.add(mVisibilitySchemaProto);
+ expectedTypes.addAll(expectedProto.getTypesList());
+ assertThat(mAppSearchImpl.getSchemaProtoLocked().getTypesList())
+ .containsExactlyElementsIn(expectedTypes);
// Save only Email to database1 this time.
schemas = Collections.singleton(new AppSearchSchema.Builder("Email").build());
- mAppSearchImpl.setSchema("database1", schemas, /*forceOverride=*/true);
+ mAppSearchImpl.setSchema("database1", schemas, /*forceOverride=*/ true);
- // Create excepted schemaType list, database 1 should only contain Email but database 2
+ // Create expected schemaType list, database 1 should only contain Email but database 2
// remains in same.
- exceptedProto = SchemaProto.newBuilder()
- .addTypes(SchemaTypeConfigProto.newBuilder().setSchemaType("database1/Email"))
- .addTypes(SchemaTypeConfigProto.newBuilder().setSchemaType("database2/Email"))
- .addTypes(SchemaTypeConfigProto.newBuilder().setSchemaType("database2/Document"))
- .build();
+ expectedProto =
+ SchemaProto.newBuilder()
+ .addTypes(
+ SchemaTypeConfigProto.newBuilder().setSchemaType("database1/Email"))
+ .addTypes(
+ SchemaTypeConfigProto.newBuilder().setSchemaType("database2/Email"))
+ .addTypes(
+ SchemaTypeConfigProto.newBuilder()
+ .setSchemaType("database2/Document"))
+ .build();
// Check nothing changed in database2.
- assertThat(mAppSearchImpl.getSchemaProto().getTypesList())
- .containsExactlyElementsIn(exceptedProto.getTypesList());
+ expectedTypes = new ArrayList<>();
+ expectedTypes.add(mVisibilitySchemaProto);
+ expectedTypes.addAll(expectedProto.getTypesList());
+ assertThat(mAppSearchImpl.getSchemaProtoLocked().getTypesList())
+ .containsExactlyElementsIn(expectedTypes);
+ }
+
+ @Test
+ public void testRemoveSchema_removedFromVisibilityStore() throws Exception {
+ mAppSearchImpl.setSchema(
+ "database",
+ Collections.singleton(new AppSearchSchema.Builder("schema1").build()),
+ /*forceOverride=*/ false);
+ mAppSearchImpl.setVisibility("database", Set.of("schema1"));
+
+ // "schema1" is platform hidden now
+ assertThat(mAppSearchImpl.getVisibilityStoreLocked().getPlatformHiddenSchemas("database"))
+ .containsExactly("database/schema1");
+
+ // Remove "schema1" by force overriding
+ mAppSearchImpl.setSchema("database", Collections.emptySet(), /*forceOverride=*/ true);
+
+ // Check that "schema1" is no longer considered platform hidden
+ assertThat(mAppSearchImpl.getVisibilityStoreLocked().getPlatformHiddenSchemas("database"))
+ .isEmpty();
+
+ // Add "schema1" back, it gets default visibility settings which means it's not platform
+ // hidden.
+ mAppSearchImpl.setSchema(
+ "database",
+ Collections.singleton(new AppSearchSchema.Builder("schema1").build()),
+ /*forceOverride=*/ false);
+ assertThat(mAppSearchImpl.getVisibilityStoreLocked().getPlatformHiddenSchemas("database"))
+ .isEmpty();
+ }
+
+ @Test
+ public void testSetVisibility_defaultPlatformVisible() throws Exception {
+ mAppSearchImpl.setSchema(
+ "database",
+ Collections.singleton(new AppSearchSchema.Builder("Schema").build()),
+ /*forceOverride=*/ false);
+ assertThat(mAppSearchImpl.getVisibilityStoreLocked().getPlatformHiddenSchemas("database"))
+ .isEmpty();
+ }
+
+ @Test
+ public void testSetVisibility_platformHidden() throws Exception {
+ mAppSearchImpl.setSchema(
+ "database",
+ Collections.singleton(new AppSearchSchema.Builder("Schema").build()),
+ /*forceOverride=*/ false);
+ mAppSearchImpl.setVisibility("database", Set.of("Schema"));
+ assertThat(mAppSearchImpl.getVisibilityStoreLocked().getPlatformHiddenSchemas("database"))
+ .containsExactly("database/Schema");
+ }
+
+ @Test
+ public void testSetVisibility_unknownSchema() throws Exception {
+ mAppSearchImpl.setSchema(
+ "database",
+ Collections.singleton(new AppSearchSchema.Builder("Schema").build()),
+ /*forceOverride=*/ false);
+
+ // We'll throw an exception if a client tries to set visibility on a schema we don't know
+ // about.
+ AppSearchException e =
+ expectThrows(
+ AppSearchException.class,
+ () -> mAppSearchImpl.setVisibility("database", Set.of("UnknownSchema")));
+ assertThat(e).hasMessageThat().contains("Unknown schema(s)");
+ }
+
+ @Test
+ public void testHasSchemaType() throws Exception {
+ // Nothing exists yet
+ assertThat(mAppSearchImpl.hasSchemaTypeLocked("database", "Schema")).isFalse();
+
+ mAppSearchImpl.setSchema(
+ "database",
+ Collections.singleton(new AppSearchSchema.Builder("Schema").build()),
+ /*forceOverride=*/ false);
+ assertThat(mAppSearchImpl.hasSchemaTypeLocked("database", "Schema")).isTrue();
+
+ assertThat(mAppSearchImpl.hasSchemaTypeLocked("database", "UnknownSchema")).isFalse();
+ }
+
+ @Test
+ public void testGetDatabases() throws Exception {
+ // No client databases exist yet, but the VisibilityStore's does
+ assertThat(mAppSearchImpl.getDatabasesLocked())
+ .containsExactly(VisibilityStore.DATABASE_NAME);
+
+ // Has database1
+ mAppSearchImpl.setSchema(
+ "database1",
+ Collections.singleton(new AppSearchSchema.Builder("schema").build()),
+ /*forceOverride=*/ false);
+ assertThat(mAppSearchImpl.getDatabasesLocked())
+ .containsExactly(VisibilityStore.DATABASE_NAME, "database1");
+
+ // Has both databases
+ mAppSearchImpl.setSchema(
+ "database2",
+ Collections.singleton(new AppSearchSchema.Builder("schema").build()),
+ /*forceOverride=*/ false);
+ assertThat(mAppSearchImpl.getDatabasesLocked())
+ .containsExactly(VisibilityStore.DATABASE_NAME, "database1", "database2");
}
}
diff --git a/services/tests/servicestests/src/com/android/server/appsearch/external/localstorage/VisibilityStoreTest.java b/services/tests/servicestests/src/com/android/server/appsearch/external/localstorage/VisibilityStoreTest.java
new file mode 100644
index 000000000000..dfe2de6538a4
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/appsearch/external/localstorage/VisibilityStoreTest.java
@@ -0,0 +1,74 @@
+/*
+ * 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 com.android.server.appsearch.external.localstorage;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.TemporaryFolder;
+
+import java.util.Collections;
+import java.util.Set;
+
+public class VisibilityStoreTest {
+
+ @Rule public TemporaryFolder mTemporaryFolder = new TemporaryFolder();
+ private AppSearchImpl mAppSearchImpl;
+ private VisibilityStore mVisibilityStore;
+
+ @Before
+ public void setUp() throws Exception {
+ mAppSearchImpl = AppSearchImpl.create(mTemporaryFolder.newFolder());
+ mVisibilityStore = mAppSearchImpl.getVisibilityStoreLocked();
+ }
+
+ @Test
+ public void testSetVisibility() throws Exception {
+ mVisibilityStore.setVisibility(
+ "database", /*platformHiddenSchemas=*/ Set.of("schema1", "schema2"));
+ assertThat(mVisibilityStore.getPlatformHiddenSchemas("database"))
+ .containsExactly("schema1", "schema2");
+
+ // New .setVisibility() call completely overrides previous visibility settings. So
+ // "schema1" isn't preserved.
+ mVisibilityStore.setVisibility(
+ "database", /*platformHiddenSchemas=*/ Set.of("schema1", "schema3"));
+ assertThat(mVisibilityStore.getPlatformHiddenSchemas("database"))
+ .containsExactly("schema1", "schema3");
+
+ mVisibilityStore.setVisibility(
+ "database", /*platformHiddenSchemas=*/ Collections.emptySet());
+ assertThat(mVisibilityStore.getPlatformHiddenSchemas("database")).isEmpty();
+ }
+
+ @Test
+ public void testRemoveSchemas() throws Exception {
+ mVisibilityStore.setVisibility(
+ "database", /*platformHiddenSchemas=*/ Set.of("schema1", "schema2"));
+
+ // Removed just schema1
+ mVisibilityStore.updateSchemas("database", /*schemasToRemove=*/ Set.of("schema1"));
+ assertThat(mVisibilityStore.getPlatformHiddenSchemas("database"))
+ .containsExactly("schema2");
+
+ // Removed everything now
+ mVisibilityStore.updateSchemas("database", /*schemasToRemove=*/ Set.of("schema2"));
+ assertThat(mVisibilityStore.getPlatformHiddenSchemas("database")).isEmpty();
+ }
+}
diff --git a/services/tests/servicestests/src/com/android/server/appsearch/external/localstorage/converter/GenericDocumentToProtoConverterTest.java b/services/tests/servicestests/src/com/android/server/appsearch/external/localstorage/converter/GenericDocumentToProtoConverterTest.java
index 85d4f01f8d41..98392a71be58 100644
--- a/services/tests/servicestests/src/com/android/server/appsearch/external/localstorage/converter/GenericDocumentToProtoConverterTest.java
+++ b/services/tests/servicestests/src/com/android/server/appsearch/external/localstorage/converter/GenericDocumentToProtoConverterTest.java
@@ -32,18 +32,18 @@ import java.util.HashMap;
import java.util.List;
public class GenericDocumentToProtoConverterTest {
- private static final byte[] BYTE_ARRAY_1 = new byte[]{(byte) 1, (byte) 2, (byte) 3};
- private static final byte[] BYTE_ARRAY_2 = new byte[]{(byte) 4, (byte) 5, (byte) 6, (byte) 7};
+ private static final byte[] BYTE_ARRAY_1 = new byte[] {(byte) 1, (byte) 2, (byte) 3};
+ private static final byte[] BYTE_ARRAY_2 = new byte[] {(byte) 4, (byte) 5, (byte) 6, (byte) 7};
private static final GenericDocument DOCUMENT_PROPERTIES_1 =
new GenericDocument.Builder<GenericDocument.Builder<?>>(
- "sDocumentProperties1", "sDocumentPropertiesSchemaType1")
- .setCreationTimestampMillis(12345L)
- .build();
+ "sDocumentProperties1", "sDocumentPropertiesSchemaType1")
+ .setCreationTimestampMillis(12345L)
+ .build();
private static final GenericDocument DOCUMENT_PROPERTIES_2 =
new GenericDocument.Builder<GenericDocument.Builder<?>>(
- "sDocumentProperties2", "sDocumentPropertiesSchemaType2")
- .setCreationTimestampMillis(6789L)
- .build();
+ "sDocumentProperties2", "sDocumentPropertiesSchemaType2")
+ .setCreationTimestampMillis(6789L)
+ .build();
@Test
public void testDocumentProtoConvert() {
@@ -63,32 +63,42 @@ public class GenericDocumentToProtoConverterTest {
.build();
// Create the Document proto. Need to sort the property order by key.
- DocumentProto.Builder documentProtoBuilder = DocumentProto.newBuilder()
- .setUri("uri1")
- .setSchema("schemaType1")
- .setCreationTimestampMs(5L)
- .setScore(1)
- .setTtlMs(1L)
- .setNamespace("namespace");
+ DocumentProto.Builder documentProtoBuilder =
+ DocumentProto.newBuilder()
+ .setUri("uri1")
+ .setSchema("schemaType1")
+ .setCreationTimestampMs(5L)
+ .setScore(1)
+ .setTtlMs(1L)
+ .setNamespace("namespace");
HashMap<String, PropertyProto.Builder> propertyProtoMap = new HashMap<>();
- propertyProtoMap.put("longKey1",
- PropertyProto.newBuilder().setName("longKey1").addInt64Values(1L));
- propertyProtoMap.put("doubleKey1",
+ propertyProtoMap.put(
+ "longKey1", PropertyProto.newBuilder().setName("longKey1").addInt64Values(1L));
+ propertyProtoMap.put(
+ "doubleKey1",
PropertyProto.newBuilder().setName("doubleKey1").addDoubleValues(1.0));
- propertyProtoMap.put("booleanKey1",
+ propertyProtoMap.put(
+ "booleanKey1",
PropertyProto.newBuilder().setName("booleanKey1").addBooleanValues(true));
- propertyProtoMap.put("stringKey1",
+ propertyProtoMap.put(
+ "stringKey1",
PropertyProto.newBuilder().setName("stringKey1").addStringValues("test-value1"));
- propertyProtoMap.put("byteKey1",
- PropertyProto.newBuilder().setName("byteKey1")
+ propertyProtoMap.put(
+ "byteKey1",
+ PropertyProto.newBuilder()
+ .setName("byteKey1")
.addBytesValues(ByteString.copyFrom(BYTE_ARRAY_1))
.addBytesValues(ByteString.copyFrom(BYTE_ARRAY_2)));
- propertyProtoMap.put("documentKey1",
- PropertyProto.newBuilder().setName("documentKey1")
+ propertyProtoMap.put(
+ "documentKey1",
+ PropertyProto.newBuilder()
+ .setName("documentKey1")
.addDocumentValues(
GenericDocumentToProtoConverter.convert(DOCUMENT_PROPERTIES_1)));
- propertyProtoMap.put("documentKey2",
- PropertyProto.newBuilder().setName("documentKey2")
+ propertyProtoMap.put(
+ "documentKey2",
+ PropertyProto.newBuilder()
+ .setName("documentKey2")
.addDocumentValues(
GenericDocumentToProtoConverter.convert(DOCUMENT_PROPERTIES_2)));
List<String> sortedKey = new ArrayList<>(propertyProtoMap.keySet());
@@ -97,8 +107,7 @@ public class GenericDocumentToProtoConverterTest {
documentProtoBuilder.addProperties(propertyProtoMap.get(key));
}
DocumentProto documentProto = documentProtoBuilder.build();
- assertThat(GenericDocumentToProtoConverter.convert(document))
- .isEqualTo(documentProto);
+ assertThat(GenericDocumentToProtoConverter.convert(document)).isEqualTo(documentProto);
assertThat(document).isEqualTo(GenericDocumentToProtoConverter.convert(documentProto));
}
}
diff --git a/services/tests/servicestests/src/com/android/server/appsearch/external/localstorage/converter/SchemaToProtoConverterTest.java b/services/tests/servicestests/src/com/android/server/appsearch/external/localstorage/converter/SchemaToProtoConverterTest.java
index 7336c3c36417..dedfca42ff90 100644
--- a/services/tests/servicestests/src/com/android/server/appsearch/external/localstorage/converter/SchemaToProtoConverterTest.java
+++ b/services/tests/servicestests/src/com/android/server/appsearch/external/localstorage/converter/SchemaToProtoConverterTest.java
@@ -20,9 +20,9 @@ import static com.google.common.truth.Truth.assertThat;
import android.app.appsearch.AppSearchSchema;
-import com.android.server.appsearch.proto.IndexingConfig;
import com.android.server.appsearch.proto.PropertyConfigProto;
import com.android.server.appsearch.proto.SchemaTypeConfigProto;
+import com.android.server.appsearch.proto.StringIndexingConfig;
import com.android.server.appsearch.proto.TermMatchType;
import org.junit.Test;
@@ -30,84 +30,126 @@ import org.junit.Test;
public class SchemaToProtoConverterTest {
@Test
public void testGetProto_Email() {
- AppSearchSchema emailSchema = new AppSearchSchema.Builder("Email")
- .addProperty(new AppSearchSchema.PropertyConfig.Builder("subject")
- .setDataType(AppSearchSchema.PropertyConfig.DATA_TYPE_STRING)
- .setCardinality(AppSearchSchema.PropertyConfig.CARDINALITY_OPTIONAL)
- .setIndexingType(AppSearchSchema.PropertyConfig.INDEXING_TYPE_PREFIXES)
- .setTokenizerType(AppSearchSchema.PropertyConfig.TOKENIZER_TYPE_PLAIN)
- .build()
- ).addProperty(new AppSearchSchema.PropertyConfig.Builder("body")
- .setDataType(AppSearchSchema.PropertyConfig.DATA_TYPE_STRING)
- .setCardinality(AppSearchSchema.PropertyConfig.CARDINALITY_OPTIONAL)
- .setIndexingType(AppSearchSchema.PropertyConfig.INDEXING_TYPE_PREFIXES)
- .setTokenizerType(AppSearchSchema.PropertyConfig.TOKENIZER_TYPE_PLAIN)
- .build()
- ).build();
+ AppSearchSchema emailSchema =
+ new AppSearchSchema.Builder("Email")
+ .addProperty(
+ new AppSearchSchema.PropertyConfig.Builder("subject")
+ .setDataType(
+ AppSearchSchema.PropertyConfig.DATA_TYPE_STRING)
+ .setCardinality(
+ AppSearchSchema.PropertyConfig.CARDINALITY_OPTIONAL)
+ .setIndexingType(
+ AppSearchSchema.PropertyConfig
+ .INDEXING_TYPE_PREFIXES)
+ .setTokenizerType(
+ AppSearchSchema.PropertyConfig.TOKENIZER_TYPE_PLAIN)
+ .build())
+ .addProperty(
+ new AppSearchSchema.PropertyConfig.Builder("body")
+ .setDataType(
+ AppSearchSchema.PropertyConfig.DATA_TYPE_STRING)
+ .setCardinality(
+ AppSearchSchema.PropertyConfig.CARDINALITY_OPTIONAL)
+ .setIndexingType(
+ AppSearchSchema.PropertyConfig
+ .INDEXING_TYPE_PREFIXES)
+ .setTokenizerType(
+ AppSearchSchema.PropertyConfig.TOKENIZER_TYPE_PLAIN)
+ .build())
+ .build();
- SchemaTypeConfigProto expectedEmailProto = SchemaTypeConfigProto.newBuilder()
- .setSchemaType("Email")
- .addProperties(PropertyConfigProto.newBuilder()
- .setPropertyName("subject")
- .setDataType(PropertyConfigProto.DataType.Code.STRING)
- .setCardinality(PropertyConfigProto.Cardinality.Code.OPTIONAL)
- .setIndexingConfig(
- com.android.server.appsearch.proto.IndexingConfig.newBuilder()
- .setTokenizerType(IndexingConfig.TokenizerType.Code.PLAIN)
- .setTermMatchType(TermMatchType.Code.PREFIX)
- )
- ).addProperties(PropertyConfigProto.newBuilder()
- .setPropertyName("body")
- .setDataType(PropertyConfigProto.DataType.Code.STRING)
- .setCardinality(PropertyConfigProto.Cardinality.Code.OPTIONAL)
- .setIndexingConfig(
- com.android.server.appsearch.proto.IndexingConfig.newBuilder()
- .setTokenizerType(IndexingConfig.TokenizerType.Code.PLAIN)
- .setTermMatchType(TermMatchType.Code.PREFIX)
- )
- ).build();
+ SchemaTypeConfigProto expectedEmailProto =
+ SchemaTypeConfigProto.newBuilder()
+ .setSchemaType("Email")
+ .addProperties(
+ PropertyConfigProto.newBuilder()
+ .setPropertyName("subject")
+ .setDataType(PropertyConfigProto.DataType.Code.STRING)
+ .setCardinality(
+ PropertyConfigProto.Cardinality.Code.OPTIONAL)
+ .setStringIndexingConfig(
+ StringIndexingConfig.newBuilder()
+ .setTokenizerType(
+ StringIndexingConfig.TokenizerType
+ .Code.PLAIN)
+ .setTermMatchType(
+ TermMatchType.Code.PREFIX)))
+ .addProperties(
+ PropertyConfigProto.newBuilder()
+ .setPropertyName("body")
+ .setDataType(PropertyConfigProto.DataType.Code.STRING)
+ .setCardinality(
+ PropertyConfigProto.Cardinality.Code.OPTIONAL)
+ .setStringIndexingConfig(
+ StringIndexingConfig.newBuilder()
+ .setTokenizerType(
+ StringIndexingConfig.TokenizerType
+ .Code.PLAIN)
+ .setTermMatchType(
+ TermMatchType.Code.PREFIX)))
+ .build();
assertThat(SchemaToProtoConverter.convert(emailSchema)).isEqualTo(expectedEmailProto);
}
@Test
public void testGetProto_MusicRecording() {
- AppSearchSchema musicRecordingSchema = new AppSearchSchema.Builder("MusicRecording")
- .addProperty(new AppSearchSchema.PropertyConfig.Builder("artist")
- .setDataType(AppSearchSchema.PropertyConfig.DATA_TYPE_STRING)
- .setCardinality(AppSearchSchema.PropertyConfig.CARDINALITY_REPEATED)
- .setIndexingType(AppSearchSchema.PropertyConfig.INDEXING_TYPE_PREFIXES)
- .setTokenizerType(AppSearchSchema.PropertyConfig.TOKENIZER_TYPE_PLAIN)
- .build()
- ).addProperty(new AppSearchSchema.PropertyConfig.Builder("pubDate")
- .setDataType(AppSearchSchema.PropertyConfig.DATA_TYPE_INT64)
- .setCardinality(AppSearchSchema.PropertyConfig.CARDINALITY_OPTIONAL)
- .setIndexingType(AppSearchSchema.PropertyConfig.INDEXING_TYPE_NONE)
- .setTokenizerType(AppSearchSchema.PropertyConfig.TOKENIZER_TYPE_NONE)
- .build()
- ).build();
+ AppSearchSchema musicRecordingSchema =
+ new AppSearchSchema.Builder("MusicRecording")
+ .addProperty(
+ new AppSearchSchema.PropertyConfig.Builder("artist")
+ .setDataType(
+ AppSearchSchema.PropertyConfig.DATA_TYPE_STRING)
+ .setCardinality(
+ AppSearchSchema.PropertyConfig.CARDINALITY_REPEATED)
+ .setIndexingType(
+ AppSearchSchema.PropertyConfig
+ .INDEXING_TYPE_PREFIXES)
+ .setTokenizerType(
+ AppSearchSchema.PropertyConfig.TOKENIZER_TYPE_PLAIN)
+ .build())
+ .addProperty(
+ new AppSearchSchema.PropertyConfig.Builder("pubDate")
+ .setDataType(AppSearchSchema.PropertyConfig.DATA_TYPE_INT64)
+ .setCardinality(
+ AppSearchSchema.PropertyConfig.CARDINALITY_OPTIONAL)
+ .setIndexingType(
+ AppSearchSchema.PropertyConfig.INDEXING_TYPE_NONE)
+ .setTokenizerType(
+ AppSearchSchema.PropertyConfig.TOKENIZER_TYPE_NONE)
+ .build())
+ .build();
- SchemaTypeConfigProto expectedMusicRecordingProto = SchemaTypeConfigProto.newBuilder()
- .setSchemaType("MusicRecording")
- .addProperties(PropertyConfigProto.newBuilder()
- .setPropertyName("artist")
- .setDataType(PropertyConfigProto.DataType.Code.STRING)
- .setCardinality(PropertyConfigProto.Cardinality.Code.REPEATED)
- .setIndexingConfig(
- com.android.server.appsearch.proto.IndexingConfig.newBuilder()
- .setTokenizerType(IndexingConfig.TokenizerType.Code.PLAIN)
- .setTermMatchType(TermMatchType.Code.PREFIX)
- )
- ).addProperties(PropertyConfigProto.newBuilder()
- .setPropertyName("pubDate")
- .setDataType(PropertyConfigProto.DataType.Code.INT64)
- .setCardinality(PropertyConfigProto.Cardinality.Code.OPTIONAL)
- .setIndexingConfig(
- com.android.server.appsearch.proto.IndexingConfig.newBuilder()
- .setTokenizerType(IndexingConfig.TokenizerType.Code.NONE)
- .setTermMatchType(TermMatchType.Code.UNKNOWN)
- )
- ).build();
+ SchemaTypeConfigProto expectedMusicRecordingProto =
+ SchemaTypeConfigProto.newBuilder()
+ .setSchemaType("MusicRecording")
+ .addProperties(
+ PropertyConfigProto.newBuilder()
+ .setPropertyName("artist")
+ .setDataType(PropertyConfigProto.DataType.Code.STRING)
+ .setCardinality(
+ PropertyConfigProto.Cardinality.Code.REPEATED)
+ .setStringIndexingConfig(
+ StringIndexingConfig.newBuilder()
+ .setTokenizerType(
+ StringIndexingConfig.TokenizerType
+ .Code.PLAIN)
+ .setTermMatchType(
+ TermMatchType.Code.PREFIX)))
+ .addProperties(
+ PropertyConfigProto.newBuilder()
+ .setPropertyName("pubDate")
+ .setDataType(PropertyConfigProto.DataType.Code.INT64)
+ .setCardinality(
+ PropertyConfigProto.Cardinality.Code.OPTIONAL)
+ .setStringIndexingConfig(
+ StringIndexingConfig.newBuilder()
+ .setTokenizerType(
+ StringIndexingConfig.TokenizerType
+ .Code.NONE)
+ .setTermMatchType(
+ TermMatchType.Code.UNKNOWN)))
+ .build();
assertThat(SchemaToProtoConverter.convert(musicRecordingSchema))
.isEqualTo(expectedMusicRecordingProto);
diff --git a/services/tests/servicestests/src/com/android/server/appsearch/external/localstorage/converter/SnippetTest.java b/services/tests/servicestests/src/com/android/server/appsearch/external/localstorage/converter/SnippetTest.java
index 2e9286c6b2ad..518f53205588 100644
--- a/services/tests/servicestests/src/com/android/server/appsearch/external/localstorage/converter/SnippetTest.java
+++ b/services/tests/servicestests/src/com/android/server/appsearch/external/localstorage/converter/SnippetTest.java
@@ -36,9 +36,10 @@ public class SnippetTest {
public void testSingleStringSnippet() {
final String propertyKeyString = "content";
- final String propertyValueString = "A commonly used fake word is foo.\n"
- + " Another nonsense word that’s used a lot\n"
- + " is bar.\n";
+ final String propertyValueString =
+ "A commonly used fake word is foo.\n"
+ + " Another nonsense word that’s used a lot\n"
+ + " is bar.\n";
final String uri = "uri1";
final String schemaType = "schema1";
final String searchWord = "foo";
@@ -46,34 +47,39 @@ public class SnippetTest {
final String window = "is foo";
// Building the SearchResult received from query.
- PropertyProto property = PropertyProto.newBuilder()
- .setName(propertyKeyString)
- .addStringValues(propertyValueString)
- .build();
- DocumentProto documentProto = DocumentProto.newBuilder()
- .setUri(uri)
- .setSchema(schemaType)
- .addProperties(property)
- .build();
- SnippetProto snippetProto = SnippetProto.newBuilder()
- .addEntries(SnippetProto.EntryProto.newBuilder()
- .setPropertyName(propertyKeyString)
- .addSnippetMatches(SnippetMatchProto.newBuilder()
- .setValuesIndex(0)
- .setExactMatchPosition(29)
- .setExactMatchBytes(3)
- .setWindowPosition(26)
- .setWindowBytes(6)
- .build())
- .build())
- .build();
- SearchResultProto.ResultProto resultProto = SearchResultProto.ResultProto.newBuilder()
- .setDocument(documentProto)
- .setSnippet(snippetProto)
- .build();
- SearchResultProto searchResultProto = SearchResultProto.newBuilder()
- .addResults(resultProto)
- .build();
+ PropertyProto property =
+ PropertyProto.newBuilder()
+ .setName(propertyKeyString)
+ .addStringValues(propertyValueString)
+ .build();
+ DocumentProto documentProto =
+ DocumentProto.newBuilder()
+ .setUri(uri)
+ .setSchema(schemaType)
+ .addProperties(property)
+ .build();
+ SnippetProto snippetProto =
+ SnippetProto.newBuilder()
+ .addEntries(
+ SnippetProto.EntryProto.newBuilder()
+ .setPropertyName(propertyKeyString)
+ .addSnippetMatches(
+ SnippetMatchProto.newBuilder()
+ .setValuesIndex(0)
+ .setExactMatchPosition(29)
+ .setExactMatchBytes(3)
+ .setWindowPosition(26)
+ .setWindowBytes(6)
+ .build())
+ .build())
+ .build();
+ SearchResultProto.ResultProto resultProto =
+ SearchResultProto.ResultProto.newBuilder()
+ .setDocument(documentProto)
+ .setSnippet(snippetProto)
+ .build();
+ SearchResultProto searchResultProto =
+ SearchResultProto.newBuilder().addResults(resultProto).build();
// Making ResultReader and getting Snippet values.
SearchResultPage searchResultPage =
@@ -83,11 +89,11 @@ public class SnippetTest {
assertThat(match.getPropertyPath()).isEqualTo(propertyKeyString);
assertThat(match.getFullText()).isEqualTo(propertyValueString);
assertThat(match.getExactMatch()).isEqualTo(exactMatch);
- assertThat(match.getExactMatchPosition()).isEqualTo(
- new SearchResult.MatchRange(/*lower=*/29, /*upper=*/32));
+ assertThat(match.getExactMatchPosition())
+ .isEqualTo(new SearchResult.MatchRange(/*lower=*/ 29, /*upper=*/ 32));
assertThat(match.getFullText()).isEqualTo(propertyValueString);
- assertThat(match.getSnippetPosition()).isEqualTo(
- new SearchResult.MatchRange(/*lower=*/26, /*upper=*/32));
+ assertThat(match.getSnippetPosition())
+ .isEqualTo(new SearchResult.MatchRange(/*lower=*/ 26, /*upper=*/ 32));
assertThat(match.getSnippet()).isEqualTo(window);
}
}
@@ -97,9 +103,10 @@ public class SnippetTest {
public void testNoSnippets() throws Exception {
final String propertyKeyString = "content";
- final String propertyValueString = "A commonly used fake word is foo.\n"
- + " Another nonsense word that’s used a lot\n"
- + " is bar.\n";
+ final String propertyValueString =
+ "A commonly used fake word is foo.\n"
+ + " Another nonsense word that’s used a lot\n"
+ + " is bar.\n";
final String uri = "uri1";
final String schemaType = "schema1";
final String searchWord = "foo";
@@ -107,21 +114,21 @@ public class SnippetTest {
final String window = "is foo";
// Building the SearchResult received from query.
- PropertyProto property = PropertyProto.newBuilder()
- .setName(propertyKeyString)
- .addStringValues(propertyValueString)
- .build();
- DocumentProto documentProto = DocumentProto.newBuilder()
- .setUri(uri)
- .setSchema(schemaType)
- .addProperties(property)
- .build();
- SearchResultProto.ResultProto resultProto = SearchResultProto.ResultProto.newBuilder()
- .setDocument(documentProto)
- .build();
- SearchResultProto searchResultProto = SearchResultProto.newBuilder()
- .addResults(resultProto)
- .build();
+ PropertyProto property =
+ PropertyProto.newBuilder()
+ .setName(propertyKeyString)
+ .addStringValues(propertyValueString)
+ .build();
+ DocumentProto documentProto =
+ DocumentProto.newBuilder()
+ .setUri(uri)
+ .setSchema(schemaType)
+ .addProperties(property)
+ .build();
+ SearchResultProto.ResultProto resultProto =
+ SearchResultProto.ResultProto.newBuilder().setDocument(documentProto).build();
+ SearchResultProto searchResultProto =
+ SearchResultProto.newBuilder().addResults(resultProto).build();
SearchResultPage searchResultPage =
SearchResultToProtoConverter.convertToSearchResultPage(searchResultProto);
@@ -135,54 +142,57 @@ public class SnippetTest {
final String searchWord = "Test";
// Building the SearchResult received from query.
- PropertyProto property1 = PropertyProto.newBuilder()
- .setName("sender.name")
- .addStringValues("Test Name Jr.")
- .build();
- PropertyProto property2 = PropertyProto.newBuilder()
- .setName("sender.email")
- .addStringValues("TestNameJr@gmail.com")
- .build();
- DocumentProto documentProto = DocumentProto.newBuilder()
- .setUri("uri1")
- .setSchema("schema1")
- .addProperties(property1)
- .addProperties(property2)
- .build();
- SnippetProto snippetProto = SnippetProto.newBuilder()
- .addEntries(
- SnippetProto.EntryProto.newBuilder()
- .setPropertyName("sender.name")
- .addSnippetMatches(
- SnippetMatchProto.newBuilder()
- .setValuesIndex(0)
- .setExactMatchPosition(0)
- .setExactMatchBytes(4)
- .setWindowPosition(0)
- .setWindowBytes(9)
- .build())
- .build())
- .addEntries(
- SnippetProto.EntryProto.newBuilder()
- .setPropertyName("sender.email")
- .addSnippetMatches(
- SnippetMatchProto.newBuilder()
- .setValuesIndex(0)
- .setExactMatchPosition(0)
- .setExactMatchBytes(20)
- .setWindowPosition(0)
- .setWindowBytes(20)
- .build())
- .build()
- )
- .build();
- SearchResultProto.ResultProto resultProto = SearchResultProto.ResultProto.newBuilder()
- .setDocument(documentProto)
- .setSnippet(snippetProto)
- .build();
- SearchResultProto searchResultProto = SearchResultProto.newBuilder()
- .addResults(resultProto)
- .build();
+ PropertyProto property1 =
+ PropertyProto.newBuilder()
+ .setName("sender.name")
+ .addStringValues("Test Name Jr.")
+ .build();
+ PropertyProto property2 =
+ PropertyProto.newBuilder()
+ .setName("sender.email")
+ .addStringValues("TestNameJr@gmail.com")
+ .build();
+ DocumentProto documentProto =
+ DocumentProto.newBuilder()
+ .setUri("uri1")
+ .setSchema("schema1")
+ .addProperties(property1)
+ .addProperties(property2)
+ .build();
+ SnippetProto snippetProto =
+ SnippetProto.newBuilder()
+ .addEntries(
+ SnippetProto.EntryProto.newBuilder()
+ .setPropertyName("sender.name")
+ .addSnippetMatches(
+ SnippetMatchProto.newBuilder()
+ .setValuesIndex(0)
+ .setExactMatchPosition(0)
+ .setExactMatchBytes(4)
+ .setWindowPosition(0)
+ .setWindowBytes(9)
+ .build())
+ .build())
+ .addEntries(
+ SnippetProto.EntryProto.newBuilder()
+ .setPropertyName("sender.email")
+ .addSnippetMatches(
+ SnippetMatchProto.newBuilder()
+ .setValuesIndex(0)
+ .setExactMatchPosition(0)
+ .setExactMatchBytes(20)
+ .setWindowPosition(0)
+ .setWindowBytes(20)
+ .build())
+ .build())
+ .build();
+ SearchResultProto.ResultProto resultProto =
+ SearchResultProto.ResultProto.newBuilder()
+ .setDocument(documentProto)
+ .setSnippet(snippetProto)
+ .build();
+ SearchResultProto searchResultProto =
+ SearchResultProto.newBuilder().addResults(resultProto).build();
// Making ResultReader and getting Snippet values.
SearchResultPage searchResultPage =
@@ -192,21 +202,21 @@ public class SnippetTest {
SearchResult.MatchInfo match1 = result.getMatches().get(0);
assertThat(match1.getPropertyPath()).isEqualTo("sender.name");
assertThat(match1.getFullText()).isEqualTo("Test Name Jr.");
- assertThat(match1.getExactMatchPosition()).isEqualTo(
- new SearchResult.MatchRange(/*lower=*/0, /*upper=*/4));
+ assertThat(match1.getExactMatchPosition())
+ .isEqualTo(new SearchResult.MatchRange(/*lower=*/ 0, /*upper=*/ 4));
assertThat(match1.getExactMatch()).isEqualTo("Test");
- assertThat(match1.getSnippetPosition()).isEqualTo(
- new SearchResult.MatchRange(/*lower=*/0, /*upper=*/9));
+ assertThat(match1.getSnippetPosition())
+ .isEqualTo(new SearchResult.MatchRange(/*lower=*/ 0, /*upper=*/ 9));
assertThat(match1.getSnippet()).isEqualTo("Test Name");
SearchResult.MatchInfo match2 = result.getMatches().get(1);
assertThat(match2.getPropertyPath()).isEqualTo("sender.email");
assertThat(match2.getFullText()).isEqualTo("TestNameJr@gmail.com");
- assertThat(match2.getExactMatchPosition()).isEqualTo(
- new SearchResult.MatchRange(/*lower=*/0, /*upper=*/20));
+ assertThat(match2.getExactMatchPosition())
+ .isEqualTo(new SearchResult.MatchRange(/*lower=*/ 0, /*upper=*/ 20));
assertThat(match2.getExactMatch()).isEqualTo("TestNameJr@gmail.com");
- assertThat(match2.getSnippetPosition()).isEqualTo(
- new SearchResult.MatchRange(/*lower=*/0, /*upper=*/20));
+ assertThat(match2.getSnippetPosition())
+ .isEqualTo(new SearchResult.MatchRange(/*lower=*/ 0, /*upper=*/ 20));
assertThat(match2.getSnippet()).isEqualTo("TestNameJr@gmail.com");
}
}
diff --git a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDevicePlaybackTest.java b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDevicePlaybackTest.java
index ce3b8d618747..dfeed1362b81 100644
--- a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDevicePlaybackTest.java
+++ b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDevicePlaybackTest.java
@@ -1248,4 +1248,91 @@ public class HdmiCecLocalDevicePlaybackTest {
assertThat(mHdmiControlService.getActiveSource().getPhysicalAddress()).isEqualTo(
externalDevice.getPhysicalAddress());
}
+
+ @Test
+ public void queryDisplayStatus() {
+ mHdmiControlService.queryDisplayStatus(new IHdmiControlCallback.Stub() {
+ @Override
+ public void onComplete(int result) {
+ }
+ });
+ mTestLooper.dispatchAll();
+
+ HdmiCecMessage expectedMessage = HdmiCecMessageBuilder.buildGiveDevicePowerStatus(
+ mPlaybackLogicalAddress, Constants.ADDR_TV);
+ assertThat(mNativeWrapper.getResultMessages()).contains(expectedMessage);
+ }
+
+ @Test
+ public void toggleAndFollowTvPower_ToTv_TvStatusOn() {
+ mHdmiCecLocalDevicePlayback.mService.getHdmiCecConfig().setStringValue(
+ HdmiControlManager.CEC_SETTING_NAME_SEND_STANDBY_ON_SLEEP,
+ HdmiControlManager.SEND_STANDBY_ON_SLEEP_TO_TV);
+ mStandby = false;
+ mHdmiControlService.toggleAndFollowTvPower();
+ HdmiCecMessage tvPowerStatus = HdmiCecMessageBuilder.buildReportPowerStatus(ADDR_TV,
+ mPlaybackLogicalAddress, HdmiControlManager.POWER_STATUS_ON);
+ assertThat(mHdmiCecLocalDevicePlayback.dispatchMessage(tvPowerStatus)).isTrue();
+ mTestLooper.dispatchAll();
+
+ HdmiCecMessage expectedMessage = HdmiCecMessageBuilder.buildStandby(
+ mPlaybackLogicalAddress, ADDR_TV);
+ assertThat(mNativeWrapper.getResultMessages()).contains(expectedMessage);
+ assertThat(mStandby).isTrue();
+ }
+
+ @Test
+ public void toggleAndFollowTvPower_Broadcast_TvStatusOn() {
+ mHdmiCecLocalDevicePlayback.mService.getHdmiCecConfig().setStringValue(
+ HdmiControlManager.CEC_SETTING_NAME_SEND_STANDBY_ON_SLEEP,
+ HdmiControlManager.SEND_STANDBY_ON_SLEEP_BROADCAST);
+ mStandby = false;
+ mHdmiControlService.toggleAndFollowTvPower();
+ HdmiCecMessage tvPowerStatus = HdmiCecMessageBuilder.buildReportPowerStatus(ADDR_TV,
+ mPlaybackLogicalAddress, HdmiControlManager.POWER_STATUS_ON);
+ assertThat(mHdmiCecLocalDevicePlayback.dispatchMessage(tvPowerStatus)).isTrue();
+ mTestLooper.dispatchAll();
+
+ HdmiCecMessage expectedMessage = HdmiCecMessageBuilder.buildStandby(
+ mPlaybackLogicalAddress, ADDR_BROADCAST);
+ assertThat(mNativeWrapper.getResultMessages()).contains(expectedMessage);
+ assertThat(mStandby).isTrue();
+ }
+
+ @Test
+ public void toggleAndFollowTvPower_TvStatusStandby() {
+ mStandby = false;
+ mHdmiControlService.toggleAndFollowTvPower();
+ HdmiCecMessage tvPowerStatus = HdmiCecMessageBuilder.buildReportPowerStatus(ADDR_TV,
+ mPlaybackLogicalAddress, HdmiControlManager.POWER_STATUS_STANDBY);
+ assertThat(mHdmiCecLocalDevicePlayback.dispatchMessage(tvPowerStatus)).isTrue();
+ mTestLooper.dispatchAll();
+
+ HdmiCecMessage textViewOn = HdmiCecMessageBuilder.buildTextViewOn(mPlaybackLogicalAddress,
+ ADDR_TV);
+ HdmiCecMessage activeSource = HdmiCecMessageBuilder.buildActiveSource(
+ mPlaybackLogicalAddress, mPlaybackPhysicalAddress);
+ assertThat(mNativeWrapper.getResultMessages()).contains(textViewOn);
+ assertThat(mNativeWrapper.getResultMessages()).contains(activeSource);
+ assertThat(mStandby).isFalse();
+ }
+
+ @Test
+ public void toggleAndFollowTvPower_TvStatusUnknown() {
+ mStandby = false;
+ mHdmiControlService.toggleAndFollowTvPower();
+ HdmiCecMessage tvPowerStatus = HdmiCecMessageBuilder.buildReportPowerStatus(ADDR_TV,
+ mPlaybackLogicalAddress, HdmiControlManager.POWER_STATUS_UNKNOWN);
+ assertThat(mHdmiCecLocalDevicePlayback.dispatchMessage(tvPowerStatus)).isTrue();
+ mTestLooper.dispatchAll();
+
+ HdmiCecMessage userControlPressed = HdmiCecMessageBuilder.buildUserControlPressed(
+ mPlaybackLogicalAddress, Constants.ADDR_TV,
+ HdmiCecKeycode.CEC_KEYCODE_POWER_TOGGLE_FUNCTION);
+ HdmiCecMessage userControlReleased = HdmiCecMessageBuilder.buildUserControlReleased(
+ mPlaybackLogicalAddress, Constants.ADDR_TV);
+ assertThat(mNativeWrapper.getResultMessages()).contains(userControlPressed);
+ assertThat(mNativeWrapper.getResultMessages()).contains(userControlReleased);
+ assertThat(mStandby).isFalse();
+ }
}
diff --git a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecMessageBuilderTest.java b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecMessageBuilderTest.java
index 6f62014f0141..649626492448 100644
--- a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecMessageBuilderTest.java
+++ b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecMessageBuilderTest.java
@@ -22,6 +22,7 @@ import static com.android.server.hdmi.HdmiUtils.buildMessage;
import static com.google.common.truth.Truth.assertThat;
+import android.hardware.hdmi.HdmiControlManager;
import android.hardware.hdmi.HdmiDeviceInfo;
import android.platform.test.annotations.Presubmit;
@@ -103,7 +104,7 @@ public class HdmiCecMessageBuilderTest {
@Test
public void buildReportFeatures_basicTv_1_4() {
HdmiCecMessage message = HdmiCecMessageBuilder.buildReportFeatures(ADDR_TV,
- Constants.VERSION_1_4,
+ HdmiControlManager.HDMI_CEC_VERSION_1_4_b,
Lists.newArrayList(HdmiDeviceInfo.DEVICE_TV), Constants.RC_PROFILE_TV,
Lists.newArrayList(Constants.RC_PROFILE_TV_NONE), Collections.emptyList());
@@ -113,7 +114,7 @@ public class HdmiCecMessageBuilderTest {
@Test
public void buildReportFeatures_basicPlayback_1_4() {
HdmiCecMessage message = HdmiCecMessageBuilder.buildReportFeatures(ADDR_PLAYBACK_1,
- Constants.VERSION_1_4,
+ HdmiControlManager.HDMI_CEC_VERSION_1_4_b,
Lists.newArrayList(HdmiDeviceInfo.DEVICE_PLAYBACK), Constants.RC_PROFILE_TV,
Lists.newArrayList(Constants.RC_PROFILE_TV_NONE), Collections.emptyList());
@@ -123,7 +124,7 @@ public class HdmiCecMessageBuilderTest {
@Test
public void buildReportFeatures_basicPlaybackAudioSystem_1_4() {
HdmiCecMessage message = HdmiCecMessageBuilder.buildReportFeatures(ADDR_PLAYBACK_1,
- Constants.VERSION_1_4,
+ HdmiControlManager.HDMI_CEC_VERSION_1_4_b,
Lists.newArrayList(HdmiDeviceInfo.DEVICE_PLAYBACK,
HdmiDeviceInfo.DEVICE_AUDIO_SYSTEM), Constants.RC_PROFILE_TV,
Lists.newArrayList(Constants.RC_PROFILE_TV_NONE), Collections.emptyList());
@@ -134,7 +135,7 @@ public class HdmiCecMessageBuilderTest {
@Test
public void buildReportFeatures_basicTv_2_0() {
HdmiCecMessage message = HdmiCecMessageBuilder.buildReportFeatures(ADDR_TV,
- Constants.VERSION_2_0,
+ HdmiControlManager.HDMI_CEC_VERSION_2_0,
Lists.newArrayList(HdmiDeviceInfo.DEVICE_TV), Constants.RC_PROFILE_TV,
Lists.newArrayList(Constants.RC_PROFILE_TV_NONE), Collections.emptyList());
@@ -144,7 +145,7 @@ public class HdmiCecMessageBuilderTest {
@Test
public void buildReportFeatures_remoteControlTv_2_0() {
HdmiCecMessage message = HdmiCecMessageBuilder.buildReportFeatures(ADDR_TV,
- Constants.VERSION_2_0,
+ HdmiControlManager.HDMI_CEC_VERSION_2_0,
Lists.newArrayList(HdmiDeviceInfo.DEVICE_TV), Constants.RC_PROFILE_TV,
Lists.newArrayList(Constants.RC_PROFILE_TV_ONE), Collections.emptyList());
@@ -154,7 +155,7 @@ public class HdmiCecMessageBuilderTest {
@Test
public void buildReportFeatures_remoteControlPlayback_2_0() {
HdmiCecMessage message = HdmiCecMessageBuilder.buildReportFeatures(ADDR_TV,
- Constants.VERSION_2_0,
+ HdmiControlManager.HDMI_CEC_VERSION_2_0,
Lists.newArrayList(HdmiDeviceInfo.DEVICE_PLAYBACK), Constants.RC_PROFILE_SOURCE,
Lists.newArrayList(Constants.RC_PROFILE_SOURCE_HANDLES_TOP_MENU,
Constants.RC_PROFILE_SOURCE_HANDLES_SETUP_MENU), Collections.emptyList());
@@ -165,7 +166,7 @@ public class HdmiCecMessageBuilderTest {
@Test
public void buildReportFeatures_deviceFeaturesTv_2_0() {
HdmiCecMessage message = HdmiCecMessageBuilder.buildReportFeatures(ADDR_TV,
- Constants.VERSION_2_0,
+ HdmiControlManager.HDMI_CEC_VERSION_2_0,
Lists.newArrayList(HdmiDeviceInfo.DEVICE_TV), Constants.RC_PROFILE_TV,
Lists.newArrayList(Constants.RC_PROFILE_TV_NONE),
Lists.newArrayList(Constants.DEVICE_FEATURE_TV_SUPPORTS_RECORD_TV_SCREEN));
@@ -176,7 +177,7 @@ public class HdmiCecMessageBuilderTest {
@Test
public void buildReportFeatures_deviceFeaturesPlayback_2_0() {
HdmiCecMessage message = HdmiCecMessageBuilder.buildReportFeatures(ADDR_TV,
- Constants.VERSION_2_0,
+ HdmiControlManager.HDMI_CEC_VERSION_2_0,
Lists.newArrayList(HdmiDeviceInfo.DEVICE_PLAYBACK), Constants.RC_PROFILE_SOURCE,
Lists.newArrayList(Constants.RC_PROFILE_SOURCE_HANDLES_TOP_MENU,
Constants.RC_PROFILE_SOURCE_HANDLES_SETUP_MENU),
diff --git a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecMessageValidatorTest.java b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecMessageValidatorTest.java
index f3a4366eaaec..a05cbb48a3f7 100644
--- a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecMessageValidatorTest.java
+++ b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecMessageValidatorTest.java
@@ -67,8 +67,8 @@ public class HdmiCecMessageValidatorTest {
public void isValid_reportPowerStatus() {
assertMessageValidity("04:90:00").isEqualTo(OK);
assertMessageValidity("04:90:03:05").isEqualTo(OK);
+ assertMessageValidity("0F:90:00").isEqualTo(OK);
- assertMessageValidity("0F:90:00").isEqualTo(ERROR_DESTINATION);
assertMessageValidity("F0:90").isEqualTo(ERROR_SOURCE);
assertMessageValidity("04:90").isEqualTo(ERROR_PARAMETER_SHORT);
assertMessageValidity("04:90:04").isEqualTo(ERROR_PARAMETER);
diff --git a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecPowerStatusControllerTest.java b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecPowerStatusControllerTest.java
new file mode 100644
index 000000000000..3cc7c6b88a0d
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecPowerStatusControllerTest.java
@@ -0,0 +1,264 @@
+/*
+ * 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.server.hdmi;
+
+import static com.android.server.hdmi.HdmiControlService.INITIATED_BY_ENABLE_CEC;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.when;
+
+import android.content.Context;
+import android.content.ContextWrapper;
+import android.hardware.hdmi.HdmiControlManager;
+import android.hardware.hdmi.HdmiPortInfo;
+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 android.platform.test.annotations.Presubmit;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.SmallTest;
+
+import com.android.server.SystemService;
+
+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;
+
+@SmallTest
+@Presubmit
+@RunWith(JUnit4.class)
+/** Tests for {@link HdmiCecPowerStatusController} class. */
+public class HdmiCecPowerStatusControllerTest {
+
+ public static final int[] ARRAY_POWER_STATUS = new int[]{HdmiControlManager.POWER_STATUS_ON,
+ HdmiControlManager.POWER_STATUS_TRANSIENT_TO_ON,
+ HdmiControlManager.POWER_STATUS_TRANSIENT_TO_STANDBY,
+ HdmiControlManager.POWER_STATUS_STANDBY};
+ private HdmiCecPowerStatusController mHdmiCecPowerStatusController;
+ private FakeNativeWrapper mNativeWrapper;
+ private TestLooper mTestLooper = new TestLooper();
+ private ArrayList<HdmiCecLocalDevice> mLocalDevices = new ArrayList<>();
+ private int mHdmiCecVersion = HdmiControlManager.HDMI_CEC_VERSION_1_4_b;
+ @Mock
+ private IPowerManager mIPowerManagerMock;
+ @Mock
+ private IThermalService mIThermalServiceMock;
+ private HdmiControlService mHdmiControlService;
+
+ @Before
+ public void setUp() throws Exception {
+ MockitoAnnotations.initMocks(this);
+
+ Context contextSpy = spy(new ContextWrapper(InstrumentationRegistry.getTargetContext()));
+ Looper myLooper = mTestLooper.getLooper();
+ PowerManager powerManager = new PowerManager(contextSpy, mIPowerManagerMock,
+ mIThermalServiceMock, new Handler(myLooper));
+ when(contextSpy.getSystemService(Context.POWER_SERVICE)).thenReturn(powerManager);
+ when(contextSpy.getSystemService(PowerManager.class)).thenReturn(powerManager);
+ when(mIPowerManagerMock.isInteractive()).thenReturn(true);
+
+ HdmiCecConfig hdmiCecConfig = new FakeHdmiCecConfig(contextSpy);
+
+ mHdmiControlService = new HdmiControlService(contextSpy) {
+ @Override
+ boolean isControlEnabled() {
+ return true;
+ }
+
+ @Override
+ boolean isPlaybackDevice() {
+ return true;
+ }
+
+ @Override
+ void writeStringSystemProperty(String key, String value) {
+ // do nothing
+ }
+
+ @Override
+ int getCecVersion() {
+ return mHdmiCecVersion;
+ }
+
+ @Override
+ boolean isPowerStandby() {
+ return false;
+ }
+
+ @Override
+ HdmiCecConfig getHdmiCecConfig() {
+ return hdmiCecConfig;
+ }
+ };
+ mHdmiControlService.onBootPhase(SystemService.PHASE_SYSTEM_SERVICES_READY);
+
+ HdmiCecLocalDevicePlayback hdmiCecLocalDevicePlayback = new HdmiCecLocalDevicePlayback(
+ mHdmiControlService);
+ hdmiCecLocalDevicePlayback.init();
+ mHdmiControlService.setIoLooper(myLooper);
+ mNativeWrapper = new FakeNativeWrapper();
+ HdmiCecController hdmiCecController = HdmiCecController.createWithNativeWrapper(
+ mHdmiControlService, mNativeWrapper, mHdmiControlService.getAtomWriter());
+ mHdmiControlService.setCecController(hdmiCecController);
+ mHdmiControlService.setHdmiMhlController(HdmiMhlControllerStub.create(mHdmiControlService));
+ mHdmiControlService.setMessageValidator(new HdmiCecMessageValidator(mHdmiControlService));
+ mLocalDevices.add(hdmiCecLocalDevicePlayback);
+ HdmiPortInfo[] hdmiPortInfos = new HdmiPortInfo[1];
+ hdmiPortInfos[0] =
+ new HdmiPortInfo(1, HdmiPortInfo.PORT_OUTPUT, 0x0000, true, false, false);
+ mNativeWrapper.setPortInfo(hdmiPortInfos);
+ mNativeWrapper.setPortConnectionStatus(1, true);
+ mHdmiControlService.initService();
+ mHdmiControlService.getHdmiCecNetwork().initPortInfo();
+ mHdmiControlService.allocateLogicalAddress(mLocalDevices, INITIATED_BY_ENABLE_CEC);
+ mNativeWrapper.setPhysicalAddress(0x2000);
+ mTestLooper.dispatchAll();
+
+ mHdmiCecPowerStatusController = new HdmiCecPowerStatusController(mHdmiControlService);
+ mNativeWrapper.clearResultMessages();
+ }
+
+ @Test
+ public void setPowerStatus() {
+ for (int status : ARRAY_POWER_STATUS) {
+ mHdmiCecPowerStatusController.setPowerStatus(status);
+ assertThat(mHdmiCecPowerStatusController.getPowerStatus()).isEqualTo(status);
+ }
+ }
+
+ @Test
+ public void isPowerStatusOn() {
+ for (int status : ARRAY_POWER_STATUS) {
+ mHdmiCecPowerStatusController.setPowerStatus(status);
+ assertThat(mHdmiCecPowerStatusController.isPowerStatusOn()).isEqualTo(
+ HdmiControlManager.POWER_STATUS_ON == status);
+ }
+ }
+
+ @Test
+ public void isPowerStatusStandby() {
+ for (int status : ARRAY_POWER_STATUS) {
+ mHdmiCecPowerStatusController.setPowerStatus(status);
+ assertThat(mHdmiCecPowerStatusController.isPowerStatusStandby()).isEqualTo(
+ HdmiControlManager.POWER_STATUS_STANDBY == status);
+ }
+ }
+
+ @Test
+ public void isPowerStatusTransientToOn() {
+ for (int status : ARRAY_POWER_STATUS) {
+ mHdmiCecPowerStatusController.setPowerStatus(status);
+ assertThat(mHdmiCecPowerStatusController.isPowerStatusTransientToOn()).isEqualTo(
+ HdmiControlManager.POWER_STATUS_TRANSIENT_TO_ON == status);
+ }
+ }
+
+ @Test
+ public void isPowerStatusTransientToStandby() {
+ for (int status : ARRAY_POWER_STATUS) {
+ mHdmiCecPowerStatusController.setPowerStatus(status);
+ assertThat(mHdmiCecPowerStatusController.isPowerStatusTransientToStandby()).isEqualTo(
+ HdmiControlManager.POWER_STATUS_TRANSIENT_TO_STANDBY == status);
+ }
+ }
+
+ @Test
+ public void setPowerStatus_doesntSendBroadcast_1_4() {
+ mHdmiCecPowerStatusController.setPowerStatus(HdmiControlManager.POWER_STATUS_ON);
+ mTestLooper.dispatchAll();
+
+ HdmiCecMessage reportPowerStatus = HdmiCecMessageBuilder.buildReportPowerStatus(
+ Constants.ADDR_PLAYBACK_1, Constants.ADDR_BROADCAST,
+ HdmiControlManager.POWER_STATUS_ON);
+ assertThat(mNativeWrapper.getResultMessages()).doesNotContain(reportPowerStatus);
+ }
+
+ @Test
+ public void setPowerStatus_transient_doesntSendBroadcast_1_4() {
+ mHdmiCecPowerStatusController.setPowerStatus(
+ HdmiControlManager.POWER_STATUS_TRANSIENT_TO_ON);
+ mTestLooper.dispatchAll();
+
+ HdmiCecMessage reportPowerStatus = HdmiCecMessageBuilder.buildReportPowerStatus(
+ Constants.ADDR_PLAYBACK_1, Constants.ADDR_BROADCAST,
+ HdmiControlManager.POWER_STATUS_TRANSIENT_TO_ON);
+ assertThat(mNativeWrapper.getResultMessages()).doesNotContain(reportPowerStatus);
+ }
+
+ @Test
+ public void setPowerStatus_fast_transient_doesntSendBroadcast_1_4() {
+ mHdmiCecPowerStatusController.setPowerStatus(
+ HdmiControlManager.POWER_STATUS_TRANSIENT_TO_ON, false);
+ mTestLooper.dispatchAll();
+
+ HdmiCecMessage reportPowerStatus = HdmiCecMessageBuilder.buildReportPowerStatus(
+ Constants.ADDR_PLAYBACK_1, Constants.ADDR_BROADCAST,
+ HdmiControlManager.POWER_STATUS_TRANSIENT_TO_ON);
+ assertThat(mNativeWrapper.getResultMessages()).doesNotContain(reportPowerStatus);
+ }
+
+ @Test
+ public void setPowerStatus_sendsBroadcast_2_0() {
+ mHdmiCecVersion = HdmiControlManager.HDMI_CEC_VERSION_2_0;
+
+ mHdmiCecPowerStatusController.setPowerStatus(HdmiControlManager.POWER_STATUS_ON);
+ mTestLooper.dispatchAll();
+
+ HdmiCecMessage reportPowerStatus = HdmiCecMessageBuilder.buildReportPowerStatus(
+ Constants.ADDR_PLAYBACK_1, Constants.ADDR_BROADCAST,
+ HdmiControlManager.POWER_STATUS_ON);
+ assertThat(mNativeWrapper.getResultMessages()).contains(reportPowerStatus);
+ }
+
+ @Test
+ public void setPowerStatus_transient_sendsBroadcast_2_0() {
+ mHdmiCecVersion = HdmiControlManager.HDMI_CEC_VERSION_2_0;
+
+ mHdmiCecPowerStatusController.setPowerStatus(
+ HdmiControlManager.POWER_STATUS_TRANSIENT_TO_ON);
+ mTestLooper.dispatchAll();
+
+ HdmiCecMessage reportPowerStatus = HdmiCecMessageBuilder.buildReportPowerStatus(
+ Constants.ADDR_PLAYBACK_1, Constants.ADDR_BROADCAST,
+ HdmiControlManager.POWER_STATUS_TRANSIENT_TO_ON);
+ assertThat(mNativeWrapper.getResultMessages()).contains(reportPowerStatus);
+ }
+
+ @Test
+ public void setPowerStatus_fast_transient_doesntSendBroadcast_2_0() {
+ mHdmiCecVersion = HdmiControlManager.HDMI_CEC_VERSION_2_0;
+
+ mHdmiCecPowerStatusController.setPowerStatus(
+ HdmiControlManager.POWER_STATUS_TRANSIENT_TO_ON, false);
+ mTestLooper.dispatchAll();
+
+ HdmiCecMessage reportPowerStatus = HdmiCecMessageBuilder.buildReportPowerStatus(
+ Constants.ADDR_PLAYBACK_1, Constants.ADDR_BROADCAST,
+ HdmiControlManager.POWER_STATUS_TRANSIENT_TO_ON);
+ assertThat(mNativeWrapper.getResultMessages()).doesNotContain(reportPowerStatus);
+ }
+}
diff --git a/services/tests/servicestests/src/com/android/server/hdmi/HdmiControlServiceTest.java b/services/tests/servicestests/src/com/android/server/hdmi/HdmiControlServiceTest.java
index 2e4bed97dbec..9d767cd94853 100644
--- a/services/tests/servicestests/src/com/android/server/hdmi/HdmiControlServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/hdmi/HdmiControlServiceTest.java
@@ -243,6 +243,50 @@ public class HdmiControlServiceTest {
}
@Test
+ public void initialPowerStatus_normalBoot_goToStandby_doesNotBroadcastsPowerStatus_1_4() {
+ mHdmiControlService.getHdmiCecConfig().setIntValue(
+ HdmiControlManager.CEC_SETTING_NAME_HDMI_CEC_VERSION,
+ HdmiControlManager.HDMI_CEC_VERSION_1_4_b);
+
+ mHdmiControlService.setControlEnabled(true);
+ mNativeWrapper.clearResultMessages();
+
+ assertThat(mHdmiControlService.getInitialPowerStatus()).isEqualTo(
+ HdmiControlManager.POWER_STATUS_TRANSIENT_TO_STANDBY);
+
+ mHdmiControlService.onStandby(HdmiControlService.STANDBY_SCREEN_OFF);
+
+ HdmiCecMessage reportPowerStatus = HdmiCecMessageBuilder.buildReportPowerStatus(
+ Constants.ADDR_PLAYBACK_1, Constants.ADDR_BROADCAST,
+ HdmiControlManager.POWER_STATUS_STANDBY);
+ assertThat(mNativeWrapper.getResultMessages()).doesNotContain(reportPowerStatus);
+ }
+
+ @Test
+ public void initialPowerStatus_normalBoot_goToStandby_broadcastsPowerStatus_2_0() {
+ mHdmiControlService.getHdmiCecConfig().setIntValue(
+ HdmiControlManager.CEC_SETTING_NAME_HDMI_CEC_VERSION,
+ HdmiControlManager.HDMI_CEC_VERSION_2_0);
+
+ mHdmiControlService.setControlEnabled(true);
+ mNativeWrapper.clearResultMessages();
+
+ mHdmiControlService.allocateLogicalAddress(mLocalDevices, INITIATED_BY_ENABLE_CEC);
+ mTestLooper.dispatchAll();
+
+ assertThat(mHdmiControlService.getInitialPowerStatus()).isEqualTo(
+ HdmiControlManager.POWER_STATUS_TRANSIENT_TO_STANDBY);
+
+ mHdmiControlService.onStandby(HdmiControlService.STANDBY_SCREEN_OFF);
+ mTestLooper.dispatchAll();
+
+ HdmiCecMessage reportPowerStatus = HdmiCecMessageBuilder.buildReportPowerStatus(
+ Constants.ADDR_PLAYBACK_1, Constants.ADDR_BROADCAST,
+ HdmiControlManager.POWER_STATUS_STANDBY);
+ assertThat(mNativeWrapper.getResultMessages()).contains(reportPowerStatus);
+ }
+
+ @Test
public void setAndGetCecVolumeControlEnabled_isApi() {
mHdmiControlService.setHdmiCecVolumeControlEnabled(false);
assertThat(mHdmiControlService.isHdmiCecVolumeControlEnabled()).isFalse();
@@ -470,7 +514,7 @@ public class HdmiControlServiceTest {
mTestLooper.dispatchAll();
HdmiCecMessage reportFeatures = HdmiCecMessageBuilder.buildReportFeatures(
- Constants.ADDR_PLAYBACK_1, Constants.VERSION_2_0,
+ Constants.ADDR_PLAYBACK_1, HdmiControlManager.HDMI_CEC_VERSION_2_0,
Arrays.asList(DEVICE_PLAYBACK, DEVICE_AUDIO_SYSTEM),
mMyPlaybackDevice.getRcProfile(), mMyPlaybackDevice.getRcFeatures(),
mMyPlaybackDevice.getDeviceFeatures());
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 7694d096917f..90c29824409f 100644
--- a/services/tests/servicestests/src/com/android/server/pm/PackageParserTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/PackageParserTest.java
@@ -21,7 +21,9 @@ import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+import static java.lang.Boolean.TRUE;
import static java.nio.file.StandardCopyOption.REPLACE_EXISTING;
import android.annotation.NonNull;
@@ -32,6 +34,7 @@ import android.content.pm.ConfigurationInfo;
import android.content.pm.FeatureGroupInfo;
import android.content.pm.FeatureInfo;
import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager.Property;
import android.content.pm.PackageParser;
import android.content.pm.PackageUserState;
import android.content.pm.ServiceInfo;
@@ -81,7 +84,9 @@ import java.nio.file.Files;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
+import java.util.Iterator;
import java.util.List;
+import java.util.Map;
import java.util.Set;
@Presubmit
@@ -99,6 +104,8 @@ public class PackageParserTest {
private static final String TEST_APP1_APK = "PackageParserTestApp1.apk";
private static final String TEST_APP2_APK = "PackageParserTestApp2.apk";
private static final String TEST_APP3_APK = "PackageParserTestApp3.apk";
+ private static final String TEST_APP4_APK = "PackageParserTestApp4.apk";
+ private static final String PACKAGE_NAME = "com.android.servicestests.apps.packageparserapp";
@Before
public void setUp() throws IOException {
@@ -270,6 +277,234 @@ public class PackageParserTest {
}
}
+ private static final int PROPERTY_TYPE_BOOLEAN = 1;
+ private static final int PROPERTY_TYPE_FLOAT = 2;
+ private static final int PROPERTY_TYPE_INTEGER = 3;
+ private static final int PROPERTY_TYPE_RESOURCE = 4;
+ private static final int PROPERTY_TYPE_STRING = 5;
+ public void assertProperty(Map<String, Property> properties, String propertyName,
+ int propertyType, Object propertyValue) {
+ assertTrue(properties.containsKey(propertyName));
+
+ final Property testProperty = properties.get(propertyName);
+ assertEquals(propertyType, testProperty.getType());
+
+ if (propertyType == PROPERTY_TYPE_BOOLEAN) {
+ assertTrue(testProperty.isBoolean());
+ assertFalse(testProperty.isFloat());
+ assertFalse(testProperty.isInteger());
+ assertFalse(testProperty.isResourceId());
+ assertFalse(testProperty.isString());
+
+ // assert the property's type is set correctly
+ final Boolean boolValue = (Boolean) propertyValue;
+ if (boolValue.booleanValue()) {
+ assertTrue(testProperty.getBoolean());
+ } else {
+ assertFalse(testProperty.getBoolean());
+ }
+ // assert the other values have an appropriate default
+ assertEquals(0.0f, testProperty.getFloat(), 0.0f);
+ assertEquals(0, testProperty.getInteger());
+ assertEquals(0, testProperty.getResourceId());
+ assertEquals(null, testProperty.getString());
+ } else if (propertyType == PROPERTY_TYPE_FLOAT) {
+ assertFalse(testProperty.isBoolean());
+ assertTrue(testProperty.isFloat());
+ assertFalse(testProperty.isInteger());
+ assertFalse(testProperty.isResourceId());
+ assertFalse(testProperty.isString());
+
+ // assert the property's type is set correctly
+ final Float floatValue = (Float) propertyValue;
+ assertEquals(floatValue.floatValue(), testProperty.getFloat(), 0.0f);
+ // assert the other values have an appropriate default
+ assertFalse(testProperty.getBoolean());
+ assertEquals(0, testProperty.getInteger());
+ assertEquals(0, testProperty.getResourceId());
+ assertEquals(null, testProperty.getString());
+ } else if (propertyType == PROPERTY_TYPE_INTEGER) {
+ assertFalse(testProperty.isBoolean());
+ assertFalse(testProperty.isFloat());
+ assertTrue(testProperty.isInteger());
+ assertFalse(testProperty.isResourceId());
+ assertFalse(testProperty.isString());
+
+ // assert the property's type is set correctly
+ final Integer integerValue = (Integer) propertyValue;
+ assertEquals(integerValue.intValue(), testProperty.getInteger());
+ // assert the other values have an appropriate default
+ assertFalse(testProperty.getBoolean());
+ assertEquals(0.0f, testProperty.getFloat(), 0.0f);
+ assertEquals(0, testProperty.getResourceId());
+ assertEquals(null, testProperty.getString());
+ } else if (propertyType == PROPERTY_TYPE_RESOURCE) {
+ assertFalse(testProperty.isBoolean());
+ assertFalse(testProperty.isFloat());
+ assertFalse(testProperty.isInteger());
+ assertTrue(testProperty.isResourceId());
+ assertFalse(testProperty.isString());
+
+ // assert the property's type is set correctly
+ final Integer resourceValue = (Integer) propertyValue;
+ assertEquals(resourceValue.intValue(), testProperty.getResourceId());
+ // assert the other values have an appropriate default
+ assertFalse(testProperty.getBoolean());
+ assertEquals(0.0f, testProperty.getFloat(), 0.0f);
+ assertEquals(0, testProperty.getInteger());
+ assertEquals(null, testProperty.getString());
+ } else if (propertyType == PROPERTY_TYPE_STRING) {
+ assertFalse(testProperty.isBoolean());
+ assertFalse(testProperty.isFloat());
+ assertFalse(testProperty.isInteger());
+ assertFalse(testProperty.isResourceId());
+ assertTrue(testProperty.isString());
+
+ // assert the property's type is set correctly
+ final String stringValue = (String) propertyValue;
+ assertEquals(stringValue, testProperty.getString());
+ // assert the other values have an appropriate default
+ assertFalse(testProperty.getBoolean());
+ assertEquals(0.0f, testProperty.getFloat(), 0.0f);
+ assertEquals(0, testProperty.getInteger());
+ assertEquals(0, testProperty.getResourceId());
+ } else {
+ fail("Unknown property type");
+ }
+ }
+
+ @Test
+ public void testParseApplicationProperties() throws Exception {
+ final File testFile = extractFile(TEST_APP4_APK);
+ try {
+ final ParsedPackage pkg = new TestPackageParser2().parsePackage(testFile, 0, false);
+ final Map<String, Property> properties = pkg.getProperties();
+ assertEquals(10, properties.size());
+ assertProperty(properties,
+ "android.cts.PROPERTY_RESOURCE_XML", PROPERTY_TYPE_RESOURCE, 0x7f060000);
+ assertProperty(properties,
+ "android.cts.PROPERTY_RESOURCE_INTEGER", PROPERTY_TYPE_RESOURCE, 0x7f040000);
+ assertProperty(properties,
+ "android.cts.PROPERTY_BOOLEAN", PROPERTY_TYPE_BOOLEAN, TRUE);
+ assertProperty(properties,
+ "android.cts.PROPERTY_BOOLEAN_VIA_RESOURCE", PROPERTY_TYPE_BOOLEAN, TRUE);
+ assertProperty(properties,
+ "android.cts.PROPERTY_FLOAT", PROPERTY_TYPE_FLOAT, 3.14f);
+ assertProperty(properties,
+ "android.cts.PROPERTY_FLOAT_VIA_RESOURCE", PROPERTY_TYPE_FLOAT, 2.718f);
+ assertProperty(properties,
+ "android.cts.PROPERTY_INTEGER", PROPERTY_TYPE_INTEGER, 42);
+ assertProperty(properties,
+ "android.cts.PROPERTY_INTEGER_VIA_RESOURCE", PROPERTY_TYPE_INTEGER, 123);
+ assertProperty(properties,
+ "android.cts.PROPERTY_STRING", PROPERTY_TYPE_STRING, "koala");
+ assertProperty(properties,
+ "android.cts.PROPERTY_STRING_VIA_RESOURCE", PROPERTY_TYPE_STRING, "giraffe");
+ } finally {
+ testFile.delete();
+ }
+ }
+
+ @Test
+ public void testParseActivityProperties() throws Exception {
+ final File testFile = extractFile(TEST_APP4_APK);
+ try {
+ final ParsedPackage pkg = new TestPackageParser2().parsePackage(testFile, 0, false);
+ final List<ParsedActivity> activities = pkg.getActivities();
+ for (ParsedActivity activity : activities) {
+ final Map<String, Property> properties = activity.getProperties();
+ if ((PACKAGE_NAME + ".MyActivityAlias").equals(activity.getName())) {
+ assertEquals(2, properties.size());
+ assertProperty(properties,
+ "android.cts.PROPERTY_ACTIVITY_ALIAS", PROPERTY_TYPE_INTEGER, 123);
+ assertProperty(properties,
+ "android.cts.PROPERTY_COMPONENT", PROPERTY_TYPE_INTEGER, 123);
+ } else if ((PACKAGE_NAME + ".MyActivity").equals(activity.getName())) {
+ assertEquals(3, properties.size());
+ assertProperty(properties,
+ "android.cts.PROPERTY_ACTIVITY", PROPERTY_TYPE_INTEGER, 123);
+ assertProperty(properties,
+ "android.cts.PROPERTY_COMPONENT", PROPERTY_TYPE_INTEGER, 123);
+ assertProperty(properties,
+ "android.cts.PROPERTY_STRING", PROPERTY_TYPE_STRING, "koala activity");
+ } else if ("android.app.AppDetailsActivity".equals(activity.getName())) {
+ // ignore default added activity
+ } else {
+ fail("Found unknown activity; name = " + activity.getName());
+ }
+ }
+ } finally {
+ testFile.delete();
+ }
+ }
+
+ @Test
+ public void testParseProviderProperties() throws Exception {
+ final File testFile = extractFile(TEST_APP4_APK);
+ try {
+ final ParsedPackage pkg = new TestPackageParser2().parsePackage(testFile, 0, false);
+ final List<ParsedProvider> providers = pkg.getProviders();
+ for (ParsedProvider provider : providers) {
+ final Map<String, Property> properties = provider.getProperties();
+ if ((PACKAGE_NAME + ".MyProvider").equals(provider.getName())) {
+ assertEquals(1, properties.size());
+ assertProperty(properties,
+ "android.cts.PROPERTY_PROVIDER", PROPERTY_TYPE_INTEGER, 123);
+ } else {
+ fail("Found unknown provider; name = " + provider.getName());
+ }
+ }
+ } finally {
+ testFile.delete();
+ }
+ }
+
+ @Test
+ public void testParseReceiverProperties() throws Exception {
+ final File testFile = extractFile(TEST_APP4_APK);
+ try {
+ final ParsedPackage pkg = new TestPackageParser2().parsePackage(testFile, 0, false);
+ final List<ParsedActivity> receivers = pkg.getReceivers();
+ for (ParsedActivity receiver : receivers) {
+ final Map<String, Property> properties = receiver.getProperties();
+ if ((PACKAGE_NAME + ".MyReceiver").equals(receiver.getName())) {
+ assertEquals(2, properties.size());
+ assertProperty(properties,
+ "android.cts.PROPERTY_RECEIVER", PROPERTY_TYPE_INTEGER, 123);
+ assertProperty(properties,
+ "android.cts.PROPERTY_STRING", PROPERTY_TYPE_STRING, "koala receiver");
+ } else {
+ fail("Found unknown receiver; name = " + receiver.getName());
+ }
+ }
+ } finally {
+ testFile.delete();
+ }
+ }
+
+ @Test
+ public void testParseServiceProperties() throws Exception {
+ final File testFile = extractFile(TEST_APP4_APK);
+ try {
+ final ParsedPackage pkg = new TestPackageParser2().parsePackage(testFile, 0, false);
+ final List<ParsedService> services = pkg.getServices();
+ for (ParsedService service : services) {
+ final Map<String, Property> properties = service.getProperties();
+ if ((PACKAGE_NAME + ".MyService").equals(service.getName())) {
+ assertEquals(2, properties.size());
+ assertProperty(properties,
+ "android.cts.PROPERTY_SERVICE", PROPERTY_TYPE_INTEGER, 123);
+ assertProperty(properties,
+ "android.cts.PROPERTY_COMPONENT", PROPERTY_TYPE_RESOURCE, 0x7f040000);
+ } else {
+ fail("Found unknown service; name = " + service.getName());
+ }
+ }
+ } finally {
+ testFile.delete();
+ }
+ }
+
/**
* A trivial subclass of package parser that only caches the package name, and throws away
* all other information.
@@ -386,6 +621,13 @@ public class PackageParserTest {
b.getInstrumentations().get(i));
}
+ assertEquals(a.getProperties().size(), b.getProperties().size());
+ final Iterator<String> iter = a.getProperties().keySet().iterator();
+ while (iter.hasNext()) {
+ final String key = iter.next();
+ assertEquals(a.getProperties().get(key), b.getProperties().get(key));
+ }
+
assertEquals(a.getRequestedPermissions(), b.getRequestedPermissions());
assertEquals(a.getProtectedBroadcasts(), b.getProtectedBroadcasts());
assertEquals(a.getLibraryNames(), b.getLibraryNames());
@@ -443,6 +685,13 @@ public class PackageParserTest {
assertEquals(aIntent.getNonLocalizedLabel(), bIntent.getNonLocalizedLabel());
assertEquals(aIntent.getIcon(), bIntent.getIcon());
}
+
+ assertEquals(a.getProperties().size(), b.getProperties().size());
+ final Iterator<String> iter = a.getProperties().keySet().iterator();
+ while (iter.hasNext()) {
+ final String key = iter.next();
+ assertEquals(a.getProperties().get(key), b.getProperties().get(key));
+ }
}
private static void assertPermissionsEqual(ParsedPermission a, ParsedPermission b) {
diff --git a/services/tests/servicestests/src/com/android/server/policy/DeviceStateProviderImplTest.java b/services/tests/servicestests/src/com/android/server/policy/DeviceStateProviderImplTest.java
new file mode 100644
index 000000000000..92942bb91528
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/policy/DeviceStateProviderImplTest.java
@@ -0,0 +1,289 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.policy;
+
+
+import static android.content.Context.SENSOR_SERVICE;
+
+import static com.android.server.policy.DeviceStateProviderImpl.DEFAULT_DEVICE_STATE;
+
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.mockito.Mockito.eq;
+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.annotation.Nullable;
+import android.content.Context;
+import android.hardware.Sensor;
+import android.hardware.SensorEvent;
+import android.hardware.SensorManager;
+import android.hardware.input.InputManagerInternal;
+
+import androidx.annotation.NonNull;
+
+import com.android.server.LocalServices;
+import com.android.server.devicestate.DeviceStateProvider;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Mockito;
+import org.mockito.internal.util.reflection.FieldSetter;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.lang.reflect.Constructor;
+import java.util.List;
+
+/**
+ * Unit tests for {@link DeviceStateProviderImpl}.
+ * <p/>
+ * Run with <code>atest DeviceStateProviderImplTest</code>.
+ */
+public final class DeviceStateProviderImplTest {
+ private final ArgumentCaptor<int[]> mIntArrayCaptor = ArgumentCaptor.forClass(int[].class);
+ private final ArgumentCaptor<Integer> mIntegerCaptor = ArgumentCaptor.forClass(Integer.class);
+
+ private Context mContext;
+ private SensorManager mSensorManager;
+
+ @Before
+ public void setup() {
+ LocalServices.addService(InputManagerInternal.class, mock(InputManagerInternal.class));
+ mContext = mock(Context.class);
+ mSensorManager = mock(SensorManager.class);
+ when(mContext.getSystemServiceName(eq(SensorManager.class))).thenReturn(SENSOR_SERVICE);
+ when(mContext.getSystemService(eq(SENSOR_SERVICE))).thenReturn(mSensorManager);
+ }
+
+ @After
+ public void tearDown() {
+ LocalServices.removeServiceForTest(InputManagerInternal.class);
+ }
+
+ @Test
+ public void create_noConfig() {
+ assertDefaultProviderValues(null);
+ }
+
+ @Test
+ public void create_emptyFile() {
+ String configString = "";
+ DeviceStateProviderImpl.ReadableConfig config = new TestReadableConfig(configString);
+
+ assertDefaultProviderValues(config);
+ }
+
+ @Test
+ public void create_emptyConfig() {
+ String configString = "<device-state-config></device-state-config>";
+ DeviceStateProviderImpl.ReadableConfig config = new TestReadableConfig(configString);
+
+ assertDefaultProviderValues(config);
+ }
+
+ @Test
+ public void create_invalidConfig() {
+ String configString = "<device-state-config>\n"
+ + " </device-state>\n"
+ + "</device-state-config>\n";
+ DeviceStateProviderImpl.ReadableConfig config = new TestReadableConfig(configString);
+
+ assertDefaultProviderValues(config);
+ }
+
+ private void assertDefaultProviderValues(
+ @Nullable DeviceStateProviderImpl.ReadableConfig config) {
+ DeviceStateProviderImpl provider = DeviceStateProviderImpl.createFromConfig(mContext,
+ config);
+
+ DeviceStateProvider.Listener listener = mock(DeviceStateProvider.Listener.class);
+ provider.setListener(listener);
+
+ verify(listener).onSupportedDeviceStatesChanged(mIntArrayCaptor.capture());
+ assertArrayEquals(new int[] { DEFAULT_DEVICE_STATE }, mIntArrayCaptor.getValue());
+
+ verify(listener).onStateChanged(mIntegerCaptor.capture());
+ assertEquals(DEFAULT_DEVICE_STATE, mIntegerCaptor.getValue().intValue());
+ }
+
+ @Test
+ public void create_lidSwitch() {
+ String configString = "<device-state-config>\n"
+ + " <device-state>\n"
+ + " <identifier>1</identifier>\n"
+ + " <conditions>\n"
+ + " <lid-switch>\n"
+ + " <open>true</open>\n"
+ + " </lid-switch>\n"
+ + " </conditions>\n"
+ + " </device-state>\n"
+ + " <device-state>\n"
+ + " <identifier>2</identifier>\n"
+ + " <conditions>\n"
+ + " <lid-switch>\n"
+ + " <open>false</open>\n"
+ + " </lid-switch>\n"
+ + " </conditions>\n"
+ + " </device-state>\n"
+ + "</device-state-config>\n";
+ DeviceStateProviderImpl.ReadableConfig config = new TestReadableConfig(configString);
+ DeviceStateProviderImpl provider = DeviceStateProviderImpl.createFromConfig(mContext,
+ config);
+
+ DeviceStateProvider.Listener listener = mock(DeviceStateProvider.Listener.class);
+ provider.setListener(listener);
+
+ verify(listener).onSupportedDeviceStatesChanged(mIntArrayCaptor.capture());
+ assertArrayEquals(new int[] { 1, 2 }, mIntArrayCaptor.getValue());
+
+ verify(listener).onStateChanged(mIntegerCaptor.capture());
+ assertEquals(2, mIntegerCaptor.getValue().intValue());
+
+ Mockito.clearInvocations(listener);
+
+ provider.notifyLidSwitchChanged(0, true /* lidOpen */);
+
+ verify(listener, never()).onSupportedDeviceStatesChanged(mIntArrayCaptor.capture());
+ verify(listener).onStateChanged(mIntegerCaptor.capture());
+ assertEquals(1, mIntegerCaptor.getValue().intValue());
+ }
+
+ @Test
+ public void create_sensor() throws Exception {
+ Sensor sensor = newSensor("sensor", Sensor.TYPE_HINGE_ANGLE);
+ when(mSensorManager.getSensorList(eq(sensor.getType()))).thenReturn(List.of(sensor));
+
+ String configString = "<device-state-config>\n"
+ + " <device-state>\n"
+ + " <identifier>1</identifier>\n"
+ + " <conditions>\n"
+ + " <sensor>\n"
+ + " <name>" + sensor.getName() + "</name>\n"
+ + " <type>" + sensor.getType() + "</type>\n"
+ + " <value>\n"
+ + " <max>90</max>\n"
+ + " </value>\n"
+ + " </sensor>\n"
+ + " </conditions>\n"
+ + " </device-state>\n"
+ + " <device-state>\n"
+ + " <identifier>2</identifier>\n"
+ + " <conditions>\n"
+ + " <sensor>\n"
+ + " <name>" + sensor.getName() + "</name>\n"
+ + " <type>" + sensor.getType() + "</type>\n"
+ + " <value>\n"
+ + " <min-inclusive>90</min-inclusive>\n"
+ + " <max>180</max>\n"
+ + " </value>\n"
+ + " </sensor>\n"
+ + " </conditions>\n"
+ + " </device-state>\n"
+ + " <device-state>\n"
+ + " <identifier>3</identifier>\n"
+ + " <conditions>\n"
+ + " <sensor>\n"
+ + " <name>" + sensor.getName() + "</name>\n"
+ + " <type>" + sensor.getType() + "</type>\n"
+ + " <value>\n"
+ + " <min-inclusive>180</min-inclusive>\n"
+ + " </value>\n"
+ + " </sensor>\n"
+ + " </conditions>\n"
+ + " </device-state>\n"
+ + "</device-state-config>\n";
+ DeviceStateProviderImpl.ReadableConfig config = new TestReadableConfig(configString);
+ DeviceStateProviderImpl provider = DeviceStateProviderImpl.createFromConfig(mContext,
+ config);
+
+ DeviceStateProvider.Listener listener = mock(DeviceStateProvider.Listener.class);
+ provider.setListener(listener);
+
+ verify(listener).onSupportedDeviceStatesChanged(mIntArrayCaptor.capture());
+ assertArrayEquals(new int[] { 1, 2, 3 }, mIntArrayCaptor.getValue());
+
+ verify(listener).onStateChanged(mIntegerCaptor.capture());
+ assertEquals(1, mIntegerCaptor.getValue().intValue());
+
+ Mockito.clearInvocations(listener);
+
+ SensorEvent event0 = mock(SensorEvent.class);
+ event0.sensor = sensor;
+ FieldSetter.setField(event0, event0.getClass().getField("values"), new float[] { 180 });
+
+ provider.onSensorChanged(event0);
+
+ verify(listener, never()).onSupportedDeviceStatesChanged(mIntArrayCaptor.capture());
+ verify(listener).onStateChanged(mIntegerCaptor.capture());
+ assertEquals(3, mIntegerCaptor.getValue().intValue());
+
+ Mockito.clearInvocations(listener);
+
+ SensorEvent event1 = mock(SensorEvent.class);
+ event1.sensor = sensor;
+ FieldSetter.setField(event1, event1.getClass().getField("values"), new float[] { 90 });
+
+ provider.onSensorChanged(event1);
+
+ verify(listener, never()).onSupportedDeviceStatesChanged(mIntArrayCaptor.capture());
+ verify(listener).onStateChanged(mIntegerCaptor.capture());
+ assertEquals(2, mIntegerCaptor.getValue().intValue());
+
+ Mockito.clearInvocations(listener);
+
+ SensorEvent event2 = mock(SensorEvent.class);
+ event2.sensor = sensor;
+ FieldSetter.setField(event2, event2.getClass().getField("values"), new float[] { 0 });
+
+ provider.onSensorChanged(event2);
+
+ verify(listener, never()).onSupportedDeviceStatesChanged(mIntArrayCaptor.capture());
+ verify(listener).onStateChanged(mIntegerCaptor.capture());
+ assertEquals(1, mIntegerCaptor.getValue().intValue());
+ }
+
+ private static Sensor newSensor(String name, int type) throws Exception {
+ Constructor<Sensor> constructor = Sensor.class.getDeclaredConstructor();
+ constructor.setAccessible(true);
+
+ Sensor sensor = constructor.newInstance();
+ FieldSetter.setField(sensor, Sensor.class.getDeclaredField("mName"), name);
+ FieldSetter.setField(sensor, Sensor.class.getDeclaredField("mType"), type);
+ return sensor;
+ }
+
+ private static final class TestReadableConfig implements
+ DeviceStateProviderImpl.ReadableConfig {
+ private final byte[] mData;
+
+ TestReadableConfig(String configFileData) {
+ mData = configFileData.getBytes();
+ }
+
+ @NonNull
+ @Override
+ public InputStream openRead() throws IOException {
+ return new ByteArrayInputStream(mData);
+ }
+ }
+}
diff --git a/services/tests/servicestests/test-apps/PackageParserApp/Android.bp b/services/tests/servicestests/test-apps/PackageParserApp/Android.bp
index c409438e94ae..f69dfe9d03c9 100644
--- a/services/tests/servicestests/test-apps/PackageParserApp/Android.bp
+++ b/services/tests/servicestests/test-apps/PackageParserApp/Android.bp
@@ -51,3 +51,17 @@ android_test_helper_app {
resource_dirs: ["res"],
manifest: "AndroidManifestApp3.xml",
}
+
+android_test_helper_app {
+ name: "PackageParserTestApp4",
+ sdk_version: "current",
+ srcs: ["**/*.java"],
+ dex_preopt: {
+ enabled: false,
+ },
+ optimize: {
+ enabled: false,
+ },
+ resource_dirs: ["res"],
+ manifest: "AndroidManifestApp4.xml",
+}
diff --git a/services/tests/servicestests/test-apps/PackageParserApp/AndroidManifestApp4.xml b/services/tests/servicestests/test-apps/PackageParserApp/AndroidManifestApp4.xml
new file mode 100644
index 000000000000..299b9a03d815
--- /dev/null
+++ b/services/tests/servicestests/test-apps/PackageParserApp/AndroidManifestApp4.xml
@@ -0,0 +1,65 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!-- Copyright (C) 2020 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.android.servicestests.apps.packageparserapp" >
+ <application>
+ <uses-library android:name="android.test.runner" />
+ <property android:name="android.cts.PROPERTY_RESOURCE_XML" android:resource="@xml/xml_property" />
+ <property android:name="android.cts.PROPERTY_RESOURCE_INTEGER" android:resource="@integer/integer_property" />
+ <property android:name="android.cts.PROPERTY_BOOLEAN" android:value="true" />
+ <property android:name="android.cts.PROPERTY_BOOLEAN_VIA_RESOURCE" android:value="@bool/boolean_property" />
+ <property android:name="android.cts.PROPERTY_FLOAT" android:value="3.14" />
+ <property android:name="android.cts.PROPERTY_FLOAT_VIA_RESOURCE" android:value="@dimen/float_property" />
+ <property android:name="android.cts.PROPERTY_INTEGER" android:value="42" />
+ <property android:name="android.cts.PROPERTY_INTEGER_VIA_RESOURCE" android:value="@integer/integer_property" />
+ <property android:name="android.cts.PROPERTY_STRING" android:value="koala" />
+ <property android:name="android.cts.PROPERTY_STRING_VIA_RESOURCE" android:value="@string/string_property" />
+
+ <activity android:name="com.android.servicestests.apps.packageparserapp.MyActivity"
+ android:exported="true" >
+ <property android:name="android.cts.PROPERTY_ACTIVITY" android:value="@integer/integer_property" />
+ <property android:name="android.cts.PROPERTY_COMPONENT" android:value="@integer/integer_property" />
+ <property android:name="android.cts.PROPERTY_STRING" android:value="koala activity" />
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity>
+ <activity-alias android:name="com.android.servicestests.apps.packageparserapp.MyActivityAlias"
+ android:targetActivity="com.android.servicestests.apps.packageparserapp.MyActivity">
+ <property android:name="android.cts.PROPERTY_ACTIVITY_ALIAS" android:value="@integer/integer_property" />
+ <property android:name="android.cts.PROPERTY_COMPONENT" android:value="@integer/integer_property" />
+ </activity-alias>
+ <provider android:name="com.android.servicestests.apps.packageparserapp.MyProvider"
+ android:authorities="propertytest">
+ <property android:name="android.cts.PROPERTY_PROVIDER" android:value="@integer/integer_property" />
+ </provider>
+ <receiver android:name="com.android.servicestests.apps.packageparserapp.MyReceiver">
+ <property android:name="android.cts.PROPERTY_RECEIVER" android:value="@integer/integer_property" />
+ <property android:name="android.cts.PROPERTY_STRING" android:value="koala receiver" />
+ </receiver>
+ <service android:name="com.android.servicestests.apps.packageparserapp.MyService">
+ <property android:name="android.cts.PROPERTY_SERVICE" android:value="@integer/integer_property" />
+ <property android:name="android.cts.PROPERTY_COMPONENT" android:resource="@integer/integer_property" />
+ </service>
+ </application>
+
+ <instrumentation
+ android:name="androidx.test.runner.AndroidJUnitRunner"
+ android:targetPackage="com.android.servicestests.apps.packageparserapp" />
+</manifest>
diff --git a/services/tests/servicestests/test-apps/PackageParserApp/res/values/values.xml b/services/tests/servicestests/test-apps/PackageParserApp/res/values/values.xml
index 6a4cc653494f..67ecf66f9c6b 100644
--- a/services/tests/servicestests/test-apps/PackageParserApp/res/values/values.xml
+++ b/services/tests/servicestests/test-apps/PackageParserApp/res/values/values.xml
@@ -16,4 +16,10 @@
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<bool name="config_isIsolated">true</bool>
-</resources> \ No newline at end of file
+ <bool name="boolean_property">true</bool>
+ <color name="color_property">#00FF00</color>
+ <item name="float_property" format="float" type="dimen">2.718</item>
+ <dimen name="dimen_property">23dp</dimen>
+ <integer name="integer_property">123</integer>
+ <string name="string_property">giraffe</string>
+</resources>
diff --git a/services/tests/servicestests/test-apps/PackageParserApp/res/xml/xml_property.xml b/services/tests/servicestests/test-apps/PackageParserApp/res/xml/xml_property.xml
new file mode 100644
index 000000000000..588db8dfa0c1
--- /dev/null
+++ b/services/tests/servicestests/test-apps/PackageParserApp/res/xml/xml_property.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2020 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<paths>
+ <external-path path="Android/data/" name="files_root" />
+ <external-path path="." name="external_storage_root" />
+</paths>
diff --git a/services/tests/servicestests/test-apps/PackageParserApp/src/com/android/servicestests/apps/packageparserapp/MyProvider.java b/services/tests/servicestests/test-apps/PackageParserApp/src/com/android/servicestests/apps/packageparserapp/MyProvider.java
new file mode 100644
index 000000000000..6627166969f3
--- /dev/null
+++ b/services/tests/servicestests/test-apps/PackageParserApp/src/com/android/servicestests/apps/packageparserapp/MyProvider.java
@@ -0,0 +1,57 @@
+/*
+ * 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.servicestests.apps.packageparserapp;
+
+import android.content.ContentProvider;
+import android.content.ContentValues;
+import android.database.Cursor;
+import android.net.Uri;
+
+public class MyProvider extends ContentProvider {
+
+ @Override
+ public boolean onCreate() {
+ return true;
+ }
+
+ @Override
+ public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs,
+ String sortOrder) {
+ return null;
+ }
+
+ @Override
+ public String getType(Uri uri) {
+ return "text/plain";
+ }
+
+ @Override
+ public Uri insert(Uri uri, ContentValues values) {
+ return null;
+ }
+
+ @Override
+ public int delete(Uri uri, String selection, String[] selectionArgs) {
+ return 0;
+ }
+
+ @Override
+ public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
+ return 0;
+ }
+
+}
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/BuzzBeepBlinkTest.java b/services/tests/uiservicestests/src/com/android/server/notification/BuzzBeepBlinkTest.java
index 9766cb546616..00f706b13c58 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/BuzzBeepBlinkTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/BuzzBeepBlinkTest.java
@@ -15,6 +15,7 @@
*/
package com.android.server.notification;
+import static android.app.Notification.FLAG_BUBBLE;
import static android.app.Notification.GROUP_ALERT_ALL;
import static android.app.Notification.GROUP_ALERT_CHILDREN;
import static android.app.Notification.GROUP_ALERT_SUMMARY;
@@ -38,6 +39,7 @@ import static org.mockito.Matchers.anyObject;
import static org.mockito.Matchers.anyString;
import static org.mockito.Matchers.argThat;
import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.timeout;
@@ -50,9 +52,11 @@ import android.app.Notification;
import android.app.Notification.Builder;
import android.app.NotificationChannel;
import android.app.NotificationManager;
+import android.app.PendingIntent;
import android.content.Context;
import android.content.pm.PackageManager;
import android.graphics.Color;
+import android.graphics.drawable.Icon;
import android.media.AudioAttributes;
import android.media.AudioManager;
import android.net.Uri;
@@ -1596,6 +1600,77 @@ public class BuzzBeepBlinkTest extends UiServiceTestCase {
assertTrue(interrupter.isInterruptive());
}
+ @Test
+ public void testBubbleSuppressedNotificationDoesntMakeSound() {
+ Notification.BubbleMetadata metadata = new Notification.BubbleMetadata.Builder(
+ mock(PendingIntent.class), mock(Icon.class))
+ .build();
+
+ NotificationRecord record = getBuzzyNotification();
+ metadata.setFlags(Notification.BubbleMetadata.FLAG_SUPPRESS_NOTIFICATION);
+ record.getNotification().setBubbleMetadata(metadata);
+ record.setAllowBubble(true);
+ record.getNotification().flags |= FLAG_BUBBLE;
+ record.isUpdate = true;
+ record.setInterruptive(false);
+
+ mService.buzzBeepBlinkLocked(record);
+ verifyNeverVibrate();
+ }
+
+ @Test
+ public void testOverflowBubbleSuppressedNotificationDoesntMakeSound() {
+ Notification.BubbleMetadata metadata = new Notification.BubbleMetadata.Builder(
+ mock(PendingIntent.class), mock(Icon.class))
+ .build();
+
+ NotificationRecord record = getBuzzyNotification();
+ metadata.setFlags(Notification.BubbleMetadata.FLAG_SUPPRESS_NOTIFICATION);
+ record.getNotification().setBubbleMetadata(metadata);
+ record.setFlagBubbleRemoved(true);
+ record.setAllowBubble(true);
+ record.isUpdate = true;
+ record.setInterruptive(false);
+
+ mService.buzzBeepBlinkLocked(record);
+ verifyNeverVibrate();
+ }
+
+ @Test
+ public void testBubbleUpdateMakesSound() {
+ Notification.BubbleMetadata metadata = new Notification.BubbleMetadata.Builder(
+ mock(PendingIntent.class), mock(Icon.class))
+ .build();
+
+ NotificationRecord record = getBuzzyNotification();
+ record.getNotification().setBubbleMetadata(metadata);
+ record.setAllowBubble(true);
+ record.getNotification().flags |= FLAG_BUBBLE;
+ record.isUpdate = true;
+ record.setInterruptive(true);
+
+ mService.buzzBeepBlinkLocked(record);
+ verifyVibrate(1);
+ }
+
+ @Test
+ public void testNewBubbleSuppressedNotifMakesSound() {
+ Notification.BubbleMetadata metadata = new Notification.BubbleMetadata.Builder(
+ mock(PendingIntent.class), mock(Icon.class))
+ .build();
+
+ NotificationRecord record = getBuzzyNotification();
+ metadata.setFlags(Notification.BubbleMetadata.FLAG_SUPPRESS_NOTIFICATION);
+ record.getNotification().setBubbleMetadata(metadata);
+ record.setAllowBubble(true);
+ record.getNotification().flags |= FLAG_BUBBLE;
+ record.isUpdate = false;
+ record.setInterruptive(true);
+
+ mService.buzzBeepBlinkLocked(record);
+ verifyVibrate(1);
+ }
+
static class VibrateRepeatMatcher implements ArgumentMatcher<VibrationEffect> {
private final int mRepeatIndex;
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java
index f607448c09a0..bded3f9de9ba 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java
@@ -126,6 +126,7 @@ public class ActivityStarterTests extends WindowTestsBase {
private static final String FAKE_CALLING_PACKAGE = "com.whatever.dude";
private static final int UNIMPORTANT_UID = 12345;
private static final int UNIMPORTANT_UID2 = 12346;
+ private static final int CURRENT_IME_UID = 12347;
@Before
public void setUp() throws Exception {
@@ -315,6 +316,12 @@ public class ActivityStarterTests extends WindowTestsBase {
return prepareStarter(launchFlags, mockGetLaunchStack, LAUNCH_MULTIPLE);
}
+ private void setupImeWindow() {
+ final WindowState imeWindow = createWindow(null, W_INPUT_METHOD,
+ "mImeWindow", CURRENT_IME_UID);
+ mDisplayContent.mInputMethodWindow = imeWindow;
+ }
+
/**
* Creates a {@link ActivityStarter} with default parameters and necessary mocks.
*
@@ -654,6 +661,14 @@ public class ActivityStarterTests extends WindowTestsBase {
UNIMPORTANT_UID, false, PROCESS_STATE_TOP + 1,
UNIMPORTANT_UID2, false, PROCESS_STATE_TOP + 1,
false, false, false, false, true);
+
+ setupImeWindow();
+ runAndVerifyBackgroundActivityStartsSubtest(
+ "disallowed_callingPackageNameIsIme_notAborted", false,
+ CURRENT_IME_UID, false, PROCESS_STATE_TOP + 1,
+ UNIMPORTANT_UID2, false, PROCESS_STATE_TOP + 1,
+ false, false, false, false, false);
+
}
private void runAndVerifyBackgroundActivityStartsSubtest(String name, boolean shouldHaveAborted,
@@ -680,14 +695,11 @@ public class ActivityStarterTests extends WindowTestsBase {
boolean isCallingUidDeviceOwner,
boolean isPinnedSingleInstance) {
// window visibility
- doReturn(callingUidHasVisibleWindow).when(mAtm.mWindowManager.mRoot)
- .isAnyNonToastWindowVisibleForUid(callingUid);
- doReturn(realCallingUidHasVisibleWindow).when(mAtm.mWindowManager.mRoot)
- .isAnyNonToastWindowVisibleForUid(realCallingUid);
-
+ doReturn(callingUidHasVisibleWindow).when(mAtm).hasActiveVisibleWindow(callingUid);
+ doReturn(realCallingUidHasVisibleWindow).when(mAtm).hasActiveVisibleWindow(realCallingUid);
// process importance
- doReturn(callingUidProcState).when(mAtm).getUidState(callingUid);
- doReturn(realCallingUidProcState).when(mAtm).getUidState(realCallingUid);
+ mAtm.mActiveUids.onUidActive(callingUid, callingUidProcState);
+ mAtm.mActiveUids.onUidActive(realCallingUid, realCallingUidProcState);
// foreground activities
final IApplicationThread caller = mock(IApplicationThread.class);
final WindowProcessListener listener = mock(WindowProcessListener.class);
diff --git a/services/tests/wmtests/src/com/android/server/wm/RootWindowContainerTests.java b/services/tests/wmtests/src/com/android/server/wm/RootWindowContainerTests.java
index 62aa02f609ad..42193c8fce78 100644
--- a/services/tests/wmtests/src/com/android/server/wm/RootWindowContainerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/RootWindowContainerTests.java
@@ -17,11 +17,6 @@
package com.android.server.wm;
import static android.view.Display.DEFAULT_DISPLAY;
-import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
-import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
-import static android.view.WindowManager.LayoutParams.TYPE_NOTIFICATION_SHADE;
-import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR;
-import static android.view.WindowManager.LayoutParams.TYPE_TOAST;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
@@ -35,7 +30,6 @@ import static com.google.common.truth.Truth.assertThat;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
import android.app.WindowConfiguration;
import android.content.ComponentName;
@@ -58,57 +52,6 @@ import org.junit.runner.RunWith;
@RunWith(WindowTestRunner.class)
public class RootWindowContainerTests extends WindowTestsBase {
- private static final int FAKE_CALLING_UID = 667;
-
- @Test
- public void testIsAnyNonToastWindowVisibleForUid_oneToastOneAppStartOneNonToastBothVisible() {
- final WindowState toastyToast = createWindow(null, TYPE_TOAST, "toast", FAKE_CALLING_UID);
- final WindowState app = createWindow(null, TYPE_APPLICATION, "app", FAKE_CALLING_UID);
- final WindowState appStart = createWindow(null, TYPE_APPLICATION_STARTING, "appStarting",
- FAKE_CALLING_UID);
- toastyToast.mHasSurface = true;
- app.mHasSurface = true;
- appStart.mHasSurface = true;
-
- assertTrue(toastyToast.isVisibleNow());
- assertTrue(app.isVisibleNow());
- assertTrue(appStart.isVisibleNow());
- assertTrue(mWm.mRoot.isAnyNonToastWindowVisibleForUid(FAKE_CALLING_UID));
- }
-
- @Test
- public void testIsAnyNonToastWindowVisibleForUid_onlyToastVisible() {
- final WindowState toastyToast = createWindow(null, TYPE_TOAST, "toast", FAKE_CALLING_UID);
- toastyToast.mHasSurface = true;
-
- assertTrue(toastyToast.isVisibleNow());
- assertFalse(mWm.mRoot.isAnyNonToastWindowVisibleForUid(FAKE_CALLING_UID));
- }
-
- @Test
- public void testIsAnyNonToastWindowVisibleForUid_onlyAppStartingVisible() {
- final WindowState appStart = createWindow(null, TYPE_APPLICATION_STARTING, "appStarting",
- FAKE_CALLING_UID);
- appStart.mHasSurface = true;
-
- assertTrue(appStart.isVisibleNow());
- assertFalse(mWm.mRoot.isAnyNonToastWindowVisibleForUid(FAKE_CALLING_UID));
- }
-
- @Test
- public void testIsAnyNonToastWindowVisibleForUid_aFewNonToastButNoneVisible() {
- final WindowState statusBar =
- createWindow(null, TYPE_STATUS_BAR, "statusBar", FAKE_CALLING_UID);
- final WindowState notificationShade = createWindow(null, TYPE_NOTIFICATION_SHADE,
- "notificationShade", FAKE_CALLING_UID);
- final WindowState app = createWindow(null, TYPE_APPLICATION, "app", FAKE_CALLING_UID);
-
- assertFalse(statusBar.isVisibleNow());
- assertFalse(notificationShade.isVisibleNow());
- assertFalse(app.isVisibleNow());
- assertFalse(mWm.mRoot.isAnyNonToastWindowVisibleForUid(FAKE_CALLING_UID));
- }
-
@Test
public void testUpdateDefaultDisplayWindowingModeOnSettingsRetrieved() {
assertEquals(WindowConfiguration.WINDOWING_MODE_FULLSCREEN,
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 75d2c5159187..1d498bd3253b 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java
@@ -35,6 +35,7 @@ import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_SUB_PANEL;
import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD;
+import static android.view.WindowManager.LayoutParams.TYPE_TOAST;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.doNothing;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
@@ -731,6 +732,39 @@ public class WindowStateTests extends WindowTestsBase {
handle.inputFeatures);
}
+ @Test
+ public void testHasActiveVisibleWindow() {
+ final int uid = ActivityBuilder.DEFAULT_FAKE_UID;
+ mAtm.mActiveUids.onUidActive(uid, 0 /* any proc state */);
+
+ final WindowState app = createWindow(null, TYPE_APPLICATION, "app", uid);
+ app.mActivityRecord.setVisible(false);
+ app.mActivityRecord.setVisibility(false /* visible */, false /* deferHidingClient */);
+ assertFalse(mAtm.hasActiveVisibleWindow(uid));
+
+ app.mActivityRecord.setVisibility(true /* visible */, false /* deferHidingClient */);
+ assertTrue(mAtm.hasActiveVisibleWindow(uid));
+
+ // Make the activity invisible and add a visible toast. The uid should have no active
+ // visible window because toast can be misused by legacy app to bypass background check.
+ app.mActivityRecord.setVisibility(false /* visible */, false /* deferHidingClient */);
+ final WindowState overlay = createWindow(null, TYPE_APPLICATION_OVERLAY, "overlay", uid);
+ final WindowState toast = createWindow(null, TYPE_TOAST, app.mToken, "toast", uid);
+ toast.onSurfaceShownChanged(true);
+ assertFalse(mAtm.hasActiveVisibleWindow(uid));
+
+ // Though starting window should belong to system. Make sure it is ignored to avoid being
+ // allow-list unexpectedly, see b/129563343.
+ final WindowState starting =
+ createWindow(null, TYPE_APPLICATION_STARTING, app.mToken, "starting", uid);
+ starting.onSurfaceShownChanged(true);
+ assertFalse(mAtm.hasActiveVisibleWindow(uid));
+
+ // Make the application overlay window visible. It should be a valid active visible window.
+ overlay.onSurfaceShownChanged(true);
+ assertTrue(mAtm.hasActiveVisibleWindow(uid));
+ }
+
@UseTestDisplay(addWindows = W_ACTIVITY)
@Test
public void testNeedsRelativeLayeringToIme_notAttached() {
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java b/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java
index ebbbc29b035c..83053813116b 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java
@@ -637,6 +637,7 @@ class WindowTestsBase extends SystemServiceTestsBase {
* Builder for creating new activities.
*/
protected static class ActivityBuilder {
+ static final int DEFAULT_FAKE_UID = 12345;
// An id appended to the end of the component name to make it unique
private static int sCurrentActivityId = 0;
@@ -647,7 +648,7 @@ class WindowTestsBase extends SystemServiceTestsBase {
private Task mTask;
private String mProcessName = "name";
private String mAffinity;
- private int mUid = 12345;
+ private int mUid = DEFAULT_FAKE_UID;
private boolean mCreateTask = false;
private Task mParentTask;
private int mActivityFlags;
@@ -857,7 +858,7 @@ class WindowTestsBase extends SystemServiceTestsBase {
} else {
wpc = new WindowProcessController(mService,
aInfo.applicationInfo, mProcessName, mUid,
- UserHandle.getUserId(12345), mock(Object.class),
+ UserHandle.getUserId(mUid), mock(Object.class),
mock(WindowProcessListener.class));
wpc.setThread(mock(IApplicationThread.class));
}
diff --git a/telephony/java/android/telephony/Annotation.java b/telephony/java/android/telephony/Annotation.java
index 031c3376f3ba..f900c387f060 100644
--- a/telephony/java/android/telephony/Annotation.java
+++ b/telephony/java/android/telephony/Annotation.java
@@ -634,4 +634,15 @@ public class Annotation {
TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_NSA,
TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_NSA_MMWAVE})
public @interface OverrideNetworkType {}
+
+ /**
+ * Result of a thermal mitigation request.
+ */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef(prefix = { "THERMAL_MITIGATION_RESULT_" }, value = {
+ TelephonyManager.THERMAL_MITIGATION_RESULT_SUCCESS,
+ TelephonyManager.THERMAL_MITIGATION_RESULT_MODEM_ERROR,
+ TelephonyManager.THERMAL_MITIGATION_RESULT_INVALID_STATE,
+ TelephonyManager.THERMAL_MITIGATION_RESULT_UNKNOWN_ERROR})
+ public @interface ThermalMitigationResult {}
}
diff --git a/telephony/java/android/telephony/DataThrottlingRequest.aidl b/telephony/java/android/telephony/DataThrottlingRequest.aidl
new file mode 100644
index 000000000000..e1a3b66d2433
--- /dev/null
+++ b/telephony/java/android/telephony/DataThrottlingRequest.aidl
@@ -0,0 +1,19 @@
+/*
+* 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.telephony;
+
+parcelable DataThrottlingRequest; \ No newline at end of file
diff --git a/telephony/java/android/telephony/DataThrottlingRequest.java b/telephony/java/android/telephony/DataThrottlingRequest.java
new file mode 100644
index 000000000000..f50bb58c4b2e
--- /dev/null
+++ b/telephony/java/android/telephony/DataThrottlingRequest.java
@@ -0,0 +1,244 @@
+/*
+ * 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.telephony;
+
+import android.annotation.IntDef;
+import android.annotation.NonNull;
+import android.annotation.SystemApi;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+
+/**
+ * Class stores information related to the type of data throttling request. Must be populated as
+ * field in {@link ThermalMitigationRequest} for sending of thermal mitigation request at {@link
+ * TelephonyManager#sendThermalMitigationRequest(ThermalMitigationResult)}.
+ * @hide
+ */
+@SystemApi
+public final class DataThrottlingRequest implements Parcelable {
+ /**
+ * Clear all existing data throttling, enable data, and attempt to enable radio for thermal
+ * mitigation all within the requested completion window. Note that attempting to enable radio
+ * will not guarantee that radio will actually be enabled.
+ *
+ * @hide
+ */
+ @SystemApi
+ public static final int DATA_THROTTLING_ACTION_NO_DATA_THROTTLING = 0;
+
+ /**
+ * Enact secondary carrier data throttling within specified completion window. This also
+ * attempts to enables radio if currently disabled for thermal mitigation, enables data, and
+ * removes any existing data throttling on primary carrier. Note that attempting to enable radio
+ * will not guarantee that radio will actually be enabled.
+ *
+ * @hide
+ */
+ @SystemApi
+ public static final int DATA_THROTTLING_ACTION_THROTTLE_SECONDARY_CARRIER = 1;
+
+ /**
+ * Enact primary carrier data throttling within specified completion window. This also attempts
+ * to enable radio if currently disabled for thermal mitigation and disables data on secondary
+ * carrier if currently enabled. Note that attempting to enable radio will not guarantee that
+ * radio will actually be enabled.
+ *
+ * @hide
+ */
+ @SystemApi
+ public static final int DATA_THROTTLING_ACTION_THROTTLE_PRIMARY_CARRIER = 2;
+
+ /**
+ * Immediately hold on to the current level of data throttling indicating that the current level
+ * of data throttling has alleviated the thermal concerns which caused the original data
+ * throttling request. A thermal module should remain actively monitoring the temperature levels
+ * and request an appropriate thermal mitigation action. {@link
+ * #THERMAL_MITIGATION_RESULT_INVALID_PARAMETERS} will be returned if completion window is not
+ * 0.
+ *
+ * @hide
+ */
+ @SystemApi
+ public static final int DATA_THROTTLING_ACTION_HOLD = 3;
+
+ /**
+ * Type of data throttling action to carry out.
+ * @hide
+ */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef(prefix = { "DATA_THROTTLING_ACTION_" }, value = {
+ DATA_THROTTLING_ACTION_NO_DATA_THROTTLING,
+ DATA_THROTTLING_ACTION_THROTTLE_SECONDARY_CARRIER,
+ DATA_THROTTLING_ACTION_THROTTLE_PRIMARY_CARRIER,
+ DATA_THROTTLING_ACTION_HOLD})
+ public @interface DataThrottlingAction {}
+
+ /**
+ * Represents the data throttling action that will be requested. See {@link
+ * DATA_THROTTLING_ACTION_NO_DATA_THROTTLING}, {@link
+ * #DATA_THROTTLING_ACTION_THROTTLE_SECONDARY_CARRIER}, {@link
+ * #DATA_THROTTLING_ACTION_THROTTLE_PRIMARY_CARRIER}, and {@link
+ * #DATA_THROTTLING_ACTION_HOLD} for more details.
+ **/
+ private @DataThrottlingAction int mDataThrottlingAction;
+ /**
+ * Represents the time over which modem should gradually execute the data thorttling request.
+ */
+ private long mCompletionDurationMillis;
+
+ private DataThrottlingRequest(@NonNull int dataThrottlingAction,
+ long completionDurationMillis) {
+ mDataThrottlingAction = dataThrottlingAction;
+ mCompletionDurationMillis = completionDurationMillis;
+ }
+
+ private DataThrottlingRequest(Parcel in) {
+ mDataThrottlingAction = in.readInt();
+ mCompletionDurationMillis = in.readLong();
+ }
+
+ /**
+ * Implement the Parcelable interface
+ */
+ @Override
+ public void writeToParcel(@NonNull Parcel dest, int flags) {
+ dest.writeInt(mDataThrottlingAction);
+ dest.writeLong(mCompletionDurationMillis);
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public String toString() {
+ return "[DataThrottlingRequest "
+ + ", DataThrottlingAction=" + mDataThrottlingAction
+ + ", completionDurationMillis=" + mCompletionDurationMillis
+ + "]";
+ }
+
+ /**
+ * @return the dataThrottlingAction.
+ */
+ public @DataThrottlingAction int getDataThrottlingAction() {
+ return mDataThrottlingAction;
+ }
+
+ /**
+ * @return the completionDurationMillis which represents the time over which modem should
+ * gradually execute the data thorttling request.
+ */
+ public long getCompletionDurationMillis() {
+ return mCompletionDurationMillis;
+ }
+
+ public static final @NonNull Parcelable.Creator<DataThrottlingRequest> CREATOR =
+ new Parcelable.Creator<DataThrottlingRequest>() {
+
+ @Override
+ public DataThrottlingRequest createFromParcel(Parcel in) {
+ return new DataThrottlingRequest(in);
+ }
+
+ @Override
+ public DataThrottlingRequest[] newArray(int size) {
+ return new DataThrottlingRequest[size];
+ }
+ };
+
+ /**
+ * Provides a convenient way to set the fields of a {@link DataThrottlingRequest} when creating
+ * a new instance.
+ *
+ * <p>The example below shows how you might create a new {@code DataThrottlingRequest}:
+ *
+ * <pre><code>
+ *
+ * DataThrottlingRequest dp = new DataThrottlingRequest.Builder()
+ * .setDataThrottlingAction(
+ * DataThrottlingRequest.DATA_THROTTLING_ACTION_THROTTLE_SECONDARY_CARRIER)
+ * .setCompletionDurationMillis(10000L)
+ * .build();
+ * </code></pre>
+ *
+ * @hide
+ */
+ @SystemApi
+ public static final class Builder {
+ private @DataThrottlingAction int mDataThrottlingAction;
+ private long mCompletionDurationMillis;
+
+ /**
+ * Default constructor for Builder.
+ */
+ public Builder() {}
+
+ /**
+ * Set the data throttling action.
+ *
+ * @param dataThrottlingAction data throttling action.
+ *
+ * @return The same instance of the builder.
+ */
+ public @NonNull Builder setDataThrottlingAction(
+ @DataThrottlingAction int dataThrottlingAction) {
+ mDataThrottlingAction = dataThrottlingAction;
+ return this;
+ }
+
+ /**
+ * Set the completion duration.
+ *
+ * @param completionDurationMillis completion duration in millis which represents the time
+ * over which modem should gradually execute the data thorttling request. This can
+ * never be a negative number and must be 0 for {@link #DATA_THROTTLING_ACTION_HOLD}.
+ * Otherwise, an IllegalArgumentException will be thrown.
+ *
+ * @return The same instance of the builder.
+ */
+ public @NonNull Builder setCompletionDurationMillis(long completionDurationMillis) {
+ mCompletionDurationMillis = completionDurationMillis;
+ return this;
+ }
+
+ /**
+ * Build the DataThrottlingRequest.
+ *
+ * @return the DataThrottlingRequest object.
+ */
+ public @NonNull DataThrottlingRequest build() {
+ if (mCompletionDurationMillis < 0) {
+ throw new IllegalArgumentException("completionDurationMillis cannot be a negative "
+ + "number");
+ }
+
+ if (mDataThrottlingAction == DataThrottlingRequest.DATA_THROTTLING_ACTION_HOLD
+ && mCompletionDurationMillis != 0) {
+ throw new IllegalArgumentException("completionDurationMillis must be 0 for "
+ + "DataThrottlingRequest.DATA_THROTTLING_ACTION_HOLD");
+ }
+
+ return new DataThrottlingRequest(mDataThrottlingAction, mCompletionDurationMillis);
+ }
+ }
+
+}
diff --git a/telephony/java/android/telephony/PhoneCapability.java b/telephony/java/android/telephony/PhoneCapability.java
index 08b6edab3f5c..b785037e51c1 100644
--- a/telephony/java/android/telephony/PhoneCapability.java
+++ b/telephony/java/android/telephony/PhoneCapability.java
@@ -29,6 +29,7 @@ import java.util.Objects;
* Define capability of a modem group. That is, the capabilities
* are shared between those modems defined by list of modem IDs.
*
+ * @hide
*/
public final class PhoneCapability implements Parcelable {
// Hardcoded default DSDS capability.
diff --git a/telephony/java/android/telephony/PhysicalChannelConfig.java b/telephony/java/android/telephony/PhysicalChannelConfig.java
index 95c69ba470c4..8d49e15da934 100644
--- a/telephony/java/android/telephony/PhysicalChannelConfig.java
+++ b/telephony/java/android/telephony/PhysicalChannelConfig.java
@@ -29,6 +29,10 @@ import java.lang.annotation.RetentionPolicy;
import java.util.Arrays;
import java.util.Objects;
+/**
+ * @hide
+ */
+@SystemApi
public final class PhysicalChannelConfig implements Parcelable {
// TODO(b/72993578) consolidate these enums in a central location.
@@ -82,7 +86,7 @@ public final class PhysicalChannelConfig implements Parcelable {
private int mFrequencyRange;
/**
- * The absolute radio frequency channel number, {@link #CHANNEL_NUMBER_UNKNOWN} if unknown.
+ * The absolute radio frequency channel number, {@link CHANNEL_NUMBER_UNKNOWN} if unknown.
*/
private int mChannelNumber;
@@ -93,7 +97,7 @@ public final class PhysicalChannelConfig implements Parcelable {
private int[] mContextIds;
/**
- * The physical cell identifier for this cell - PCI, PSC, {@link #PHYSICAL_CELL_ID_UNKNOWN}
+ * The physical cell identifier for this cell - PCI, PSC, {@link PHYSICAL_CELL_ID_UNKNOWN}
* if unknown.
*/
private int mPhysicalCellId;
@@ -149,7 +153,7 @@ public final class PhysicalChannelConfig implements Parcelable {
/**
* @return the absolute radio frequency channel number for this physical channel,
- * {@link #CHANNEL_NUMBER_UNKNOWN} if unknown.
+ * {@link CHANNEL_NUMBER_UNKNOWN} if unknown.
*/
public int getChannelNumber() {
return mChannelNumber;
@@ -165,7 +169,7 @@ public final class PhysicalChannelConfig implements Parcelable {
* In 5G RAN, this value is physical layer cell identity. The range is [0, 1007].
* Reference: 3GPP TS 38.211 section 7.4.2.1.
*
- * @return the physical cell identifier for this cell, {@link #PHYSICAL_CELL_ID_UNKNOWN}
+ * @return the physical cell identifier for this cell, {@link PHYSICAL_CELL_ID_UNKNOWN}
* if {@link android.telephony.CellInfo#UNAVAILABLE}.
*/
@IntRange(from = 0, to = 1007)
diff --git a/telephony/java/android/telephony/RadioInterfaceCapabilities.java b/telephony/java/android/telephony/RadioInterfaceCapabilities.java
new file mode 100644
index 000000000000..7c7eb9fbbeb2
--- /dev/null
+++ b/telephony/java/android/telephony/RadioInterfaceCapabilities.java
@@ -0,0 +1,53 @@
+/*
+ * 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.telephony;
+
+import android.util.ArraySet;
+
+/**
+ * Contains the set of supported capabilities that the Radio Interface supports on this device.
+ *
+ * @hide
+ */
+public class RadioInterfaceCapabilities {
+
+ private final ArraySet<String> mSupportedCapabilities;
+
+
+ public RadioInterfaceCapabilities() {
+ mSupportedCapabilities = new ArraySet<>();
+ }
+
+ /**
+ * Marks a capability as supported
+ *
+ * @param capabilityName the name of the capability
+ */
+ public void addSupportedCapability(
+ @TelephonyManager.RadioInterfaceCapability String capabilityName) {
+ mSupportedCapabilities.add(capabilityName);
+ }
+
+ /**
+ * Whether the capability is supported
+ *
+ * @param capabilityName the name of the capability
+ */
+ public boolean isSupported(String capabilityName) {
+ return mSupportedCapabilities.contains(capabilityName);
+ }
+}
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index 683f200c1a35..e341e0c19cf5 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -78,6 +78,7 @@ import android.telephony.Annotation.CarrierPrivilegeStatus;
import android.telephony.Annotation.NetworkType;
import android.telephony.Annotation.RadioPowerState;
import android.telephony.Annotation.SimActivationState;
+import android.telephony.Annotation.ThermalMitigationResult;
import android.telephony.Annotation.UiccAppType;
import android.telephony.CallForwardingInfo.CallForwardingReason;
import android.telephony.VisualVoicemailService.VisualVoicemailTask;
@@ -123,7 +124,6 @@ import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Objects;
-import java.util.Set;
import java.util.UUID;
import java.util.concurrent.Executor;
import java.util.function.Consumer;
@@ -155,7 +155,6 @@ import java.util.function.Consumer;
public class TelephonyManager {
private static final String TAG = "TelephonyManager";
- private TelephonyRegistryManager mTelephonyRegistryMgr;
/**
* To expand the error codes for {@link TelephonyManager#updateAvailableNetworks} and
* {@link TelephonyManager#setPreferredOpportunisticDataSubscription}.
@@ -5595,22 +5594,12 @@ public class TelephonyManager {
* @param events The telephony state(s) of interest to the listener,
* as a bitwise-OR combination of {@link PhoneStateListener}
* LISTEN_ flags.
- * @deprecated Use {@link #registerPhoneStateListener(Executor, PhoneStateListener)}.
+ * @deprecated use {@link #listen(long, PhoneStateListener) instead due to the event number
+ * limit increased to 64.
*/
@Deprecated
public void listen(PhoneStateListener listener, int events) {
- boolean notifyNow = getITelephony() != null;
- mTelephonyRegistryMgr = mContext.getSystemService(TelephonyRegistryManager.class);
- if (mTelephonyRegistryMgr != null) {
- if (events != PhoneStateListener.LISTEN_NONE) {
- mTelephonyRegistryMgr.registerPhoneStateListenerWithEvents(getSubId(),
- getOpPackageName(), getAttributionTag(), listener, events, notifyNow);
- } else {
- unregisterPhoneStateListener(listener);
- }
- } else {
- throw new IllegalStateException("telephony service is null.");
- }
+ listen(events, listener);
}
/**
@@ -5646,21 +5635,18 @@ public class TelephonyManager {
* LISTEN_ flags.
* @param listener The {@link PhoneStateListener} object to register
* (or unregister)
- * @deprecated Use {@link #registerPhoneStateListener(Executor, PhoneStateListener)}.
*/
- @Deprecated
public void listen(long events, @NonNull PhoneStateListener listener) {
- mTelephonyRegistryMgr = mContext.getSystemService(TelephonyRegistryManager.class);
- if (mTelephonyRegistryMgr != null) {
- if (events != PhoneStateListener.LISTEN_NONE) {
- mTelephonyRegistryMgr.registerPhoneStateListenerWithEvents(getSubId(),
- getOpPackageName(), getAttributionTag(), listener,
- Long.valueOf(events).intValue(), getITelephony() != null);
- } else {
- unregisterPhoneStateListener(listener);
- }
+ if (mContext == null) return;
+ boolean notifyNow = (getITelephony() != null);
+ TelephonyRegistryManager telephonyRegistry =
+ (TelephonyRegistryManager)
+ mContext.getSystemService(Context.TELEPHONY_REGISTRY_SERVICE);
+ if (telephonyRegistry != null) {
+ telephonyRegistry.listenForSubscriber(mSubId, getOpPackageName(), getAttributionTag(),
+ listener, events, notifyNow);
} else {
- throw new IllegalStateException("telephony service is null.");
+ Rlog.w(TAG, "telephony registry not ready.");
}
}
@@ -13215,6 +13201,37 @@ public class TelephonyManager {
}
/**
+ * Get which bands the modem's background scan is acting on, specified by
+ * {@link #setSystemSelectionChannels}.
+ *
+ * <p>Requires Permission:
+ * {@link android.Manifest.permission#READ_PRIVILEGED_PHONE_STATE READ_PRIVILEGED_PHONE_STATE}
+ * or that the calling app has carrier privileges (see {@link #hasCarrierPrivileges}).
+ *
+ * @return a list of {@link RadioAccessSpecifier}, or an empty list if no bands are specified.
+ * @throws IllegalStateException if the Telephony process is not currently available.
+ *
+ * @hide
+ */
+ @SystemApi
+ @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
+ public @NonNull List<RadioAccessSpecifier> getSystemSelectionChannels() {
+ try {
+ ITelephony service = getITelephony();
+ if (service != null) {
+ return service.getSystemSelectionChannels(getSubId());
+ } else {
+ throw new IllegalStateException("telephony service is null.");
+ }
+ } catch (RemoteException ex) {
+ if (!isSystemProcess()) {
+ ex.rethrowAsRuntimeException();
+ }
+ }
+ return new ArrayList<>();
+ }
+
+ /**
* Verifies whether the input MCC/MNC and MVNO correspond to the current carrier.
*
* @param mccmnc the carrier's mccmnc that you want to match
@@ -14194,69 +14211,140 @@ public class TelephonyManager {
return Collections.emptyList();
}
+ /** @hide */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef(prefix = {"RADIO_INTERFACE_CAPABILITY_"},
+ value = {})
+ public @interface RadioInterfaceCapability {}
+
/**
- * Registers a listener object to receive notification of changes
- * in specified telephony states.
- * <p>
- * To register a listener, pass a {@link PhoneStateListener} which implements
- * interfaces of events. For example,
- * FakeServiceStateChangedListener extends {@link PhoneStateListener} implements
- * {@link PhoneStateListener.ServiceStateChangedListener}.
+ * Whether the device supports a given capability on the radio interface.
*
- * At registration, and when a specified telephony state changes, the telephony manager invokes
- * the appropriate callback method on the listener object and passes the current (updated)
- * values.
- * <p>
+ * If the capability is not in the set of radio interface capabilities, false is returned.
*
- * If this TelephonyManager object has been created with {@link #createForSubscriptionId},
- * applies to the given subId. Otherwise, applies to
- * {@link SubscriptionManager#getDefaultSubscriptionId()}. To listen events for multiple subIds,
- * pass a separate listener object to each TelephonyManager object created with
- * {@link #createForSubscriptionId}.
- *
- * Note: if you call this method while in the middle of a binder transaction, you <b>must</b>
- * call {@link android.os.Binder#clearCallingIdentity()} before calling this method. A
- * {@link SecurityException} will be thrown otherwise.
+ * @param capability the name of the capability to check for
+ * @return the availability of the capability
*
- * This API should be used sparingly -- large numbers of listeners will cause system
- * instability. If a process has registered too many listeners without unregistering them, it
- * may encounter an {@link IllegalStateException} when trying to register more listeners.
- *
- * @param executor The executor of where the callback will execute.
- * @param listener The {@link PhoneStateListener} object to register.
+ * @hide
*/
- public void registerPhoneStateListener(@NonNull @CallbackExecutor Executor executor,
- @NonNull PhoneStateListener listener) {
- if (executor == null || listener == null) {
- throw new IllegalStateException("telephony service is null.");
- }
- mTelephonyRegistryMgr = (TelephonyRegistryManager)
- mContext.getSystemService(Context.TELEPHONY_REGISTRY_SERVICE);
- if (mTelephonyRegistryMgr != null) {
- mTelephonyRegistryMgr.registerPhoneStateListener(executor, getSubId(),
- getOpPackageName(), getAttributionTag(), listener, getITelephony() != null);
- } else {
- throw new IllegalStateException("telephony service is null.");
+ public boolean isRadioInterfaceCapabilitySupported(
+ @NonNull @RadioInterfaceCapability String capability) {
+ try {
+ if (capability == null) return false;
+
+ ITelephony telephony = getITelephony();
+ if (telephony != null) {
+ return telephony.isRadioInterfaceCapabilitySupported(capability);
+ } else {
+ throw new IllegalStateException("telephony service is null.");
+ }
+ } catch (RemoteException ex) {
+ if (!isSystemProcess()) {
+ ex.rethrowAsRuntimeException();
+ }
}
+ return false;
}
/**
- * Unregister an existing {@link PhoneStateListener}.
+ * Indicates that the thermal mitigation request was completed successfully.
*
- * @param listener The {@link PhoneStateListener} object to unregister.
+ * @hide
*/
- public void unregisterPhoneStateListener(@NonNull PhoneStateListener listener) {
+ @SystemApi
+ public static final int THERMAL_MITIGATION_RESULT_SUCCESS = 0;
- if (mContext == null) {
- throw new IllegalStateException("telephony service is null.");
- }
+ /**
+ * Indicates that the thermal mitigation request was not completed because of a modem error.
+ *
+ * @hide
+ */
+ @SystemApi
+ public static final int THERMAL_MITIGATION_RESULT_MODEM_ERROR = 1;
- mTelephonyRegistryMgr = mContext.getSystemService(TelephonyRegistryManager.class);
- if (mTelephonyRegistryMgr != null) {
- mTelephonyRegistryMgr.unregisterPhoneStateListener(getSubId(), getOpPackageName(),
- getAttributionTag(), listener, getITelephony() != null);
- } else {
+ /**
+ * Indicates that the thermal mitigation request was not completed because the modem is not
+ * available.
+ *
+ * @hide
+ */
+ @SystemApi
+ public static final int THERMAL_MITIGATION_RESULT_MODEM_NOT_AVAILABLE = 2;
+
+ /**
+ * Indicates that the thermal mitigation request could not power off the radio due to the device
+ * either being in an active voice call, device pending an emergency call, or any other state
+ * that would dissallow powering off of radio.
+ *
+ * @hide
+ */
+ @SystemApi
+ public static final int THERMAL_MITIGATION_RESULT_INVALID_STATE = 3;
+
+ /**
+ * Indicates that the thermal mitigation request resulted an unknown error.
+ *
+ * @hide
+ */
+ @SystemApi
+ public static final int THERMAL_MITIGATION_RESULT_UNKNOWN_ERROR = 4;
+
+ /**
+ * Thermal mitigation request to control functionalities at modem. Thermal mitigation is done
+ * per-subscription. Caller must be sure to bind the TelephonyManager instance to subId by
+ * calling {@link #createForSubscriptionId(int)} if they want thermal mitigation on a specific
+ * subscription Id. Otherwise, TelephonyManager will use the default subscription.
+ *
+ * Calling this does not guarantee that the thermal mitigation action requested was done to
+ * completion. A thermal module should actively monitor the temperature levels and request an
+ * appropriate thermal mitigation action. Every action is assumed to be done 'on top of' the
+ * previous action, where the order of actions from least thermal mitigation to most is as
+ * follows:
+ * <ol>
+ * <li>{@link ThermalMitigationRequest#THERMAL_MITIGATION_ACTION_DATA_THROTTLING}</li>
+ * <ol>
+ * <li>{@link DataThrottlingRequest#DATA_THROTTLING_ACTION_NO_DATA_THROTTLING}</li>
+ * <li>{@link DataThrottlingRequest#DATA_THROTTLING_ACTION_THROTTLE_SECONDARY_CARRIER}</li>
+ * <li>{@link DataThrottlingRequest#DATA_THROTTLING_ACTION_THROTTLE_PRIMARY_CARRIER}</li>
+ * </ol>
+ * <li>{@link ThermalMitigationRequest#THERMAL_MITIGATION_ACTION_VOICE_ONLY}</li>
+ * <li>{@link ThermalMitigationRequest#THERMAL_MITIGATION_ACTION_RADIO_OFF}</li>
+ * </ol>
+ *
+ * So, for example, requesting {@link
+ * DataThrottlingRequest#DATA_THROTTLING_ACTION_THROTTLE_PRIMARY_CARRIER} will ensure that the
+ * data on secondary carrier has been disabled before throttling on primary carrier. {@link
+ * ThermalMitigationRequest#THERMAL_MITIGATION_ACTION_VOICE_ONLY} will ensure that data on both
+ * primary and secondary have been disabled. {@link
+ * ThermalMitigationRequest#THERMAL_MITIGATION_ACTION_RADIO_OFF} will ensure that voice is
+ * disabled and that data on both primary and secondary carriers are disabled before turning
+ * radio off. {@link DataThrottlingRequest#DATA_THROTTLING_ACTION_HOLD} is not part of the order
+ * and can be used at any time during data throttling to hold onto the current level of data
+ * throttling.
+ *
+ * @param thermalMitigationRequest Thermal mitigation request. See {@link
+ * ThermalMitigationRequest} for details.
+ *
+ * @throws IllegalStateException if the Telephony process is not currently available.
+ * @throws IllegalArgumentException if the thermalMitigationRequest had invalid parameters.
+ *
+ * @hide
+ */
+ @SystemApi
+ @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
+ @ThermalMitigationResult
+ public int sendThermalMitigationRequest(
+ @NonNull ThermalMitigationRequest thermalMitigationRequest) {
+ try {
+ ITelephony telephony = getITelephony();
+ if (telephony != null) {
+ return telephony.sendThermalMitigationRequest(getSubId(), thermalMitigationRequest);
+ }
throw new IllegalStateException("telephony service is null.");
+ } catch (RemoteException ex) {
+ Log.e(TAG, "Telephony#thermalMitigationRequest RemoteException", ex);
+ ex.rethrowFromSystemServer();
}
+ return THERMAL_MITIGATION_RESULT_UNKNOWN_ERROR;
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/PointerCountEvaluator.java b/telephony/java/android/telephony/ThermalMitigationRequest.aidl
index d7a3af0360af..a912f77a1de8 100644
--- a/packages/SystemUI/src/com/android/systemui/classifier/PointerCountEvaluator.java
+++ b/telephony/java/android/telephony/ThermalMitigationRequest.aidl
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2015 The Android Open Source Project
+ * 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.
@@ -11,13 +11,9 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
-package com.android.systemui.classifier;
+package android.telephony;
-public class PointerCountEvaluator {
- public static float evaluate(int value) {
- return (value - 1) * (value - 1);
- }
-}
+parcelable ThermalMitigationRequest; \ No newline at end of file
diff --git a/telephony/java/android/telephony/ThermalMitigationRequest.java b/telephony/java/android/telephony/ThermalMitigationRequest.java
new file mode 100644
index 000000000000..91ad9c3e1f51
--- /dev/null
+++ b/telephony/java/android/telephony/ThermalMitigationRequest.java
@@ -0,0 +1,248 @@
+/*
+ * 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.telephony;
+
+import android.annotation.IntDef;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.SystemApi;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+
+/**
+ * Class stores information related to the type of data throttling request to be sent to {@link
+ * TelephonyManager#sendThermalMitigationRequest(ThermalMitigationResult)}.
+ * @hide
+ */
+@SystemApi
+public final class ThermalMitigationRequest implements Parcelable {
+ /**
+ * Sent as a thermal mititgation action to {@link
+ * TelephonyManager#sendThermalMitigationRequest(ThermalMitigationResult)} to start data
+ * throttling. {@link TelephonyManager#InvalidThermalMitigationRequestException} will be thrown
+ * if dataThrottlingRequest is {@code null} or if completion duration is < 0.
+ *
+ * @hide
+ */
+ @SystemApi
+ public static final int THERMAL_MITIGATION_ACTION_DATA_THROTTLING = 0;
+
+ /**
+ * Sent as a thermal mititgation action to {@link
+ * TelephonyManager#sendThermalMitigationRequest(ThermalMitigationResult)} to allow only voice
+ * calls and internet data will not be available. This attempts to enable radio if currently
+ * disabled for thermal mitigation with no guarantee of it actually turning on.
+ * dataThrottlingRequest must be {@code null} or {@link
+ * TelephonyManager#InvalidThermalMitigationRequestException} will be thrown.
+ *
+ * @hide
+ */
+ @SystemApi
+ public static final int THERMAL_MITIGATION_ACTION_VOICE_ONLY = 1;
+
+ /**
+ * Sent as a thermal mititgation action to {@link'
+ * TelephonyManager#sendThermalMitigationRequest(ThermalMitigationResult)} to turn radio off. If
+ * radio is not able to be powered off because of an ongoing voice call, pending emergency call,
+ * or any other state that wouldn't allow radio off, {@link
+ * TelephonyManager#THERMAL_MITIGATION_RESULT_INVALID_STATE}.
+ * dataThrottlingRequest must be {@code null} or
+ * {@link TelephonyManager#InvalidThermalMitigationRequestException} will be returned.
+ *
+ * @hide
+ */
+ @SystemApi
+ public static final int THERMAL_MITIGATION_ACTION_RADIO_OFF = 2;
+
+ /**
+ * Type of thermal mitigation action.
+ * @hide
+ */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef(prefix = { "THERMAL_MITIGATION_ACTION_" }, value = {
+ THERMAL_MITIGATION_ACTION_DATA_THROTTLING,
+ THERMAL_MITIGATION_ACTION_VOICE_ONLY,
+ THERMAL_MITIGATION_ACTION_RADIO_OFF})
+ public @interface ThermalMitigationAction {}
+
+ private @ThermalMitigationAction int mThermalMitigationAction;
+ private DataThrottlingRequest mDataThrottlingRequest;
+
+ /**
+ * @param thermalMitigationAction thermal mitigation action.
+ * @param dataThrottlingRequest is the parameters for more fine-controlled data throttling. This
+ * is only applicable if thermalMitigationAction is
+ * {@link #THERMAL_MITIGATION_ACTION_DATA_THROTTLING}. Otherwise, it must be set to
+ * {@code null}. See {@link DataThrottlingRequest} for more details.
+ */
+ private ThermalMitigationRequest(@ThermalMitigationAction int thermalMitigationAction,
+ @Nullable DataThrottlingRequest dataThrottlingRequest) {
+ mThermalMitigationAction = thermalMitigationAction;
+ mDataThrottlingRequest = dataThrottlingRequest;
+ }
+
+ private ThermalMitigationRequest(Parcel in) {
+ mThermalMitigationAction = in.readInt();
+ mDataThrottlingRequest = in.readParcelable(DataThrottlingRequest.class.getClassLoader());
+ }
+
+ /**
+ * Implement the Parcelable interface
+ */
+ @Override
+ public void writeToParcel(@NonNull Parcel dest, int flags) {
+ dest.writeInt(mThermalMitigationAction);
+ dest.writeParcelable(mDataThrottlingRequest, 0);
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public String toString() {
+ return "[ThermalMitigationRequest "
+ + ", thermalMitigationAction=" + mThermalMitigationAction
+ + ", dataThrottlingRequest=" + mDataThrottlingRequest
+ + "]";
+ }
+
+ /**
+ * @return the thermal mitigation action.
+ */
+ public @ThermalMitigationAction int getThermalMitigationAction() {
+ return mThermalMitigationAction;
+ }
+
+ /**
+ * @return the data throttling request.
+ */
+ @Nullable
+ public DataThrottlingRequest getDataThrottlingRequest() {
+ return mDataThrottlingRequest;
+ }
+
+ public static final @NonNull Parcelable.Creator<ThermalMitigationRequest> CREATOR =
+ new Parcelable.Creator<ThermalMitigationRequest>() {
+
+ @Override
+ public ThermalMitigationRequest createFromParcel(Parcel in) {
+ return new ThermalMitigationRequest(in);
+ }
+
+ @Override
+ public ThermalMitigationRequest[] newArray(int size) {
+ return new ThermalMitigationRequest[size];
+ }
+ };
+
+ /**
+ * Provides a convenient way to set the fields of a {@link ThermalMitigationRequest} when
+ * creating a new instance.
+ *
+ * <p>The example below shows how you might create a new {@code ThermalMitigationRequest}:
+ *
+ * <pre><code>
+ *
+ * ThermalMitigationRequest dp = new ThermalMitigationRequest.Builder()
+ * .setThermalMitigationAction(
+ * ThermalMitigationRequest.THERMAL_MITIGATION_ACTION_DATA_THROTTLING)
+ * .setDataThrottlingRequest(new DataThrottlingRequest.Builder()
+ * .setDataThrottlingAction(
+ * DataThrottlingRequest.DATA_THROTTLING_ACTION_THROTTLE_SECONDARY_CARRIER)
+ * .setCompletionDurationMillis(10000L)
+ * .build())
+ * .build();
+ * </code></pre>
+ *
+ * @hide
+ */
+ @SystemApi
+ public static final class Builder {
+ private @ThermalMitigationAction int mThermalMitigationAction = -1;
+ private DataThrottlingRequest mDataThrottlingRequest;
+
+ /**
+ * Default constructor for Builder.
+ */
+ public Builder() {}
+
+ /**
+ * Set the thermal mitigation action.
+ *
+ * @param thermalMitigationAction thermal mitigation action. See {@link
+ * #THERMAL_MITIGATION_ACTION_DATA_THROTTLING}, {@link
+ * #THERMAL_MITIGATION_ACTION_VOICE_ONLY}, and {@link
+ * #THERMAL_MITIGATION_ACTION_RADIO_OFF} for more details.
+ *
+ * @return The same instance of the builder.
+ */
+ public @NonNull Builder setThermalMitigationAction(
+ @ThermalMitigationAction int thermalMitigationAction) {
+ mThermalMitigationAction = thermalMitigationAction;
+ return this;
+ }
+
+ /**
+ * Set the data throttling request.
+ *
+ * @param dataThrottlingRequest is the parameters for more fine-controlled data throttling.
+ * This is only applicable if thermalMitigationAction is {@link
+ * #THERMAL_MITIGATION_ACTION_DATA_THROTTLING}. Otherwise, it should not be set and
+ * will throw an IllegalArgumentException if it is. See {@link DataThrottlingRequest}
+ * for more details.
+ *
+ * @return The same instance of the builder.
+ */
+ public @NonNull Builder setDataThrottlingRequest(
+ @NonNull DataThrottlingRequest dataThrottlingRequest) {
+ mDataThrottlingRequest = dataThrottlingRequest;
+ return this;
+ }
+
+ /**
+ * Build the ThermalMitigationRequest.
+ *
+ * @return the ThermalMitigationRequest object.
+ */
+ public @NonNull ThermalMitigationRequest build() {
+ if (mThermalMitigationAction < 0) {
+ throw new IllegalArgumentException("thermalMitigationAction was "
+ + " not set");
+ }
+
+ if (mThermalMitigationAction == THERMAL_MITIGATION_ACTION_DATA_THROTTLING) {
+ if (mDataThrottlingRequest == null) {
+ throw new IllegalArgumentException("dataThrottlingRequest cannot be null for "
+ + "THERMAL_MITIGATION_ACTION_DATA_THROTTLING");
+ }
+
+
+ } else if (mDataThrottlingRequest != null) {
+ throw new IllegalArgumentException("dataThrottlingRequest must be null for "
+ + "THERMAL_MITIGATION_ACTION_VOICE_ONLY and "
+ + "THERMAL_MITIGATION_ACTION_RADIO_OFF");
+ }
+
+ return new ThermalMitigationRequest(mThermalMitigationAction, mDataThrottlingRequest);
+ }
+ }
+}
diff --git a/telephony/java/android/telephony/data/DataCallResponse.java b/telephony/java/android/telephony/data/DataCallResponse.java
index 623c4e20b3e1..090c970c2b53 100644
--- a/telephony/java/android/telephony/data/DataCallResponse.java
+++ b/telephony/java/android/telephony/data/DataCallResponse.java
@@ -487,10 +487,14 @@ public final class DataCallResponse implements Parcelable {
dest.writeInt(mMtuV6);
dest.writeInt(mHandoverFailureMode);
dest.writeInt(mPduSessionId);
- if (mDefaultQos.getType() == Qos.QOS_TYPE_EPS) {
- dest.writeParcelable((EpsQos)mDefaultQos, flags);
+ if (mDefaultQos != null) {
+ if (mDefaultQos.getType() == Qos.QOS_TYPE_EPS) {
+ dest.writeParcelable((EpsQos) mDefaultQos, flags);
+ } else {
+ dest.writeParcelable((NrQos) mDefaultQos, flags);
+ }
} else {
- dest.writeParcelable((NrQos)mDefaultQos, flags);
+ dest.writeParcelable(null, flags);
}
dest.writeList(mQosSessions);
}
diff --git a/telephony/java/android/telephony/ims/DelegateRequest.java b/telephony/java/android/telephony/ims/DelegateRequest.java
index f384901d58bd..73d0840177dd 100644
--- a/telephony/java/android/telephony/ims/DelegateRequest.java
+++ b/telephony/java/android/telephony/ims/DelegateRequest.java
@@ -98,4 +98,9 @@ public final class DelegateRequest implements Parcelable {
public int hashCode() {
return Objects.hash(mFeatureTags);
}
+
+ @Override
+ public String toString() {
+ return "DelegateRequest{mFeatureTags=" + mFeatureTags + '}';
+ }
}
diff --git a/telephony/java/android/telephony/ims/SipDelegateManager.java b/telephony/java/android/telephony/ims/SipDelegateManager.java
index 337b7d49323d..190a792b5a9a 100644
--- a/telephony/java/android/telephony/ims/SipDelegateManager.java
+++ b/telephony/java/android/telephony/ims/SipDelegateManager.java
@@ -236,17 +236,17 @@ public class SipDelegateManager {
public static final int SIP_DELEGATE_DESTROY_REASON_REQUESTED_BY_APP = 2;
/**
- * The SipDelegate has closed because the IMS service does not support the creation of
- * SipDelegates.
+ * The SipDelegate has been closed due to the user disabling RCS.
* @hide
*/
- public static final int SIP_DELEGATE_DESTROY_REASON_SERVICE_NOT_SUPPORTED = 3;
+ public static final int SIP_DELEGATE_DESTROY_REASON_USER_DISABLED_RCS = 3;
/**
- * The SipDelegate has been closed due to the user disabling RCS.
+ * The SipDelegate has been closed due to the subscription associated with this delegate being
+ * torn down.
* @hide
*/
- public static final int SIP_DELEGATE_DESTROY_REASON_USER_DISABLED_RCS = 4;
+ public static final int SIP_DELEGATE_DESTROY_REASON_SUBSCRIPTION_TORN_DOWN = 4;
/** @hide */
@Retention(RetentionPolicy.SOURCE)
@@ -254,8 +254,8 @@ public class SipDelegateManager {
SIP_DELEGATE_DESTROY_REASON_UNKNOWN,
SIP_DELEGATE_DESTROY_REASON_SERVICE_DEAD,
SIP_DELEGATE_DESTROY_REASON_REQUESTED_BY_APP,
- SIP_DELEGATE_DESTROY_REASON_SERVICE_NOT_SUPPORTED,
- SIP_DELEGATE_DESTROY_REASON_USER_DISABLED_RCS
+ SIP_DELEGATE_DESTROY_REASON_USER_DISABLED_RCS,
+ SIP_DELEGATE_DESTROY_REASON_SUBSCRIPTION_TORN_DOWN
})
public @interface SipDelegateDestroyReason {}
@@ -316,6 +316,9 @@ public class SipDelegateManager {
* always be available to handle incoming messages. One mechanism that can be used for this is
* the {@link android.service.carrier.CarrierMessagingClientService}, which the framework keeps
* a persistent binding to when the app is the default SMS application.
+ * <p>
+ * Note: the ability to create SipDelegates is only available applications running as the
+ * primary user.
* @param request The parameters that are associated with the SipDelegate creation request that
* will be used to create the SipDelegate connection.
* @param executor The executor that will be used to call the callbacks associated with this
@@ -346,8 +349,8 @@ public class SipDelegateManager {
throw new ImsException("Telephony server is down",
ImsException.CODE_ERROR_SERVICE_UNAVAILABLE);
}
- controller.createSipDelegate(mSubId, request, wrapper.getStateCallbackBinder(),
- wrapper.getMessageCallbackBinder());
+ controller.createSipDelegate(mSubId, request, mContext.getOpPackageName(),
+ wrapper.getStateCallbackBinder(), wrapper.getMessageCallbackBinder());
} catch (ServiceSpecificException e) {
throw new ImsException(e.getMessage(), e.errorCode);
} catch (RemoteException e) {
diff --git a/telephony/java/android/telephony/ims/aidl/IImsRcsController.aidl b/telephony/java/android/telephony/ims/aidl/IImsRcsController.aidl
index f218e35a5a9b..c6d9a8629556 100644
--- a/telephony/java/android/telephony/ims/aidl/IImsRcsController.aidl
+++ b/telephony/java/android/telephony/ims/aidl/IImsRcsController.aidl
@@ -63,7 +63,7 @@ interface IImsRcsController {
// SipDelegateManager
boolean isSipDelegateSupported(int subId);
- void createSipDelegate(int subId, in DelegateRequest request,
+ void createSipDelegate(int subId, in DelegateRequest request, String packageName,
ISipDelegateConnectionStateCallback delegateState,
ISipDelegateMessageCallback delegateMessage);
void destroySipDelegate(int subId, ISipDelegate connection, int reason);
diff --git a/telephony/java/android/telephony/ims/aidl/ISipTransport.aidl b/telephony/java/android/telephony/ims/aidl/ISipTransport.aidl
index cd888391c584..3438587b7348 100644
--- a/telephony/java/android/telephony/ims/aidl/ISipTransport.aidl
+++ b/telephony/java/android/telephony/ims/aidl/ISipTransport.aidl
@@ -26,7 +26,7 @@ import android.telephony.ims.aidl.ISipDelegateStateCallback;
* {@hide}
*/
oneway interface ISipTransport {
- void createSipDelegate(in DelegateRequest request, ISipDelegateStateCallback dc,
+ void createSipDelegate(int subId, in DelegateRequest request, ISipDelegateStateCallback dc,
ISipDelegateMessageCallback mc);
void destroySipDelegate(ISipDelegate delegate, int reason);
}
diff --git a/telephony/java/android/telephony/ims/stub/SipTransportImplBase.java b/telephony/java/android/telephony/ims/stub/SipTransportImplBase.java
index b48f6317e413..93d438cf7f4d 100644
--- a/telephony/java/android/telephony/ims/stub/SipTransportImplBase.java
+++ b/telephony/java/android/telephony/ims/stub/SipTransportImplBase.java
@@ -58,11 +58,11 @@ public class SipTransportImplBase {
private final ISipTransport.Stub mSipTransportImpl = new ISipTransport.Stub() {
@Override
- public void createSipDelegate(DelegateRequest request, ISipDelegateStateCallback dc,
- ISipDelegateMessageCallback mc) {
+ public void createSipDelegate(int subId, DelegateRequest request,
+ ISipDelegateStateCallback dc, ISipDelegateMessageCallback mc) {
final long token = Binder.clearCallingIdentity();
try {
- mBinderExecutor.execute(() -> createSipDelegateInternal(request, dc, mc));
+ mBinderExecutor.execute(() -> createSipDelegateInternal(subId, request, dc, mc));
} finally {
Binder.restoreCallingIdentity(token);
}
@@ -105,6 +105,7 @@ public class SipTransportImplBase {
* This method will be called on the Executor specified in
* {@link SipTransportImplBase#SipTransportImplBase(Executor)}.
*
+ * @param subscriptionId The subscription ID associated with the requested {@link SipDelegate}.
* @param request A SIP delegate request containing the parameters that the remote RCS
* application wishes to use.
* @param dc A callback back to the remote application to be used to communicate state callbacks
@@ -113,9 +114,9 @@ public class SipTransportImplBase {
* remote application and acknowledge the sending of outgoing SIP messages.
* @hide
*/
- public void createSipDelegate(@NonNull DelegateRequest request,
+ public void createSipDelegate(int subscriptionId, @NonNull DelegateRequest request,
@NonNull DelegateStateCallback dc, @NonNull DelegateMessageCallback mc) {
- throw new UnsupportedOperationException("destroySipDelegate not implemented!");
+ throw new UnsupportedOperationException("createSipDelegate not implemented!");
}
/**
@@ -136,11 +137,11 @@ public class SipTransportImplBase {
throw new UnsupportedOperationException("destroySipDelegate not implemented!");
}
- private void createSipDelegateInternal(DelegateRequest r, ISipDelegateStateCallback cb,
- ISipDelegateMessageCallback mc) {
+ private void createSipDelegateInternal(int subId, DelegateRequest r,
+ ISipDelegateStateCallback cb, ISipDelegateMessageCallback mc) {
SipDelegateAidlWrapper wrapper = new SipDelegateAidlWrapper(mBinderExecutor, cb, mc);
mDelegates.add(wrapper);
- createSipDelegate(r, wrapper, wrapper);
+ createSipDelegate(subId, r, wrapper, wrapper);
}
private void destroySipDelegateInternal(ISipDelegate d, int reason) {
diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl
index 0bd485139331..b524549440da 100644
--- a/telephony/java/com/android/internal/telephony/ITelephony.aidl
+++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl
@@ -36,6 +36,7 @@ import android.telephony.CarrierRestrictionRules;
import android.telephony.CellIdentity;
import android.telephony.CellInfo;
import android.telephony.ClientRequestStats;
+import android.telephony.ThermalMitigationRequest;
import android.telephony.IccOpenLogicalChannelResponse;
import android.telephony.ICellInfoCallback;
import android.telephony.ModemActivityInfo;
@@ -2154,6 +2155,8 @@ interface ITelephony {
oneway void setSystemSelectionChannels(in List<RadioAccessSpecifier> specifiers,
int subId, IBooleanConsumer resultCallback);
+ List<RadioAccessSpecifier> getSystemSelectionChannels(int subId);
+
boolean isMvnoMatched(int subId, int mvnoType, String mvnoMatchData);
/**
@@ -2247,4 +2250,22 @@ interface ITelephony {
* @return CarrierBandwidth with bandwidth of both primary and secondary carrier.
*/
CarrierBandwidth getCarrierBandwidth(int subId);
+
+ /**
+ * Checks whether the device supports the given capability on the radio interface.
+ *
+ * @param capability the name of the capability
+ * @return the availability of the capability
+ */
+ boolean isRadioInterfaceCapabilitySupported(String capability);
+
+ /**
+ * Thermal mitigation request to control functionalities at modem.
+ *
+ * @param subId the id of the subscription
+ * @param thermalMitigationRequest holds the parameters necessary for the request.
+ * @throws InvalidThermalMitigationRequestException if the parametes are invalid.
+ */
+ int sendThermalMitigationRequest(int subId,
+ in ThermalMitigationRequest thermalMitigationRequest);
}
diff --git a/telephony/java/com/android/internal/telephony/RILConstants.java b/telephony/java/com/android/internal/telephony/RILConstants.java
index 9d4072f1cf1c..42dee0e4060b 100644
--- a/telephony/java/com/android/internal/telephony/RILConstants.java
+++ b/telephony/java/com/android/internal/telephony/RILConstants.java
@@ -519,6 +519,9 @@ public interface RILConstants {
int RIL_REQUEST_RELEASE_PDU_SESSION_ID = 216;
int RIL_REQUEST_START_HANDOVER = 217;
int RIL_REQUEST_CANCEL_HANDOVER = 218;
+ int RIL_REQUEST_GET_SYSTEM_SELECTION_CHANNELS = 219;
+ int RIL_REQUEST_GET_HAL_DEVICE_CAPABILITIES = 220;
+ int RIL_REQUEST_SET_DATA_THROTTLING = 221;
/* Responses begin */
int RIL_RESPONSE_ACKNOWLEDGEMENT = 800;
diff --git a/tests/BatteryStatsPerfTest/Android.bp b/tests/BatteryStatsPerfTest/Android.bp
new file mode 100644
index 000000000000..58ccec705419
--- /dev/null
+++ b/tests/BatteryStatsPerfTest/Android.bp
@@ -0,0 +1,25 @@
+// Copyright (C) 2020 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+android_test {
+ name: "BatteryStatsPerfTests",
+ srcs: ["src/**/*.java"],
+ static_libs: [
+ "androidx.test.rules",
+ "apct-perftests-utils",
+ "truth-prebuilt",
+ ],
+ platform_apis: true,
+ certificate: "platform",
+}
diff --git a/tests/BatteryStatsPerfTest/AndroidManifest.xml b/tests/BatteryStatsPerfTest/AndroidManifest.xml
new file mode 100644
index 000000000000..7633d5283f5e
--- /dev/null
+++ b/tests/BatteryStatsPerfTest/AndroidManifest.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2020 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.android.frameworks.perftests.batterystats">
+ <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
+ <uses-permission android:name="android.permission.BATTERY_STATS"/>
+
+ <application>
+ <uses-library android:name="android.test.runner" />
+ </application>
+
+ <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
+ android:targetPackage="com.android.frameworks.perftests.batterystats"/>
+</manifest>
diff --git a/tests/BatteryStatsPerfTest/AndroidTest.xml b/tests/BatteryStatsPerfTest/AndroidTest.xml
new file mode 100644
index 000000000000..2f9e114756d1
--- /dev/null
+++ b/tests/BatteryStatsPerfTest/AndroidTest.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2020 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<configuration description="Runs BatteryStats service Performance Tests">
+ <target_preparer class="com.android.tradefed.targetprep.TestAppInstallSetup">
+ <option name="test-file-name" value="BatteryStatsPerfTests.apk"/>
+ <option name="cleanup-apks" value="true"/>
+ </target_preparer>
+
+ <option name="test-suite-tag" value="apct"/>
+ <option name="test-tag" value="BatteryStatsPerfTests"/>
+ <test class="com.android.tradefed.testtype.AndroidJUnitTest">
+ <option name="package" value="com.android.frameworks.perftests.batterystats"/>
+ <option name="runner" value="androidx.test.runner.AndroidJUnitRunner"/>
+ </test>
+</configuration>
diff --git a/tests/BatteryStatsPerfTest/src/com/android/internal/os/BatteryStatsHelperPerfTest.java b/tests/BatteryStatsPerfTest/src/com/android/internal/os/BatteryStatsHelperPerfTest.java
new file mode 100644
index 000000000000..6266cda204b0
--- /dev/null
+++ b/tests/BatteryStatsPerfTest/src/com/android/internal/os/BatteryStatsHelperPerfTest.java
@@ -0,0 +1,135 @@
+/*
+ * 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.internal.os;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.content.Context;
+import android.os.BatteryStats;
+import android.os.Bundle;
+import android.os.UserHandle;
+import android.perftests.utils.BenchmarkState;
+import android.perftests.utils.PerfStatusReporter;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.LargeTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.List;
+
+@RunWith(AndroidJUnit4.class)
+@LargeTest
+public class BatteryStatsHelperPerfTest {
+
+ @Rule
+ public final PerfStatusReporter mPerfStatusReporter = new PerfStatusReporter();
+
+ /**
+ * Measures the performance of {@link BatteryStatsHelper#getStats()}, which triggers
+ * a battery stats sync on every iteration.
+ */
+ @Test
+ public void testGetStats_forceUpdate() {
+ final Context context = InstrumentationRegistry.getContext();
+ final BatteryStatsHelper statsHelper = new BatteryStatsHelper(context,
+ true /* collectBatteryBroadcast */);
+ statsHelper.create((Bundle) null);
+ statsHelper.refreshStats(BatteryStats.STATS_SINCE_CHARGED, UserHandle.myUserId());
+
+ final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+ while (state.keepRunning()) {
+ state.pauseTiming();
+ statsHelper.clearStats();
+ state.resumeTiming();
+
+ statsHelper.getStats();
+
+ assertThat(statsHelper.getUsageList()).isNotEmpty();
+ }
+ }
+
+ /**
+ * Measures performance of the {@link BatteryStatsHelper#getStats(boolean)}, which does
+ * not trigger a sync and just returns current values.
+ */
+ @Test
+ public void testGetStats_cached() {
+ final Context context = InstrumentationRegistry.getContext();
+ final BatteryStatsHelper statsHelper = new BatteryStatsHelper(context,
+ true /* collectBatteryBroadcast */);
+ statsHelper.create((Bundle) null);
+ statsHelper.refreshStats(BatteryStats.STATS_SINCE_CHARGED, UserHandle.myUserId());
+
+ final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+ while (state.keepRunning()) {
+ state.pauseTiming();
+ statsHelper.clearStats();
+ state.resumeTiming();
+
+ statsHelper.getStats(false /* forceUpdate */);
+
+ assertThat(statsHelper.getUsageList()).isNotEmpty();
+ }
+ }
+
+ @Test
+ public void testPowerCalculation() {
+ final Context context = InstrumentationRegistry.getContext();
+ final BatteryStatsHelper statsHelper = new BatteryStatsHelper(context,
+ true /* collectBatteryBroadcast */);
+ statsHelper.create((Bundle) null);
+ statsHelper.getStats();
+
+ final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+ while (state.keepRunning()) {
+ // This will use the cached BatteryStatsObject
+ statsHelper.refreshStats(BatteryStats.STATS_SINCE_CHARGED, UserHandle.myUserId());
+
+ assertThat(statsHelper.getUsageList()).isNotEmpty();
+ }
+ }
+
+ @Test
+ public void testEndToEnd() {
+ final Context context = InstrumentationRegistry.getContext();
+ final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+ while (state.keepRunning()) {
+ final BatteryStatsHelper statsHelper = new BatteryStatsHelper(context,
+ true /* collectBatteryBroadcast */);
+ statsHelper.create((Bundle) null);
+ statsHelper.clearStats();
+ statsHelper.refreshStats(BatteryStats.STATS_SINCE_CHARGED, UserHandle.myUserId());
+
+ state.pauseTiming();
+
+ List<BatterySipper> usageList = statsHelper.getUsageList();
+ double power = 0;
+ for (int i = 0; i < usageList.size(); i++) {
+ BatterySipper sipper = usageList.get(i);
+ power += sipper.sumPower();
+ }
+
+ assertThat(power).isGreaterThan(0.0);
+
+ state.resumeTiming();
+ }
+ }
+}
diff --git a/tests/FlickerTests/AndroidManifest.xml b/tests/FlickerTests/AndroidManifest.xml
index 98e02ced8d0b..58f56f29528c 100644
--- a/tests/FlickerTests/AndroidManifest.xml
+++ b/tests/FlickerTests/AndroidManifest.xml
@@ -27,6 +27,8 @@
<uses-permission android:name="android.permission.ACCESS_SURFACE_FLINGER" />
<!-- Enable / Disable tracing !-->
<uses-permission android:name="android.permission.DUMP" />
+ <!-- Force-stop test apps -->
+ <uses-permission android:name="android.permission.FORCE_STOP_PACKAGES"/>
<!-- Run layers trace -->
<uses-permission android:name="android.permission.HARDWARE_TEST"/>
<!-- Workaround grant runtime permission exception from b/152733071 -->
diff --git a/tests/SurfaceViewBufferTests/Android.bp b/tests/SurfaceViewBufferTests/Android.bp
index 647da2abd213..48031de15f54 100644
--- a/tests/SurfaceViewBufferTests/Android.bp
+++ b/tests/SurfaceViewBufferTests/Android.bp
@@ -33,6 +33,8 @@ android_test {
"kotlinx-coroutines-android",
"flickerlib",
"truth-prebuilt",
+ "cts-wm-util",
+ "CtsSurfaceValidatorLib",
],
}
@@ -43,6 +45,7 @@ cc_library_shared {
],
shared_libs: [
"libutils",
+ "libui",
"libgui",
"liblog",
"libandroid",
diff --git a/tests/SurfaceViewBufferTests/AndroidManifest.xml b/tests/SurfaceViewBufferTests/AndroidManifest.xml
index 95885c1ca635..c910ecdac1b3 100644
--- a/tests/SurfaceViewBufferTests/AndroidManifest.xml
+++ b/tests/SurfaceViewBufferTests/AndroidManifest.xml
@@ -23,12 +23,19 @@
<uses-permission android:name="android.permission.DUMP" />
<!-- Enable / Disable sv blast adapter !-->
<uses-permission android:name="android.permission.WRITE_SECURE_SETTINGS" />
+ <!-- Readback virtual display output !-->
+ <uses-permission android:name="android.permission.CAPTURE_VIDEO_OUTPUT"/>
+ <uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>
+ <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
+ <!-- Save failed test bitmap images !-->
+ <uses-permission android:name="android.Manifest.permission.WRITE_EXTERNAL_STORAGE"/>
<application android:allowBackup="false"
android:supportsRtl="true">
<activity android:name=".MainActivity"
android:taskAffinity="com.android.test.MainActivity"
android:theme="@style/AppTheme"
+ android:configChanges="orientation|screenSize"
android:label="SurfaceViewBufferTestApp"
android:exported="true">
<intent-filter>
@@ -36,6 +43,10 @@
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
+ <service android:name="android.view.cts.surfacevalidator.LocalMediaProjectionService"
+ android:foregroundServiceType="mediaProjection"
+ android:enabled="true">
+ </service>
<uses-library android:name="android.test.runner"/>
</application>
diff --git a/tests/SurfaceViewBufferTests/cpp/SurfaceProxy.cpp b/tests/SurfaceViewBufferTests/cpp/SurfaceProxy.cpp
index 0c86524293e7..ce226fdce320 100644
--- a/tests/SurfaceViewBufferTests/cpp/SurfaceProxy.cpp
+++ b/tests/SurfaceViewBufferTests/cpp/SurfaceProxy.cpp
@@ -32,6 +32,7 @@
extern "C" {
int i = 0;
static ANativeWindow* sAnw;
+static std::map<uint32_t /* slot */, ANativeWindowBuffer*> sBuffers;
JNIEXPORT jint JNICALL Java_com_android_test_SurfaceProxy_setSurface(JNIEnv* env, jclass,
jobject surfaceObject) {
@@ -39,11 +40,14 @@ JNIEXPORT jint JNICALL Java_com_android_test_SurfaceProxy_setSurface(JNIEnv* env
assert(sAnw);
android::sp<android::Surface> surface = static_cast<android::Surface*>(sAnw);
surface->enableFrameTimestamps(true);
+ surface->connect(NATIVE_WINDOW_API_CPU, nullptr, false);
+ native_window_set_usage(sAnw, GRALLOC_USAGE_SW_WRITE_OFTEN);
+ native_window_set_buffers_format(sAnw, HAL_PIXEL_FORMAT_RGBA_8888);
return 0;
}
JNIEXPORT jint JNICALL Java_com_android_test_SurfaceProxy_waitUntilBufferDisplayed(
- JNIEnv*, jclass, jint jFrameNumber, jint timeoutSec) {
+ JNIEnv*, jclass, jlong jFrameNumber, jint timeoutMs) {
using namespace std::chrono_literals;
assert(sAnw);
android::sp<android::Surface> surface = static_cast<android::Surface*>(sAnw);
@@ -63,8 +67,8 @@ JNIEXPORT jint JNICALL Java_com_android_test_SurfaceProxy_waitUntilBufferDisplay
&outDisplayPresentTime, &outDequeueReadyTime, &outReleaseTime);
if (outDisplayPresentTime < 0) {
auto end = std::chrono::steady_clock::now();
- if (std::chrono::duration_cast<std::chrono::seconds>(end - start).count() >
- timeoutSec) {
+ if (std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count() >
+ timeoutMs) {
return -1;
}
}
@@ -99,4 +103,121 @@ JNIEXPORT jint JNICALL Java_com_android_test_SurfaceProxy_ANativeWindowSetBuffer
assert(sAnw);
return ANativeWindow_setBuffersGeometry(sAnw, w, h, format);
}
+
+JNIEXPORT jint JNICALL Java_com_android_test_SurfaceProxy_ANativeWindowSetBuffersTransform(
+ JNIEnv* /* env */, jclass /* clazz */, jint transform) {
+ assert(sAnw);
+ return native_window_set_buffers_transform(sAnw, transform);
+}
+
+JNIEXPORT jint JNICALL Java_com_android_test_SurfaceProxy_SurfaceSetScalingMode(JNIEnv* /* env */,
+ jclass /* clazz */,
+ jint scalingMode) {
+ assert(sAnw);
+ android::sp<android::Surface> surface = static_cast<android::Surface*>(sAnw);
+ return surface->setScalingMode(scalingMode);
+}
+
+JNIEXPORT jint JNICALL Java_com_android_test_SurfaceProxy_SurfaceDequeueBuffer(JNIEnv* /* env */,
+ jclass /* clazz */,
+ jint slot,
+ jint timeoutMs) {
+ assert(sAnw);
+ ANativeWindowBuffer* anb;
+ int fenceFd;
+ int result = sAnw->dequeueBuffer(sAnw, &anb, &fenceFd);
+ if (result != android::OK) {
+ return result;
+ }
+ sBuffers[slot] = anb;
+ android::sp<android::Fence> fence(new android::Fence(fenceFd));
+ int waitResult = fence->wait(timeoutMs);
+ if (waitResult != android::OK) {
+ sAnw->cancelBuffer(sAnw, sBuffers[slot], -1);
+ sBuffers[slot] = nullptr;
+ return waitResult;
+ }
+ return 0;
+}
+
+JNIEXPORT jint JNICALL Java_com_android_test_SurfaceProxy_SurfaceCancelBuffer(JNIEnv* /* env */,
+ jclass /* clazz */,
+ jint slot) {
+ assert(sAnw);
+ assert(sBuffers[slot]);
+ int result = sAnw->cancelBuffer(sAnw, sBuffers[slot], -1);
+ sBuffers[slot] = nullptr;
+ return result;
+}
+
+JNIEXPORT jint JNICALL Java_com_android_test_SurfaceProxy_drawBuffer(JNIEnv* env,
+ jclass /* clazz */, jint slot,
+ jintArray jintArrayColor) {
+ assert(sAnw);
+ assert(sBuffers[slot]);
+
+ int* color = env->GetIntArrayElements(jintArrayColor, nullptr);
+
+ ANativeWindowBuffer* buffer = sBuffers[slot];
+ android::sp<android::GraphicBuffer> graphicBuffer(static_cast<android::GraphicBuffer*>(buffer));
+ const android::Rect bounds(buffer->width, buffer->height);
+ android::Region newDirtyRegion;
+ newDirtyRegion.set(bounds);
+
+ void* vaddr;
+ int fenceFd = -1;
+ graphicBuffer->lockAsync(GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN,
+ newDirtyRegion.bounds(), &vaddr, fenceFd);
+
+ for (int32_t row = 0; row < buffer->height; row++) {
+ uint8_t* dst = static_cast<uint8_t*>(vaddr) + (buffer->stride * row) * 4;
+ for (int32_t column = 0; column < buffer->width; column++) {
+ dst[0] = color[0];
+ dst[1] = color[1];
+ dst[2] = color[2];
+ dst[3] = color[3];
+ dst += 4;
+ }
+ }
+ graphicBuffer->unlockAsync(&fenceFd);
+ env->ReleaseIntArrayElements(jintArrayColor, color, JNI_ABORT);
+ return 0;
+}
+
+JNIEXPORT jint JNICALL Java_com_android_test_SurfaceProxy_SurfaceQueueBuffer(JNIEnv* /* env */,
+ jclass /* clazz */,
+ jint slot,
+ jboolean freeSlot) {
+ assert(sAnw);
+ assert(sBuffers[slot]);
+ int result = sAnw->queueBuffer(sAnw, sBuffers[slot], -1);
+ if (freeSlot) {
+ sBuffers[slot] = nullptr;
+ }
+ return result;
+}
+
+JNIEXPORT jint JNICALL Java_com_android_test_SurfaceProxy_NativeWindowSetBufferCount(
+ JNIEnv* /* env */, jclass /* clazz */, jint count) {
+ assert(sAnw);
+ android::sp<android::Surface> surface = static_cast<android::Surface*>(sAnw);
+ int result = native_window_set_buffer_count(sAnw, count);
+ return result;
+}
+
+JNIEXPORT jint JNICALL Java_com_android_test_SurfaceProxy_NativeWindowSetSharedBufferMode(
+ JNIEnv* /* env */, jclass /* clazz */, jboolean shared) {
+ assert(sAnw);
+ android::sp<android::Surface> surface = static_cast<android::Surface*>(sAnw);
+ int result = native_window_set_shared_buffer_mode(sAnw, shared);
+ return result;
+}
+
+JNIEXPORT jint JNICALL Java_com_android_test_SurfaceProxy_NativeWindowSetAutoRefresh(
+ JNIEnv* /* env */, jclass /* clazz */, jboolean autoRefresh) {
+ assert(sAnw);
+ android::sp<android::Surface> surface = static_cast<android::Surface*>(sAnw);
+ int result = native_window_set_auto_refresh(sAnw, autoRefresh);
+ return result;
+}
} \ No newline at end of file
diff --git a/tests/SurfaceViewBufferTests/src/com/android/test/BufferPresentationTests.kt b/tests/SurfaceViewBufferTests/src/com/android/test/BufferPresentationTests.kt
new file mode 100644
index 000000000000..eb16bad81d19
--- /dev/null
+++ b/tests/SurfaceViewBufferTests/src/com/android/test/BufferPresentationTests.kt
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.test
+
+import com.android.server.wm.flicker.traces.layers.LayersTraceSubject.Companion.assertThat
+import junit.framework.Assert.assertEquals
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.Parameterized
+
+@RunWith(Parameterized::class)
+class BufferPresentationTests(useBlastAdapter: Boolean) : SurfaceTracingTestBase(useBlastAdapter) {
+ /** Submit buffers as fast as possible and make sure they are presented on display */
+ @Test
+ fun testQueueBuffers() {
+ val numFrames = 100L
+ val trace = withTrace {
+ for (i in 1..numFrames) {
+ it.mSurfaceProxy.ANativeWindowLock()
+ it.mSurfaceProxy.ANativeWindowUnlockAndPost()
+ }
+ assertEquals(0, it.mSurfaceProxy.waitUntilBufferDisplayed(numFrames, 1000 /* ms */))
+ }
+
+ assertThat(trace).hasFrameSequence("SurfaceView", 1..numFrames)
+ }
+
+ @Test
+ fun testSetBufferScalingMode_outOfOrderQueueBuffer() {
+ val trace = withTrace {
+ assertEquals(0, it.mSurfaceProxy.SurfaceDequeueBuffer(0, 1000 /* ms */))
+ assertEquals(0, it.mSurfaceProxy.SurfaceDequeueBuffer(1, 1000 /* ms */))
+
+ it.mSurfaceProxy.SurfaceQueueBuffer(1)
+ it.mSurfaceProxy.SurfaceQueueBuffer(0)
+ assertEquals(0, it.mSurfaceProxy.waitUntilBufferDisplayed(2, 5000 /* ms */))
+ }
+
+ assertThat(trace).hasFrameSequence("SurfaceView", 1..2L)
+ }
+
+ @Test
+ fun testSetBufferScalingMode_multipleDequeueBuffer() {
+ val numFrames = 20L
+ val trace = withTrace {
+ for (count in 1..(numFrames / 2)) {
+ assertEquals(0, it.mSurfaceProxy.SurfaceDequeueBuffer(0, 1000 /* ms */))
+ assertEquals(0, it.mSurfaceProxy.SurfaceDequeueBuffer(1, 1000 /* ms */))
+
+ it.mSurfaceProxy.SurfaceQueueBuffer(0)
+ it.mSurfaceProxy.SurfaceQueueBuffer(1)
+ }
+ assertEquals(0, it.mSurfaceProxy.waitUntilBufferDisplayed(numFrames, 5000 /* ms */))
+ }
+
+ assertThat(trace).hasFrameSequence("SurfaceView", 1..numFrames)
+ }
+
+ @Test
+ fun testSetBufferCount_queueMaxBufferCountMinusOne() {
+ val numBufferCount = 8
+ val numFrames = numBufferCount * 5L
+ val trace = withTrace {
+ assertEquals(0, it.mSurfaceProxy.NativeWindowSetBufferCount(numBufferCount + 1))
+ for (i in 1..numFrames / numBufferCount) {
+ for (bufferSlot in 0..numBufferCount - 1) {
+ assertEquals(0,
+ it.mSurfaceProxy.SurfaceDequeueBuffer(bufferSlot, 1000 /* ms */))
+ }
+
+ for (bufferSlot in 0..numBufferCount - 1) {
+ it.mSurfaceProxy.SurfaceQueueBuffer(bufferSlot)
+ }
+ }
+ assertEquals(0, it.mSurfaceProxy.waitUntilBufferDisplayed(numFrames, 5000 /* ms */))
+ }
+
+ assertThat(trace).hasFrameSequence("SurfaceView", 1..numFrames)
+ }
+} \ No newline at end of file
diff --git a/tests/SurfaceViewBufferTests/src/com/android/test/BufferRejectionTests.kt b/tests/SurfaceViewBufferTests/src/com/android/test/BufferRejectionTests.kt
new file mode 100644
index 000000000000..95a7fd5b7a39
--- /dev/null
+++ b/tests/SurfaceViewBufferTests/src/com/android/test/BufferRejectionTests.kt
@@ -0,0 +1,151 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.test
+
+import android.graphics.Point
+import com.android.server.wm.flicker.traces.layers.LayersTraceSubject.Companion.assertThat
+import com.android.test.SurfaceViewBufferTestBase.Companion.ScalingMode
+import com.android.test.SurfaceViewBufferTestBase.Companion.Transform
+import junit.framework.Assert.assertEquals
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.Parameterized
+
+@RunWith(Parameterized::class)
+class BufferRejectionTests(useBlastAdapter: Boolean) : SurfaceTracingTestBase(useBlastAdapter) {
+ @Test
+ fun testSetBuffersGeometry_0x0_rejectsBuffer() {
+ val trace = withTrace {
+ it.mSurfaceProxy.ANativeWindowSetBuffersGeometry(it.surface!!, 100, 100,
+ R8G8B8A8_UNORM)
+ it.mSurfaceProxy.ANativeWindowLock()
+ it.mSurfaceProxy.ANativeWindowUnlockAndPost()
+ it.mSurfaceProxy.ANativeWindowLock()
+ it.mSurfaceProxy.ANativeWindowSetBuffersGeometry(it.surface!!, 0, 0, R8G8B8A8_UNORM)
+ // Submit buffer one with a different size which should be rejected
+ it.mSurfaceProxy.ANativeWindowUnlockAndPost()
+
+ // submit a buffer with the default buffer size
+ it.mSurfaceProxy.ANativeWindowLock()
+ it.mSurfaceProxy.ANativeWindowUnlockAndPost()
+ it.mSurfaceProxy.waitUntilBufferDisplayed(3, 500 /* ms */)
+ }
+ // Verify we reject buffers since scaling mode == NATIVE_WINDOW_SCALING_MODE_FREEZE
+ assertThat(trace).layer("SurfaceView", 2).doesNotExist()
+
+ // Verify the next buffer is submitted with the correct size
+ assertThat(trace).layer("SurfaceView", 3).also {
+ it.hasBufferSize(defaultBufferSize)
+ // scaling mode is not passed down to the layer for blast
+ if (useBlastAdapter) {
+ it.hasScalingMode(ScalingMode.SCALE_TO_WINDOW.ordinal)
+ } else {
+ it.hasScalingMode(ScalingMode.FREEZE.ordinal)
+ }
+ }
+ }
+
+ @Test
+ fun testSetBufferScalingMode_freeze() {
+ val bufferSize = Point(300, 200)
+ val trace = withTrace {
+ it.drawFrame()
+ assertEquals(it.mSurfaceProxy.waitUntilBufferDisplayed(1, 500 /* ms */), 0)
+ it.mSurfaceProxy.ANativeWindowSetBuffersGeometry(it.surface!!, bufferSize,
+ R8G8B8A8_UNORM)
+ assertEquals(0, it.mSurfaceProxy.SurfaceDequeueBuffer(0, 1000 /* ms */))
+ assertEquals(0, it.mSurfaceProxy.SurfaceDequeueBuffer(1, 1000 /* ms */))
+ // Change buffer size and set scaling mode to freeze
+ it.mSurfaceProxy.ANativeWindowSetBuffersGeometry(it.surface!!, Point(0, 0),
+ R8G8B8A8_UNORM)
+
+ // first dequeued buffer does not have the new size so it should be rejected.
+ it.mSurfaceProxy.SurfaceQueueBuffer(0)
+ it.mSurfaceProxy.SurfaceSetScalingMode(ScalingMode.SCALE_TO_WINDOW)
+ it.mSurfaceProxy.SurfaceQueueBuffer(1)
+ assertEquals(it.mSurfaceProxy.waitUntilBufferDisplayed(3, 500 /* ms */), 0)
+ }
+
+ // verify buffer size is reset to default buffer size
+ assertThat(trace).layer("SurfaceView", 1).hasBufferSize(defaultBufferSize)
+ assertThat(trace).layer("SurfaceView", 2).doesNotExist()
+ assertThat(trace).layer("SurfaceView", 3).hasBufferSize(bufferSize)
+ }
+
+ @Test
+ fun testSetBufferScalingMode_freeze_withBufferRotation() {
+ val rotatedBufferSize = Point(defaultBufferSize.y, defaultBufferSize.x)
+ val trace = withTrace {
+ it.drawFrame()
+ assertEquals(it.mSurfaceProxy.waitUntilBufferDisplayed(1, 500 /* ms */), 0)
+ it.mSurfaceProxy.ANativeWindowSetBuffersGeometry(it.surface!!, rotatedBufferSize,
+ R8G8B8A8_UNORM)
+ assertEquals(0, it.mSurfaceProxy.SurfaceDequeueBuffer(0, 1000 /* ms */))
+ assertEquals(0, it.mSurfaceProxy.SurfaceDequeueBuffer(1, 1000 /* ms */))
+ // Change buffer size and set scaling mode to freeze
+ it.mSurfaceProxy.ANativeWindowSetBuffersGeometry(it.surface!!, Point(0, 0),
+ R8G8B8A8_UNORM)
+
+ // first dequeued buffer does not have the new size so it should be rejected.
+ it.mSurfaceProxy.SurfaceQueueBuffer(0)
+ // add a buffer transform so the buffer size is correct.
+ it.mSurfaceProxy.ANativeWindowSetBuffersTransform(Transform.ROT_90)
+ it.mSurfaceProxy.SurfaceQueueBuffer(1)
+ assertEquals(it.mSurfaceProxy.waitUntilBufferDisplayed(3, 500 /* ms */), 0)
+ }
+
+ // verify buffer size is reset to default buffer size
+ assertThat(trace).layer("SurfaceView", 1).hasBufferSize(defaultBufferSize)
+ assertThat(trace).layer("SurfaceView", 2).doesNotExist()
+ assertThat(trace).layer("SurfaceView", 3).hasBufferSize(rotatedBufferSize)
+ assertThat(trace).layer("SurfaceView", 3).hasBufferOrientation(Transform.ROT_90.value)
+ }
+
+ @Test
+ fun testRejectedBuffersAreReleased() {
+ val bufferSize = Point(300, 200)
+ val trace = withTrace {
+ for (count in 0 until 5) {
+ it.drawFrame()
+ assertEquals(it.mSurfaceProxy.waitUntilBufferDisplayed((count * 3) + 1L,
+ 500 /* ms */), 0)
+ it.mSurfaceProxy.ANativeWindowSetBuffersGeometry(it.surface!!, bufferSize,
+ R8G8B8A8_UNORM)
+ assertEquals(0, it.mSurfaceProxy.SurfaceDequeueBuffer(0, 1000 /* ms */))
+ assertEquals(0, it.mSurfaceProxy.SurfaceDequeueBuffer(1, 1000 /* ms */))
+ // Change buffer size and set scaling mode to freeze
+ it.mSurfaceProxy.ANativeWindowSetBuffersGeometry(it.surface!!, Point(0, 0),
+ R8G8B8A8_UNORM)
+
+ // first dequeued buffer does not have the new size so it should be rejected.
+ it.mSurfaceProxy.SurfaceQueueBuffer(0)
+ it.mSurfaceProxy.SurfaceSetScalingMode(ScalingMode.SCALE_TO_WINDOW)
+ it.mSurfaceProxy.SurfaceQueueBuffer(1)
+ assertEquals(it.mSurfaceProxy.waitUntilBufferDisplayed((count * 3) + 3L,
+ 500 /* ms */), 0)
+ }
+ }
+
+ for (count in 0 until 5) {
+ assertThat(trace).layer("SurfaceView", (count * 3) + 1L)
+ .hasBufferSize(defaultBufferSize)
+ assertThat(trace).layer("SurfaceView", (count * 3) + 2L)
+ .doesNotExist()
+ assertThat(trace).layer("SurfaceView", (count * 3) + 3L)
+ .hasBufferSize(bufferSize)
+ }
+ }
+} \ No newline at end of file
diff --git a/tests/SurfaceViewBufferTests/src/com/android/test/GeometryTests.kt b/tests/SurfaceViewBufferTests/src/com/android/test/GeometryTests.kt
new file mode 100644
index 000000000000..03f8c05346b7
--- /dev/null
+++ b/tests/SurfaceViewBufferTests/src/com/android/test/GeometryTests.kt
@@ -0,0 +1,122 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.test
+
+import android.graphics.Point
+import com.android.server.wm.flicker.traces.layers.LayersTraceSubject.Companion.assertThat
+import com.android.test.SurfaceViewBufferTestBase.Companion.ScalingMode
+import com.android.test.SurfaceViewBufferTestBase.Companion.Transform
+import junit.framework.Assert.assertEquals
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.Parameterized
+
+@RunWith(Parameterized::class)
+class GeometryTests(useBlastAdapter: Boolean) : SurfaceTracingTestBase(useBlastAdapter) {
+ @Test
+ fun testSetBuffersGeometry_0x0_resetsBufferSize() {
+ val trace = withTrace {
+ it.mSurfaceProxy.ANativeWindowSetBuffersGeometry(it.surface!!, 0, 0,
+ R8G8B8A8_UNORM)
+ it.mSurfaceProxy.ANativeWindowLock()
+ it.mSurfaceProxy.ANativeWindowUnlockAndPost()
+ it.mSurfaceProxy.waitUntilBufferDisplayed(1, 500 /* ms */)
+ }
+
+ // verify buffer size is reset to default buffer size
+ assertThat(trace).layer("SurfaceView", 1).hasBufferSize(defaultBufferSize)
+ }
+
+ @Test
+ fun testSetBuffersGeometry_smallerThanBuffer() {
+ val bufferSize = Point(300, 200)
+ val trace = withTrace {
+ it.mSurfaceProxy.ANativeWindowSetBuffersGeometry(it.surface!!, bufferSize,
+ R8G8B8A8_UNORM)
+ it.drawFrame()
+ it.mSurfaceProxy.waitUntilBufferDisplayed(1, 500 /* ms */)
+ }
+
+ assertThat(trace).layer("SurfaceView", 1).also {
+ it.hasBufferSize(bufferSize)
+ it.hasLayerSize(defaultBufferSize)
+ it.hasScalingMode(ScalingMode.SCALE_TO_WINDOW.ordinal)
+ }
+ }
+
+ @Test
+ fun testSetBuffersGeometry_largerThanBuffer() {
+ val bufferSize = Point(3000, 2000)
+ val trace = withTrace {
+ it.mSurfaceProxy.ANativeWindowSetBuffersGeometry(it.surface!!, bufferSize,
+ R8G8B8A8_UNORM)
+ it.drawFrame()
+ it.mSurfaceProxy.waitUntilBufferDisplayed(1, 500 /* ms */)
+ }
+
+ assertThat(trace).layer("SurfaceView", 1).also {
+ it.hasBufferSize(bufferSize)
+ it.hasLayerSize(defaultBufferSize)
+ it.hasScalingMode(ScalingMode.SCALE_TO_WINDOW.ordinal)
+ }
+ }
+
+ @Test
+ fun testSetBufferScalingMode_freeze() {
+ val bufferSize = Point(300, 200)
+ val trace = withTrace {
+ it.drawFrame()
+ assertEquals(it.mSurfaceProxy.waitUntilBufferDisplayed(1, 500 /* ms */), 0)
+ it.mSurfaceProxy.ANativeWindowSetBuffersGeometry(it.surface!!, bufferSize,
+ R8G8B8A8_UNORM)
+ assertEquals(0, it.mSurfaceProxy.SurfaceDequeueBuffer(0, 1000 /* ms */))
+ assertEquals(0, it.mSurfaceProxy.SurfaceDequeueBuffer(1, 1000 /* ms */))
+ // Change buffer size and set scaling mode to freeze
+ it.mSurfaceProxy.ANativeWindowSetBuffersGeometry(it.surface!!, Point(0, 0),
+ R8G8B8A8_UNORM)
+
+ // first dequeued buffer does not have the new size so it should be rejected.
+ it.mSurfaceProxy.SurfaceQueueBuffer(0)
+ it.mSurfaceProxy.SurfaceSetScalingMode(ScalingMode.SCALE_TO_WINDOW)
+ it.mSurfaceProxy.SurfaceQueueBuffer(1)
+ assertEquals(it.mSurfaceProxy.waitUntilBufferDisplayed(3, 500 /* ms */), 0)
+ }
+
+ // verify buffer size is reset to default buffer size
+ assertThat(trace).layer("SurfaceView", 1).hasBufferSize(defaultBufferSize)
+ assertThat(trace).layer("SurfaceView", 2).doesNotExist()
+ assertThat(trace).layer("SurfaceView", 3).hasBufferSize(bufferSize)
+ }
+
+ @Test
+ fun testSetBuffersTransform_FLIP() {
+ val transforms = arrayOf(Transform.FLIP_H, Transform.FLIP_V, Transform.ROT_180).withIndex()
+ for ((index, transform) in transforms) {
+ val trace = withTrace {
+ it.mSurfaceProxy.ANativeWindowSetBuffersTransform(transform)
+ it.mSurfaceProxy.ANativeWindowLock()
+ it.mSurfaceProxy.ANativeWindowUnlockAndPost()
+ it.mSurfaceProxy.waitUntilBufferDisplayed(index + 1L, 500 /* ms */)
+ }
+
+ assertThat(trace).layer("SurfaceView", index + 1L).also {
+ it.hasBufferSize(defaultBufferSize)
+ it.hasLayerSize(defaultBufferSize)
+ it.hasBufferOrientation(transform.value)
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/tests/SurfaceViewBufferTests/src/com/android/test/InverseDisplayTransformTests.kt b/tests/SurfaceViewBufferTests/src/com/android/test/InverseDisplayTransformTests.kt
new file mode 100644
index 000000000000..eac30417dfae
--- /dev/null
+++ b/tests/SurfaceViewBufferTests/src/com/android/test/InverseDisplayTransformTests.kt
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.test
+
+import android.graphics.Point
+import com.android.server.wm.flicker.traces.layers.LayersTraceSubject.Companion.assertThat
+import com.android.test.SurfaceViewBufferTestBase.Companion.Transform
+import junit.framework.Assert.assertEquals
+import org.junit.Assume.assumeFalse
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.Parameterized
+
+@RunWith(Parameterized::class)
+class InverseDisplayTransformTests(useBlastAdapter: Boolean) :
+ SurfaceTracingTestBase(useBlastAdapter) {
+ @Before
+ override fun setup() {
+ scenarioRule.getScenario().onActivity {
+ it.rotate90()
+ }
+ instrumentation.waitForIdleSync()
+ super.setup()
+ }
+
+ @Test
+ fun testSetBufferScalingMode_freeze_withInvDisplayTransform() {
+ assumeFalse("Blast does not support buffer rejection with Inv display " +
+ "transform since the only user for this hidden api is camera which does not use" +
+ "fixed scaling mode.", useBlastAdapter)
+
+ val rotatedBufferSize = Point(defaultBufferSize.y, defaultBufferSize.x)
+ val trace = withTrace {
+ // Inverse display transforms are sticky AND they are only consumed by the sf after
+ // a valid buffer has been acquired.
+ it.mSurfaceProxy.ANativeWindowSetBuffersTransform(Transform.INVERSE_DISPLAY.value)
+ assertEquals(0, it.mSurfaceProxy.SurfaceDequeueBuffer(0, 1000 /* ms */))
+ it.mSurfaceProxy.SurfaceQueueBuffer(0)
+
+ assertEquals(it.mSurfaceProxy.waitUntilBufferDisplayed(1, 500 /* ms */), 0)
+ it.mSurfaceProxy.ANativeWindowSetBuffersGeometry(it.surface!!, rotatedBufferSize,
+ R8G8B8A8_UNORM)
+ assertEquals(0, it.mSurfaceProxy.SurfaceDequeueBuffer(0, 1000 /* ms */))
+ assertEquals(0, it.mSurfaceProxy.SurfaceDequeueBuffer(1, 1000 /* ms */))
+ // Change buffer size and set scaling mode to freeze
+ it.mSurfaceProxy.ANativeWindowSetBuffersGeometry(it.surface!!, Point(0, 0),
+ R8G8B8A8_UNORM)
+
+ // first dequeued buffer does not have the new size so it should be rejected.
+ it.mSurfaceProxy.ANativeWindowSetBuffersTransform(Transform.ROT_90.value)
+ it.mSurfaceProxy.SurfaceQueueBuffer(0)
+ it.mSurfaceProxy.ANativeWindowSetBuffersTransform(0)
+ it.mSurfaceProxy.SurfaceQueueBuffer(1)
+ assertEquals(it.mSurfaceProxy.waitUntilBufferDisplayed(3, 500 /* ms */), 0)
+ }
+
+ // verify buffer size is reset to default buffer size
+ assertThat(trace).layer("SurfaceView", 1).hasBufferSize(defaultBufferSize)
+ assertThat(trace).layer("SurfaceView", 2).doesNotExist()
+ assertThat(trace).layer("SurfaceView", 3).hasBufferSize(rotatedBufferSize)
+ }
+} \ No newline at end of file
diff --git a/tests/SurfaceViewBufferTests/src/com/android/test/MainActivity.kt b/tests/SurfaceViewBufferTests/src/com/android/test/MainActivity.kt
index b1e1336c4f6d..ed79054409ea 100644
--- a/tests/SurfaceViewBufferTests/src/com/android/test/MainActivity.kt
+++ b/tests/SurfaceViewBufferTests/src/com/android/test/MainActivity.kt
@@ -15,51 +15,80 @@
*/
package com.android.test
-import android.app.Activity
import android.content.Context
+import android.content.pm.ActivityInfo
+import android.content.res.Configuration.ORIENTATION_LANDSCAPE
import android.graphics.Color
import android.graphics.Paint
+import android.graphics.Point
import android.graphics.Rect
import android.os.Bundle
import android.view.Gravity
import android.view.Surface
import android.view.SurfaceHolder
import android.view.SurfaceView
+import android.view.View
+import android.view.WindowManager
+import android.view.cts.surfacevalidator.CapturedActivity
import android.widget.FrameLayout
import java.util.concurrent.CountDownLatch
import java.util.concurrent.locks.ReentrantLock
import kotlin.concurrent.withLock
-class MainActivity : Activity() {
+class MainActivity : CapturedActivity() {
val mSurfaceProxy = SurfaceProxy()
private var mSurfaceHolder: SurfaceHolder? = null
private val mDrawLock = ReentrantLock()
+ var mSurfaceView: SurfaceView? = null
val surface: Surface? get() = mSurfaceHolder?.surface
- public override fun onCreate(savedInstanceState: Bundle?) {
+ override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
- addSurfaceView(Rect(0, 0, 500, 200))
+ addSurfaceView(Point(500, 200))
+ window.decorView.apply {
+ systemUiVisibility =
+ View.SYSTEM_UI_FLAG_HIDE_NAVIGATION or View.SYSTEM_UI_FLAG_FULLSCREEN
+ }
+ }
+
+ override fun getCaptureDurationMs(): Long {
+ return 30000
}
- fun addSurfaceView(size: Rect): CountDownLatch {
+ fun addSurfaceView(size: Point): CountDownLatch {
val layout = findViewById<FrameLayout>(android.R.id.content)
val surfaceReadyLatch = CountDownLatch(1)
- val surfaceView = createSurfaceView(applicationContext, size, surfaceReadyLatch)
- layout.addView(surfaceView,
- FrameLayout.LayoutParams(size.width(), size.height(), Gravity.TOP or Gravity.LEFT)
+ mSurfaceView = createSurfaceView(applicationContext, size, surfaceReadyLatch)
+ layout.addView(mSurfaceView!!,
+ FrameLayout.LayoutParams(size.x, size.y, Gravity.TOP or Gravity.LEFT)
.also { it.setMargins(100, 100, 0, 0) })
+
return surfaceReadyLatch
}
+ fun enableSeamlessRotation() {
+ val p: WindowManager.LayoutParams = window.attributes
+ p.rotationAnimation = WindowManager.LayoutParams.ROTATION_ANIMATION_SEAMLESS
+ window.attributes = p
+ }
+
+ fun rotate90() {
+ if (getResources().getConfiguration().orientation == ORIENTATION_LANDSCAPE) {
+ setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT)
+ } else {
+ setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE)
+ }
+ }
+
private fun createSurfaceView(
context: Context,
- size: Rect,
+ size: Point,
surfaceReadyLatch: CountDownLatch
): SurfaceView {
val surfaceView = SurfaceView(context)
surfaceView.setWillNotDraw(false)
- surfaceView.holder.setFixedSize(size.width(), size.height())
+ surfaceView.holder.setFixedSize(size.x, size.y)
surfaceView.holder.addCallback(object : SurfaceHolder.Callback {
override fun surfaceCreated(holder: SurfaceHolder) {
mDrawLock.withLock {
diff --git a/tests/SurfaceViewBufferTests/src/com/android/test/ScreenRecordTestBase.kt b/tests/SurfaceViewBufferTests/src/com/android/test/ScreenRecordTestBase.kt
new file mode 100644
index 000000000000..df3d30e13908
--- /dev/null
+++ b/tests/SurfaceViewBufferTests/src/com/android/test/ScreenRecordTestBase.kt
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.test
+
+import android.annotation.ColorInt
+import android.content.Context
+import android.content.Intent
+import android.graphics.Rect
+import android.server.wm.WindowManagerState.getLogicalDisplaySize
+import android.view.cts.surfacevalidator.CapturedActivity
+import android.view.cts.surfacevalidator.ISurfaceValidatorTestCase
+import android.view.cts.surfacevalidator.PixelChecker
+import android.view.cts.surfacevalidator.RectChecker
+import android.widget.FrameLayout
+import androidx.test.rule.ActivityTestRule
+import org.junit.After
+import org.junit.Before
+import org.junit.Rule
+import java.util.concurrent.CountDownLatch
+
+open class ScreenRecordTestBase(useBlastAdapter: Boolean) :
+ SurfaceViewBufferTestBase(useBlastAdapter) {
+ @get:Rule
+ var mActivityRule = ActivityTestRule(MainActivity::class.java)
+
+ private lateinit var mActivity: MainActivity
+
+ @Before
+ override fun setup() {
+ super.setup()
+ mActivity = mActivityRule.launchActivity(Intent())
+ lateinit var surfaceReadyLatch: CountDownLatch
+ runOnUiThread {
+ it.dismissPermissionDialog()
+ it.setLogicalDisplaySize(getLogicalDisplaySize())
+ surfaceReadyLatch = it.addSurfaceView(defaultBufferSize)
+ }
+ surfaceReadyLatch.await()
+ // sleep to finish animations
+ instrumentation.waitForIdleSync()
+ }
+
+ @After
+ override fun teardown() {
+ super.teardown()
+ mActivityRule.finishActivity()
+ }
+
+ fun runOnUiThread(predicate: (it: MainActivity) -> Unit) {
+ mActivityRule.runOnUiThread {
+ predicate(mActivity)
+ }
+ }
+
+ fun withScreenRecording(
+ boundsToCheck: Rect,
+ @ColorInt color: Int,
+ predicate: (it: MainActivity) -> Unit
+ ): CapturedActivity.TestResult {
+ val testCase = object : ISurfaceValidatorTestCase {
+ override fun getChecker(): PixelChecker = RectChecker(boundsToCheck, color)
+ override fun start(context: Context, parent: FrameLayout) {
+ predicate(mActivity)
+ }
+ override fun end() { /* do nothing */ }
+ }
+
+ return mActivity.runTest(testCase)
+ }
+} \ No newline at end of file
diff --git a/tests/SurfaceViewBufferTests/src/com/android/test/SharedBufferModeScreenRecordTests.kt b/tests/SurfaceViewBufferTests/src/com/android/test/SharedBufferModeScreenRecordTests.kt
new file mode 100644
index 000000000000..996a1d3d79da
--- /dev/null
+++ b/tests/SurfaceViewBufferTests/src/com/android/test/SharedBufferModeScreenRecordTests.kt
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.test
+
+import android.graphics.Color
+import android.graphics.Rect
+import android.os.SystemClock
+import android.view.cts.surfacevalidator.PixelColor
+import junit.framework.Assert.assertEquals
+import org.junit.Assert.assertTrue
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.Parameterized
+
+@RunWith(Parameterized::class)
+class SharedBufferModeScreenRecordTests(useBlastAdapter: Boolean) :
+ ScreenRecordTestBase(useBlastAdapter) {
+
+ /** When auto refresh is set, surface flinger will wake up and refresh the display presenting
+ * the latest content in the buffer.
+ */
+ @Test
+ fun testAutoRefresh() {
+ var svBounds = Rect()
+ runOnUiThread {
+ assertEquals(0, it.mSurfaceProxy.NativeWindowSetSharedBufferMode(true))
+ assertEquals(0, it.mSurfaceProxy.NativeWindowSetAutoRefresh(true))
+ assertEquals(0, it.mSurfaceProxy.SurfaceDequeueBuffer(0, 1 /* ms */))
+ it.mSurfaceProxy.SurfaceQueueBuffer(0, false /* freeSlot */)
+ assertEquals(0,
+ it.mSurfaceProxy.waitUntilBufferDisplayed(1, 5000 /* ms */))
+
+ svBounds = Rect(0, 0, it.mSurfaceView!!.width, it.mSurfaceView!!.height)
+ val position = Rect()
+ it.mSurfaceView!!.getBoundsOnScreen(position)
+ svBounds.offsetTo(position.left, position.top)
+
+ // wait for buffers from other layers to be latched and transactions to be processed before
+ // updating the buffer
+ SystemClock.sleep(4000)
+ }
+
+ val result = withScreenRecording(svBounds, PixelColor.RED) {
+ it.mSurfaceProxy.drawBuffer(0, Color.RED)
+ }
+ val failRatio = 1.0f * result.failFrames / (result.failFrames + result.passFrames)
+
+ assertTrue("Error: " + result.failFrames +
+ " incorrect frames observed (out of " + (result.failFrames + result.passFrames) +
+ " frames)", failRatio < 0.05)
+ assertTrue("Error: Did not receive sufficient frame updates expected: >1000 actual:" +
+ result.passFrames, result.passFrames > 1000)
+ }
+} \ No newline at end of file
diff --git a/tests/SurfaceViewBufferTests/src/com/android/test/SharedBufferModeTests.kt b/tests/SurfaceViewBufferTests/src/com/android/test/SharedBufferModeTests.kt
new file mode 100644
index 000000000000..ae662506bc77
--- /dev/null
+++ b/tests/SurfaceViewBufferTests/src/com/android/test/SharedBufferModeTests.kt
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.test
+
+import android.graphics.Color
+import android.graphics.Rect
+import com.android.server.wm.flicker.traces.layers.LayersTraceSubject.Companion.assertThat
+import junit.framework.Assert.assertEquals
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.Parameterized
+
+@RunWith(Parameterized::class)
+class SharedBufferModeTests(useBlastAdapter: Boolean) : SurfaceTracingTestBase(useBlastAdapter) {
+ /** Sanity test to check each buffer is presented if its submitted with enough delay
+ * for SF to present the buffers. */
+ @Test
+ fun testCanPresentBuffers() {
+ val numFrames = 15L
+ val trace = withTrace {
+ assertEquals(0, it.mSurfaceProxy.NativeWindowSetSharedBufferMode(true))
+ for (i in 1..numFrames) {
+ assertEquals(0, it.mSurfaceProxy.SurfaceDequeueBuffer(0, 1 /* ms */))
+ it.mSurfaceProxy.SurfaceQueueBuffer(0)
+ assertEquals(0, it.mSurfaceProxy.waitUntilBufferDisplayed(i, 5000 /* ms */))
+ }
+ }
+
+ assertThat(trace).hasFrameSequence("SurfaceView", 1..numFrames)
+ }
+
+ /** Submit buffers as fast as possible testing that we are not blocked when dequeuing the buffer
+ * by setting the dequeue timeout to 1ms and checking that we present the newest buffer. */
+ @Test
+ fun testFastQueueBuffers() {
+ val numFrames = 15L
+ val trace = withTrace {
+ assertEquals(0, it.mSurfaceProxy.NativeWindowSetSharedBufferMode(true))
+ for (i in 1..numFrames) {
+ assertEquals(0, it.mSurfaceProxy.SurfaceDequeueBuffer(0, 1 /* ms */))
+ it.mSurfaceProxy.SurfaceQueueBuffer(0)
+ }
+ assertEquals(0, it.mSurfaceProxy.waitUntilBufferDisplayed(numFrames, 5000 /* ms */))
+ }
+
+ assertThat(trace).hasFrameSequence("SurfaceView", numFrames..numFrames)
+ }
+
+ /** Keep overwriting the buffer without queuing buffers and check that we present the latest
+ * buffer content. */
+ @Test
+ fun testAutoRefresh() {
+ var svBounds = Rect()
+ runOnUiThread {
+ assertEquals(0, it.mSurfaceProxy.NativeWindowSetSharedBufferMode(true))
+ assertEquals(0, it.mSurfaceProxy.NativeWindowSetAutoRefresh(true))
+ assertEquals(0, it.mSurfaceProxy.SurfaceDequeueBuffer(0, 1 /* ms */))
+ it.mSurfaceProxy.SurfaceQueueBuffer(0, false /* freeSlot */)
+ assertEquals(0, it.mSurfaceProxy.waitUntilBufferDisplayed(1, 5000 /* ms */))
+
+ svBounds = Rect(0, 0, it.mSurfaceView!!.width, it.mSurfaceView!!.height)
+ val position = Rect()
+ it.mSurfaceView!!.getBoundsOnScreen(position)
+ svBounds.offsetTo(position.left, position.top)
+ }
+
+ runOnUiThread {
+ it.mSurfaceProxy.drawBuffer(0, Color.RED)
+ checkPixels(svBounds, Color.RED)
+ it.mSurfaceProxy.drawBuffer(0, Color.GREEN)
+ checkPixels(svBounds, Color.GREEN)
+ it.mSurfaceProxy.drawBuffer(0, Color.BLUE)
+ checkPixels(svBounds, Color.BLUE)
+ }
+ }
+} \ No newline at end of file
diff --git a/tests/SurfaceViewBufferTests/src/com/android/test/SurfaceProxy.kt b/tests/SurfaceViewBufferTests/src/com/android/test/SurfaceProxy.kt
index 884aae41446c..cfbd3ac11acb 100644
--- a/tests/SurfaceViewBufferTests/src/com/android/test/SurfaceProxy.kt
+++ b/tests/SurfaceViewBufferTests/src/com/android/test/SurfaceProxy.kt
@@ -16,17 +16,46 @@
package com.android.test
+import android.annotation.ColorInt
+import android.graphics.Color
+import android.graphics.Point
+import com.android.test.SurfaceViewBufferTestBase.Companion.ScalingMode
+import com.android.test.SurfaceViewBufferTestBase.Companion.Transform
+
class SurfaceProxy {
init {
System.loadLibrary("surface_jni")
}
external fun setSurface(surface: Any)
- external fun waitUntilBufferDisplayed(frameNumber: Int, timeoutSec: Int)
+ external fun waitUntilBufferDisplayed(frameNumber: Long, timeoutMs: Int): Int
external fun draw()
+ fun drawBuffer(slot: Int, @ColorInt c: Int) {
+ drawBuffer(slot, intArrayOf(Color.red(c), Color.green(c), Color.blue(c), Color.alpha(c)))
+ }
+ external fun drawBuffer(slot: Int, color: IntArray)
// android/native_window.h functions
external fun ANativeWindowLock()
external fun ANativeWindowUnlockAndPost()
+ fun ANativeWindowSetBuffersGeometry(surface: Any, size: Point, format: Int) {
+ ANativeWindowSetBuffersGeometry(surface, size.x, size.y, format)
+ }
external fun ANativeWindowSetBuffersGeometry(surface: Any, width: Int, height: Int, format: Int)
+ fun ANativeWindowSetBuffersTransform(transform: Transform) {
+ ANativeWindowSetBuffersTransform(transform.value)
+ }
+ external fun ANativeWindowSetBuffersTransform(transform: Int)
+
+ // gui/Surface.h functions
+ fun SurfaceSetScalingMode(scalingMode: ScalingMode) {
+ SurfaceSetScalingMode(scalingMode.ordinal)
+ }
+ external fun SurfaceSetScalingMode(scalingMode: Int)
+ external fun SurfaceDequeueBuffer(slot: Int, timeoutMs: Int): Int
+ external fun SurfaceCancelBuffer(slot: Int)
+ external fun SurfaceQueueBuffer(slot: Int, freeSlot: Boolean = true)
+ external fun NativeWindowSetBufferCount(count: Int): Int
+ external fun NativeWindowSetSharedBufferMode(shared: Boolean): Int
+ external fun NativeWindowSetAutoRefresh(autoRefresh: Boolean): Int
}
diff --git a/tests/SurfaceViewBufferTests/src/com/android/test/SurfaceTracingTestBase.kt b/tests/SurfaceViewBufferTests/src/com/android/test/SurfaceTracingTestBase.kt
new file mode 100644
index 000000000000..cd4b38516bc3
--- /dev/null
+++ b/tests/SurfaceViewBufferTests/src/com/android/test/SurfaceTracingTestBase.kt
@@ -0,0 +1,112 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.test
+
+import android.annotation.ColorInt
+import android.graphics.Bitmap
+import android.graphics.Color
+import android.graphics.Rect
+import android.util.Log
+import androidx.test.ext.junit.rules.ActivityScenarioRule
+import com.android.server.wm.flicker.monitor.LayersTraceMonitor
+import com.android.server.wm.flicker.monitor.withSFTracing
+import com.android.server.wm.flicker.traces.layers.LayersTrace
+import junit.framework.Assert
+import org.junit.After
+import org.junit.Before
+import org.junit.Rule
+import java.io.FileOutputStream
+import java.io.IOException
+import java.util.concurrent.CountDownLatch
+
+open class SurfaceTracingTestBase(useBlastAdapter: Boolean) :
+ SurfaceViewBufferTestBase(useBlastAdapter) {
+ @get:Rule
+ var scenarioRule: ActivityScenarioRule<MainActivity> =
+ ActivityScenarioRule<MainActivity>(MainActivity::class.java)
+
+ @Before
+ override fun setup() {
+ super.setup()
+ stopLayerTrace()
+ addSurfaceView()
+ }
+
+ @After
+ override fun teardown() {
+ super.teardown()
+ scenarioRule.getScenario().close()
+ }
+
+ fun withTrace(predicate: (it: MainActivity) -> Unit): LayersTrace {
+ return withSFTracing(instrumentation, TRACE_FLAGS) {
+ scenarioRule.getScenario().onActivity {
+ predicate(it)
+ }
+ }
+ }
+
+ fun runOnUiThread(predicate: (it: MainActivity) -> Unit) {
+ scenarioRule.getScenario().onActivity {
+ predicate(it)
+ }
+ }
+
+ private fun addSurfaceView() {
+ lateinit var surfaceReadyLatch: CountDownLatch
+ scenarioRule.getScenario().onActivity {
+ surfaceReadyLatch = it.addSurfaceView(defaultBufferSize)
+ }
+ surfaceReadyLatch.await()
+ // sleep to finish animations
+ instrumentation.waitForIdleSync()
+ }
+
+ private fun stopLayerTrace() {
+ val tmpDir = instrumentation.targetContext.dataDir.toPath()
+ LayersTraceMonitor(tmpDir).stop()
+ }
+
+ fun checkPixels(bounds: Rect, @ColorInt color: Int) {
+ val screenshot = instrumentation.getUiAutomation().takeScreenshot()
+ val pixels = IntArray(screenshot.width * screenshot.height)
+ screenshot.getPixels(pixels, 0, screenshot.width, 0, 0, screenshot.width, screenshot.height)
+ for (i in bounds.left + 10..bounds.right - 10) {
+ for (j in bounds.top + 10..bounds.bottom - 10) {
+ val actualColor = pixels[j * screenshot.width + i]
+ if (actualColor != color) {
+ val screenshotPath = instrumentation.targetContext
+ .getExternalFilesDir(null)?.resolve("screenshot.png")
+ try {
+ FileOutputStream(screenshotPath).use { out ->
+ screenshot.compress(Bitmap.CompressFormat.PNG, 100, out)
+ }
+ Log.e("SurfaceViewBufferTests", "Bitmap written to $screenshotPath")
+ } catch (e: IOException) {
+ Log.e("SurfaceViewBufferTests", "Error writing bitmap to file", e)
+ }
+ }
+ Assert.assertEquals("Checking $bounds found mismatch $i,$j",
+ Color.valueOf(color), Color.valueOf(actualColor))
+ }
+ }
+ }
+
+ private companion object {
+ private const val TRACE_FLAGS =
+ (1 shl 0) or (1 shl 5) or (1 shl 6) // TRACE_CRITICAL | TRACE_BUFFERS | TRACE_SYNC
+ }
+} \ No newline at end of file
diff --git a/tests/SurfaceViewBufferTests/src/com/android/test/SurfaceViewBufferTest.kt b/tests/SurfaceViewBufferTests/src/com/android/test/SurfaceViewBufferTest.kt
deleted file mode 100644
index b48a91d49b91..000000000000
--- a/tests/SurfaceViewBufferTests/src/com/android/test/SurfaceViewBufferTest.kt
+++ /dev/null
@@ -1,185 +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.test
-
-import android.app.Instrumentation
-import android.graphics.Rect
-import android.provider.Settings
-import androidx.test.ext.junit.rules.ActivityScenarioRule
-import androidx.test.platform.app.InstrumentationRegistry
-import com.android.server.wm.flicker.monitor.LayersTraceMonitor
-import com.android.server.wm.flicker.monitor.withSFTracing
-import com.android.server.wm.flicker.traces.layers.LayersTraceSubject.Companion.assertThat
-import org.junit.After
-import org.junit.Before
-import org.junit.Rule
-import org.junit.Test
-import org.junit.runner.RunWith
-import org.junit.runners.Parameterized
-import java.util.concurrent.CountDownLatch
-import kotlin.properties.Delegates
-
-@RunWith(Parameterized::class)
-class SurfaceViewBufferTest(val useBlastAdapter: Boolean) {
- private var mInitialUseBlastConfig by Delegates.notNull<Int>()
-
- @get:Rule
- var scenarioRule: ActivityScenarioRule<MainActivity> =
- ActivityScenarioRule<MainActivity>(MainActivity::class.java)
-
- protected val instrumentation: Instrumentation = InstrumentationRegistry.getInstrumentation()
- val defaultBufferSize = Rect(0, 0, 640, 480)
-
- @Before
- fun setup() {
- mInitialUseBlastConfig = Settings.Global.getInt(instrumentation.context.contentResolver,
- "use_blast_adapter_sv", 0)
- val enable = if (useBlastAdapter) 1 else 0
- Settings.Global.putInt(instrumentation.context.contentResolver, "use_blast_adapter_sv",
- enable)
- val tmpDir = instrumentation.targetContext.dataDir.toPath()
- LayersTraceMonitor(tmpDir).stop()
-
- lateinit var surfaceReadyLatch: CountDownLatch
- scenarioRule.getScenario().onActivity {
- surfaceReadyLatch = it.addSurfaceView(defaultBufferSize)
- }
- surfaceReadyLatch.await()
- }
-
- @After
- fun teardown() {
- scenarioRule.getScenario().close()
- Settings.Global.putInt(instrumentation.context.contentResolver,
- "use_blast_adapter_sv", mInitialUseBlastConfig)
- }
-
- @Test
- fun testSetBuffersGeometry_0x0_resetsBufferSize() {
- val trace = withSFTracing(instrumentation, TRACE_FLAGS) {
- scenarioRule.getScenario().onActivity {
- it.mSurfaceProxy.ANativeWindowSetBuffersGeometry(it.surface!!, 0, 0,
- R8G8B8A8_UNORM)
- it.mSurfaceProxy.ANativeWindowLock()
- it.mSurfaceProxy.ANativeWindowUnlockAndPost()
- it.mSurfaceProxy.waitUntilBufferDisplayed(1, 1 /* sec */)
- }
- }
-
- // verify buffer size is reset to default buffer size
- assertThat(trace).layer("SurfaceView", 1).hasBufferSize(defaultBufferSize)
- }
-
- @Test
- fun testSetBuffersGeometry_0x0_rejectsBuffer() {
- val trace = withSFTracing(instrumentation, TRACE_FLAGS) {
- scenarioRule.getScenario().onActivity {
- it.mSurfaceProxy.ANativeWindowSetBuffersGeometry(it.surface!!, 100, 100,
- R8G8B8A8_UNORM)
- it.mSurfaceProxy.ANativeWindowLock()
- it.mSurfaceProxy.ANativeWindowUnlockAndPost()
- it.mSurfaceProxy.ANativeWindowLock()
- it.mSurfaceProxy.ANativeWindowSetBuffersGeometry(it.surface!!, 0, 0, R8G8B8A8_UNORM)
- // Submit buffer one with a different size which should be rejected
- it.mSurfaceProxy.ANativeWindowUnlockAndPost()
-
- // submit a buffer with the default buffer size
- it.mSurfaceProxy.ANativeWindowLock()
- it.mSurfaceProxy.ANativeWindowUnlockAndPost()
- it.mSurfaceProxy.waitUntilBufferDisplayed(3, 1 /* sec */)
- }
- }
- // Verify we reject buffers since scaling mode == NATIVE_WINDOW_SCALING_MODE_FREEZE
- assertThat(trace).layer("SurfaceView", 2).doesNotExist()
-
- // Verify the next buffer is submitted with the correct size
- assertThat(trace).layer("SurfaceView", 3).also {
- it.hasBufferSize(defaultBufferSize)
- it.hasScalingMode(0 /* NATIVE_WINDOW_SCALING_MODE_FREEZE */)
- }
- }
-
- @Test
- fun testSetBuffersGeometry_smallerThanBuffer() {
- val bufferSize = Rect(0, 0, 300, 200)
- val trace = withSFTracing(instrumentation, TRACE_FLAGS) {
- scenarioRule.getScenario().onActivity {
- it.mSurfaceProxy.ANativeWindowSetBuffersGeometry(it.surface!!, bufferSize.width(),
- bufferSize.height(), R8G8B8A8_UNORM)
- it.drawFrame()
- it.mSurfaceProxy.waitUntilBufferDisplayed(1, 1 /* sec */)
- }
- }
-
- assertThat(trace).layer("SurfaceView", 1).also {
- it.hasBufferSize(bufferSize)
- it.hasLayerSize(defaultBufferSize)
- it.hasScalingMode(1 /* NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW */)
- }
- }
-
- @Test
- fun testSetBuffersGeometry_largerThanBuffer() {
- val bufferSize = Rect(0, 0, 3000, 2000)
- val trace = withSFTracing(instrumentation, TRACE_FLAGS) {
- scenarioRule.getScenario().onActivity {
- it.mSurfaceProxy.ANativeWindowSetBuffersGeometry(it.surface!!, bufferSize.width(),
- bufferSize.height(), R8G8B8A8_UNORM)
- it.drawFrame()
- it.mSurfaceProxy.waitUntilBufferDisplayed(1, 1 /* sec */)
- }
- }
-
- assertThat(trace).layer("SurfaceView", 1).also {
- it.hasBufferSize(bufferSize)
- it.hasLayerSize(defaultBufferSize)
- it.hasScalingMode(1 /* NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW */)
- }
- }
-
- /** Submit buffers as fast as possible and make sure they are queued */
- @Test
- fun testQueueBuffers() {
- val trace = withSFTracing(instrumentation, TRACE_FLAGS) {
- scenarioRule.getScenario().onActivity {
- it.mSurfaceProxy.ANativeWindowSetBuffersGeometry(it.surface!!, 100, 100,
- R8G8B8A8_UNORM)
- for (i in 0..100) {
- it.mSurfaceProxy.ANativeWindowLock()
- it.mSurfaceProxy.ANativeWindowUnlockAndPost()
- }
- it.mSurfaceProxy.waitUntilBufferDisplayed(100, 1 /* sec */)
- }
- }
- for (frameNumber in 1..100) {
- assertThat(trace).layer("SurfaceView", frameNumber.toLong())
- }
- }
-
- companion object {
- private const val TRACE_FLAGS = 0x1 // TRACE_CRITICAL
- private const val R8G8B8A8_UNORM = 1
-
- @JvmStatic
- @Parameterized.Parameters(name = "blast={0}")
- fun data(): Collection<Array<Any>> {
- return listOf(
- arrayOf(false), // First test: submit buffers via bufferqueue
- arrayOf(true) // Second test: submit buffers via blast adapter
- )
- }
- }
-} \ No newline at end of file
diff --git a/tests/SurfaceViewBufferTests/src/com/android/test/SurfaceViewBufferTestBase.kt b/tests/SurfaceViewBufferTests/src/com/android/test/SurfaceViewBufferTestBase.kt
new file mode 100644
index 000000000000..093c3125f253
--- /dev/null
+++ b/tests/SurfaceViewBufferTests/src/com/android/test/SurfaceViewBufferTestBase.kt
@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.test
+
+import android.app.Instrumentation
+import android.graphics.Point
+import android.provider.Settings
+import androidx.test.InstrumentationRegistry
+import org.junit.After
+import org.junit.Before
+import org.junit.Rule
+import org.junit.rules.TestName
+import org.junit.runners.Parameterized
+import kotlin.properties.Delegates
+
+open class SurfaceViewBufferTestBase(val useBlastAdapter: Boolean) {
+ private var mInitialBlastConfig by Delegates.notNull<Boolean>()
+
+ val instrumentation: Instrumentation
+ get() = InstrumentationRegistry.getInstrumentation()
+
+ @get:Rule
+ var mName = TestName()
+
+ @Before
+ open fun setup() {
+ mInitialBlastConfig = getBlastAdapterSvEnabled()
+ setBlastAdapterSvEnabled(useBlastAdapter)
+ }
+
+ @After
+ open fun teardown() {
+ setBlastAdapterSvEnabled(mInitialBlastConfig)
+ }
+
+ private fun getBlastAdapterSvEnabled(): Boolean {
+ return Settings.Global.getInt(instrumentation.context.contentResolver,
+ "use_blast_adapter_sv", 0) != 0
+ }
+
+ private fun setBlastAdapterSvEnabled(enable: Boolean) {
+ Settings.Global.putInt(instrumentation.context.contentResolver, "use_blast_adapter_sv",
+ if (enable) 1 else 0)
+ }
+
+ companion object {
+ @JvmStatic
+ @Parameterized.Parameters(name = "blast={0}")
+ fun data(): Collection<Array<Any>> {
+ return listOf(
+ arrayOf(false), // First test: submit buffers via bufferqueue
+ arrayOf(true) // Second test: submit buffers via blast adapter
+ )
+ }
+
+ const val R8G8B8A8_UNORM = 1
+ val defaultBufferSize = Point(640, 480)
+
+ // system/window.h definitions
+ enum class ScalingMode() {
+ FREEZE, // = 0
+ SCALE_TO_WINDOW, // =1
+ SCALE_CROP, // = 2
+ NO_SCALE_CROP // = 3
+ }
+
+ // system/window.h definitions
+ enum class Transform(val value: Int) {
+ /* flip source image horizontally */
+ FLIP_H(1),
+ /* flip source image vertically */
+ FLIP_V(2),
+ /* rotate source image 90 degrees clock-wise, and is applied after TRANSFORM_FLIP_{H|V} */
+ ROT_90(4),
+ /* rotate source image 180 degrees */
+ ROT_180(3),
+ /* rotate source image 270 degrees clock-wise */
+ ROT_270(7),
+ /* transforms source by the inverse transform of the screen it is displayed onto. This
+ * transform is applied last */
+ INVERSE_DISPLAY(0x08)
+ }
+ }
+} \ No newline at end of file
diff --git a/tests/TaskOrganizerTest/src/com/android/test/taskembed/ResizeTasksSyncTest.kt b/tests/TaskOrganizerTest/src/com/android/test/taskembed/ResizeTasksSyncTest.kt
index abccd6cf77bd..fe9deae80407 100644
--- a/tests/TaskOrganizerTest/src/com/android/test/taskembed/ResizeTasksSyncTest.kt
+++ b/tests/TaskOrganizerTest/src/com/android/test/taskembed/ResizeTasksSyncTest.kt
@@ -16,6 +16,7 @@
package com.android.test.taskembed
import android.app.Instrumentation
+import android.graphics.Point
import android.graphics.Rect
import androidx.test.ext.junit.rules.ActivityScenarioRule
import androidx.test.platform.app.InstrumentationRegistry
@@ -93,13 +94,15 @@ class ResizeTasksSyncTest {
// verify buffer size should be changed to expected values.
assertThat(trace).layer(FIRST_ACTIVITY, frame).also {
- it.hasLayerSize(firstBounds)
- it.hasBufferSize(firstBounds)
+ val firstTaskSize = Point(firstBounds.width(), firstBounds.height())
+ it.hasLayerSize(firstTaskSize)
+ it.hasBufferSize(firstTaskSize)
}
assertThat(trace).layer(SECOND_ACTIVITY, frame).also {
- it.hasLayerSize(secondBounds)
- it.hasBufferSize(secondBounds)
+ val secondTaskSize = Point(secondBounds.width(), secondBounds.height())
+ it.hasLayerSize(secondTaskSize)
+ it.hasBufferSize(secondTaskSize)
}
}
diff --git a/tests/net/integration/src/com/android/server/net/integrationtests/ConnectivityServiceIntegrationTest.kt b/tests/net/integration/src/com/android/server/net/integrationtests/ConnectivityServiceIntegrationTest.kt
index dba1856ea6d0..70f6386aa891 100644
--- a/tests/net/integration/src/com/android/server/net/integrationtests/ConnectivityServiceIntegrationTest.kt
+++ b/tests/net/integration/src/com/android/server/net/integrationtests/ConnectivityServiceIntegrationTest.kt
@@ -200,7 +200,8 @@ class ConnectivityServiceIntegrationTest {
nsInstrumentation.addHttpResponse(HttpResponse(httpProbeUrl, responseCode = 204))
nsInstrumentation.addHttpResponse(HttpResponse(httpsProbeUrl, responseCode = 204))
- val na = NetworkAgentWrapper(TRANSPORT_CELLULAR, LinkProperties(), context)
+ val na = NetworkAgentWrapper(TRANSPORT_CELLULAR, LinkProperties(), null /* ncTemplate */,
+ context)
networkStackClient.verifyNetworkMonitorCreated(na.network, TEST_TIMEOUT_MS)
na.addCapability(NET_CAPABILITY_INTERNET)
@@ -238,7 +239,7 @@ class ConnectivityServiceIntegrationTest {
val lp = LinkProperties()
lp.captivePortalApiUrl = Uri.parse(apiUrl)
- val na = NetworkAgentWrapper(TRANSPORT_CELLULAR, lp, context)
+ val na = NetworkAgentWrapper(TRANSPORT_CELLULAR, lp, null /* ncTemplate */, context)
networkStackClient.verifyNetworkMonitorCreated(na.network, TEST_TIMEOUT_MS)
na.addCapability(NET_CAPABILITY_INTERNET)
diff --git a/tests/net/integration/util/com/android/server/NetworkAgentWrapper.java b/tests/net/integration/util/com/android/server/NetworkAgentWrapper.java
index 85704d033634..2a24d1ac22d2 100644
--- a/tests/net/integration/util/com/android/server/NetworkAgentWrapper.java
+++ b/tests/net/integration/util/com/android/server/NetworkAgentWrapper.java
@@ -72,12 +72,12 @@ public class NetworkAgentWrapper implements TestableNetworkCallback.HasNetwork {
private long mKeepaliveResponseDelay = 0L;
private Integer mExpectedKeepaliveSlot = null;
- public NetworkAgentWrapper(int transport, LinkProperties linkProperties, Context context)
- throws Exception {
+ public NetworkAgentWrapper(int transport, LinkProperties linkProperties,
+ NetworkCapabilities ncTemplate, Context context) throws Exception {
final int type = transportToLegacyType(transport);
final String typeName = ConnectivityManager.getNetworkTypeName(type);
mNetworkInfo = new NetworkInfo(type, 0, typeName, "Mock");
- mNetworkCapabilities = new NetworkCapabilities();
+ mNetworkCapabilities = (ncTemplate != null) ? ncTemplate : new NetworkCapabilities();
mNetworkCapabilities.addCapability(NET_CAPABILITY_NOT_SUSPENDED);
mNetworkCapabilities.addTransportType(transport);
switch (transport) {
diff --git a/tests/net/integration/util/com/android/server/TestNetIdManager.kt b/tests/net/integration/util/com/android/server/TestNetIdManager.kt
index eb290dc7d24a..938a694e8ba9 100644
--- a/tests/net/integration/util/com/android/server/TestNetIdManager.kt
+++ b/tests/net/integration/util/com/android/server/TestNetIdManager.kt
@@ -35,4 +35,5 @@ class TestNetIdManager : NetIdManager() {
private val nextId = AtomicInteger(MAX_NET_ID)
override fun reserveNetId() = nextId.decrementAndGet()
override fun releaseNetId(id: Int) = Unit
+ fun peekNextNetId() = nextId.get() - 1
}
diff --git a/tests/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java
index b78f0e237bc5..2758f6156c16 100644
--- a/tests/net/java/com/android/server/ConnectivityServiceTest.java
+++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java
@@ -259,7 +259,10 @@ import org.mockito.MockitoAnnotations;
import org.mockito.Spy;
import org.mockito.stubbing.Answer;
+import java.io.FileDescriptor;
import java.io.IOException;
+import java.io.PrintWriter;
+import java.io.StringWriter;
import java.net.DatagramSocket;
import java.net.Inet4Address;
import java.net.Inet6Address;
@@ -322,6 +325,7 @@ public class ConnectivityServiceTest {
private static final String MOBILE_IFNAME = "test_rmnet_data0";
private static final String WIFI_IFNAME = "test_wlan0";
private static final String WIFI_WOL_IFNAME = "test_wlan_wol";
+ private static final String VPN_IFNAME = "tun10042";
private static final String TEST_PACKAGE_NAME = "com.android.test.package";
private static final String[] EMPTY_STRING_ARRAY = new String[0];
@@ -339,6 +343,7 @@ public class ConnectivityServiceTest {
private INetworkPolicyListener mPolicyListener;
private WrappedMultinetworkPolicyTracker mPolicyTracker;
private HandlerThread mAlarmManagerThread;
+ private TestNetIdManager mNetIdManager;
@Mock IIpConnectivityMetrics mIpConnectivityMetrics;
@Mock IpConnectivityMetrics.Logger mMetricsService;
@@ -617,12 +622,17 @@ public class ConnectivityServiceTest {
private String mRedirectUrl;
TestNetworkAgentWrapper(int transport) throws Exception {
- this(transport, new LinkProperties());
+ this(transport, new LinkProperties(), null);
}
TestNetworkAgentWrapper(int transport, LinkProperties linkProperties)
throws Exception {
- super(transport, linkProperties, mServiceContext);
+ this(transport, linkProperties, null);
+ }
+
+ private TestNetworkAgentWrapper(int transport, LinkProperties linkProperties,
+ NetworkCapabilities ncTemplate) throws Exception {
+ super(transport, linkProperties, ncTemplate, mServiceContext);
// Waits for the NetworkAgent to be registered, which includes the creation of the
// NetworkMonitor.
@@ -1017,46 +1027,36 @@ public class ConnectivityServiceTest {
}
}
+ private Set<UidRange> uidRangesForUid(int uid) {
+ final ArraySet<UidRange> ranges = new ArraySet<>();
+ ranges.add(new UidRange(uid, uid));
+ return ranges;
+ }
+
private static Looper startHandlerThreadAndReturnLooper() {
final HandlerThread handlerThread = new HandlerThread("MockVpnThread");
handlerThread.start();
return handlerThread.getLooper();
}
- private class MockVpn extends Vpn {
- // TODO : the interactions between this mock and the mock network agent are too
- // hard to get right at this moment, because it's unclear in which case which
- // target needs to get a method call or both, and in what order. It's because
- // MockNetworkAgent wants to manage its own NetworkCapabilities, but the Vpn
- // parent class of MockVpn agent wants that responsibility.
- // That being said inside the test it should be possible to make the interactions
- // harder to get wrong with precise speccing, judicious comments, helper methods
- // and a few sprinkled assertions.
-
- private boolean mConnected = false;
+ private class MockVpn extends Vpn implements TestableNetworkCallback.HasNetwork {
// Careful ! This is different from mNetworkAgent, because MockNetworkAgent does
// not inherit from NetworkAgent.
private TestNetworkAgentWrapper mMockNetworkAgent;
- private int mVpnType = VpnManager.TYPE_VPN_SERVICE;
+ private boolean mAgentRegistered = false;
+ private int mVpnType = VpnManager.TYPE_VPN_SERVICE;
private VpnInfo mVpnInfo;
- private Network[] mUnderlyingNetworks;
public MockVpn(int userId) {
super(startHandlerThreadAndReturnLooper(), mServiceContext, mNetworkManagementService,
userId, mock(KeyStore.class));
- }
-
- public void setNetworkAgent(TestNetworkAgentWrapper agent) {
- agent.waitForIdle(TIMEOUT_MS);
- mMockNetworkAgent = agent;
- mNetworkAgent = agent.getNetworkAgent();
- mNetworkCapabilities.set(agent.getNetworkCapabilities());
+ mConfig = new VpnConfig();
}
public void setUids(Set<UidRange> uids) {
mNetworkCapabilities.setUids(uids);
- updateCapabilities(null /* defaultNetwork */);
+ updateCapabilitiesInternal(null /* defaultNetwork */, true);
}
public void setVpnType(int vpnType) {
@@ -1064,21 +1064,13 @@ public class ConnectivityServiceTest {
}
@Override
- public int getNetId() {
- if (mMockNetworkAgent == null) {
- return NETID_UNSET;
- }
- return mMockNetworkAgent.getNetwork().netId;
+ public Network getNetwork() {
+ return (mMockNetworkAgent == null) ? null : mMockNetworkAgent.getNetwork();
}
@Override
- public boolean appliesToUid(int uid) {
- return mConnected; // Trickery to simplify testing.
- }
-
- @Override
- protected boolean isCallerEstablishedOwnerLocked() {
- return mConnected; // Similar trickery
+ public int getNetId() {
+ return (mMockNetworkAgent == null) ? NETID_UNSET : mMockNetworkAgent.getNetwork().netId;
}
@Override
@@ -1086,41 +1078,94 @@ public class ConnectivityServiceTest {
return mVpnType;
}
- private void connect(boolean isAlwaysMetered) {
- mNetworkCapabilities.set(mMockNetworkAgent.getNetworkCapabilities());
- mConnected = true;
- mConfig = new VpnConfig();
+ private void registerAgent(boolean isAlwaysMetered, Set<UidRange> uids, LinkProperties lp)
+ throws Exception {
+ if (mAgentRegistered) throw new IllegalStateException("already registered");
+ setUids(uids);
mConfig.isMetered = isAlwaysMetered;
+ mInterface = VPN_IFNAME;
+ mMockNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_VPN, lp,
+ mNetworkCapabilities);
+ mMockNetworkAgent.waitForIdle(TIMEOUT_MS);
+ mAgentRegistered = true;
+ mNetworkCapabilities.set(mMockNetworkAgent.getNetworkCapabilities());
+ mNetworkAgent = mMockNetworkAgent.getNetworkAgent();
}
- public void connectAsAlwaysMetered() {
- connect(true /* isAlwaysMetered */);
+ private void registerAgent(Set<UidRange> uids) throws Exception {
+ registerAgent(false /* isAlwaysMetered */, uids, new LinkProperties());
}
- public void connect() {
- connect(false /* isAlwaysMetered */);
+ private void connect(boolean validated, boolean hasInternet, boolean isStrictMode) {
+ mMockNetworkAgent.connect(validated, hasInternet, isStrictMode);
}
- @Override
- public NetworkCapabilities updateCapabilities(Network defaultNetwork) {
- if (!mConnected) return null;
+ private void connect(boolean validated) {
+ mMockNetworkAgent.connect(validated);
+ }
+
+ private TestNetworkAgentWrapper getAgent() {
+ return mMockNetworkAgent;
+ }
+
+ public void establish(LinkProperties lp, int uid, Set<UidRange> ranges, boolean validated,
+ boolean hasInternet, boolean isStrictMode) throws Exception {
+ mNetworkCapabilities.setOwnerUid(uid);
+ mNetworkCapabilities.setAdministratorUids(new int[]{uid});
+ registerAgent(false, ranges, lp);
+ connect(validated, hasInternet, isStrictMode);
+ waitForIdle();
+ }
+
+ public void establish(LinkProperties lp, int uid, Set<UidRange> ranges) throws Exception {
+ establish(lp, uid, ranges, true, true, false);
+ }
+
+ public void establishForMyUid(LinkProperties lp) throws Exception {
+ final int uid = Process.myUid();
+ establish(lp, uid, uidRangesForUid(uid), true, true, false);
+ }
+
+ public void establishForMyUid(boolean validated, boolean hasInternet, boolean isStrictMode)
+ throws Exception {
+ final int uid = Process.myUid();
+ establish(new LinkProperties(), uid, uidRangesForUid(uid), validated, hasInternet,
+ isStrictMode);
+ }
+
+ public void establishForMyUid() throws Exception {
+ establishForMyUid(new LinkProperties());
+ }
+
+ public void sendLinkProperties(LinkProperties lp) {
+ mMockNetworkAgent.sendLinkProperties(lp);
+ }
+
+ private NetworkCapabilities updateCapabilitiesInternal(Network defaultNetwork,
+ boolean sendToConnectivityService) {
+ if (!mAgentRegistered) return null;
super.updateCapabilities(defaultNetwork);
// Because super.updateCapabilities will update the capabilities of the agent but
// not the mock agent, the mock agent needs to know about them.
- copyCapabilitiesToNetworkAgent();
+ copyCapabilitiesToNetworkAgent(sendToConnectivityService);
return new NetworkCapabilities(mNetworkCapabilities);
}
- private void copyCapabilitiesToNetworkAgent() {
+ private void copyCapabilitiesToNetworkAgent(boolean sendToConnectivityService) {
if (null != mMockNetworkAgent) {
mMockNetworkAgent.setNetworkCapabilities(mNetworkCapabilities,
- false /* sendToConnectivityService */);
+ sendToConnectivityService);
}
}
+ @Override
+ public NetworkCapabilities updateCapabilities(Network defaultNetwork) {
+ return updateCapabilitiesInternal(defaultNetwork, false);
+ }
+
public void disconnect() {
- mConnected = false;
- mConfig = null;
+ if (mMockNetworkAgent != null) mMockNetworkAgent.disconnect();
+ mAgentRegistered = false;
}
@Override
@@ -1133,18 +1178,6 @@ public class ConnectivityServiceTest {
private synchronized void setVpnInfo(VpnInfo vpnInfo) {
mVpnInfo = vpnInfo;
}
-
- @Override
- public synchronized Network[] getUnderlyingNetworks() {
- if (mUnderlyingNetworks != null) return mUnderlyingNetworks;
-
- return super.getUnderlyingNetworks();
- }
-
- /** Don't override behavior for {@link Vpn#setUnderlyingNetworks}. */
- private synchronized void overrideUnderlyingNetworks(Network[] underlyingNetworks) {
- mUnderlyingNetworks = underlyingNetworks;
- }
}
private void mockVpn(int uid) {
@@ -1207,6 +1240,8 @@ public class ConnectivityServiceTest {
@Before
public void setUp() throws Exception {
+ mNetIdManager = new TestNetIdManager();
+
mContext = InstrumentationRegistry.getContext();
MockitoAnnotations.initMocks(this);
@@ -1277,7 +1312,7 @@ public class ConnectivityServiceTest {
doNothing().when(mSystemProperties).setTcpInitRwnd(anyInt());
final ConnectivityService.Dependencies deps = mock(ConnectivityService.Dependencies.class);
doReturn(mCsHandlerThread).when(deps).makeHandlerThread();
- doReturn(new TestNetIdManager()).when(deps).makeNetIdManager();
+ doReturn(mNetIdManager).when(deps).makeNetIdManager();
doReturn(mNetworkStack).when(deps).getNetworkStack();
doReturn(mSystemProperties).when(deps).getSystemProperties();
doReturn(mock(ProxyTracker.class)).when(deps).makeProxyTracker(any(), any());
@@ -1335,6 +1370,9 @@ public class ConnectivityServiceTest {
mEthernetNetworkAgent.disconnect();
mEthernetNetworkAgent = null;
}
+ mMockVpn.disconnect();
+ waitForIdle();
+
FakeSettingsProvider.clearSettingsProvider();
mCsHandlerThread.quitSafely();
@@ -3218,20 +3256,12 @@ public class ConnectivityServiceTest {
waitForIdle();
assertEquals(null, mCm.getActiveNetwork());
- final int uid = Process.myUid();
- final TestNetworkAgentWrapper
- vpnNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_VPN);
- final ArraySet<UidRange> ranges = new ArraySet<>();
- ranges.add(new UidRange(uid, uid));
- mMockVpn.setNetworkAgent(vpnNetworkAgent);
- mMockVpn.setUids(ranges);
- vpnNetworkAgent.connect(true);
- mMockVpn.connect();
- defaultNetworkCallback.expectAvailableThenValidatedCallbacks(vpnNetworkAgent);
+ mMockVpn.establishForMyUid();
+ defaultNetworkCallback.expectAvailableThenValidatedCallbacks(mMockVpn);
assertEquals(defaultNetworkCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
- vpnNetworkAgent.disconnect();
- defaultNetworkCallback.expectCallback(CallbackEntry.LOST, vpnNetworkAgent);
+ mMockVpn.disconnect();
+ defaultNetworkCallback.expectCallback(CallbackEntry.LOST, mMockVpn);
waitForIdle();
assertEquals(null, mCm.getActiveNetwork());
}
@@ -4808,13 +4838,52 @@ public class ConnectivityServiceTest {
mCm.unregisterNetworkCallback(networkCallback);
}
+ private <T> void assertSameElementsNoDuplicates(T[] expected, T[] actual) {
+ // Easier to implement than a proper "assertSameElements" method that also correctly deals
+ // with duplicates.
+ final String msg = Arrays.toString(expected) + " != " + Arrays.toString(actual);
+ assertEquals(msg, expected.length, actual.length);
+ Set expectedSet = new ArraySet<>(Arrays.asList(expected));
+ assertEquals("expected contains duplicates", expectedSet.size(), expected.length);
+ // actual cannot have duplicates because it's the same length and has the same elements.
+ Set actualSet = new ArraySet<>(Arrays.asList(actual));
+ assertEquals(expectedSet, actualSet);
+ }
+
+ private void expectForceUpdateIfaces(Network[] networks, String defaultIface,
+ Integer vpnUid, String vpnIfname, String[] underlyingIfaces) throws Exception {
+ ArgumentCaptor<Network[]> networksCaptor = ArgumentCaptor.forClass(Network[].class);
+ ArgumentCaptor<VpnInfo[]> vpnInfosCaptor = ArgumentCaptor.forClass(VpnInfo[].class);
+
+ verify(mStatsService, atLeastOnce()).forceUpdateIfaces(networksCaptor.capture(),
+ any(NetworkState[].class), eq(defaultIface), vpnInfosCaptor.capture());
+
+ assertSameElementsNoDuplicates(networksCaptor.getValue(), networks);
+
+ VpnInfo[] infos = vpnInfosCaptor.getValue();
+ if (vpnUid != null) {
+ assertEquals("Should have exactly one VPN:", 1, infos.length);
+ VpnInfo info = infos[0];
+ assertEquals("Unexpected VPN owner:", (int) vpnUid, info.ownerUid);
+ assertEquals("Unexpected VPN interface:", vpnIfname, info.vpnIface);
+ assertSameElementsNoDuplicates(underlyingIfaces, info.underlyingIfaces);
+ } else {
+ assertEquals(0, infos.length);
+ return;
+ }
+ }
+
+ private void expectForceUpdateIfaces(Network[] networks, String defaultIface) throws Exception {
+ expectForceUpdateIfaces(networks, defaultIface, null, null, new String[0]);
+ }
+
@Test
public void testStatsIfacesChanged() throws Exception {
mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
- Network[] onlyCell = new Network[] {mCellNetworkAgent.getNetwork()};
- Network[] onlyWifi = new Network[] {mWiFiNetworkAgent.getNetwork()};
+ final Network[] onlyCell = new Network[] {mCellNetworkAgent.getNetwork()};
+ final Network[] onlyWifi = new Network[] {mWiFiNetworkAgent.getNetwork()};
LinkProperties cellLp = new LinkProperties();
cellLp.setInterfaceName(MOBILE_IFNAME);
@@ -4825,9 +4894,7 @@ public class ConnectivityServiceTest {
mCellNetworkAgent.connect(false);
mCellNetworkAgent.sendLinkProperties(cellLp);
waitForIdle();
- verify(mStatsService, atLeastOnce())
- .forceUpdateIfaces(eq(onlyCell), any(NetworkState[].class), eq(MOBILE_IFNAME),
- eq(new VpnInfo[0]));
+ expectForceUpdateIfaces(onlyCell, MOBILE_IFNAME);
reset(mStatsService);
// Default network switch should update ifaces.
@@ -4835,32 +4902,24 @@ public class ConnectivityServiceTest {
mWiFiNetworkAgent.sendLinkProperties(wifiLp);
waitForIdle();
assertEquals(wifiLp, mService.getActiveLinkProperties());
- verify(mStatsService, atLeastOnce())
- .forceUpdateIfaces(eq(onlyWifi), any(NetworkState[].class), eq(WIFI_IFNAME),
- eq(new VpnInfo[0]));
+ expectForceUpdateIfaces(onlyWifi, WIFI_IFNAME);
reset(mStatsService);
// Disconnect should update ifaces.
mWiFiNetworkAgent.disconnect();
waitForIdle();
- verify(mStatsService, atLeastOnce())
- .forceUpdateIfaces(eq(onlyCell), any(NetworkState[].class),
- eq(MOBILE_IFNAME), eq(new VpnInfo[0]));
+ expectForceUpdateIfaces(onlyCell, MOBILE_IFNAME);
reset(mStatsService);
// Metered change should update ifaces
mCellNetworkAgent.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED);
waitForIdle();
- verify(mStatsService, atLeastOnce())
- .forceUpdateIfaces(eq(onlyCell), any(NetworkState[].class), eq(MOBILE_IFNAME),
- eq(new VpnInfo[0]));
+ expectForceUpdateIfaces(onlyCell, MOBILE_IFNAME);
reset(mStatsService);
mCellNetworkAgent.removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED);
waitForIdle();
- verify(mStatsService, atLeastOnce())
- .forceUpdateIfaces(eq(onlyCell), any(NetworkState[].class), eq(MOBILE_IFNAME),
- eq(new VpnInfo[0]));
+ expectForceUpdateIfaces(onlyCell, MOBILE_IFNAME);
reset(mStatsService);
// Captive portal change shouldn't update ifaces
@@ -4874,9 +4933,102 @@ public class ConnectivityServiceTest {
// Roaming change should update ifaces
mCellNetworkAgent.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING);
waitForIdle();
- verify(mStatsService, atLeastOnce())
- .forceUpdateIfaces(eq(onlyCell), any(NetworkState[].class), eq(MOBILE_IFNAME),
- eq(new VpnInfo[0]));
+ expectForceUpdateIfaces(onlyCell, MOBILE_IFNAME);
+ reset(mStatsService);
+
+ // Test VPNs.
+ final LinkProperties lp = new LinkProperties();
+ lp.setInterfaceName(VPN_IFNAME);
+
+ mMockVpn.establishForMyUid(lp);
+
+ final Network[] cellAndVpn = new Network[] {
+ mCellNetworkAgent.getNetwork(), mMockVpn.getNetwork()};
+ Network[] cellAndWifi = new Network[] {
+ mCellNetworkAgent.getNetwork(), mWiFiNetworkAgent.getNetwork()};
+
+ // A VPN with default (null) underlying networks sets the underlying network's interfaces...
+ expectForceUpdateIfaces(cellAndVpn, MOBILE_IFNAME, Process.myUid(), VPN_IFNAME,
+ new String[]{MOBILE_IFNAME});
+
+ // ...and updates them as the default network switches.
+ mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
+ mWiFiNetworkAgent.connect(false);
+ mWiFiNetworkAgent.sendLinkProperties(wifiLp);
+ final Network[] wifiAndVpn = new Network[] {
+ mWiFiNetworkAgent.getNetwork(), mMockVpn.getNetwork()};
+ cellAndWifi = new Network[] {
+ mCellNetworkAgent.getNetwork(), mWiFiNetworkAgent.getNetwork()};
+
+ waitForIdle();
+ assertEquals(wifiLp, mService.getActiveLinkProperties());
+ expectForceUpdateIfaces(wifiAndVpn, WIFI_IFNAME, Process.myUid(), VPN_IFNAME,
+ new String[]{WIFI_IFNAME});
+ reset(mStatsService);
+
+ // A VPN that sets its underlying networks passes the underlying interfaces, and influences
+ // the default interface sent to NetworkStatsService by virtue of applying to the system
+ // server UID (or, in this test, to the test's UID). This is the reason for sending
+ // MOBILE_IFNAME even though the default network is wifi.
+ // TODO: fix this to pass in the actual default network interface. Whether or not the VPN
+ // applies to the system server UID should not have any bearing on network stats.
+ mService.setUnderlyingNetworksForVpn(onlyCell);
+ waitForIdle();
+ expectForceUpdateIfaces(wifiAndVpn, MOBILE_IFNAME, Process.myUid(), VPN_IFNAME,
+ new String[]{MOBILE_IFNAME});
+ reset(mStatsService);
+
+ mService.setUnderlyingNetworksForVpn(cellAndWifi);
+ waitForIdle();
+ expectForceUpdateIfaces(wifiAndVpn, MOBILE_IFNAME, Process.myUid(), VPN_IFNAME,
+ new String[]{MOBILE_IFNAME, WIFI_IFNAME});
+ reset(mStatsService);
+
+ // If an underlying network disconnects, that interface should no longer be underlying.
+ // This doesn't actually work because disconnectAndDestroyNetwork only notifies
+ // NetworkStatsService before the underlying network is actually removed. So the underlying
+ // network will only be removed if notifyIfacesChangedForNetworkStats is called again. This
+ // could result in incorrect data usage measurements if the interface used by the
+ // disconnected network is reused by a system component that does not register an agent for
+ // it (e.g., tethering).
+ mCellNetworkAgent.disconnect();
+ waitForIdle();
+ assertNull(mService.getLinkProperties(mCellNetworkAgent.getNetwork()));
+ expectForceUpdateIfaces(wifiAndVpn, MOBILE_IFNAME, Process.myUid(), VPN_IFNAME,
+ new String[]{MOBILE_IFNAME, WIFI_IFNAME});
+
+ // Confirm that we never tell NetworkStatsService that cell is no longer the underlying
+ // network for the VPN...
+ verify(mStatsService, never()).forceUpdateIfaces(any(Network[].class),
+ any(NetworkState[].class), any() /* anyString() doesn't match null */,
+ argThat(infos -> infos[0].underlyingIfaces.length == 1
+ && WIFI_IFNAME.equals(infos[0].underlyingIfaces[0])));
+ verifyNoMoreInteractions(mStatsService);
+ reset(mStatsService);
+
+ // ... but if something else happens that causes notifyIfacesChangedForNetworkStats to be
+ // called again, it does. For example, connect Ethernet, but with a low score, such that it
+ // does not become the default network.
+ mEthernetNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_ETHERNET);
+ mEthernetNetworkAgent.adjustScore(-40);
+ mEthernetNetworkAgent.connect(false);
+ waitForIdle();
+ verify(mStatsService).forceUpdateIfaces(any(Network[].class),
+ any(NetworkState[].class), any() /* anyString() doesn't match null */,
+ argThat(vpnInfos -> vpnInfos[0].underlyingIfaces.length == 1
+ && WIFI_IFNAME.equals(vpnInfos[0].underlyingIfaces[0])));
+ mEthernetNetworkAgent.disconnect();
+ reset(mStatsService);
+
+ // When a VPN declares no underlying networks (i.e., no connectivity), getAllVpnInfo
+ // does not return the VPN, so CS does not pass it to NetworkStatsService. This causes
+ // NetworkStatsFactory#adjustForTunAnd464Xlat not to attempt any VPN data migration, which
+ // is probably a performance improvement (though it's very unlikely that a VPN would declare
+ // no underlying networks).
+ // Also, for the same reason as above, the active interface passed in is null.
+ mService.setUnderlyingNetworksForVpn(new Network[0]);
+ waitForIdle();
+ expectForceUpdateIfaces(wifiAndVpn, null);
reset(mStatsService);
}
@@ -5232,6 +5384,58 @@ public class ConnectivityServiceTest {
}
@Test
+ public void testVpnConnectDisconnectUnderlyingNetwork() throws Exception {
+ final TestNetworkCallback callback = new TestNetworkCallback();
+ final NetworkRequest request = new NetworkRequest.Builder()
+ .removeCapability(NET_CAPABILITY_NOT_VPN).build();
+
+ mCm.registerNetworkCallback(request, callback);
+
+ // Bring up a VPN that specifies an underlying network that does not exist yet.
+ // Note: it's sort of meaningless for a VPN app to declare a network that doesn't exist yet,
+ // (and doing so is difficult without using reflection) but it's good to test that the code
+ // behaves approximately correctly.
+ mMockVpn.establishForMyUid(false, true, false);
+ final Network wifiNetwork = new Network(mNetIdManager.peekNextNetId());
+ mService.setUnderlyingNetworksForVpn(new Network[]{wifiNetwork});
+ callback.expectAvailableCallbacksUnvalidated(mMockVpn);
+ assertTrue(mCm.getNetworkCapabilities(mMockVpn.getNetwork())
+ .hasTransport(TRANSPORT_VPN));
+ assertFalse(mCm.getNetworkCapabilities(mMockVpn.getNetwork())
+ .hasTransport(TRANSPORT_WIFI));
+
+ // Make that underlying network connect, and expect to see its capabilities immediately
+ // reflected in the VPN's capabilities.
+ mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
+ assertEquals(wifiNetwork, mWiFiNetworkAgent.getNetwork());
+ mWiFiNetworkAgent.connect(false);
+ // TODO: the callback for the VPN happens before any callbacks are called for the wifi
+ // network that has just connected. There appear to be two issues here:
+ // 1. The VPN code will accept an underlying network as soon as getNetworkCapabilities() for
+ // it returns non-null (which happens very early, during handleRegisterNetworkAgent).
+ // This is not correct because that that point the network is not connected and cannot
+ // pass any traffic.
+ // 2. When a network connects, updateNetworkInfo propagates underlying network capabilities
+ // before rematching networks.
+ // Given that this scenario can't really happen, this is probably fine for now.
+ callback.expectCallback(CallbackEntry.NETWORK_CAPS_UPDATED, mMockVpn);
+ callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
+ assertTrue(mCm.getNetworkCapabilities(mMockVpn.getNetwork())
+ .hasTransport(TRANSPORT_VPN));
+ assertTrue(mCm.getNetworkCapabilities(mMockVpn.getNetwork())
+ .hasTransport(TRANSPORT_WIFI));
+
+ // Disconnect the network, and expect to see the VPN capabilities change accordingly.
+ mWiFiNetworkAgent.disconnect();
+ callback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
+ callback.expectCapabilitiesThat(mMockVpn, (nc) ->
+ nc.getTransportTypes().length == 1 && nc.hasTransport(TRANSPORT_VPN));
+
+ mMockVpn.disconnect();
+ mCm.unregisterNetworkCallback(callback);
+ }
+
+ @Test
public void testVpnNetworkActive() throws Exception {
final int uid = Process.myUid();
@@ -5265,42 +5469,38 @@ public class ConnectivityServiceTest {
vpnNetworkCallback.assertNoCallback();
assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
- final TestNetworkAgentWrapper
- vpnNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_VPN);
- final ArraySet<UidRange> ranges = new ArraySet<>();
- ranges.add(new UidRange(uid, uid));
- mMockVpn.setNetworkAgent(vpnNetworkAgent);
- mMockVpn.setUids(ranges);
+ final Set<UidRange> ranges = uidRangesForUid(uid);
+ mMockVpn.registerAgent(ranges);
+
// VPN networks do not satisfy the default request and are automatically validated
// by NetworkMonitor
assertFalse(NetworkMonitorUtils.isValidationRequired(
- vpnNetworkAgent.getNetworkCapabilities()));
- vpnNetworkAgent.setNetworkValid(false /* isStrictMode */);
+ mMockVpn.getAgent().getNetworkCapabilities()));
+ mMockVpn.getAgent().setNetworkValid(false /* isStrictMode */);
- vpnNetworkAgent.connect(false);
- mMockVpn.connect();
- mMockVpn.setUnderlyingNetworks(new Network[0]);
+ mMockVpn.connect(false);
+ mService.setUnderlyingNetworksForVpn(new Network[0]);
- genericNetworkCallback.expectAvailableCallbacksUnvalidated(vpnNetworkAgent);
+ genericNetworkCallback.expectAvailableCallbacksUnvalidated(mMockVpn);
genericNotVpnNetworkCallback.assertNoCallback();
wifiNetworkCallback.assertNoCallback();
- vpnNetworkCallback.expectAvailableCallbacksUnvalidated(vpnNetworkAgent);
- defaultCallback.expectAvailableCallbacksUnvalidated(vpnNetworkAgent);
+ vpnNetworkCallback.expectAvailableCallbacksUnvalidated(mMockVpn);
+ defaultCallback.expectAvailableCallbacksUnvalidated(mMockVpn);
assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
- genericNetworkCallback.expectCallback(CallbackEntry.NETWORK_CAPS_UPDATED, vpnNetworkAgent);
+ genericNetworkCallback.expectCallback(CallbackEntry.NETWORK_CAPS_UPDATED, mMockVpn);
genericNotVpnNetworkCallback.assertNoCallback();
- vpnNetworkCallback.expectCapabilitiesThat(vpnNetworkAgent, nc -> null == nc.getUids());
- defaultCallback.expectCallback(CallbackEntry.NETWORK_CAPS_UPDATED, vpnNetworkAgent);
+ vpnNetworkCallback.expectCapabilitiesThat(mMockVpn, nc -> null == nc.getUids());
+ defaultCallback.expectCallback(CallbackEntry.NETWORK_CAPS_UPDATED, mMockVpn);
assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
ranges.clear();
- vpnNetworkAgent.setUids(ranges);
+ mMockVpn.setUids(ranges);
- genericNetworkCallback.expectCallback(CallbackEntry.LOST, vpnNetworkAgent);
+ genericNetworkCallback.expectCallback(CallbackEntry.LOST, mMockVpn);
genericNotVpnNetworkCallback.assertNoCallback();
wifiNetworkCallback.assertNoCallback();
- vpnNetworkCallback.expectCallback(CallbackEntry.LOST, vpnNetworkAgent);
+ vpnNetworkCallback.expectCallback(CallbackEntry.LOST, mMockVpn);
// TODO : The default network callback should actually get a LOST call here (also see the
// comment below for AVAILABLE). This is because ConnectivityService does not look at UID
@@ -5308,19 +5508,18 @@ public class ConnectivityServiceTest {
// can't currently update their UIDs without disconnecting, so this does not matter too
// much, but that is the reason the test here has to check for an update to the
// capabilities instead of the expected LOST then AVAILABLE.
- defaultCallback.expectCallback(CallbackEntry.NETWORK_CAPS_UPDATED, vpnNetworkAgent);
+ defaultCallback.expectCallback(CallbackEntry.NETWORK_CAPS_UPDATED, mMockVpn);
ranges.add(new UidRange(uid, uid));
mMockVpn.setUids(ranges);
- vpnNetworkAgent.setUids(ranges);
- genericNetworkCallback.expectAvailableCallbacksValidated(vpnNetworkAgent);
+ genericNetworkCallback.expectAvailableCallbacksValidated(mMockVpn);
genericNotVpnNetworkCallback.assertNoCallback();
wifiNetworkCallback.assertNoCallback();
- vpnNetworkCallback.expectAvailableCallbacksValidated(vpnNetworkAgent);
+ vpnNetworkCallback.expectAvailableCallbacksValidated(mMockVpn);
// TODO : Here like above, AVAILABLE would be correct, but because this can't actually
// happen outside of the test, ConnectivityService does not rematch callbacks.
- defaultCallback.expectCallback(CallbackEntry.NETWORK_CAPS_UPDATED, vpnNetworkAgent);
+ defaultCallback.expectCallback(CallbackEntry.NETWORK_CAPS_UPDATED, mMockVpn);
mWiFiNetworkAgent.disconnect();
@@ -5330,13 +5529,13 @@ public class ConnectivityServiceTest {
vpnNetworkCallback.assertNoCallback();
defaultCallback.assertNoCallback();
- vpnNetworkAgent.disconnect();
+ mMockVpn.disconnect();
- genericNetworkCallback.expectCallback(CallbackEntry.LOST, vpnNetworkAgent);
+ genericNetworkCallback.expectCallback(CallbackEntry.LOST, mMockVpn);
genericNotVpnNetworkCallback.assertNoCallback();
wifiNetworkCallback.assertNoCallback();
- vpnNetworkCallback.expectCallback(CallbackEntry.LOST, vpnNetworkAgent);
- defaultCallback.expectCallback(CallbackEntry.LOST, vpnNetworkAgent);
+ vpnNetworkCallback.expectCallback(CallbackEntry.LOST, mMockVpn);
+ defaultCallback.expectCallback(CallbackEntry.LOST, mMockVpn);
assertEquals(null, mCm.getActiveNetwork());
mCm.unregisterNetworkCallback(genericNetworkCallback);
@@ -5358,20 +5557,13 @@ public class ConnectivityServiceTest {
defaultCallback.expectAvailableThenValidatedCallbacks(mWiFiNetworkAgent);
assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
- TestNetworkAgentWrapper
- vpnNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_VPN);
- final ArraySet<UidRange> ranges = new ArraySet<>();
- ranges.add(new UidRange(uid, uid));
- mMockVpn.setNetworkAgent(vpnNetworkAgent);
- mMockVpn.setUids(ranges);
- vpnNetworkAgent.connect(true /* validated */, false /* hasInternet */,
+ mMockVpn.establishForMyUid(true /* validated */, false /* hasInternet */,
false /* isStrictMode */);
- mMockVpn.connect();
defaultCallback.assertNoCallback();
assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
- vpnNetworkAgent.disconnect();
+ mMockVpn.disconnect();
defaultCallback.assertNoCallback();
mCm.unregisterNetworkCallback(defaultCallback);
@@ -5390,21 +5582,14 @@ public class ConnectivityServiceTest {
defaultCallback.expectAvailableThenValidatedCallbacks(mWiFiNetworkAgent);
assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
- TestNetworkAgentWrapper
- vpnNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_VPN);
- final ArraySet<UidRange> ranges = new ArraySet<>();
- ranges.add(new UidRange(uid, uid));
- mMockVpn.setNetworkAgent(vpnNetworkAgent);
- mMockVpn.setUids(ranges);
- vpnNetworkAgent.connect(true /* validated */, true /* hasInternet */,
+ mMockVpn.establishForMyUid(true /* validated */, true /* hasInternet */,
false /* isStrictMode */);
- mMockVpn.connect();
- defaultCallback.expectAvailableThenValidatedCallbacks(vpnNetworkAgent);
+ defaultCallback.expectAvailableThenValidatedCallbacks(mMockVpn);
assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
- vpnNetworkAgent.disconnect();
- defaultCallback.expectCallback(CallbackEntry.LOST, vpnNetworkAgent);
+ mMockVpn.disconnect();
+ defaultCallback.expectCallback(CallbackEntry.LOST, mMockVpn);
defaultCallback.expectAvailableCallbacksValidated(mWiFiNetworkAgent);
mCm.unregisterNetworkCallback(defaultCallback);
@@ -5422,44 +5607,36 @@ public class ConnectivityServiceTest {
callback.assertNoCallback();
// Bring up a VPN that has the INTERNET capability, initially unvalidated.
- final int uid = Process.myUid();
- final TestNetworkAgentWrapper
- vpnNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_VPN);
- final ArraySet<UidRange> ranges = new ArraySet<>();
- ranges.add(new UidRange(uid, uid));
- mMockVpn.setNetworkAgent(vpnNetworkAgent);
- mMockVpn.setUids(ranges);
- vpnNetworkAgent.connect(false /* validated */, true /* hasInternet */,
+ mMockVpn.establishForMyUid(false /* validated */, true /* hasInternet */,
false /* isStrictMode */);
- mMockVpn.connect();
// Even though the VPN is unvalidated, it becomes the default network for our app.
- callback.expectAvailableCallbacksUnvalidated(vpnNetworkAgent);
+ callback.expectAvailableCallbacksUnvalidated(mMockVpn);
callback.assertNoCallback();
- assertTrue(vpnNetworkAgent.getScore() > mEthernetNetworkAgent.getScore());
- assertEquals(ConnectivityConstants.VPN_DEFAULT_SCORE, vpnNetworkAgent.getScore());
- assertEquals(vpnNetworkAgent.getNetwork(), mCm.getActiveNetwork());
+ assertTrue(mMockVpn.getAgent().getScore() > mEthernetNetworkAgent.getScore());
+ assertEquals(ConnectivityConstants.VPN_DEFAULT_SCORE, mMockVpn.getAgent().getScore());
+ assertEquals(mMockVpn.getNetwork(), mCm.getActiveNetwork());
- NetworkCapabilities nc = mCm.getNetworkCapabilities(vpnNetworkAgent.getNetwork());
+ NetworkCapabilities nc = mCm.getNetworkCapabilities(mMockVpn.getNetwork());
assertFalse(nc.hasCapability(NET_CAPABILITY_VALIDATED));
assertTrue(nc.hasCapability(NET_CAPABILITY_INTERNET));
assertFalse(NetworkMonitorUtils.isValidationRequired(
- vpnNetworkAgent.getNetworkCapabilities()));
+ mMockVpn.getAgent().getNetworkCapabilities()));
assertTrue(NetworkMonitorUtils.isPrivateDnsValidationRequired(
- vpnNetworkAgent.getNetworkCapabilities()));
+ mMockVpn.getAgent().getNetworkCapabilities()));
// Pretend that the VPN network validates.
- vpnNetworkAgent.setNetworkValid(false /* isStrictMode */);
- vpnNetworkAgent.mNetworkMonitor.forceReevaluation(Process.myUid());
+ mMockVpn.getAgent().setNetworkValid(false /* isStrictMode */);
+ mMockVpn.getAgent().mNetworkMonitor.forceReevaluation(Process.myUid());
// Expect to see the validated capability, but no other changes, because the VPN is already
// the default network for the app.
- callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, vpnNetworkAgent);
+ callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mMockVpn);
callback.assertNoCallback();
- vpnNetworkAgent.disconnect();
- callback.expectCallback(CallbackEntry.LOST, vpnNetworkAgent);
+ mMockVpn.disconnect();
+ callback.expectCallback(CallbackEntry.LOST, mMockVpn);
callback.expectAvailableCallbacksValidated(mEthernetNetworkAgent);
}
@@ -5481,21 +5658,15 @@ public class ConnectivityServiceTest {
mCellNetworkAgent.addCapability(NET_CAPABILITY_NOT_SUSPENDED);
mCellNetworkAgent.connect(true);
- final TestNetworkAgentWrapper vpnNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_VPN);
- final ArraySet<UidRange> ranges = new ArraySet<>();
- ranges.add(new UidRange(uid, uid));
- mMockVpn.setNetworkAgent(vpnNetworkAgent);
- mMockVpn.connect();
- mMockVpn.setUids(ranges);
- vpnNetworkAgent.connect(true /* validated */, false /* hasInternet */,
+ mMockVpn.establishForMyUid(true /* validated */, false /* hasInternet */,
false /* isStrictMode */);
- vpnNetworkCallback.expectAvailableCallbacks(vpnNetworkAgent.getNetwork(),
+ vpnNetworkCallback.expectAvailableCallbacks(mMockVpn.getNetwork(),
false /* suspended */, false /* validated */, false /* blocked */, TIMEOUT_MS);
- vpnNetworkCallback.expectCapabilitiesThat(vpnNetworkAgent.getNetwork(), TIMEOUT_MS,
+ vpnNetworkCallback.expectCapabilitiesThat(mMockVpn.getNetwork(), TIMEOUT_MS,
nc -> nc.hasCapability(NET_CAPABILITY_VALIDATED));
- final NetworkCapabilities nc = mCm.getNetworkCapabilities(vpnNetworkAgent.getNetwork());
+ final NetworkCapabilities nc = mCm.getNetworkCapabilities(mMockVpn.getNetwork());
assertTrue(nc.hasTransport(TRANSPORT_VPN));
assertTrue(nc.hasTransport(TRANSPORT_CELLULAR));
assertFalse(nc.hasTransport(TRANSPORT_WIFI));
@@ -5517,18 +5688,11 @@ public class ConnectivityServiceTest {
mCm.registerNetworkCallback(vpnNetworkRequest, vpnNetworkCallback);
vpnNetworkCallback.assertNoCallback();
- final TestNetworkAgentWrapper
- vpnNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_VPN);
- final ArraySet<UidRange> ranges = new ArraySet<>();
- ranges.add(new UidRange(uid, uid));
- mMockVpn.setNetworkAgent(vpnNetworkAgent);
- mMockVpn.connect();
- mMockVpn.setUids(ranges);
- vpnNetworkAgent.connect(true /* validated */, false /* hasInternet */,
+ mMockVpn.establishForMyUid(true /* validated */, false /* hasInternet */,
false /* isStrictMode */);
- vpnNetworkCallback.expectAvailableThenValidatedCallbacks(vpnNetworkAgent);
- nc = mCm.getNetworkCapabilities(vpnNetworkAgent.getNetwork());
+ vpnNetworkCallback.expectAvailableThenValidatedCallbacks(mMockVpn);
+ nc = mCm.getNetworkCapabilities(mMockVpn.getNetwork());
assertTrue(nc.hasTransport(TRANSPORT_VPN));
assertFalse(nc.hasTransport(TRANSPORT_CELLULAR));
assertFalse(nc.hasTransport(TRANSPORT_WIFI));
@@ -5545,7 +5709,7 @@ public class ConnectivityServiceTest {
mService.setUnderlyingNetworksForVpn(
new Network[] { mCellNetworkAgent.getNetwork() });
- vpnNetworkCallback.expectCapabilitiesThat(vpnNetworkAgent,
+ vpnNetworkCallback.expectCapabilitiesThat(mMockVpn,
(caps) -> caps.hasTransport(TRANSPORT_VPN)
&& caps.hasTransport(TRANSPORT_CELLULAR) && !caps.hasTransport(TRANSPORT_WIFI)
&& !caps.hasCapability(NET_CAPABILITY_NOT_METERED)
@@ -5559,7 +5723,7 @@ public class ConnectivityServiceTest {
mService.setUnderlyingNetworksForVpn(
new Network[] { mCellNetworkAgent.getNetwork(), mWiFiNetworkAgent.getNetwork() });
- vpnNetworkCallback.expectCapabilitiesThat(vpnNetworkAgent,
+ vpnNetworkCallback.expectCapabilitiesThat(mMockVpn,
(caps) -> caps.hasTransport(TRANSPORT_VPN)
&& caps.hasTransport(TRANSPORT_CELLULAR) && caps.hasTransport(TRANSPORT_WIFI)
&& !caps.hasCapability(NET_CAPABILITY_NOT_METERED)
@@ -5569,7 +5733,7 @@ public class ConnectivityServiceTest {
mService.setUnderlyingNetworksForVpn(
new Network[] { mCellNetworkAgent.getNetwork() });
- vpnNetworkCallback.expectCapabilitiesThat(vpnNetworkAgent,
+ vpnNetworkCallback.expectCapabilitiesThat(mMockVpn,
(caps) -> caps.hasTransport(TRANSPORT_VPN)
&& caps.hasTransport(TRANSPORT_CELLULAR) && !caps.hasTransport(TRANSPORT_WIFI)
&& !caps.hasCapability(NET_CAPABILITY_NOT_METERED)
@@ -5577,27 +5741,27 @@ public class ConnectivityServiceTest {
// Remove NOT_SUSPENDED from the only network and observe VPN is now suspended.
mCellNetworkAgent.removeCapability(NET_CAPABILITY_NOT_SUSPENDED);
- vpnNetworkCallback.expectCapabilitiesThat(vpnNetworkAgent,
+ vpnNetworkCallback.expectCapabilitiesThat(mMockVpn,
(caps) -> caps.hasTransport(TRANSPORT_VPN)
&& caps.hasTransport(TRANSPORT_CELLULAR) && !caps.hasTransport(TRANSPORT_WIFI)
&& !caps.hasCapability(NET_CAPABILITY_NOT_METERED)
&& !caps.hasCapability(NET_CAPABILITY_NOT_SUSPENDED));
- vpnNetworkCallback.expectCallback(CallbackEntry.SUSPENDED, vpnNetworkAgent);
+ vpnNetworkCallback.expectCallback(CallbackEntry.SUSPENDED, mMockVpn);
// Add NOT_SUSPENDED again and observe VPN is no longer suspended.
mCellNetworkAgent.addCapability(NET_CAPABILITY_NOT_SUSPENDED);
- vpnNetworkCallback.expectCapabilitiesThat(vpnNetworkAgent,
+ vpnNetworkCallback.expectCapabilitiesThat(mMockVpn,
(caps) -> caps.hasTransport(TRANSPORT_VPN)
&& caps.hasTransport(TRANSPORT_CELLULAR) && !caps.hasTransport(TRANSPORT_WIFI)
&& !caps.hasCapability(NET_CAPABILITY_NOT_METERED)
&& caps.hasCapability(NET_CAPABILITY_NOT_SUSPENDED));
- vpnNetworkCallback.expectCallback(CallbackEntry.RESUMED, vpnNetworkAgent);
+ vpnNetworkCallback.expectCallback(CallbackEntry.RESUMED, mMockVpn);
// Use Wifi but not cell. Note the VPN is now unmetered and not suspended.
mService.setUnderlyingNetworksForVpn(
new Network[] { mWiFiNetworkAgent.getNetwork() });
- vpnNetworkCallback.expectCapabilitiesThat(vpnNetworkAgent,
+ vpnNetworkCallback.expectCapabilitiesThat(mMockVpn,
(caps) -> caps.hasTransport(TRANSPORT_VPN)
&& !caps.hasTransport(TRANSPORT_CELLULAR) && caps.hasTransport(TRANSPORT_WIFI)
&& caps.hasCapability(NET_CAPABILITY_NOT_METERED)
@@ -5607,7 +5771,7 @@ public class ConnectivityServiceTest {
mService.setUnderlyingNetworksForVpn(
new Network[] { mCellNetworkAgent.getNetwork(), mWiFiNetworkAgent.getNetwork() });
- vpnNetworkCallback.expectCapabilitiesThat(vpnNetworkAgent,
+ vpnNetworkCallback.expectCapabilitiesThat(mMockVpn,
(caps) -> caps.hasTransport(TRANSPORT_VPN)
&& caps.hasTransport(TRANSPORT_CELLULAR) && caps.hasTransport(TRANSPORT_WIFI)
&& !caps.hasCapability(NET_CAPABILITY_NOT_METERED)
@@ -5620,7 +5784,7 @@ public class ConnectivityServiceTest {
// Stop using WiFi. The VPN is suspended again.
mService.setUnderlyingNetworksForVpn(
new Network[] { mCellNetworkAgent.getNetwork() });
- vpnNetworkCallback.expectCapabilitiesThat(vpnNetworkAgent,
+ vpnNetworkCallback.expectCapabilitiesThat(mMockVpn,
(caps) -> caps.hasTransport(TRANSPORT_VPN)
&& caps.hasTransport(TRANSPORT_CELLULAR)
&& !caps.hasCapability(NET_CAPABILITY_NOT_METERED)
@@ -5634,7 +5798,7 @@ public class ConnectivityServiceTest {
mService.setUnderlyingNetworksForVpn(
new Network[] { mCellNetworkAgent.getNetwork(), mWiFiNetworkAgent.getNetwork() });
- vpnNetworkCallback.expectCapabilitiesThat(vpnNetworkAgent,
+ vpnNetworkCallback.expectCapabilitiesThat(mMockVpn,
(caps) -> caps.hasTransport(TRANSPORT_VPN)
&& caps.hasTransport(TRANSPORT_CELLULAR) && caps.hasTransport(TRANSPORT_WIFI)
&& !caps.hasCapability(NET_CAPABILITY_NOT_METERED)
@@ -5645,14 +5809,14 @@ public class ConnectivityServiceTest {
// Disconnect cell. Receive update without even removing the dead network from the
// underlying networks – it's dead anyway. Not metered any more.
mCellNetworkAgent.disconnect();
- vpnNetworkCallback.expectCapabilitiesThat(vpnNetworkAgent,
+ vpnNetworkCallback.expectCapabilitiesThat(mMockVpn,
(caps) -> caps.hasTransport(TRANSPORT_VPN)
&& !caps.hasTransport(TRANSPORT_CELLULAR) && caps.hasTransport(TRANSPORT_WIFI)
&& caps.hasCapability(NET_CAPABILITY_NOT_METERED));
// Disconnect wifi too. No underlying networks means this is now metered.
mWiFiNetworkAgent.disconnect();
- vpnNetworkCallback.expectCapabilitiesThat(vpnNetworkAgent,
+ vpnNetworkCallback.expectCapabilitiesThat(mMockVpn,
(caps) -> caps.hasTransport(TRANSPORT_VPN)
&& !caps.hasTransport(TRANSPORT_CELLULAR) && !caps.hasTransport(TRANSPORT_WIFI)
&& !caps.hasCapability(NET_CAPABILITY_NOT_METERED));
@@ -5673,18 +5837,11 @@ public class ConnectivityServiceTest {
mCm.registerNetworkCallback(vpnNetworkRequest, vpnNetworkCallback);
vpnNetworkCallback.assertNoCallback();
- final TestNetworkAgentWrapper
- vpnNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_VPN);
- final ArraySet<UidRange> ranges = new ArraySet<>();
- ranges.add(new UidRange(uid, uid));
- mMockVpn.setNetworkAgent(vpnNetworkAgent);
- mMockVpn.connect();
- mMockVpn.setUids(ranges);
- vpnNetworkAgent.connect(true /* validated */, false /* hasInternet */,
+ mMockVpn.establishForMyUid(true /* validated */, false /* hasInternet */,
false /* isStrictMode */);
- vpnNetworkCallback.expectAvailableThenValidatedCallbacks(vpnNetworkAgent);
- nc = mCm.getNetworkCapabilities(vpnNetworkAgent.getNetwork());
+ vpnNetworkCallback.expectAvailableThenValidatedCallbacks(mMockVpn);
+ nc = mCm.getNetworkCapabilities(mMockVpn.getNetwork());
assertTrue(nc.hasTransport(TRANSPORT_VPN));
assertFalse(nc.hasTransport(TRANSPORT_CELLULAR));
assertFalse(nc.hasTransport(TRANSPORT_WIFI));
@@ -5696,7 +5853,7 @@ public class ConnectivityServiceTest {
mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
mCellNetworkAgent.connect(true);
- vpnNetworkCallback.expectCapabilitiesThat(vpnNetworkAgent,
+ vpnNetworkCallback.expectCapabilitiesThat(mMockVpn,
(caps) -> caps.hasTransport(TRANSPORT_VPN)
&& caps.hasTransport(TRANSPORT_CELLULAR) && !caps.hasTransport(TRANSPORT_WIFI)
&& !caps.hasCapability(NET_CAPABILITY_NOT_METERED));
@@ -5706,7 +5863,7 @@ public class ConnectivityServiceTest {
mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
mWiFiNetworkAgent.connect(true);
- vpnNetworkCallback.expectCapabilitiesThat(vpnNetworkAgent,
+ vpnNetworkCallback.expectCapabilitiesThat(mMockVpn,
(caps) -> caps.hasTransport(TRANSPORT_VPN)
&& !caps.hasTransport(TRANSPORT_CELLULAR) && caps.hasTransport(TRANSPORT_WIFI)
&& caps.hasCapability(NET_CAPABILITY_NOT_METERED));
@@ -5718,7 +5875,7 @@ public class ConnectivityServiceTest {
// Disconnect wifi too. Now we have no default network.
mWiFiNetworkAgent.disconnect();
- vpnNetworkCallback.expectCapabilitiesThat(vpnNetworkAgent,
+ vpnNetworkCallback.expectCapabilitiesThat(mMockVpn,
(caps) -> caps.hasTransport(TRANSPORT_VPN)
&& !caps.hasTransport(TRANSPORT_CELLULAR) && !caps.hasTransport(TRANSPORT_WIFI)
&& !caps.hasCapability(NET_CAPABILITY_NOT_METERED));
@@ -5761,18 +5918,10 @@ public class ConnectivityServiceTest {
assertTrue(mCm.isActiveNetworkMetered());
// Connect VPN network. By default it is using current default network (Cell).
- TestNetworkAgentWrapper
- vpnNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_VPN);
- final ArraySet<UidRange> ranges = new ArraySet<>();
- final int uid = Process.myUid();
- ranges.add(new UidRange(uid, uid));
- mMockVpn.setNetworkAgent(vpnNetworkAgent);
- mMockVpn.setUids(ranges);
- vpnNetworkAgent.connect(true);
- mMockVpn.connect();
- waitForIdle();
+ mMockVpn.establishForMyUid();
+
// Ensure VPN is now the active network.
- assertEquals(vpnNetworkAgent.getNetwork(), mCm.getActiveNetwork());
+ assertEquals(mMockVpn.getNetwork(), mCm.getActiveNetwork());
// Expect VPN to be metered.
assertTrue(mCm.isActiveNetworkMetered());
@@ -5783,7 +5932,7 @@ public class ConnectivityServiceTest {
mWiFiNetworkAgent.connect(true);
waitForIdle();
// VPN should still be the active network.
- assertEquals(vpnNetworkAgent.getNetwork(), mCm.getActiveNetwork());
+ assertEquals(mMockVpn.getNetwork(), mCm.getActiveNetwork());
// Expect VPN to be unmetered as it should now be using WiFi (new default).
assertFalse(mCm.isActiveNetworkMetered());
@@ -5801,7 +5950,6 @@ public class ConnectivityServiceTest {
// VPN without any underlying networks is treated as metered.
assertTrue(mCm.isActiveNetworkMetered());
- vpnNetworkAgent.disconnect();
mMockVpn.disconnect();
}
@@ -5822,18 +5970,10 @@ public class ConnectivityServiceTest {
assertFalse(mCm.isActiveNetworkMetered());
// Connect VPN network.
- TestNetworkAgentWrapper
- vpnNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_VPN);
- final ArraySet<UidRange> ranges = new ArraySet<>();
- final int uid = Process.myUid();
- ranges.add(new UidRange(uid, uid));
- mMockVpn.setNetworkAgent(vpnNetworkAgent);
- mMockVpn.setUids(ranges);
- vpnNetworkAgent.connect(true);
- mMockVpn.connect();
- waitForIdle();
+ mMockVpn.establishForMyUid();
+
// Ensure VPN is now the active network.
- assertEquals(vpnNetworkAgent.getNetwork(), mCm.getActiveNetwork());
+ assertEquals(mMockVpn.getNetwork(), mCm.getActiveNetwork());
// VPN is using Cell
mService.setUnderlyingNetworksForVpn(
new Network[] { mCellNetworkAgent.getNetwork() });
@@ -5873,7 +6013,6 @@ public class ConnectivityServiceTest {
// VPN without underlying networks is treated as metered.
assertTrue(mCm.isActiveNetworkMetered());
- vpnNetworkAgent.disconnect();
mMockVpn.disconnect();
}
@@ -5888,17 +6027,11 @@ public class ConnectivityServiceTest {
assertFalse(mCm.isActiveNetworkMetered());
// Connect VPN network.
- TestNetworkAgentWrapper
- vpnNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_VPN);
- final ArraySet<UidRange> ranges = new ArraySet<>();
- final int uid = Process.myUid();
- ranges.add(new UidRange(uid, uid));
- mMockVpn.setNetworkAgent(vpnNetworkAgent);
- mMockVpn.setUids(ranges);
- vpnNetworkAgent.connect(true);
- mMockVpn.connectAsAlwaysMetered();
+ mMockVpn.registerAgent(true /* isAlwaysMetered */, uidRangesForUid(Process.myUid()),
+ new LinkProperties());
+ mMockVpn.connect(true);
waitForIdle();
- assertEquals(vpnNetworkAgent.getNetwork(), mCm.getActiveNetwork());
+ assertEquals(mMockVpn.getNetwork(), mCm.getActiveNetwork());
// VPN is tracking current platform default (WiFi).
mService.setUnderlyingNetworksForVpn(null);
@@ -5922,7 +6055,7 @@ public class ConnectivityServiceTest {
assertTrue(mCm.isActiveNetworkMetered());
- vpnNetworkAgent.disconnect();
+ mMockVpn.disconnect();
}
@Test
@@ -6654,34 +6787,21 @@ public class ConnectivityServiceTest {
waitForIdle();
assertNull(mService.getProxyForNetwork(null));
- // Set up a VPN network with a proxy
- final int uid = Process.myUid();
- final TestNetworkAgentWrapper
- vpnNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_VPN);
- final ArraySet<UidRange> ranges = new ArraySet<>();
- ranges.add(new UidRange(uid, uid));
- mMockVpn.setUids(ranges);
+ // Connect a VPN network with a proxy.
LinkProperties testLinkProperties = new LinkProperties();
testLinkProperties.setHttpProxy(testProxyInfo);
- vpnNetworkAgent.sendLinkProperties(testLinkProperties);
- waitForIdle();
-
- // Connect to VPN with proxy
- mMockVpn.setNetworkAgent(vpnNetworkAgent);
- vpnNetworkAgent.connect(true);
- mMockVpn.connect();
- waitForIdle();
+ mMockVpn.establishForMyUid(testLinkProperties);
// Test that the VPN network returns a proxy, and the WiFi does not.
- assertEquals(testProxyInfo, mService.getProxyForNetwork(vpnNetworkAgent.getNetwork()));
+ assertEquals(testProxyInfo, mService.getProxyForNetwork(mMockVpn.getNetwork()));
assertEquals(testProxyInfo, mService.getProxyForNetwork(null));
assertNull(mService.getProxyForNetwork(mWiFiNetworkAgent.getNetwork()));
// Test that the VPN network returns no proxy when it is set to null.
testLinkProperties.setHttpProxy(null);
- vpnNetworkAgent.sendLinkProperties(testLinkProperties);
+ mMockVpn.sendLinkProperties(testLinkProperties);
waitForIdle();
- assertNull(mService.getProxyForNetwork(vpnNetworkAgent.getNetwork()));
+ assertNull(mService.getProxyForNetwork(mMockVpn.getNetwork()));
assertNull(mService.getProxyForNetwork(null));
// Set WiFi proxy and check that the vpn proxy is still null.
@@ -6692,7 +6812,7 @@ public class ConnectivityServiceTest {
// Disconnect from VPN and check that the active network, which is now the WiFi, has the
// correct proxy setting.
- vpnNetworkAgent.disconnect();
+ mMockVpn.disconnect();
waitForIdle();
assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
assertEquals(testProxyInfo, mService.getProxyForNetwork(mWiFiNetworkAgent.getNetwork()));
@@ -6707,7 +6827,7 @@ public class ConnectivityServiceTest {
lp.addRoute(new RouteInfo(new IpPrefix(Inet6Address.ANY, 0), RTN_UNREACHABLE));
// The uid range needs to cover the test app so the network is visible to it.
final Set<UidRange> vpnRange = Collections.singleton(UidRange.createForUser(VPN_USER));
- final TestNetworkAgentWrapper vpnNetworkAgent = establishVpn(lp, VPN_UID, vpnRange);
+ mMockVpn.establish(lp, VPN_UID, vpnRange);
// Connected VPN should have interface rules set up. There are two expected invocations,
// one during VPN uid update, one during VPN LinkProperties update
@@ -6717,7 +6837,7 @@ public class ConnectivityServiceTest {
assertContainsExactly(uidCaptor.getAllValues().get(1), APP1_UID, APP2_UID);
assertTrue(mService.mPermissionMonitor.getVpnUidRanges("tun0").equals(vpnRange));
- vpnNetworkAgent.disconnect();
+ mMockVpn.disconnect();
waitForIdle();
// Disconnected VPN should have interface rules removed
@@ -6734,8 +6854,7 @@ public class ConnectivityServiceTest {
lp.addRoute(new RouteInfo(new IpPrefix(Inet4Address.ANY, 0), null));
// The uid range needs to cover the test app so the network is visible to it.
final Set<UidRange> vpnRange = Collections.singleton(UidRange.createForUser(VPN_USER));
- final TestNetworkAgentWrapper vpnNetworkAgent = establishVpn(
- lp, Process.SYSTEM_UID, vpnRange);
+ mMockVpn.establish(lp, Process.SYSTEM_UID, vpnRange);
// Legacy VPN should not have interface rules set up
verify(mMockNetd, never()).firewallAddUidInterfaceRules(any(), any());
@@ -6750,8 +6869,7 @@ public class ConnectivityServiceTest {
lp.addRoute(new RouteInfo(new IpPrefix(Inet6Address.ANY, 0), RTN_UNREACHABLE));
// The uid range needs to cover the test app so the network is visible to it.
final Set<UidRange> vpnRange = Collections.singleton(UidRange.createForUser(VPN_USER));
- final TestNetworkAgentWrapper vpnNetworkAgent = establishVpn(
- lp, Process.SYSTEM_UID, vpnRange);
+ mMockVpn.establish(lp, Process.SYSTEM_UID, vpnRange);
// IPv6 unreachable route should not be misinterpreted as a default route
verify(mMockNetd, never()).firewallAddUidInterfaceRules(any(), any());
@@ -6765,7 +6883,7 @@ public class ConnectivityServiceTest {
lp.addRoute(new RouteInfo(new IpPrefix(Inet6Address.ANY, 0), null));
// The uid range needs to cover the test app so the network is visible to it.
final Set<UidRange> vpnRange = Collections.singleton(UidRange.createForUser(VPN_USER));
- final TestNetworkAgentWrapper vpnNetworkAgent = establishVpn(lp, VPN_UID, vpnRange);
+ mMockVpn.establish(lp, VPN_UID, vpnRange);
// Connected VPN should have interface rules set up. There are two expected invocations,
// one during VPN uid update, one during VPN LinkProperties update
@@ -6777,7 +6895,7 @@ public class ConnectivityServiceTest {
reset(mMockNetd);
InOrder inOrder = inOrder(mMockNetd);
lp.setInterfaceName("tun1");
- vpnNetworkAgent.sendLinkProperties(lp);
+ mMockVpn.sendLinkProperties(lp);
waitForIdle();
// VPN handover (switch to a new interface) should result in rules being updated (old rules
// removed first, then new rules added)
@@ -6790,7 +6908,7 @@ public class ConnectivityServiceTest {
lp = new LinkProperties();
lp.setInterfaceName("tun1");
lp.addRoute(new RouteInfo(new IpPrefix("192.0.2.0/24"), null, "tun1"));
- vpnNetworkAgent.sendLinkProperties(lp);
+ mMockVpn.sendLinkProperties(lp);
waitForIdle();
// VPN not routing everything should no longer have interface filtering rules
verify(mMockNetd).firewallRemoveUidInterfaceRules(uidCaptor.capture());
@@ -6801,7 +6919,7 @@ public class ConnectivityServiceTest {
lp.setInterfaceName("tun1");
lp.addRoute(new RouteInfo(new IpPrefix(Inet4Address.ANY, 0), RTN_UNREACHABLE));
lp.addRoute(new RouteInfo(new IpPrefix(Inet6Address.ANY, 0), null));
- vpnNetworkAgent.sendLinkProperties(lp);
+ mMockVpn.sendLinkProperties(lp);
waitForIdle();
// Back to routing all IPv6 traffic should have filtering rules
verify(mMockNetd).firewallAddUidInterfaceRules(eq("tun1"), uidCaptor.capture());
@@ -6816,8 +6934,7 @@ public class ConnectivityServiceTest {
lp.addRoute(new RouteInfo(new IpPrefix(Inet6Address.ANY, 0), null));
// The uid range needs to cover the test app so the network is visible to it.
final UidRange vpnRange = UidRange.createForUser(VPN_USER);
- final TestNetworkAgentWrapper vpnNetworkAgent = establishVpn(lp, VPN_UID,
- Collections.singleton(vpnRange));
+ mMockVpn.establish(lp, VPN_UID, Collections.singleton(vpnRange));
reset(mMockNetd);
InOrder inOrder = inOrder(mMockNetd);
@@ -6826,7 +6943,7 @@ public class ConnectivityServiceTest {
final Set<UidRange> newRanges = new HashSet<>(Arrays.asList(
new UidRange(vpnRange.start, APP1_UID - 1),
new UidRange(APP1_UID + 1, vpnRange.stop)));
- vpnNetworkAgent.setUids(newRanges);
+ mMockVpn.setUids(newRanges);
waitForIdle();
ArgumentCaptor<int[]> uidCaptor = ArgumentCaptor.forClass(int[].class);
@@ -6967,7 +7084,7 @@ public class ConnectivityServiceTest {
private void setupConnectionOwnerUid(int vpnOwnerUid, @VpnManager.VpnType int vpnType)
throws Exception {
final Set<UidRange> vpnRange = Collections.singleton(UidRange.createForUser(VPN_USER));
- establishVpn(new LinkProperties(), vpnOwnerUid, vpnRange);
+ mMockVpn.establish(new LinkProperties(), vpnOwnerUid, vpnRange);
mMockVpn.setVpnType(vpnType);
final VpnInfo vpnInfo = new VpnInfo();
@@ -7048,19 +7165,6 @@ public class ConnectivityServiceTest {
mService.getConnectionOwnerUid(getTestConnectionInfo());
}
- private TestNetworkAgentWrapper establishVpn(
- LinkProperties lp, int ownerUid, Set<UidRange> vpnRange) throws Exception {
- final TestNetworkAgentWrapper
- vpnNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_VPN, lp);
- vpnNetworkAgent.getNetworkCapabilities().setOwnerUid(ownerUid);
- mMockVpn.setNetworkAgent(vpnNetworkAgent);
- mMockVpn.connect();
- mMockVpn.setUids(vpnRange);
- vpnNetworkAgent.connect(true);
- waitForIdle();
- return vpnNetworkAgent;
- }
-
private static PackageInfo buildPackageInfo(boolean hasSystemPermission, int uid) {
final PackageInfo packageInfo = new PackageInfo();
if (hasSystemPermission) {
@@ -7240,22 +7344,28 @@ public class ConnectivityServiceTest {
setupLocationPermissions(Build.VERSION_CODES.Q, true, AppOpsManager.OPSTR_FINE_LOCATION,
Manifest.permission.ACCESS_FINE_LOCATION);
- mServiceContext.setPermission(android.Manifest.permission.NETWORK_STACK, PERMISSION_DENIED);
// setUp() calls mockVpn() which adds a VPN with the Test Runner's uid. Configure it to be
// active
final VpnInfo info = new VpnInfo();
info.ownerUid = Process.myUid();
- info.vpnIface = "interface";
+ info.vpnIface = VPN_IFNAME;
mMockVpn.setVpnInfo(info);
- mMockVpn.overrideUnderlyingNetworks(new Network[] {network});
+
+ mMockVpn.establishForMyUid();
+ waitForIdle();
+
+ mServiceContext.setPermission(android.Manifest.permission.NETWORK_STACK, PERMISSION_DENIED);
+
+
+ assertTrue(mService.setUnderlyingNetworksForVpn(new Network[] {network}));
assertTrue(
"Active VPN permission not applied",
mService.checkConnectivityDiagnosticsPermissions(
Process.myPid(), Process.myUid(), naiWithoutUid,
mContext.getOpPackageName()));
- mMockVpn.overrideUnderlyingNetworks(null);
+ assertTrue(mService.setUnderlyingNetworksForVpn(null));
assertFalse(
"VPN shouldn't receive callback on non-underlying network",
mService.checkConnectivityDiagnosticsPermissions(
@@ -7276,8 +7386,6 @@ public class ConnectivityServiceTest {
Manifest.permission.ACCESS_FINE_LOCATION);
mServiceContext.setPermission(android.Manifest.permission.NETWORK_STACK, PERMISSION_DENIED);
- // Disconnect mock vpn so the uid check on NetworkAgentInfo is tested
- mMockVpn.disconnect();
assertTrue(
"NetworkCapabilities administrator uid permission not applied",
mService.checkConnectivityDiagnosticsPermissions(
@@ -7480,4 +7588,39 @@ public class ConnectivityServiceTest {
mCm.unregisterNetworkCallback(networkCallback);
}
+
+ @Test
+ public void testDumpDoesNotCrash() {
+ StringWriter stringWriter = new StringWriter();
+
+ mService.dump(new FileDescriptor(), new PrintWriter(stringWriter), new String[0]);
+
+ assertFalse(stringWriter.toString().isEmpty());
+ }
+
+ @Test
+ public void testRequestsSortedByIdSortsCorrectly() {
+ final TestNetworkCallback genericNetworkCallback = new TestNetworkCallback();
+ final TestNetworkCallback wifiNetworkCallback = new TestNetworkCallback();
+ final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
+ final NetworkRequest genericRequest = new NetworkRequest.Builder()
+ .clearCapabilities().build();
+ final NetworkRequest wifiRequest = new NetworkRequest.Builder()
+ .addTransportType(TRANSPORT_WIFI).build();
+ final NetworkRequest cellRequest = new NetworkRequest.Builder()
+ .addTransportType(TRANSPORT_CELLULAR).build();
+ mCm.registerNetworkCallback(genericRequest, genericNetworkCallback);
+ mCm.registerNetworkCallback(wifiRequest, wifiNetworkCallback);
+ mCm.registerNetworkCallback(cellRequest, cellNetworkCallback);
+
+ ConnectivityService.NetworkRequestInfo[] nriOutput = mService.requestsSortedById();
+
+ assertTrue(nriOutput.length > 1);
+ for (int i = 0; i < nriOutput.length - 1; i++) {
+ boolean isRequestIdInOrder =
+ nriOutput[i].mRequests.get(0).requestId
+ < nriOutput[i + 1].mRequests.get(0).requestId;
+ assertTrue(isRequestIdInOrder);
+ }
+ }
}
diff --git a/tools/aapt2/cmd/Link.cpp b/tools/aapt2/cmd/Link.cpp
index f92c602fd761..b760958e0edc 100644
--- a/tools/aapt2/cmd/Link.cpp
+++ b/tools/aapt2/cmd/Link.cpp
@@ -1568,6 +1568,22 @@ class Linker {
return true;
}
+ ResourceEntry* ResolveTableEntry(LinkContext* context, ResourceTable* table,
+ Reference* reference) {
+ if (!reference || !reference->name) {
+ return nullptr;
+ }
+ auto name_ref = ResourceNameRef(reference->name.value());
+ if (name_ref.package.empty()) {
+ name_ref.package = context->GetCompilationPackage();
+ }
+ const auto search_result = table->FindResource(name_ref);
+ if (!search_result) {
+ return nullptr;
+ }
+ return search_result.value().entry;
+ }
+
void AliasAdaptiveIcon(xml::XmlResource* manifest, ResourceTable* table) {
const xml::Element* application = manifest->root->FindChild("", "application");
if (!application) {
@@ -1582,22 +1598,13 @@ class Linker {
// Find the icon resource defined within the application.
const auto icon_reference = ValueCast<Reference>(icon->compiled_value.get());
- if (!icon_reference || !icon_reference->name) {
- return;
- }
-
- auto icon_name = ResourceNameRef(icon_reference->name.value());
- if (icon_name.package.empty()) {
- icon_name.package = context_->GetCompilationPackage();
- }
-
- const auto icon_entry_result = table->FindResource(icon_name);
- if (!icon_entry_result) {
+ const auto icon_entry = ResolveTableEntry(context_, table, icon_reference);
+ if (!icon_entry) {
return;
}
int icon_max_sdk = 0;
- for (auto& config_value : icon_entry_result.value().entry->values) {
+ for (auto& config_value : icon_entry->values) {
icon_max_sdk = (icon_max_sdk < config_value->config.sdkVersion)
? config_value->config.sdkVersion : icon_max_sdk;
}
@@ -1608,22 +1615,13 @@ class Linker {
// Find the roundIcon resource defined within the application.
const auto round_icon_reference = ValueCast<Reference>(round_icon->compiled_value.get());
- if (!round_icon_reference || !round_icon_reference->name) {
- return;
- }
-
- auto round_icon_name = ResourceNameRef(round_icon_reference->name.value());
- if (round_icon_name.package.empty()) {
- round_icon_name.package = context_->GetCompilationPackage();
- }
-
- const auto round_icon_entry_result = table->FindResource(round_icon_name);
- if (!round_icon_entry_result) {
+ const auto round_icon_entry = ResolveTableEntry(context_, table, round_icon_reference);
+ if (!round_icon_entry) {
return;
}
int round_icon_max_sdk = 0;
- for (auto& config_value : round_icon_entry_result.value().entry->values) {
+ for (auto& config_value : round_icon_entry->values) {
round_icon_max_sdk = (round_icon_max_sdk < config_value->config.sdkVersion)
? config_value->config.sdkVersion : round_icon_max_sdk;
}
@@ -1634,7 +1632,7 @@ class Linker {
}
// Add an equivalent v26 entry to the roundIcon for each v26 variant of the regular icon.
- for (auto& config_value : icon_entry_result.value().entry->values) {
+ for (auto& config_value : icon_entry->values) {
if (config_value->config.sdkVersion < SDK_O) {
continue;
}
@@ -1645,12 +1643,62 @@ class Linker {
<< "\" for round icon compatibility");
auto value = icon_reference->Clone(&table->string_pool);
- auto round_config_value = round_icon_entry_result.value().entry->FindOrCreateValue(
- config_value->config, config_value->product);
+ auto round_config_value =
+ round_icon_entry->FindOrCreateValue(config_value->config, config_value->product);
round_config_value->value.reset(value);
}
}
+ bool VerifySharedUserId(xml::XmlResource* manifest, ResourceTable* table) {
+ const xml::Element* manifest_el = xml::FindRootElement(manifest->root.get());
+ if (manifest_el == nullptr) {
+ return true;
+ }
+ if (!manifest_el->namespace_uri.empty() || manifest_el->name != "manifest") {
+ return true;
+ }
+ const xml::Attribute* attr = manifest_el->FindAttribute(xml::kSchemaAndroid, "sharedUserId");
+ if (!attr) {
+ return true;
+ }
+ const auto validate = [&](const std::string& shared_user_id) -> bool {
+ if (util::IsAndroidSharedUserId(context_->GetCompilationPackage(), shared_user_id)) {
+ return true;
+ }
+ DiagMessage error_msg(manifest_el->line_number);
+ error_msg << "attribute 'sharedUserId' in <manifest> tag is not a valid shared user id: '"
+ << shared_user_id << "'";
+ if (options_.manifest_fixer_options.warn_validation) {
+ // Treat the error only as a warning.
+ context_->GetDiagnostics()->Warn(error_msg);
+ return true;
+ }
+ context_->GetDiagnostics()->Error(error_msg);
+ return false;
+ };
+ // If attr->compiled_value is not null, check if it is a ref
+ if (attr->compiled_value) {
+ const auto ref = ValueCast<Reference>(attr->compiled_value.get());
+ if (ref == nullptr) {
+ return true;
+ }
+ const auto shared_user_id_entry = ResolveTableEntry(context_, table, ref);
+ if (!shared_user_id_entry) {
+ return true;
+ }
+ for (const auto& value : shared_user_id_entry->values) {
+ const auto str_value = ValueCast<String>(value->value.get());
+ if (str_value != nullptr && !validate(*str_value->value)) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ // Fallback to checking the raw value
+ return validate(attr->value);
+ }
+
// Writes the AndroidManifest, ResourceTable, and all XML files referenced by the ResourceTable
// to the IArchiveWriter.
bool WriteApk(IArchiveWriter* writer, proguard::KeepSet* keep_set, xml::XmlResource* manifest,
@@ -1672,6 +1720,11 @@ class Linker {
// See (b/34829129)
AliasAdaptiveIcon(manifest, table);
+ // Verify the shared user id here to handle the case of reference value.
+ if (!VerifySharedUserId(manifest, table)) {
+ return false;
+ }
+
ResourceFileFlattenerOptions file_flattener_options;
file_flattener_options.keep_raw_values = keep_raw_values;
file_flattener_options.do_not_compress_anything = options_.do_not_compress_anything;
diff --git a/tools/aapt2/link/ManifestFixer.cpp b/tools/aapt2/link/ManifestFixer.cpp
index fd3a4c035076..c03661ca2366 100644
--- a/tools/aapt2/link/ManifestFixer.cpp
+++ b/tools/aapt2/link/ManifestFixer.cpp
@@ -163,7 +163,8 @@ static bool AutoGenerateIsFeatureSplit(xml::Element* el, SourcePathDiagnostics*
return true;
}
-static bool VerifyManifest(xml::Element* el, SourcePathDiagnostics* diag) {
+static bool VerifyManifest(xml::Element* el, xml::XmlActionExecutorPolicy policy,
+ SourcePathDiagnostics* diag) {
xml::Attribute* attr = el->FindAttribute({}, "package");
if (!attr) {
diag->Error(DiagMessage(el->line_number)
@@ -174,10 +175,16 @@ static bool VerifyManifest(xml::Element* el, SourcePathDiagnostics* diag) {
<< "attribute 'package' in <manifest> tag must not be a reference");
return false;
} else if (!util::IsAndroidPackageName(attr->value)) {
- diag->Error(DiagMessage(el->line_number)
- << "attribute 'package' in <manifest> tag is not a valid Android package name: '"
- << attr->value << "'");
- return false;
+ DiagMessage error_msg(el->line_number);
+ error_msg << "attribute 'package' in <manifest> tag is not a valid Android package name: '"
+ << attr->value << "'";
+ if (policy == xml::XmlActionExecutorPolicy::kAllowListWarning) {
+ // Treat the error only as a warning.
+ diag->Warn(error_msg);
+ } else {
+ diag->Error(error_msg);
+ return false;
+ }
}
attr = el->FindAttribute({}, "split");
diff --git a/tools/aapt2/util/Util.cpp b/tools/aapt2/util/Util.cpp
index ef33c3463a81..28330db966af 100644
--- a/tools/aapt2/util/Util.cpp
+++ b/tools/aapt2/util/Util.cpp
@@ -38,6 +38,11 @@ using ::android::StringPiece16;
namespace aapt {
namespace util {
+// Package name and shared user id would be used as a part of the file name.
+// Limits size to 223 and reserves 32 for the OS.
+// See frameworks/base/core/java/android/content/pm/parsing/ParsingPackageUtils.java
+constexpr static const size_t kMaxPackageNameSize = 223;
+
static std::vector<std::string> SplitAndTransform(
const StringPiece& str, char sep, const std::function<char(char)>& f) {
std::vector<std::string> parts;
@@ -169,9 +174,21 @@ static int IsAndroidNameImpl(const StringPiece& str) {
}
bool IsAndroidPackageName(const StringPiece& str) {
+ if (str.size() > kMaxPackageNameSize) {
+ return false;
+ }
return IsAndroidNameImpl(str) > 1 || str == "android";
}
+bool IsAndroidSharedUserId(const android::StringPiece& package_name,
+ const android::StringPiece& shared_user_id) {
+ if (shared_user_id.size() > kMaxPackageNameSize) {
+ return false;
+ }
+ return shared_user_id.empty() || IsAndroidNameImpl(shared_user_id) > 1 ||
+ package_name == "android";
+}
+
bool IsAndroidSplitName(const StringPiece& str) {
return IsAndroidNameImpl(str) > 0;
}
diff --git a/tools/aapt2/util/Util.h b/tools/aapt2/util/Util.h
index a956957eace8..c77aca31a810 100644
--- a/tools/aapt2/util/Util.h
+++ b/tools/aapt2/util/Util.h
@@ -81,6 +81,7 @@ bool IsJavaPackageName(const android::StringPiece& str);
// - First character of each component (separated by '.') must be an ASCII letter.
// - Subsequent characters of a component can be ASCII alphanumeric or an underscore.
// - Package must contain at least two components, unless it is 'android'.
+// - The maximum package name length is 223.
bool IsAndroidPackageName(const android::StringPiece& str);
// Tests that the string is a valid Android split name.
@@ -88,6 +89,15 @@ bool IsAndroidPackageName(const android::StringPiece& str);
// - Subsequent characters of a component can be ASCII alphanumeric or an underscore.
bool IsAndroidSplitName(const android::StringPiece& str);
+// Tests that the string is a valid Android shared user id.
+// - First character of each component (separated by '.') must be an ASCII letter.
+// - Subsequent characters of a component can be ASCII alphanumeric or an underscore.
+// - Must contain at least two components, unless package name is 'android'.
+// - The maximum shared user id length is 223.
+// - Treat empty string as valid, it's the case of no shared user id.
+bool IsAndroidSharedUserId(const android::StringPiece& package_name,
+ const android::StringPiece& shared_user_id);
+
// Converts the class name to a fully qualified class name from the given
// `package`. Ex:
//
diff --git a/tools/aapt2/util/Util_test.cpp b/tools/aapt2/util/Util_test.cpp
index d4e3bec24bd1..4ebcb115306f 100644
--- a/tools/aapt2/util/Util_test.cpp
+++ b/tools/aapt2/util/Util_test.cpp
@@ -27,6 +27,17 @@ using ::testing::SizeIs;
namespace aapt {
+// Test that a max package name size 223 is valid.
+static const std::string kMaxPackageName =
+ "com.foo.nameRw8ajIGbYmqPuO0K7TYJFsI2pjlDAS0pYOYQlJvtQux"
+ "SoBKV1hMyNh4XfmcMj8OgPHfFaTXeKEHFMdGQHpw9Dz9Uqr8h1krgJLRv2aXyPCsGdVwBJzfZ4COVRiX3sc9O"
+ "CUrTTvZe6wXlgKb5Qz5qdkTBZ5euzGeoyZwestDTBIgT5exAl5efnznwzceS7VsIntgY10UUQvaoTsLBO6l";
+// Test that a long package name size 224 is invalid.
+static const std::string kLongPackageName =
+ "com.foo.nameRw8ajIGbYmqPuO0K7TYJFsI2pjlDAS0pYOYQlJvtQu"
+ "xSoBKV1hMyNh4XfmcMj8OgPHfFaTXeKEHFMdGQHpw9Dz9Uqr8h1krgJLRv2aXyPCsGdVwBJzfZ4COVRiX3sc9O"
+ "CUrTTvZe6wXlgKb5Qz5qdkTBZ5euzGeoyZwestDTBIgT5exAl5efnznwzceS7VsIntgY10UUQvaoTsLBO6le";
+
TEST(UtilTest, TrimOnlyWhitespace) {
const StringPiece trimmed = util::TrimWhitespace("\n ");
EXPECT_TRUE(trimmed.empty());
@@ -108,6 +119,7 @@ TEST(UtilTest, IsAndroidPackageName) {
EXPECT_TRUE(util::IsAndroidPackageName("com.foo.test_thing"));
EXPECT_TRUE(util::IsAndroidPackageName("com.foo.testing_thing_"));
EXPECT_TRUE(util::IsAndroidPackageName("com.foo.test_99_"));
+ EXPECT_TRUE(util::IsAndroidPackageName(kMaxPackageName));
EXPECT_FALSE(util::IsAndroidPackageName("android._test"));
EXPECT_FALSE(util::IsAndroidPackageName("com"));
@@ -116,6 +128,27 @@ TEST(UtilTest, IsAndroidPackageName) {
EXPECT_FALSE(util::IsAndroidPackageName(".android"));
EXPECT_FALSE(util::IsAndroidPackageName(".."));
EXPECT_FALSE(util::IsAndroidPackageName("cøm.foo"));
+ EXPECT_FALSE(util::IsAndroidPackageName(kLongPackageName));
+}
+
+TEST(UtilTest, IsAndroidSharedUserId) {
+ EXPECT_TRUE(util::IsAndroidSharedUserId("android", "foo"));
+ EXPECT_TRUE(util::IsAndroidSharedUserId("com.foo", "android.test"));
+ EXPECT_TRUE(util::IsAndroidSharedUserId("com.foo", "com.foo"));
+ EXPECT_TRUE(util::IsAndroidSharedUserId("com.foo", "com.foo.test_thing"));
+ EXPECT_TRUE(util::IsAndroidSharedUserId("com.foo", "com.foo.testing_thing_"));
+ EXPECT_TRUE(util::IsAndroidSharedUserId("com.foo", "com.foo.test_99_"));
+ EXPECT_TRUE(util::IsAndroidSharedUserId("com.foo", ""));
+ EXPECT_TRUE(util::IsAndroidSharedUserId("com.foo", kMaxPackageName));
+
+ EXPECT_FALSE(util::IsAndroidSharedUserId("com.foo", "android._test"));
+ EXPECT_FALSE(util::IsAndroidSharedUserId("com.foo", "com"));
+ EXPECT_FALSE(util::IsAndroidSharedUserId("com.foo", "_android"));
+ EXPECT_FALSE(util::IsAndroidSharedUserId("com.foo", "android."));
+ EXPECT_FALSE(util::IsAndroidSharedUserId("com.foo", ".android"));
+ EXPECT_FALSE(util::IsAndroidSharedUserId("com.foo", ".."));
+ EXPECT_FALSE(util::IsAndroidSharedUserId("com.foo", "cøm.foo"));
+ EXPECT_FALSE(util::IsAndroidSharedUserId("com.foo", kLongPackageName));
}
TEST(UtilTest, FullyQualifiedClassName) {
diff --git a/tools/aapt2/xml/XmlActionExecutor.cpp b/tools/aapt2/xml/XmlActionExecutor.cpp
index fab17c949dd8..ea42d26358a8 100644
--- a/tools/aapt2/xml/XmlActionExecutor.cpp
+++ b/tools/aapt2/xml/XmlActionExecutor.cpp
@@ -21,23 +21,34 @@ using ::android::StringPiece;
namespace aapt {
namespace xml {
-static bool wrapper_one(XmlNodeAction::ActionFunc& f, Element* el, SourcePathDiagnostics*) {
+static bool wrapper_one(const XmlNodeAction::ActionFunc& f, Element* el,
+ const XmlActionExecutorPolicy& policy, SourcePathDiagnostics*) {
return f(el);
}
-static bool wrapper_two(XmlNodeAction::ActionFuncWithDiag& f, Element* el,
- SourcePathDiagnostics* diag) {
+static bool wrapper_two(const XmlNodeAction::ActionFuncWithDiag& f, Element* el,
+ const XmlActionExecutorPolicy& policy, SourcePathDiagnostics* diag) {
return f(el, diag);
}
+static bool wrapper_three(const XmlNodeAction::ActionFuncWithPolicyAndDiag& f, Element* el,
+ const XmlActionExecutorPolicy& policy, SourcePathDiagnostics* diag) {
+ return f(el, policy, diag);
+}
+
void XmlNodeAction::Action(XmlNodeAction::ActionFunc f) {
- actions_.emplace_back(std::bind(
- wrapper_one, std::move(f), std::placeholders::_1, std::placeholders::_2));
+ actions_.emplace_back(std::bind(wrapper_one, std::move(f), std::placeholders::_1,
+ std::placeholders::_2, std::placeholders::_3));
}
void XmlNodeAction::Action(XmlNodeAction::ActionFuncWithDiag f) {
- actions_.emplace_back(std::bind(
- wrapper_two, std::move(f), std::placeholders::_1, std::placeholders::_2));
+ actions_.emplace_back(std::bind(wrapper_two, std::move(f), std::placeholders::_1,
+ std::placeholders::_2, std::placeholders::_3));
+}
+
+void XmlNodeAction::Action(XmlNodeAction::ActionFuncWithPolicyAndDiag f) {
+ actions_.emplace_back(std::bind(wrapper_three, std::move(f), std::placeholders::_1,
+ std::placeholders::_2, std::placeholders::_3));
}
static void PrintElementToDiagMessage(const Element* el, DiagMessage* msg) {
@@ -51,8 +62,8 @@ static void PrintElementToDiagMessage(const Element* el, DiagMessage* msg) {
bool XmlNodeAction::Execute(XmlActionExecutorPolicy policy, std::vector<StringPiece>* bread_crumb,
SourcePathDiagnostics* diag, Element* el) const {
bool error = false;
- for (const ActionFuncWithDiag& action : actions_) {
- error |= !action(el, diag);
+ for (const ActionFuncWithPolicyAndDiag& action : actions_) {
+ error |= !action(el, policy, diag);
}
for (Element* child_el : el->GetChildElements()) {
diff --git a/tools/aapt2/xml/XmlActionExecutor.h b/tools/aapt2/xml/XmlActionExecutor.h
index a0ad1dadeddf..78c43345deb7 100644
--- a/tools/aapt2/xml/XmlActionExecutor.h
+++ b/tools/aapt2/xml/XmlActionExecutor.h
@@ -49,6 +49,8 @@ enum class XmlActionExecutorPolicy {
// holds XmlNodeActions for child XML nodes.
class XmlNodeAction {
public:
+ using ActionFuncWithPolicyAndDiag =
+ std::function<bool(Element*, XmlActionExecutorPolicy, SourcePathDiagnostics*)>;
using ActionFuncWithDiag = std::function<bool(Element*, SourcePathDiagnostics*)>;
using ActionFunc = std::function<bool(Element*)>;
@@ -61,6 +63,7 @@ class XmlNodeAction {
// Add an action to be performed at this XmlNodeAction.
void Action(ActionFunc f);
void Action(ActionFuncWithDiag);
+ void Action(ActionFuncWithPolicyAndDiag);
private:
friend class XmlActionExecutor;
@@ -69,7 +72,7 @@ class XmlNodeAction {
SourcePathDiagnostics* diag, Element* el) const;
std::map<std::string, XmlNodeAction> map_;
- std::vector<ActionFuncWithDiag> actions_;
+ std::vector<ActionFuncWithPolicyAndDiag> actions_;
};
// Allows the definition of actions to execute at specific XML elements defined by their hierarchy.
diff --git a/wifi/java/android/net/wifi/SoftApConfiguration.java b/wifi/java/android/net/wifi/SoftApConfiguration.java
index e9d1a008eb5f..9f9d7f3c3051 100644
--- a/wifi/java/android/net/wifi/SoftApConfiguration.java
+++ b/wifi/java/android/net/wifi/SoftApConfiguration.java
@@ -538,7 +538,7 @@ public final class SoftApConfiguration implements Parcelable {
if (!SdkLevel.isAtLeastS()) {
throw new UnsupportedOperationException();
}
- return mChannels;
+ return mChannels.clone();
}
/**