summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--AconfigFlags.bp79
-rw-r--r--Android.bp10
-rw-r--r--apex/blobstore/service/java/com/android/server/blob/BlobStoreManagerService.java3
-rw-r--r--apex/jobscheduler/framework/java/android/os/PowerExemptionManager.java9
-rw-r--r--apex/jobscheduler/service/java/com/android/server/DeviceIdleController.java2
-rw-r--r--apex/jobscheduler/service/java/com/android/server/alarm/MetricsHelper.java4
-rw-r--r--boot/preloaded-classes1
-rw-r--r--cmds/idmap2/libidmap2/RawPrintVisitor.cpp2
-rw-r--r--cmds/idmap2/libidmap2/XmlParser.cpp11
-rw-r--r--config/preloaded-classes1
-rw-r--r--core/api/current.txt736
-rw-r--r--core/api/module-lib-current.txt11
-rw-r--r--core/api/module-lib-lint-baseline.txt12
-rw-r--r--core/api/system-current.txt712
-rw-r--r--core/api/system-lint-baseline.txt10
-rw-r--r--core/api/system-removed.txt14
-rw-r--r--core/api/test-current.txt113
-rw-r--r--core/api/test-lint-baseline.txt52
-rw-r--r--core/java/android/app/AppOps.md4
-rw-r--r--core/java/android/app/AppOpsManager.java20
-rw-r--r--core/java/android/app/IUriGrantsManager.aidl3
-rw-r--r--core/java/android/app/WindowConfiguration.java17
-rw-r--r--core/java/android/app/assist/AssistStructure.java3
-rw-r--r--core/java/android/app/usage/flags.aconfig9
-rw-r--r--core/java/android/companion/virtual/IVirtualDevice.aidl16
-rw-r--r--core/java/android/companion/virtual/IVirtualDeviceListener.aidl35
-rw-r--r--core/java/android/companion/virtual/IVirtualDeviceManager.aidl20
-rw-r--r--core/java/android/companion/virtual/VirtualDevice.java70
-rw-r--r--core/java/android/companion/virtual/VirtualDeviceInternal.java9
-rw-r--r--core/java/android/companion/virtual/VirtualDeviceManager.java174
-rw-r--r--core/java/android/companion/virtual/VirtualDeviceParams.java119
-rw-r--r--core/java/android/companion/virtual/flags.aconfig22
-rw-r--r--core/java/android/content/AttributionSource.java31
-rw-r--r--core/java/android/content/Intent.java10
-rw-r--r--core/java/android/content/pm/ArchivedPackageParcel.aidl37
-rw-r--r--core/java/android/content/pm/IPackageArchiverService.aidl3
-rw-r--r--core/java/android/content/pm/IPackageManager.aidl3
-rw-r--r--core/java/android/content/pm/PackageArchiver.java52
-rw-r--r--core/java/android/content/pm/PackageInfo.java14
-rw-r--r--core/java/android/content/pm/PackageManager.java24
-rw-r--r--core/java/android/content/pm/SigningDetails.aidl (renamed from packages/SystemUI/compose/facade/disabled/src/com/android/systemui/scene/ui/composable/SceneModule.kt)12
-rw-r--r--core/java/android/content/pm/TEST_MAPPING3
-rw-r--r--core/java/android/content/pm/parsing/ApkLite.java130
-rw-r--r--core/java/android/content/pm/parsing/ApkLiteParseUtils.java34
-rw-r--r--core/java/android/content/pm/parsing/PackageLite.java88
-rw-r--r--core/java/android/content/res/ResourcesImpl.java55
-rw-r--r--core/java/android/hardware/camera2/CameraDevice.java88
-rw-r--r--core/java/android/inputmethodservice/InputMethodService.java11
-rw-r--r--core/java/android/inputmethodservice/NavigationBarController.java2
-rw-r--r--core/java/android/location/GeocoderParams.java (renamed from location/java/android/location/GeocoderParams.java)0
-rw-r--r--core/java/android/location/Geofence.java (renamed from location/java/android/location/Geofence.java)0
-rw-r--r--core/java/android/location/GnssSignalQuality.java (renamed from location/java/android/location/GnssSignalQuality.java)0
-rw-r--r--core/java/android/location/IFusedGeofenceHardware.aidl (renamed from location/java/android/location/IFusedGeofenceHardware.aidl)0
-rw-r--r--core/java/android/location/IGpsGeofenceHardware.aidl (renamed from location/java/android/location/IGpsGeofenceHardware.aidl)0
-rw-r--r--core/java/android/location/Location.aidl (renamed from location/java/android/location/Location.aidl)0
-rw-r--r--core/java/android/location/Location.java (renamed from location/java/android/location/Location.java)8
-rw-r--r--core/java/android/location/LocationTime.java (renamed from location/java/android/location/LocationTime.java)0
-rw-r--r--core/java/android/os/AggregateBatteryConsumer.java5
-rw-r--r--core/java/android/os/BatteryConsumer.java5
-rw-r--r--core/java/android/os/BatteryUsageStats.java18
-rw-r--r--core/java/android/os/BatteryUsageStatsQuery.java22
-rw-r--r--core/java/android/os/BugreportParams.java8
-rw-r--r--core/java/android/os/IVibratorManagerService.aidl6
-rw-r--r--core/java/android/os/PowerComponents.java10
-rw-r--r--core/java/android/os/SystemVibrator.java9
-rw-r--r--core/java/android/os/SystemVibratorManager.java20
-rw-r--r--core/java/android/os/UidBatteryConsumer.java13
-rw-r--r--core/java/android/os/UserBatteryConsumer.java4
-rw-r--r--core/java/android/os/UserManager.java19
-rw-r--r--core/java/android/os/Vibrator.java22
-rw-r--r--core/java/android/os/VibratorManager.java18
-rw-r--r--core/java/android/os/vibrator/flags.aconfig15
-rw-r--r--core/java/android/os/vibrator/persistence/ParsedVibration.java2
-rw-r--r--core/java/android/permission/PermissionUsageHelper.java12
-rw-r--r--core/java/android/provider/Settings.java121
-rw-r--r--core/java/android/security/FileIntegrityManager.java8
-rw-r--r--core/java/android/service/trust/OWNERS1
-rw-r--r--core/java/android/service/wallpaper/WallpaperService.java6
-rw-r--r--core/java/android/text/flags/deprecate_fonts_xml.aconfig8
-rw-r--r--core/java/android/text/flags/phrase_strict_fallback.aconfig8
-rw-r--r--core/java/android/util/FeatureFlagUtils.java10
-rw-r--r--core/java/android/view/HandwritingInitiator.java38
-rw-r--r--core/java/android/view/InsetsAnimationControlImpl.java9
-rw-r--r--core/java/android/view/InsetsController.java29
-rw-r--r--core/java/android/view/InsetsState.java35
-rw-r--r--core/java/android/view/View.java182
-rw-r--r--core/java/android/view/ViewRootImpl.java9
-rw-r--r--core/java/android/view/WindowManager.java8
-rw-r--r--core/java/android/view/inputmethod/RemoteInputConnectionImpl.java22
-rw-r--r--core/java/android/view/inputmethod/flags.aconfig8
-rw-r--r--core/java/android/webkit/WebView.java12
-rw-r--r--core/java/android/webkit/WebViewProvider.java10
-rw-r--r--core/java/android/widget/Editor.java19
-rwxr-xr-xcore/java/android/widget/SearchView.java2
-rw-r--r--core/java/android/window/DisplayWindowPolicyController.java38
-rw-r--r--core/java/android/window/WindowMetricsController.java23
-rw-r--r--core/java/android/window/flags/windowing_sdk.aconfig7
-rw-r--r--core/java/com/android/internal/config/sysui/SystemUiDeviceConfigFlags.java5
-rw-r--r--core/java/com/android/internal/content/InstallLocationUtils.java6
-rw-r--r--core/java/com/android/internal/policy/DecorView.java14
-rw-r--r--core/java/com/android/internal/policy/TransitionAnimation.java7
-rw-r--r--core/java/com/android/internal/security/TEST_MAPPING10
-rw-r--r--core/java/com/android/internal/util/SettingsWrapper.java36
-rw-r--r--core/jni/android_media_AudioSystem.cpp167
-rw-r--r--core/res/OWNERS3
-rw-r--r--core/res/res/layout/autofill_fill_dialog.xml17
-rw-r--r--core/res/res/layout/autofill_save.xml17
-rw-r--r--core/res/res/values-af/strings.xml4
-rw-r--r--core/res/res/values-am/strings.xml5
-rw-r--r--core/res/res/values-ar/strings.xml4
-rw-r--r--core/res/res/values-as/strings.xml5
-rw-r--r--core/res/res/values-az/strings.xml4
-rw-r--r--core/res/res/values-b+sr+Latn/strings.xml14
-rw-r--r--core/res/res/values-be/strings.xml17
-rw-r--r--core/res/res/values-bg/strings.xml4
-rw-r--r--core/res/res/values-bn/strings.xml5
-rw-r--r--core/res/res/values-bs/strings.xml4
-rw-r--r--core/res/res/values-ca/strings.xml5
-rw-r--r--core/res/res/values-cs/strings.xml4
-rw-r--r--core/res/res/values-da/strings.xml29
-rw-r--r--core/res/res/values-de/strings.xml17
-rw-r--r--core/res/res/values-el/strings.xml4
-rw-r--r--core/res/res/values-en-rAU/strings.xml4
-rw-r--r--core/res/res/values-en-rCA/strings.xml4
-rw-r--r--core/res/res/values-en-rGB/strings.xml4
-rw-r--r--core/res/res/values-en-rIN/strings.xml4
-rw-r--r--core/res/res/values-en-rXC/strings.xml4
-rw-r--r--core/res/res/values-es-rUS/strings.xml4
-rw-r--r--core/res/res/values-es/strings.xml5
-rw-r--r--core/res/res/values-et/strings.xml4
-rw-r--r--core/res/res/values-eu/strings.xml17
-rw-r--r--core/res/res/values-fa/strings.xml11
-rw-r--r--core/res/res/values-fi/strings.xml5
-rw-r--r--core/res/res/values-fr-rCA/strings.xml4
-rw-r--r--core/res/res/values-fr/strings.xml5
-rw-r--r--core/res/res/values-gl/strings.xml5
-rw-r--r--core/res/res/values-gu/strings.xml5
-rw-r--r--core/res/res/values-hi/strings.xml5
-rw-r--r--core/res/res/values-hr/strings.xml4
-rw-r--r--core/res/res/values-hu/strings.xml4
-rw-r--r--core/res/res/values-hy/strings.xml5
-rw-r--r--core/res/res/values-in/strings.xml6
-rw-r--r--core/res/res/values-is/strings.xml5
-rw-r--r--core/res/res/values-it/strings.xml4
-rw-r--r--core/res/res/values-iw/strings.xml7
-rw-r--r--core/res/res/values-ja/strings.xml6
-rw-r--r--core/res/res/values-ka/strings.xml4
-rw-r--r--core/res/res/values-kk/strings.xml5
-rw-r--r--core/res/res/values-km/strings.xml4
-rw-r--r--core/res/res/values-kn/strings.xml4
-rw-r--r--core/res/res/values-ko/strings.xml5
-rw-r--r--core/res/res/values-ky/strings.xml5
-rw-r--r--core/res/res/values-lo/strings.xml5
-rw-r--r--core/res/res/values-lt/strings.xml4
-rw-r--r--core/res/res/values-lv/strings.xml5
-rw-r--r--core/res/res/values-mk/strings.xml4
-rw-r--r--core/res/res/values-ml/strings.xml4
-rw-r--r--core/res/res/values-mn/strings.xml6
-rw-r--r--core/res/res/values-mr/strings.xml5
-rw-r--r--core/res/res/values-ms/strings.xml4
-rw-r--r--core/res/res/values-my/strings.xml4
-rw-r--r--core/res/res/values-nb/strings.xml5
-rw-r--r--core/res/res/values-ne/strings.xml5
-rw-r--r--core/res/res/values-nl/strings.xml4
-rw-r--r--core/res/res/values-or/strings.xml5
-rw-r--r--core/res/res/values-pa/strings.xml5
-rw-r--r--core/res/res/values-pl/strings.xml5
-rw-r--r--core/res/res/values-pt-rBR/strings.xml4
-rw-r--r--core/res/res/values-pt-rPT/strings.xml4
-rw-r--r--core/res/res/values-pt/strings.xml4
-rw-r--r--core/res/res/values-ro/strings.xml17
-rw-r--r--core/res/res/values-ru/strings.xml5
-rw-r--r--core/res/res/values-si/strings.xml5
-rw-r--r--core/res/res/values-sk/strings.xml5
-rw-r--r--core/res/res/values-sl/strings.xml4
-rw-r--r--core/res/res/values-sq/strings.xml5
-rw-r--r--core/res/res/values-sr/strings.xml14
-rw-r--r--core/res/res/values-sv/strings.xml5
-rw-r--r--core/res/res/values-sw/strings.xml4
-rw-r--r--core/res/res/values-ta/strings.xml5
-rw-r--r--core/res/res/values-te/strings.xml4
-rw-r--r--core/res/res/values-th/strings.xml4
-rw-r--r--core/res/res/values-tl/strings.xml4
-rw-r--r--core/res/res/values-tr/strings.xml5
-rw-r--r--core/res/res/values-uk/strings.xml5
-rw-r--r--core/res/res/values-ur/strings.xml5
-rw-r--r--core/res/res/values-uz/strings.xml4
-rw-r--r--core/res/res/values-vi/strings.xml5
-rw-r--r--core/res/res/values-zh-rCN/strings.xml4
-rw-r--r--core/res/res/values-zh-rHK/strings.xml4
-rw-r--r--core/res/res/values-zh-rTW/strings.xml4
-rw-r--r--core/res/res/values-zu/strings.xml4
-rw-r--r--core/res/res/values/config.xml15
-rw-r--r--core/res/res/values/styles.xml8
-rw-r--r--core/res/res/values/symbols.xml5
-rw-r--r--core/tests/batterystatstests/BatteryUsageStatsProtoTests/src/com/android/internal/os/BatteryUsageStatsPulledTest.java5
-rw-r--r--core/tests/coretests/res/layout/viewgroup_test.xml4
-rw-r--r--core/tests/coretests/src/android/app/activity/ActivityThreadTest.java16
-rw-r--r--core/tests/coretests/src/android/provider/DeviceConfigTest.java84
-rw-r--r--core/tests/coretests/src/android/view/ImeInsetsSourceConsumerTest.java5
-rw-r--r--core/tests/coretests/src/android/view/InsetsControllerTest.java5
-rw-r--r--core/tests/coretests/src/android/view/InsetsStateTest.java88
-rw-r--r--core/tests/vibrator/src/android/os/vibrator/persistence/ParsedVibrationTest.java8
-rw-r--r--core/tests/vibrator/src/android/os/vibrator/persistence/VibrationEffectXmlSerializationTest.java6
-rw-r--r--graphics/java/android/graphics/Typeface.java5
-rw-r--r--graphics/java/android/graphics/fonts/SystemFonts.java26
-rw-r--r--libs/WindowManager/Jetpack/src/androidx/window/extensions/WindowExtensionsImpl.java8
-rw-r--r--libs/WindowManager/Jetpack/src/androidx/window/extensions/layout/WindowLayoutComponentImpl.java6
-rw-r--r--libs/WindowManager/Jetpack/src/androidx/window/sidecar/SampleSidecarImpl.java4
-rw-r--r--libs/WindowManager/Jetpack/src/androidx/window/util/ExtensionHelper.java70
-rw-r--r--libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/WindowExtensionsTest.java11
-rw-r--r--libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/util/ExtensionHelperTest.java130
-rw-r--r--libs/WindowManager/Shell/res/values-af/strings.xml6
-rw-r--r--libs/WindowManager/Shell/res/values-am/strings.xml6
-rw-r--r--libs/WindowManager/Shell/res/values-ar/strings.xml6
-rw-r--r--libs/WindowManager/Shell/res/values-as/strings.xml6
-rw-r--r--libs/WindowManager/Shell/res/values-az/strings.xml6
-rw-r--r--libs/WindowManager/Shell/res/values-b+sr+Latn/strings.xml6
-rw-r--r--libs/WindowManager/Shell/res/values-be/strings.xml6
-rw-r--r--libs/WindowManager/Shell/res/values-bg/strings.xml6
-rw-r--r--libs/WindowManager/Shell/res/values-bn/strings.xml6
-rw-r--r--libs/WindowManager/Shell/res/values-bs/strings.xml6
-rw-r--r--libs/WindowManager/Shell/res/values-ca/strings.xml6
-rw-r--r--libs/WindowManager/Shell/res/values-cs/strings.xml6
-rw-r--r--libs/WindowManager/Shell/res/values-da/strings.xml6
-rw-r--r--libs/WindowManager/Shell/res/values-de/strings.xml6
-rw-r--r--libs/WindowManager/Shell/res/values-el/strings.xml6
-rw-r--r--libs/WindowManager/Shell/res/values-en-rAU/strings.xml6
-rw-r--r--libs/WindowManager/Shell/res/values-en-rCA/strings.xml6
-rw-r--r--libs/WindowManager/Shell/res/values-en-rGB/strings.xml6
-rw-r--r--libs/WindowManager/Shell/res/values-en-rIN/strings.xml6
-rw-r--r--libs/WindowManager/Shell/res/values-en-rXC/strings.xml6
-rw-r--r--libs/WindowManager/Shell/res/values-es-rUS/strings.xml6
-rw-r--r--libs/WindowManager/Shell/res/values-es/strings.xml6
-rw-r--r--libs/WindowManager/Shell/res/values-et/strings.xml6
-rw-r--r--libs/WindowManager/Shell/res/values-eu/strings.xml6
-rw-r--r--libs/WindowManager/Shell/res/values-fa/strings.xml6
-rw-r--r--libs/WindowManager/Shell/res/values-fi/strings.xml6
-rw-r--r--libs/WindowManager/Shell/res/values-fr-rCA/strings.xml6
-rw-r--r--libs/WindowManager/Shell/res/values-fr/strings.xml6
-rw-r--r--libs/WindowManager/Shell/res/values-gl/strings.xml6
-rw-r--r--libs/WindowManager/Shell/res/values-gu/strings.xml6
-rw-r--r--libs/WindowManager/Shell/res/values-hi/strings.xml15
-rw-r--r--libs/WindowManager/Shell/res/values-hr/strings.xml6
-rw-r--r--libs/WindowManager/Shell/res/values-hu/strings.xml6
-rw-r--r--libs/WindowManager/Shell/res/values-hy/strings.xml6
-rw-r--r--libs/WindowManager/Shell/res/values-in/strings.xml6
-rw-r--r--libs/WindowManager/Shell/res/values-is/strings.xml6
-rw-r--r--libs/WindowManager/Shell/res/values-it/strings.xml6
-rw-r--r--libs/WindowManager/Shell/res/values-iw/strings.xml6
-rw-r--r--libs/WindowManager/Shell/res/values-ja/strings.xml6
-rw-r--r--libs/WindowManager/Shell/res/values-ka/strings.xml6
-rw-r--r--libs/WindowManager/Shell/res/values-kk/strings.xml6
-rw-r--r--libs/WindowManager/Shell/res/values-km/strings.xml6
-rw-r--r--libs/WindowManager/Shell/res/values-kn/strings.xml6
-rw-r--r--libs/WindowManager/Shell/res/values-ko/strings.xml6
-rw-r--r--libs/WindowManager/Shell/res/values-ky/strings.xml6
-rw-r--r--libs/WindowManager/Shell/res/values-lo/strings.xml6
-rw-r--r--libs/WindowManager/Shell/res/values-lt/strings.xml6
-rw-r--r--libs/WindowManager/Shell/res/values-lv/strings.xml6
-rw-r--r--libs/WindowManager/Shell/res/values-mk/strings.xml6
-rw-r--r--libs/WindowManager/Shell/res/values-ml/strings.xml6
-rw-r--r--libs/WindowManager/Shell/res/values-mn/strings.xml6
-rw-r--r--libs/WindowManager/Shell/res/values-mr/strings.xml6
-rw-r--r--libs/WindowManager/Shell/res/values-ms/strings.xml6
-rw-r--r--libs/WindowManager/Shell/res/values-my/strings.xml6
-rw-r--r--libs/WindowManager/Shell/res/values-nb/strings.xml6
-rw-r--r--libs/WindowManager/Shell/res/values-ne/strings.xml6
-rw-r--r--libs/WindowManager/Shell/res/values-nl/strings.xml6
-rw-r--r--libs/WindowManager/Shell/res/values-or/strings.xml6
-rw-r--r--libs/WindowManager/Shell/res/values-pa/strings.xml6
-rw-r--r--libs/WindowManager/Shell/res/values-pl/strings.xml6
-rw-r--r--libs/WindowManager/Shell/res/values-pt-rBR/strings.xml6
-rw-r--r--libs/WindowManager/Shell/res/values-pt-rPT/strings.xml6
-rw-r--r--libs/WindowManager/Shell/res/values-pt/strings.xml6
-rw-r--r--libs/WindowManager/Shell/res/values-ro/strings.xml6
-rw-r--r--libs/WindowManager/Shell/res/values-ru/strings.xml6
-rw-r--r--libs/WindowManager/Shell/res/values-si/strings.xml6
-rw-r--r--libs/WindowManager/Shell/res/values-sk/strings.xml6
-rw-r--r--libs/WindowManager/Shell/res/values-sl/strings.xml6
-rw-r--r--libs/WindowManager/Shell/res/values-sq/strings.xml6
-rw-r--r--libs/WindowManager/Shell/res/values-sr/strings.xml6
-rw-r--r--libs/WindowManager/Shell/res/values-sv/strings.xml6
-rw-r--r--libs/WindowManager/Shell/res/values-sw/strings.xml6
-rw-r--r--libs/WindowManager/Shell/res/values-ta/strings.xml6
-rw-r--r--libs/WindowManager/Shell/res/values-te/strings.xml6
-rw-r--r--libs/WindowManager/Shell/res/values-th/strings.xml6
-rw-r--r--libs/WindowManager/Shell/res/values-tl/strings.xml6
-rw-r--r--libs/WindowManager/Shell/res/values-tr/strings.xml6
-rw-r--r--libs/WindowManager/Shell/res/values-uk/strings.xml6
-rw-r--r--libs/WindowManager/Shell/res/values-ur/strings.xml6
-rw-r--r--libs/WindowManager/Shell/res/values-uz/strings.xml6
-rw-r--r--libs/WindowManager/Shell/res/values-vi/strings.xml6
-rw-r--r--libs/WindowManager/Shell/res/values-zh-rCN/strings.xml6
-rw-r--r--libs/WindowManager/Shell/res/values-zh-rHK/strings.xml6
-rw-r--r--libs/WindowManager/Shell/res/values-zh-rTW/strings.xml6
-rw-r--r--libs/WindowManager/Shell/res/values-zu/strings.xml6
-rw-r--r--libs/WindowManager/Shell/res/values/dimen.xml5
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/ShellTaskOrganizer.java2
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/Bubble.java4
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleController.java12
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleData.java13
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleDebugConfig.java13
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleExpandedView.java8
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleStackView.java6
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayChangeController.java15
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/compatui/UserAspectRatioSettingsWindowManager.java2
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellBaseModule.java31
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java29
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeController.java557
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeStatus.java54
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksController.kt2
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/freeform/FreeformTaskListener.java10
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTransition.java16
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/pip2/OWNERS1
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/recents/RecentTasksController.java2
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java9
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultMixedHandler.java13
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CaptionWindowDecoration.java3
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModel.java37
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecoration.java28
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/HandleMenu.java25
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/WindowDecoration.java34
-rw-r--r--libs/WindowManager/Shell/tests/flicker/Android.bp1
-rw-r--r--libs/WindowManager/Shell/tests/flicker/AndroidTestTemplate.xml2
-rw-r--r--libs/WindowManager/Shell/tests/flicker/manifests/AndroidManifest.xml8
-rw-r--r--libs/WindowManager/Shell/tests/flicker/res/xml/network_security_config.xml22
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopModeControllerTest.java531
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTasksControllerTest.kt4
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/recents/RecentTasksControllerTest.java4
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModelTests.java3
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DragPositioningCallbackUtilityTest.kt2
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/FluidResizeTaskPositionerTest.kt2
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/VeiledResizeTaskPositionerTest.kt2
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/WindowDecorationTests.java11
-rw-r--r--libs/androidfw/tests/ConfigDescription_test.cpp6
-rw-r--r--libs/androidfw/tests/ResTable_test.cpp2
-rw-r--r--libs/hwui/renderthread/VulkanManager.cpp3
-rw-r--r--location/Android.bp8
-rw-r--r--location/api/current.txt724
-rw-r--r--location/api/module-lib-current.txt10
-rw-r--r--location/api/module-lib-lint-baseline.txt13
-rw-r--r--location/api/system-current.txt645
-rw-r--r--location/api/system-lint-baseline.txt11
-rw-r--r--location/api/system-removed.txt14
-rw-r--r--location/api/test-current.txt103
-rw-r--r--location/api/test-lint-baseline.txt54
-rw-r--r--location/java/Android.bp17
-rw-r--r--media/java/android/media/AudioManager.java4
-rw-r--r--media/java/android/media/AudioSystem.java6
-rw-r--r--media/java/android/media/IAudioService.aidl7
-rw-r--r--media/java/android/media/MediaMetadataRetriever.java2
-rw-r--r--media/java/android/media/RingtoneManager.java60
-rw-r--r--media/java/android/media/audiopolicy/AudioMix.aidl3
-rw-r--r--media/java/android/media/audiopolicy/AudioMix.java78
-rw-r--r--media/java/android/media/audiopolicy/AudioMixingRule.aidl3
-rw-r--r--media/java/android/media/audiopolicy/AudioMixingRule.java158
-rw-r--r--media/java/android/media/audiopolicy/AudioPolicy.java34
-rw-r--r--media/java/android/media/audiopolicy/AudioPolicyConfig.java82
-rw-r--r--media/tests/AudioPolicyTest/src/com/android/audiopolicytest/AudioMixUnitTests.java274
-rw-r--r--media/tests/AudioPolicyTest/src/com/android/audiopolicytest/AudioMixingRuleUnitTests.java322
-rw-r--r--packages/CompanionDeviceManager/res/values-th/strings.xml2
-rw-r--r--packages/CredentialManager/res/values-el/strings.xml2
-rw-r--r--packages/CredentialManager/res/values-fa/strings.xml2
-rw-r--r--packages/CredentialManager/res/values-hi/strings.xml2
-rw-r--r--packages/CredentialManager/res/values-ka/strings.xml2
-rw-r--r--packages/CredentialManager/res/values-kn/strings.xml2
-rw-r--r--packages/CredentialManager/res/values-lt/strings.xml2
-rw-r--r--packages/CredentialManager/res/values-mk/strings.xml2
-rw-r--r--packages/CredentialManager/res/values-sk/strings.xml2
-rw-r--r--packages/EncryptedLocalTransport/Android.bp3
-rw-r--r--packages/EncryptedLocalTransport/proguard.flags2
-rw-r--r--packages/Keyguard/proguard.flags27
-rw-r--r--packages/LocalTransport/Android.bp4
-rw-r--r--packages/LocalTransport/proguard.flags5
-rw-r--r--packages/LocalTransport/src/com/android/localtransport/LocalTransport.java10
-rw-r--r--packages/PackageInstaller/res/values-it/strings.xml2
-rw-r--r--packages/SettingsLib/Android.bp72
-rw-r--r--packages/SettingsLib/AndroidManifest-SettingsLibWidget.xml18
-rw-r--r--packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/scaffold/CustomizedAppBar.kt12
-rw-r--r--packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/scaffold/SearchScaffold.kt4
-rw-r--r--packages/SettingsLib/res/values-af/strings.xml1
-rw-r--r--packages/SettingsLib/res/values-am/strings.xml1
-rw-r--r--packages/SettingsLib/res/values-ar/strings.xml1
-rw-r--r--packages/SettingsLib/res/values-as/strings.xml1
-rw-r--r--packages/SettingsLib/res/values-az/strings.xml1
-rw-r--r--packages/SettingsLib/res/values-b+sr+Latn/strings.xml1
-rw-r--r--packages/SettingsLib/res/values-be/strings.xml1
-rw-r--r--packages/SettingsLib/res/values-bg/strings.xml1
-rw-r--r--packages/SettingsLib/res/values-bn/strings.xml1
-rw-r--r--packages/SettingsLib/res/values-bs/strings.xml1
-rw-r--r--packages/SettingsLib/res/values-ca/strings.xml1
-rw-r--r--packages/SettingsLib/res/values-cs/strings.xml1
-rw-r--r--packages/SettingsLib/res/values-da/strings.xml1
-rw-r--r--packages/SettingsLib/res/values-de/strings.xml1
-rw-r--r--packages/SettingsLib/res/values-el/strings.xml1
-rw-r--r--packages/SettingsLib/res/values-en-rAU/strings.xml1
-rw-r--r--packages/SettingsLib/res/values-en-rCA/strings.xml1
-rw-r--r--packages/SettingsLib/res/values-en-rGB/strings.xml1
-rw-r--r--packages/SettingsLib/res/values-en-rIN/strings.xml1
-rw-r--r--packages/SettingsLib/res/values-en-rXC/strings.xml1
-rw-r--r--packages/SettingsLib/res/values-es-rUS/strings.xml1
-rw-r--r--packages/SettingsLib/res/values-es/strings.xml1
-rw-r--r--packages/SettingsLib/res/values-et/strings.xml1
-rw-r--r--packages/SettingsLib/res/values-eu/strings.xml1
-rw-r--r--packages/SettingsLib/res/values-fa/strings.xml1
-rw-r--r--packages/SettingsLib/res/values-fi/strings.xml1
-rw-r--r--packages/SettingsLib/res/values-fr-rCA/strings.xml1
-rw-r--r--packages/SettingsLib/res/values-fr/strings.xml1
-rw-r--r--packages/SettingsLib/res/values-gl/strings.xml1
-rw-r--r--packages/SettingsLib/res/values-gu/strings.xml3
-rw-r--r--packages/SettingsLib/res/values-hi/strings.xml1
-rw-r--r--packages/SettingsLib/res/values-hr/strings.xml1
-rw-r--r--packages/SettingsLib/res/values-hu/strings.xml1
-rw-r--r--packages/SettingsLib/res/values-hy/strings.xml1
-rw-r--r--packages/SettingsLib/res/values-in/strings.xml1
-rw-r--r--packages/SettingsLib/res/values-is/strings.xml1
-rw-r--r--packages/SettingsLib/res/values-it/strings.xml1
-rw-r--r--packages/SettingsLib/res/values-iw/strings.xml1
-rw-r--r--packages/SettingsLib/res/values-ja/strings.xml1
-rw-r--r--packages/SettingsLib/res/values-ka/strings.xml1
-rw-r--r--packages/SettingsLib/res/values-kk/strings.xml1
-rw-r--r--packages/SettingsLib/res/values-km/strings.xml1
-rw-r--r--packages/SettingsLib/res/values-kn/strings.xml1
-rw-r--r--packages/SettingsLib/res/values-ko/strings.xml1
-rw-r--r--packages/SettingsLib/res/values-ky/strings.xml1
-rw-r--r--packages/SettingsLib/res/values-lo/strings.xml1
-rw-r--r--packages/SettingsLib/res/values-lt/strings.xml1
-rw-r--r--packages/SettingsLib/res/values-lv/strings.xml1
-rw-r--r--packages/SettingsLib/res/values-mk/strings.xml1
-rw-r--r--packages/SettingsLib/res/values-ml/strings.xml1
-rw-r--r--packages/SettingsLib/res/values-mn/strings.xml1
-rw-r--r--packages/SettingsLib/res/values-mr/strings.xml1
-rw-r--r--packages/SettingsLib/res/values-ms/strings.xml1
-rw-r--r--packages/SettingsLib/res/values-my/strings.xml1
-rw-r--r--packages/SettingsLib/res/values-nb/strings.xml1
-rw-r--r--packages/SettingsLib/res/values-ne/strings.xml1
-rw-r--r--packages/SettingsLib/res/values-nl/strings.xml1
-rw-r--r--packages/SettingsLib/res/values-or/strings.xml1
-rw-r--r--packages/SettingsLib/res/values-pa/strings.xml1
-rw-r--r--packages/SettingsLib/res/values-pl/strings.xml1
-rw-r--r--packages/SettingsLib/res/values-pt-rBR/strings.xml1
-rw-r--r--packages/SettingsLib/res/values-pt-rPT/strings.xml1
-rw-r--r--packages/SettingsLib/res/values-pt/strings.xml1
-rw-r--r--packages/SettingsLib/res/values-ro/strings.xml1
-rw-r--r--packages/SettingsLib/res/values-ru/strings.xml1
-rw-r--r--packages/SettingsLib/res/values-si/strings.xml1
-rw-r--r--packages/SettingsLib/res/values-sk/strings.xml1
-rw-r--r--packages/SettingsLib/res/values-sl/strings.xml1
-rw-r--r--packages/SettingsLib/res/values-sq/strings.xml1
-rw-r--r--packages/SettingsLib/res/values-sr/strings.xml1
-rw-r--r--packages/SettingsLib/res/values-sv/strings.xml1
-rw-r--r--packages/SettingsLib/res/values-sw/strings.xml1
-rw-r--r--packages/SettingsLib/res/values-ta/strings.xml1
-rw-r--r--packages/SettingsLib/res/values-te/strings.xml1
-rw-r--r--packages/SettingsLib/res/values-th/strings.xml1
-rw-r--r--packages/SettingsLib/res/values-tl/strings.xml1
-rw-r--r--packages/SettingsLib/res/values-tr/strings.xml1
-rw-r--r--packages/SettingsLib/res/values-uk/strings.xml1
-rw-r--r--packages/SettingsLib/res/values-ur/strings.xml1
-rw-r--r--packages/SettingsLib/res/values-uz/strings.xml1
-rw-r--r--packages/SettingsLib/res/values-vi/strings.xml1
-rw-r--r--packages/SettingsLib/res/values-zh-rCN/strings.xml1
-rw-r--r--packages/SettingsLib/res/values-zh-rHK/strings.xml1
-rw-r--r--packages/SettingsLib/res/values-zh-rTW/strings.xml1
-rw-r--r--packages/SettingsLib/res/values-zu/strings.xml1
-rw-r--r--packages/SettingsLib/res/values/strings.xml3
-rw-r--r--packages/SettingsLib/src/com/android/settingslib/RestrictedSwitchPreference.java4
-rw-r--r--packages/SettingsLib/src/com/android/settingslib/applications/ApplicationsState.java3
-rw-r--r--packages/SettingsLib/src/com/android/settingslib/bluetooth/BroadcastDialog.java3
-rw-r--r--packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java8
-rw-r--r--packages/SettingsLib/src/com/android/settingslib/inputmethod/InputMethodPreference.java2
-rw-r--r--packages/SettingsLib/src/com/android/settingslib/notification/ConversationIconFactory.java3
-rw-r--r--packages/SettingsLib/src/com/android/settingslib/wifi/AccessPointPreference.java3
-rw-r--r--packages/SettingsLib/src/com/android/settingslib/wifi/WifiStatusTracker.java3
-rw-r--r--packages/SettingsLib/tests/robotests/src/com/android/settingslib/PrimarySwitchPreferenceTest.java2
-rw-r--r--packages/SettingsLib/tests/robotests/src/com/android/settingslib/collapsingtoolbar/widget/CollapsingCoordinatorLayoutTest.java3
-rw-r--r--packages/SettingsLib/tests/robotests/src/com/android/settingslib/core/lifecycle/HideNonSystemOverlayMixinTest.java4
-rw-r--r--packages/SettingsLib/tests/robotests/src/com/android/settingslib/enterprise/FinancedDeviceActionDisabledByAdminControllerTest.java4
-rw-r--r--packages/SettingsLib/tests/robotests/src/com/android/settingslib/enterprise/ManagedDeviceActionDisabledByAdminControllerTest.java4
-rw-r--r--packages/SettingsLib/tests/robotests/src/com/android/settingslib/users/CreateUserDialogControllerTest.java2
-rw-r--r--packages/SettingsLib/tests/robotests/src/com/android/settingslib/users/EditUserInfoControllerTest.java2
-rw-r--r--packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/AdaptiveIconTest.java10
-rw-r--r--packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/AdaptiveOutlineDrawableTest.java2
-rw-r--r--packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/FooterPreferenceTest.java19
-rw-r--r--packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/TwoTargetPreferenceTest.java2
-rw-r--r--packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java2
-rw-r--r--packages/SettingsProvider/src/android/provider/settings/backup/SystemSettings.java2
-rw-r--r--packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java2
-rw-r--r--packages/SettingsProvider/src/android/provider/settings/validators/SystemSettingsValidators.java2
-rw-r--r--packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java1
-rw-r--r--packages/SharedStorageBackup/Android.bp3
-rw-r--r--packages/SharedStorageBackup/proguard.flags2
-rw-r--r--packages/SystemUI/Android.bp45
-rw-r--r--packages/SystemUI/aconfig/Android.bp13
-rw-r--r--packages/SystemUI/aconfig/accessibility.aconfig (renamed from packages/SystemUI/src/com/android/systemui/accessibility/aconfig/accessibility.aconfig)5
-rw-r--r--packages/SystemUI/aconfig/systemui.aconfig (renamed from packages/SystemUI/src/com/android/systemui/aconfig/systemui.aconfig)4
-rw-r--r--packages/SystemUI/animation/Android.bp1
-rw-r--r--packages/SystemUI/compose/facade/disabled/src/com/android/systemui/scene/BouncerSceneModule.kt (renamed from tests/ApkVerityTest/ApkVerityTestApp/src/com/android/apkverity/DummyActivity.java)9
-rw-r--r--packages/SystemUI/compose/facade/disabled/src/com/android/systemui/scene/GoneSceneModule.kt (renamed from tests/ApkVerityTest/ApkVerityTestApp/feature_split/src/com/android/apkverity/feature_x/DummyActivity.java)9
-rw-r--r--packages/SystemUI/compose/facade/disabled/src/com/android/systemui/scene/LockscreenSceneModule.kt21
-rw-r--r--packages/SystemUI/compose/facade/disabled/src/com/android/systemui/scene/QuickSettingsSceneModule.kt21
-rw-r--r--packages/SystemUI/compose/facade/disabled/src/com/android/systemui/scene/ShadeSceneModule.kt21
-rw-r--r--packages/SystemUI/compose/facade/enabled/src/com/android/systemui/scene/BouncerSceneModule.kt (renamed from packages/SystemUI/compose/facade/enabled/src/com/android/systemui/scene/ui/composable/SceneModule.kt)44
-rw-r--r--packages/SystemUI/compose/facade/enabled/src/com/android/systemui/scene/GoneSceneModule.kt (renamed from packages/SystemUI/src/com/android/systemui/scene/domain/startable/SceneContainerStartableModule.kt)23
-rw-r--r--packages/SystemUI/compose/facade/enabled/src/com/android/systemui/scene/LockscreenSceneModule.kt (renamed from packages/SystemUI/src/com/android/systemui/keyguard/ui/view/LockscreenSceneModule.kt)30
-rw-r--r--packages/SystemUI/compose/facade/enabled/src/com/android/systemui/scene/QuickSettingsSceneModule.kt29
-rw-r--r--packages/SystemUI/compose/facade/enabled/src/com/android/systemui/scene/ShadeSceneModule.kt29
-rw-r--r--packages/SystemUI/compose/features/src/com/android/systemui/dialog/ui/composable/AlertDialogContent.kt109
-rw-r--r--packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/LockscreenScene.kt12
-rw-r--r--packages/SystemUI/compose/features/src/com/android/systemui/qs/footer/ui/compose/FooterActions.kt3
-rw-r--r--packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/SceneContainer.kt1
-rw-r--r--packages/SystemUI/proguard_common.flags3
-rw-r--r--packages/SystemUI/res-keyguard/layout-land/keyguard_pin_view.xml25
-rw-r--r--packages/SystemUI/res-keyguard/layout-sw600dp-land/keyguard_pin_view.xml25
-rw-r--r--packages/SystemUI/res-keyguard/layout/keyguard_pin_view.xml203
-rw-r--r--packages/SystemUI/res-keyguard/layout/keyguard_pin_view_landscape.xml231
-rw-r--r--packages/SystemUI/res-keyguard/layout/keyguard_pin_view_portrait.xml218
-rw-r--r--packages/SystemUI/res-keyguard/values-da/strings.xml2
-rw-r--r--packages/SystemUI/res/layout/zen_mode_condition.xml85
-rw-r--r--packages/SystemUI/res/values-af/strings.xml13
-rw-r--r--packages/SystemUI/res/values-am/strings.xml13
-rw-r--r--packages/SystemUI/res/values-ar/strings.xml13
-rw-r--r--packages/SystemUI/res/values-as/strings.xml13
-rw-r--r--packages/SystemUI/res/values-az/strings.xml13
-rw-r--r--packages/SystemUI/res/values-b+sr+Latn/strings.xml13
-rw-r--r--packages/SystemUI/res/values-be/strings.xml13
-rw-r--r--packages/SystemUI/res/values-bg/strings.xml13
-rw-r--r--packages/SystemUI/res/values-bn/strings.xml13
-rw-r--r--packages/SystemUI/res/values-bs/strings.xml13
-rw-r--r--packages/SystemUI/res/values-ca/strings.xml13
-rw-r--r--packages/SystemUI/res/values-cs/strings.xml13
-rw-r--r--packages/SystemUI/res/values-da/strings.xml27
-rw-r--r--packages/SystemUI/res/values-de/strings.xml13
-rw-r--r--packages/SystemUI/res/values-el/strings.xml13
-rw-r--r--packages/SystemUI/res/values-en-rAU/strings.xml11
-rw-r--r--packages/SystemUI/res/values-en-rCA/strings.xml11
-rw-r--r--packages/SystemUI/res/values-en-rGB/strings.xml11
-rw-r--r--packages/SystemUI/res/values-en-rIN/strings.xml11
-rw-r--r--packages/SystemUI/res/values-en-rXC/strings.xml11
-rw-r--r--packages/SystemUI/res/values-es-rUS/strings.xml13
-rw-r--r--packages/SystemUI/res/values-es/strings.xml13
-rw-r--r--packages/SystemUI/res/values-et/strings.xml13
-rw-r--r--packages/SystemUI/res/values-eu/strings.xml13
-rw-r--r--packages/SystemUI/res/values-fa/strings.xml13
-rw-r--r--packages/SystemUI/res/values-fi/strings.xml13
-rw-r--r--packages/SystemUI/res/values-fr-rCA/strings.xml13
-rw-r--r--packages/SystemUI/res/values-fr/strings.xml13
-rw-r--r--packages/SystemUI/res/values-gl/strings.xml13
-rw-r--r--packages/SystemUI/res/values-gu/strings.xml13
-rw-r--r--packages/SystemUI/res/values-hi/strings.xml13
-rw-r--r--packages/SystemUI/res/values-hr/strings.xml13
-rw-r--r--packages/SystemUI/res/values-hu/strings.xml13
-rw-r--r--packages/SystemUI/res/values-hy/strings.xml13
-rw-r--r--packages/SystemUI/res/values-in/strings.xml15
-rw-r--r--packages/SystemUI/res/values-is/strings.xml13
-rw-r--r--packages/SystemUI/res/values-it/strings.xml13
-rw-r--r--packages/SystemUI/res/values-iw/strings.xml13
-rw-r--r--packages/SystemUI/res/values-ja/strings.xml13
-rw-r--r--packages/SystemUI/res/values-ka/strings.xml11
-rw-r--r--packages/SystemUI/res/values-kk/strings.xml13
-rw-r--r--packages/SystemUI/res/values-km/strings.xml13
-rw-r--r--packages/SystemUI/res/values-kn/strings.xml13
-rw-r--r--packages/SystemUI/res/values-ko/strings.xml13
-rw-r--r--packages/SystemUI/res/values-ky/strings.xml13
-rw-r--r--packages/SystemUI/res/values-lo/strings.xml13
-rw-r--r--packages/SystemUI/res/values-lt/strings.xml13
-rw-r--r--packages/SystemUI/res/values-lv/strings.xml13
-rw-r--r--packages/SystemUI/res/values-mk/strings.xml13
-rw-r--r--packages/SystemUI/res/values-ml/strings.xml13
-rw-r--r--packages/SystemUI/res/values-mn/strings.xml13
-rw-r--r--packages/SystemUI/res/values-mr/strings.xml13
-rw-r--r--packages/SystemUI/res/values-ms/strings.xml11
-rw-r--r--packages/SystemUI/res/values-my/strings.xml13
-rw-r--r--packages/SystemUI/res/values-nb/strings.xml13
-rw-r--r--packages/SystemUI/res/values-ne/strings.xml13
-rw-r--r--packages/SystemUI/res/values-nl/strings.xml13
-rw-r--r--packages/SystemUI/res/values-or/strings.xml13
-rw-r--r--packages/SystemUI/res/values-pa/strings.xml13
-rw-r--r--packages/SystemUI/res/values-pl/strings.xml13
-rw-r--r--packages/SystemUI/res/values-pt-rBR/strings.xml13
-rw-r--r--packages/SystemUI/res/values-pt-rPT/strings.xml11
-rw-r--r--packages/SystemUI/res/values-pt/strings.xml13
-rw-r--r--packages/SystemUI/res/values-ro/strings.xml13
-rw-r--r--packages/SystemUI/res/values-ru/strings.xml13
-rw-r--r--packages/SystemUI/res/values-si/strings.xml13
-rw-r--r--packages/SystemUI/res/values-sk/strings.xml13
-rw-r--r--packages/SystemUI/res/values-sl/strings.xml13
-rw-r--r--packages/SystemUI/res/values-sq/strings.xml13
-rw-r--r--packages/SystemUI/res/values-sr/strings.xml13
-rw-r--r--packages/SystemUI/res/values-sv/strings.xml13
-rw-r--r--packages/SystemUI/res/values-sw/strings.xml13
-rw-r--r--packages/SystemUI/res/values-sw600dp/bools.xml8
-rw-r--r--packages/SystemUI/res/values-ta/strings.xml13
-rw-r--r--packages/SystemUI/res/values-te/strings.xml13
-rw-r--r--packages/SystemUI/res/values-th/strings.xml13
-rw-r--r--packages/SystemUI/res/values-tl/strings.xml11
-rw-r--r--packages/SystemUI/res/values-tr/strings.xml13
-rw-r--r--packages/SystemUI/res/values-uk/strings.xml13
-rw-r--r--packages/SystemUI/res/values-ur/strings.xml13
-rw-r--r--packages/SystemUI/res/values-uz/strings.xml13
-rw-r--r--packages/SystemUI/res/values-vi/strings.xml13
-rw-r--r--packages/SystemUI/res/values-zh-rCN/strings.xml13
-rw-r--r--packages/SystemUI/res/values-zh-rHK/strings.xml13
-rw-r--r--packages/SystemUI/res/values-zh-rTW/strings.xml13
-rw-r--r--packages/SystemUI/res/values-zu/strings.xml13
-rw-r--r--packages/SystemUI/res/values/bools.xml8
-rw-r--r--packages/SystemUI/res/values/config.xml8
-rw-r--r--packages/SystemUI/res/values/ids.xml3
-rw-r--r--packages/SystemUI/res/xml/media_session_expanded.xml4
-rw-r--r--packages/SystemUI/src/com/android/keyguard/KeyguardInputView.java5
-rw-r--r--packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java14
-rw-r--r--packages/SystemUI/src/com/android/keyguard/KeyguardSecurityViewFlipper.java8
-rw-r--r--packages/SystemUI/src/com/android/keyguard/KeyguardSecurityViewFlipperController.java40
-rw-r--r--packages/SystemUI/src/com/android/keyguard/PinShapeNonHintingView.java2
-rw-r--r--packages/SystemUI/src/com/android/keyguard/dagger/KeyguardBouncerScope.java2
-rw-r--r--packages/SystemUI/src/com/android/keyguard/dagger/KeyguardStatusBarViewScope.java2
-rw-r--r--packages/SystemUI/src/com/android/keyguard/dagger/KeyguardStatusViewScope.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/MenuView.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/MenuViewAppearance.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/MenuViewLayerController.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/aconfig/AConfigModule.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/appops/AppOpsControllerImpl.java28
-rw-r--r--packages/SystemUI/src/com/android/systemui/assist/AssistManager.java14
-rw-r--r--packages/SystemUI/src/com/android/systemui/biometrics/SideFpsController.kt4
-rw-r--r--packages/SystemUI/src/com/android/systemui/bouncer/domain/interactor/BouncerInteractor.kt7
-rw-r--r--packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/BouncerViewModel.kt7
-rw-r--r--packages/SystemUI/src/com/android/systemui/classifier/FalsingModule.java7
-rw-r--r--packages/SystemUI/src/com/android/systemui/communal/ui/view/layout/blueprints/DefaultCommunalBlueprint.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/communal/ui/view/layout/sections/DefaultCommunalWidgetSection.kt9
-rw-r--r--packages/SystemUI/src/com/android/systemui/controls/dagger/ControlsComponent.kt39
-rw-r--r--packages/SystemUI/src/com/android/systemui/controls/ui/ThumbnailBehavior.kt5
-rw-r--r--packages/SystemUI/src/com/android/systemui/dagger/ReferenceSystemUIModule.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java6
-rw-r--r--packages/SystemUI/src/com/android/systemui/display/data/repository/DisplayRepository.kt134
-rw-r--r--packages/SystemUI/src/com/android/systemui/display/domain/interactor/ConnectedDisplayInteractor.kt41
-rw-r--r--packages/SystemUI/src/com/android/systemui/display/ui/view/MirroringConfirmationDialog.kt20
-rw-r--r--packages/SystemUI/src/com/android/systemui/display/ui/viewmodel/ConnectingDisplayViewModel.kt11
-rw-r--r--packages/SystemUI/src/com/android/systemui/flags/Flags.kt49
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewConfigurator.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractor.kt32
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/shared/model/KeyguardBlueprint.kt31
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/shared/model/KeyguardSection.kt34
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardBlueprintViewBinder.kt29
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardRootViewBinder.kt28
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/blueprints/DefaultKeyguardBlueprint.kt9
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/blueprints/ShortcutsBesideUdfpsKeyguardBlueprint.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/AlignShortcutsToUdfpsSection.kt76
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/BaseShortcutsSection.kt101
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultAmbientIndicationAreaSection.kt21
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultIndicationAreaSection.kt16
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultLockIconSection.kt28
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultNotificationStackScrollLayoutSection.kt32
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultSettingsPopupMenuSection.kt32
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultShortcutsSection.kt76
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultStatusViewSection.kt38
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/Extensions.kt8
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/SplitShadeGuidelines.kt7
-rw-r--r--packages/SystemUI/src/com/android/systemui/log/dagger/LogModule.java8
-rw-r--r--packages/SystemUI/src/com/android/systemui/log/dagger/NotifInflationLog.java33
-rw-r--r--packages/SystemUI/src/com/android/systemui/media/MediaProjectionPermissionActivity.java16
-rw-r--r--packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaCarouselScrollHandler.kt19
-rw-r--r--packages/SystemUI/src/com/android/systemui/people/widget/PeopleSpaceWidgetManager.java47
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/QSContainerImpl.java14
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/QSFragment.java11
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/TEST_MAPPING4
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java9
-rw-r--r--packages/SystemUI/src/com/android/systemui/scene/EmptySceneModule.kt32
-rw-r--r--packages/SystemUI/src/com/android/systemui/scene/KeyguardlessSceneContainerFrameworkModule.kt54
-rw-r--r--packages/SystemUI/src/com/android/systemui/scene/SceneContainerFrameworkModule.kt59
-rw-r--r--packages/SystemUI/src/com/android/systemui/scene/ShadelessSceneContainerFrameworkModule.kt (renamed from packages/SystemUI/src/com/android/systemui/scene/shared/model/SceneContainerConfigModule.kt)28
-rw-r--r--packages/SystemUI/src/com/android/systemui/scene/domain/startable/SceneContainerStartable.kt12
-rw-r--r--packages/SystemUI/src/com/android/systemui/scene/shared/flag/SceneContainerFlags.kt136
-rw-r--r--packages/SystemUI/src/com/android/systemui/scene/shared/logger/SceneLogger.kt13
-rw-r--r--packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java8
-rw-r--r--packages/SystemUI/src/com/android/systemui/shade/ShadeViewProviderModule.kt12
-rw-r--r--packages/SystemUI/src/com/android/systemui/shade/data/repository/ShadeRepository.kt56
-rw-r--r--packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeInteractor.kt34
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/LockscreenShadeTransitionController.kt14
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/core/StatusBarInitializer.kt19
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/events/SystemStatusAnimationSchedulerImpl.kt5
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/events/SystemStatusAnimationSchedulerLegacyImpl.kt5
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/ConversationNotifications.kt8
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifInflaterImpl.java32
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifInflaterLogger.kt86
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/StackCoordinator.kt5
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/NotificationRowBinderImpl.java11
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/NotificationRowBinderLogger.kt92
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/GroupExpansionManagerImpl.java40
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/GroupMembershipManager.java15
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/GroupMembershipManagerImpl.java51
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/dagger/NotificationsModule.java7
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/logging/NotificationLogger.java6
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentInflater.java120
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentInflaterLogger.kt129
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationRowContentBinder.java3
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/row/RowContentBindStage.java7
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/row/RowContentBindStageLogger.kt16
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfaces.java14
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesEmptyImpl.kt7
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java57
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewController.kt91
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarTouchableRegionManager.java7
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/UnlockedScreenOffAnimationController.kt5
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/CentralSurfacesComponent.java76
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarViewModule.java127
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragment.java5
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragmentStartable.kt58
-rw-r--r--packages/SystemUI/tests/src/com/android/keyguard/ClockEventControllerTest.kt2
-rw-r--r--packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerControllerTest.kt49
-rw-r--r--packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityViewFlipperControllerTest.java5
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/appops/AppOpsControllerTest.java215
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerTest.java5
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/communal/data/repository/CommunalWidgetRepositoryImplTest.kt2
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/communal/ui/view/layout/blueprints/DefaultCommunalBlueprintTest.kt8
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/controls/dagger/ControlsComponentTest.kt8
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/controls/ui/TemperatureControlBehaviorTest.kt98
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/display/data/repository/DisplayRepositoryTest.kt228
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/display/domain/interactor/ConnectedDisplayInteractorTest.kt54
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/display/ui/view/MirroringConfirmationDialogTest.kt22
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayAnimationsControllerTest.kt6
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayCallbackControllerTest.kt6
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayContainerViewControllerTest.java10
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayNotificationCountProviderTest.java6
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayServiceTest.java6
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayStateControllerTest.java7
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayStatusBarItemsProviderTest.java7
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayStatusBarViewControllerTest.java13
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/dreams/complication/HideComplicationTouchHandlerTest.java6
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/dreams/conditions/AssistantAttentionConditionTest.java7
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/dreams/conditions/DreamConditionTest.java6
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/dreams/touch/BouncerSwipeTouchHandlerTest.java19
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/dreams/touch/ShadeTouchHandlerTest.java6
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/dreams/touch/scrim/BouncerlessScrimControllerTest.java6
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/dreams/touch/scrim/ScrimManagerTest.java7
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/keyguard/CustomizationProviderTest.kt5
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractorTest.kt57
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/OccludingAppDeviceEntryInteractorTest.kt3
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/view/layout/blueprints/DefaultKeyguardBlueprintTest.kt31
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultIndicationAreaSectionTest.kt21
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultLockIconSectionTest.kt21
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardQuickAffordancesCombinedViewModelTest.kt215
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/MediaCarouselScrollHandlerTest.kt127
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/recents/OverviewProxyServiceTest.kt2
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/scene/SceneFrameworkIntegrationTest.kt6
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/scene/domain/startable/SceneContainerStartableTest.kt8
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/scene/shared/flag/SceneContainerFlagsTest.kt96
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/screenshot/ScreenshotPolicyImplTest.kt8
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelViewControllerBaseTest.java1
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/shade/QuickSettingsControllerBaseTest.java5
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/shade/data/repository/ShadeInteractorTest.kt59
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/shade/data/repository/ShadeRepositoryImplTest.kt31
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/LockscreenShadeTransitionControllerTest.kt8
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/events/SystemStatusAnimationSchedulerImplTest.kt28
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/ConversationCoordinatorTest.kt10
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/render/GroupExpansionManagerTest.kt118
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/render/GroupMembershipManagerTest.kt106
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationContentInflaterTest.java6
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationTestHelper.java3
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/SharedNotificationContainerViewModelTest.kt30
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CentralSurfacesImplTest.java14
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewControllerTest.kt98
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/UnlockedScreenOffAnimationControllerTest.kt16
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/volume/VolumeDialogImplTest.java3
-rw-r--r--packages/SystemUI/tests/utils/src/com/android/systemui/SysuiTestCase.java4
-rw-r--r--packages/SystemUI/tests/utils/src/com/android/systemui/display/data/repository/FakeDisplayRepository.kt12
-rw-r--r--packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractorFactory.kt10
-rw-r--r--packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionInteractorFactory.kt5
-rw-r--r--packages/SystemUI/tests/utils/src/com/android/systemui/scene/SceneTestUtils.kt16
-rw-r--r--packages/SystemUI/tests/utils/src/com/android/systemui/scene/shared/flag/FakeSceneContainerFlags.kt30
-rw-r--r--packages/SystemUI/tests/utils/src/com/android/systemui/shade/data/repository/FakeShadeRepository.kt17
-rw-r--r--packages/WallpaperBackup/Android.bp3
-rw-r--r--packages/WallpaperBackup/proguard.flags1
-rw-r--r--services/autofill/Android.bp15
-rw-r--r--services/autofill/bugfixes.aconfig8
-rw-r--r--services/autofill/features.aconfig1
-rw-r--r--services/autofill/java/com/android/server/autofill/AutofillManagerServiceShellCommand.java49
-rw-r--r--services/companion/java/com/android/server/companion/virtual/CameraAccessController.java4
-rw-r--r--services/companion/java/com/android/server/companion/virtual/GenericWindowPolicyController.java236
-rw-r--r--services/companion/java/com/android/server/companion/virtual/InputController.java4
-rw-r--r--services/companion/java/com/android/server/companion/virtual/SensorController.java3
-rw-r--r--services/companion/java/com/android/server/companion/virtual/VirtualDeviceImpl.java149
-rw-r--r--services/companion/java/com/android/server/companion/virtual/VirtualDeviceManagerService.java71
-rw-r--r--services/companion/java/com/android/server/companion/virtual/flags.aconfig2
-rw-r--r--services/core/java/android/content/pm/PackageManagerInternal.java6
-rw-r--r--services/core/java/com/android/server/LogMteState.java5
-rw-r--r--services/core/java/com/android/server/am/ActivityManagerService.java27
-rw-r--r--services/core/java/com/android/server/am/BatteryStatsService.java17
-rw-r--r--services/core/java/com/android/server/am/ContentProviderHelper.java5
-rw-r--r--services/core/java/com/android/server/am/SettingsToPropertiesMapper.java29
-rw-r--r--services/core/java/com/android/server/app/GameManagerService.java7
-rw-r--r--services/core/java/com/android/server/appop/AttributedOp.java51
-rw-r--r--services/core/java/com/android/server/appop/HistoricalRegistry.java23
-rw-r--r--services/core/java/com/android/server/audio/AudioService.java102
-rw-r--r--services/core/java/com/android/server/audio/AudioSystemAdapter.java16
-rw-r--r--services/core/java/com/android/server/audio/SpatializerHelper.java43
-rw-r--r--services/core/java/com/android/server/biometrics/AuthenticationStatsCollector.java2
-rw-r--r--services/core/java/com/android/server/biometrics/AuthenticationStatsPersister.java8
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/BiometricNotificationUtils.java20
-rw-r--r--services/core/java/com/android/server/connectivity/Vpn.java15
-rw-r--r--services/core/java/com/android/server/display/BrightnessMappingStrategy.java43
-rw-r--r--services/core/java/com/android/server/display/ColorFade.java6
-rw-r--r--services/core/java/com/android/server/display/DisplayDeviceConfig.java43
-rw-r--r--services/core/java/com/android/server/display/DisplayManagerService.java16
-rw-r--r--services/core/java/com/android/server/display/DisplayPowerController.java17
-rw-r--r--services/core/java/com/android/server/display/DisplayPowerController2.java19
-rw-r--r--services/core/java/com/android/server/display/DisplayPowerState.java11
-rw-r--r--services/core/java/com/android/server/display/LogicalDisplayMapper.java31
-rw-r--r--services/core/java/com/android/server/display/SmallAreaDetectionController.java177
-rw-r--r--services/core/java/com/android/server/inputmethod/InputMethodManagerService.java20
-rwxr-xr-xservices/core/java/com/android/server/notification/NotificationManagerService.java2
-rw-r--r--services/core/java/com/android/server/notification/ZenModeHelper.java5
-rw-r--r--services/core/java/com/android/server/notification/flags.aconfig7
-rw-r--r--services/core/java/com/android/server/pm/ComputerEngine.java27
-rw-r--r--services/core/java/com/android/server/pm/DeletePackageHelper.java21
-rw-r--r--services/core/java/com/android/server/pm/InstallPackageHelper.java17
-rw-r--r--services/core/java/com/android/server/pm/InstallRequest.java14
-rw-r--r--services/core/java/com/android/server/pm/PackageArchiverService.java229
-rw-r--r--services/core/java/com/android/server/pm/PackageInstallerHistoricalSession.java203
-rw-r--r--services/core/java/com/android/server/pm/PackageInstallerService.java28
-rw-r--r--services/core/java/com/android/server/pm/PackageInstallerSession.java167
-rw-r--r--services/core/java/com/android/server/pm/PackageManagerService.java43
-rw-r--r--services/core/java/com/android/server/pm/PackageManagerServiceUtils.java24
-rw-r--r--services/core/java/com/android/server/pm/PackageManagerShellCommand.java193
-rw-r--r--services/core/java/com/android/server/pm/PackageManagerShellCommandDataLoader.java66
-rw-r--r--services/core/java/com/android/server/pm/PackageMetrics.java2
-rw-r--r--services/core/java/com/android/server/pm/PackageRemovedInfo.java7
-rw-r--r--services/core/java/com/android/server/pm/PackageSetting.java2
-rw-r--r--services/core/java/com/android/server/pm/PrepareFailure.java3
-rw-r--r--services/core/java/com/android/server/pm/RemovePackageHelper.java14
-rw-r--r--services/core/java/com/android/server/pm/Settings.java24
-rw-r--r--services/core/java/com/android/server/pm/ShortcutService.java4
-rw-r--r--services/core/java/com/android/server/pm/ShortcutUser.java4
-rw-r--r--services/core/java/com/android/server/pm/UserManagerService.java14
-rw-r--r--services/core/java/com/android/server/pm/UserRestrictionsUtils.java4
-rw-r--r--services/core/java/com/android/server/pm/UserTypeFactory.java5
-rw-r--r--services/core/java/com/android/server/pm/VerifyingSession.java5
-rw-r--r--services/core/java/com/android/server/pm/dex/ArtManagerService.java13
-rw-r--r--services/core/java/com/android/server/pm/dex/ViewCompiler.java7
-rw-r--r--services/core/java/com/android/server/pm/flags.aconfig8
-rw-r--r--services/core/java/com/android/server/pm/parsing/PackageInfoUtils.java47
-rw-r--r--services/core/java/com/android/server/pm/parsing/PackageParser2.java18
-rw-r--r--services/core/java/com/android/server/pm/permission/PermissionManagerService.java6
-rw-r--r--services/core/java/com/android/server/pm/pkg/PackageUserState.java7
-rw-r--r--services/core/java/com/android/server/pm/pkg/PackageUserStateDefault.java5
-rw-r--r--services/core/java/com/android/server/pm/pkg/PackageUserStateImpl.java4
-rw-r--r--services/core/java/com/android/server/pm/pkg/PackageUserStateUtils.java35
-rw-r--r--services/core/java/com/android/server/pm/pkg/parsing/ParsingPackage.java4
-rw-r--r--services/core/java/com/android/server/pm/pkg/parsing/ParsingPackageUtils.java131
-rw-r--r--services/core/java/com/android/server/policy/PhoneWindowManager.java54
-rw-r--r--services/core/java/com/android/server/power/hint/HintManagerService.java5
-rw-r--r--services/core/java/com/android/server/power/stats/BatteryUsageStatsProvider.java7
-rw-r--r--services/core/java/com/android/server/security/Android.bp17
-rw-r--r--services/core/java/com/android/server/security/OWNERS2
-rw-r--r--services/core/java/com/android/server/security/flags.aconfig8
-rw-r--r--services/core/java/com/android/server/stats/pull/StatsPullAtomService.java6
-rw-r--r--services/core/java/com/android/server/trust/TrustManagerService.java126
-rwxr-xr-xservices/core/java/com/android/server/tv/TvInputHardwareManager.java24
-rw-r--r--services/core/java/com/android/server/tv/TvInputManagerService.java61
-rw-r--r--services/core/java/com/android/server/uri/UriGrantsManagerService.java42
-rw-r--r--services/core/java/com/android/server/utils/FoldSettingProvider.java102
-rw-r--r--services/core/java/com/android/server/utils/FoldSettingWrapper.java48
-rw-r--r--services/core/java/com/android/server/vibrator/HapticFeedbackCustomization.java10
-rw-r--r--services/core/java/com/android/server/vibrator/HapticFeedbackVibrationProvider.java51
-rw-r--r--services/core/java/com/android/server/vibrator/VibratorManagerService.java259
-rw-r--r--services/core/java/com/android/server/wm/ActivityRecord.java8
-rw-r--r--services/core/java/com/android/server/wm/ActivityStartInterceptor.java65
-rw-r--r--services/core/java/com/android/server/wm/ActivityStarter.java13
-rw-r--r--services/core/java/com/android/server/wm/ActivityTaskManagerService.java14
-rw-r--r--services/core/java/com/android/server/wm/DesktopModeLaunchParamsModifier.java4
-rw-r--r--services/core/java/com/android/server/wm/Dimmer.java20
-rw-r--r--services/core/java/com/android/server/wm/DisplayContent.java29
-rw-r--r--services/core/java/com/android/server/wm/DisplayPolicy.java5
-rw-r--r--services/core/java/com/android/server/wm/DisplayRotation.java6
-rw-r--r--services/core/java/com/android/server/wm/DisplayWindowPolicyControllerHelper.java40
-rw-r--r--services/core/java/com/android/server/wm/LetterboxConfiguration.java56
-rw-r--r--services/core/java/com/android/server/wm/RemoteDisplayChangeController.java22
-rw-r--r--services/core/java/com/android/server/wm/RootWindowContainer.java22
-rw-r--r--services/core/java/com/android/server/wm/Task.java7
-rw-r--r--services/core/java/com/android/server/wm/TaskLaunchParamsModifier.java89
-rw-r--r--services/core/java/com/android/server/wm/Transition.java9
-rw-r--r--services/core/java/com/android/server/wm/WindowContainer.java7
-rw-r--r--services/core/java/com/android/server/wm/WindowManagerShellCommand.java96
-rw-r--r--services/core/java/com/android/server/wm/WindowState.java37
-rw-r--r--services/core/java/com/android/server/wm/WindowToken.java12
-rw-r--r--services/core/jni/Android.bp1
-rw-r--r--services/core/jni/com_android_server_display_SmallAreaDetectionController.cpp67
-rw-r--r--services/core/jni/onload.cpp2
-rw-r--r--services/core/xsd/display-device-config/display-device-config.xsd12
-rw-r--r--services/core/xsd/display-device-config/schema/current.txt4
-rw-r--r--services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java44
-rw-r--r--services/devicepolicy/java/com/android/server/devicepolicy/PolicyDefinition.java1
-rw-r--r--services/devicepolicy/java/com/android/server/devicepolicy/PolicyVersionUpgrader.java17
-rw-r--r--services/devicepolicy/java/com/android/server/devicepolicy/RemoteBugreportManager.java31
-rw-r--r--services/tests/InputMethodSystemServerTests/src/com/android/inputmethodservice/InputMethodServiceTest.java20
-rw-r--r--services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/PackageManagerServiceTest.java12
-rw-r--r--services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/ScanTests.java3
-rw-r--r--services/tests/displayservicetests/Android.bp1
-rw-r--r--services/tests/displayservicetests/src/com/android/server/display/AutomaticBrightnessControllerTest.java20
-rw-r--r--services/tests/displayservicetests/src/com/android/server/display/BrightnessMappingStrategyTest.java14
-rw-r--r--services/tests/displayservicetests/src/com/android/server/display/DisplayManagerServiceTest.java159
-rw-r--r--services/tests/displayservicetests/src/com/android/server/display/DisplayPowerController2Test.java63
-rw-r--r--services/tests/displayservicetests/src/com/android/server/display/DisplayPowerControllerTest.java63
-rw-r--r--services/tests/displayservicetests/src/com/android/server/display/DisplayPowerStateTest.java64
-rw-r--r--services/tests/displayservicetests/src/com/android/server/display/LogicalDisplayMapperTest.java54
-rw-r--r--services/tests/mockingservicestests/src/com/android/server/display/SmallAreaDetectionControllerTest.java138
-rw-r--r--services/tests/mockingservicestests/src/com/android/server/pm/PackageArchiverServiceTest.java177
-rw-r--r--services/tests/mockingservicestests/src/com/android/server/utils/FoldSettingProviderTest.java143
-rw-r--r--services/tests/powerstatstests/src/com/android/server/power/stats/BatteryUsageStatsRule.java4
-rw-r--r--services/tests/powerstatstests/src/com/android/server/power/stats/BatteryUsageStatsTest.java10
-rw-r--r--services/tests/servicestests/assets/PolicyVersionUpgraderTest/device_policies_keep_profiles_running_false.xml10
-rw-r--r--services/tests/servicestests/assets/PolicyVersionUpgraderTest/device_policies_keep_profiles_running_true.xml10
-rw-r--r--services/tests/servicestests/src/com/android/server/biometrics/AuthenticationStatsCollectorTest.java5
-rw-r--r--services/tests/servicestests/src/com/android/server/biometrics/AuthenticationStatsPersisterTest.java14
-rw-r--r--services/tests/servicestests/src/com/android/server/companion/virtual/VirtualDeviceManagerServiceTest.java68
-rw-r--r--services/tests/servicestests/src/com/android/server/companion/virtual/VirtualDeviceTest.java59
-rw-r--r--services/tests/servicestests/src/com/android/server/companion/virtual/audio/VirtualAudioControllerTest.java10
-rw-r--r--services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java8
-rw-r--r--services/tests/servicestests/src/com/android/server/devicepolicy/PolicyVersionUpgraderTest.java107
-rw-r--r--services/tests/servicestests/src/com/android/server/pm/UserManagerTest.java18
-rw-r--r--services/tests/servicestests/src/com/android/server/pm/UserRestrictionsUtilsTest.java4
-rw-r--r--services/tests/uiservicestests/src/com/android/server/notification/ZenModeHelperTest.java137
-rw-r--r--services/tests/vibrator/src/com/android/server/vibrator/HapticFeedbackCustomizationTest.java17
-rw-r--r--services/tests/vibrator/src/com/android/server/vibrator/HapticFeedbackVibrationProviderTest.java90
-rw-r--r--services/tests/vibrator/src/com/android/server/vibrator/VibratorManagerServiceTest.java100
-rw-r--r--services/tests/wmtests/src/com/android/server/policy/ShortcutLoggingTests.java6
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/ActivityStartInterceptorTest.java89
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java3
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/DisplayPolicyTests.java13
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/DisplayRotationTests.java11
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/DisplayWindowPolicyControllerTests.java23
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/LetterboxConfigurationPersisterTest.java2
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/LetterboxConfigurationTest.java38
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/TaskLaunchParamsModifierTests.java33
-rw-r--r--startop/apps/ColorChanging/app/build.gradle2
-rw-r--r--startop/apps/ColorChanging/app/proguard-rules.pro21
-rw-r--r--telecomm/java/android/telecom/Call.java3
-rw-r--r--telecomm/java/android/telecom/CallEndpoint.java2
-rw-r--r--telephony/java/android/telephony/CarrierConfigManager.java20
-rw-r--r--telephony/java/android/telephony/TelephonyManager.java135
-rw-r--r--telephony/java/android/telephony/satellite/SatelliteManager.java434
-rw-r--r--telephony/java/android/telephony/satellite/SatelliteTransmissionUpdateCallback.java4
-rw-r--r--telephony/java/android/telephony/satellite/stub/ISatellite.aidl60
-rw-r--r--telephony/java/android/telephony/satellite/stub/ISatelliteListener.aidl1
-rw-r--r--telephony/java/android/telephony/satellite/stub/SatelliteImplBase.java100
-rw-r--r--telephony/java/android/telephony/satellite/stub/SatelliteResult.aidl (renamed from telephony/java/android/telephony/satellite/stub/SatelliteError.aidl)44
-rw-r--r--telephony/java/com/android/internal/telephony/ITelephony.aidl38
-rw-r--r--tests/ApkVerityTest/ApkVerityTestApp/feature_split/AndroidManifest.xml25
-rw-r--r--tests/ApkVerityTest/src/com/android/apkverity/ApkVerityTest.java579
-rw-r--r--tests/ApkVerityTest/src/com/android/apkverity/BaseInstallMultiple.java140
-rw-r--r--tests/ApkVerityTest/testdata/ApkVerityTestApp.dmbin237348 -> 0 bytes
-rw-r--r--tests/ApkVerityTest/testdata/ApkVerityTestAppSplit.dmbin237025 -> 0 bytes
-rw-r--r--tests/ApkVerityTest/testdata/README.md13
-rw-r--r--tests/BatteryStatsPerfTest/src/com/android/internal/os/BatteryUsageStatsPerfTest.java2
-rw-r--r--tests/ChoreographerTests/src/main/java/android/view/choreographertests/AttachedChoreographerTest.java2
-rw-r--r--tests/FlickerTests/Android.bp1
-rw-r--r--tests/FlickerTests/AndroidTestTemplate.xml2
-rw-r--r--tests/FlickerTests/manifests/AndroidManifest.xml8
-rw-r--r--tests/FlickerTests/res/xml/network_security_config.xml22
-rw-r--r--tests/FsVerityTest/Android.bp (renamed from tests/ApkVerityTest/Android.bp)14
-rw-r--r--tests/FsVerityTest/AndroidTest.xml (renamed from tests/ApkVerityTest/AndroidTest.xml)22
-rw-r--r--tests/FsVerityTest/FsVerityTestApp/Android.bp (renamed from tests/ApkVerityTest/ApkVerityTestApp/Android.bp)17
-rw-r--r--tests/FsVerityTest/FsVerityTestApp/AndroidManifest.xml (renamed from tests/ApkVerityTest/ApkVerityTestApp/AndroidManifest.xml)6
-rw-r--r--tests/FsVerityTest/FsVerityTestApp/src/com/android/fsverity/Helper.java108
-rw-r--r--tests/FsVerityTest/OWNERS (renamed from tests/ApkVerityTest/OWNERS)0
-rw-r--r--tests/FsVerityTest/TEST_MAPPING (renamed from tests/ApkVerityTest/TEST_MAPPING)6
-rw-r--r--tests/FsVerityTest/block_device_writer/Android.bp (renamed from tests/ApkVerityTest/block_device_writer/Android.bp)0
-rw-r--r--tests/FsVerityTest/block_device_writer/block_device_writer.cpp (renamed from tests/ApkVerityTest/block_device_writer/block_device_writer.cpp)0
-rw-r--r--tests/FsVerityTest/block_device_writer/src/com/android/blockdevicewriter/BlockDeviceWriter.java (renamed from tests/ApkVerityTest/block_device_writer/src/com/android/blockdevicewriter/BlockDeviceWriter.java)0
-rw-r--r--tests/FsVerityTest/src/com/android/fsverity/FsVerityHostTest.java103
-rw-r--r--tests/FsVerityTest/testdata/Android.bp (renamed from tests/ApkVerityTest/testdata/Android.bp)48
-rw-r--r--tests/FsVerityTest/testdata/ApkVerityTestCert.der (renamed from tests/ApkVerityTest/testdata/ApkVerityTestCert.der)bin1330 -> 1330 bytes
-rw-r--r--tests/FsVerityTest/testdata/ApkVerityTestCert.pem (renamed from tests/ApkVerityTest/testdata/ApkVerityTestCert.pem)0
-rw-r--r--tests/FsVerityTest/testdata/ApkVerityTestKey.pem (renamed from tests/ApkVerityTest/testdata/ApkVerityTestKey.pem)0
-rw-r--r--tests/SurfaceViewBufferTests/Android.bp8
-rw-r--r--tests/SurfaceViewBufferTests/AndroidManifest.xml5
-rw-r--r--tests/SurfaceViewBufferTests/res/xml/network_security_config.xml22
-rw-r--r--tests/SurfaceViewBufferTests/src/com/android/test/SurfaceTracingTestBase.kt24
-rw-r--r--tests/TaskOrganizerTest/Android.bp8
-rw-r--r--tests/TaskOrganizerTest/AndroidManifest.xml4
-rw-r--r--tests/TaskOrganizerTest/res/xml/network_security_config.xml21
-rw-r--r--tests/TaskOrganizerTest/src/com/android/test/taskembed/ResizeTasksSyncTest.kt12
-rw-r--r--tools/hoststubgen/.gitignore3
-rw-r--r--tools/hoststubgen/OWNERS3
-rw-r--r--tools/hoststubgen/README.md76
-rw-r--r--tools/hoststubgen/TEST_MAPPING6
-rw-r--r--tools/hoststubgen/common.sh116
-rw-r--r--tools/hoststubgen/hoststubgen/.gitignore1
-rw-r--r--tools/hoststubgen/hoststubgen/Android.bp303
-rw-r--r--tools/hoststubgen/hoststubgen/annotations-src/android/hosttest/annotation/HostSideTestClassLoadHook.java38
-rw-r--r--tools/hoststubgen/hoststubgen/annotations-src/android/hosttest/annotation/HostSideTestKeep.java43
-rw-r--r--tools/hoststubgen/hoststubgen/annotations-src/android/hosttest/annotation/HostSideTestNativeSubstitutionClass.java35
-rw-r--r--tools/hoststubgen/hoststubgen/annotations-src/android/hosttest/annotation/HostSideTestRemove.java39
-rw-r--r--tools/hoststubgen/hoststubgen/annotations-src/android/hosttest/annotation/HostSideTestStub.java43
-rw-r--r--tools/hoststubgen/hoststubgen/annotations-src/android/hosttest/annotation/HostSideTestSubstitute.java40
-rw-r--r--tools/hoststubgen/hoststubgen/annotations-src/android/hosttest/annotation/HostSideTestThrow.java36
-rw-r--r--tools/hoststubgen/hoststubgen/annotations-src/android/hosttest/annotation/HostSideTestWholeClassKeep.java34
-rw-r--r--tools/hoststubgen/hoststubgen/annotations-src/android/hosttest/annotation/HostSideTestWholeClassStub.java35
-rw-r--r--tools/hoststubgen/hoststubgen/annotations-src/android/hosttest/annotation/tests/HostSideTestSuppress.java31
-rw-r--r--tools/hoststubgen/hoststubgen/framework-policy-override.txt98
-rw-r--r--tools/hoststubgen/hoststubgen/helper-framework-buildtime-src/android/test/AndroidTestCase.java27
-rw-r--r--tools/hoststubgen/hoststubgen/helper-framework-buildtime-src/androidx/annotation/NonNull.java40
-rw-r--r--tools/hoststubgen/hoststubgen/helper-framework-buildtime-src/androidx/annotation/Nullable.java47
-rw-r--r--tools/hoststubgen/hoststubgen/helper-framework-buildtime-src/androidx/test/ext/junit/runners/AndroidJUnit4.java30
-rw-r--r--tools/hoststubgen/hoststubgen/helper-framework-buildtime-src/androidx/test/filters/FlakyTest.java46
-rw-r--r--tools/hoststubgen/hoststubgen/helper-framework-buildtime-src/androidx/test/filters/LargeTest.java44
-rw-r--r--tools/hoststubgen/hoststubgen/helper-framework-buildtime-src/androidx/test/filters/MediumTest.java45
-rw-r--r--tools/hoststubgen/hoststubgen/helper-framework-buildtime-src/androidx/test/filters/RequiresDevice.java30
-rw-r--r--tools/hoststubgen/hoststubgen/helper-framework-buildtime-src/androidx/test/filters/SdkSuppress.java47
-rw-r--r--tools/hoststubgen/hoststubgen/helper-framework-buildtime-src/androidx/test/filters/SmallTest.java46
-rw-r--r--tools/hoststubgen/hoststubgen/helper-framework-buildtime-src/androidx/test/filters/Suppress.java36
-rw-r--r--tools/hoststubgen/hoststubgen/helper-framework-buildtime-src/androidx/test/runner/AndroidJUnit4.java24
-rw-r--r--tools/hoststubgen/hoststubgen/helper-framework-runtime-src/framework/com/android/hoststubgen/nativesubstitution/Log_host.java61
-rw-r--r--tools/hoststubgen/hoststubgen/helper-framework-runtime-src/framework/com/android/hoststubgen/nativesubstitution/Parcel_host.java404
-rw-r--r--tools/hoststubgen/hoststubgen/helper-framework-runtime-src/framework/com/android/hoststubgen/nativesubstitution/SystemProperties_host.java56
-rw-r--r--tools/hoststubgen/hoststubgen/helper-framework-runtime-src/framework/com/android/hoststubgen/runtimehelper/ClassLoadHook.java182
-rw-r--r--tools/hoststubgen/hoststubgen/helper-framework-runtime-src/libcore-fake/dalvik/system/VMRuntime.java45
-rw-r--r--tools/hoststubgen/hoststubgen/helper-framework-runtime-src/libcore-fake/libcore/util/EmptyArray.java54
-rw-r--r--tools/hoststubgen/hoststubgen/helper-framework-runtime-src/libcore-fake/libcore/util/SneakyThrow.java33
-rw-r--r--tools/hoststubgen/hoststubgen/helper-runtime-src/com/android/hoststubgen/hosthelper/HostStubGenProcessedKeepClass.java34
-rw-r--r--tools/hoststubgen/hoststubgen/helper-runtime-src/com/android/hoststubgen/hosthelper/HostStubGenProcessedStubClass.java34
-rw-r--r--tools/hoststubgen/hoststubgen/helper-runtime-src/com/android/hoststubgen/hosthelper/HostTestException.java26
-rw-r--r--tools/hoststubgen/hoststubgen/helper-runtime-src/com/android/hoststubgen/hosthelper/HostTestSuite.java102
-rw-r--r--tools/hoststubgen/hoststubgen/helper-runtime-src/com/android/hoststubgen/hosthelper/HostTestUtils.java197
-rw-r--r--tools/hoststubgen/hoststubgen/hoststubgen-standard-options.txt39
-rw-r--r--tools/hoststubgen/hoststubgen/jarjar-rules.txt2
-rw-r--r--tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/Exceptions.kt48
-rw-r--r--tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/HostStubGen.kt402
-rw-r--r--tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/HostStubGenErrors.kt24
-rw-r--r--tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/HostStubGenLogger.kt198
-rw-r--r--tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/HostStubGenOptions.kt307
-rw-r--r--tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/Main.kt55
-rw-r--r--tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/Utils.kt33
-rw-r--r--tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/asm/AsmUtils.kt177
-rw-r--r--tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/asm/ClassNodes.kt149
-rw-r--r--tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/AnnotationBasedFilter.kt401
-rw-r--r--tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/ClassWidePolicyPropagatingFilter.kt80
-rw-r--r--tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/ConstantFilter.kt69
-rw-r--r--tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/DelegatingFilter.kt72
-rw-r--r--tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/FilterPolicy.kt133
-rw-r--r--tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/FilterPolicyWithReason.kt66
-rw-r--r--tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/ImplicitOutputFilter.kt86
-rw-r--r--tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/InMemoryOutputFilter.kt138
-rw-r--r--tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/KeepAllClassesFilter.kt30
-rw-r--r--tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/OutputFilter.kt81
-rw-r--r--tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/StubIntersectingFilter.kt91
-rw-r--r--tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/TextFileFilterPolicyParser.kt213
-rw-r--r--tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/visitors/BaseAdapter.kt252
-rw-r--r--tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/visitors/BodyReplacingMethodVisitor.kt354
-rw-r--r--tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/visitors/ImplGeneratingAdapter.kt370
-rw-r--r--tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/visitors/StubGeneratingAdapter.kt85
-rw-r--r--tools/hoststubgen/hoststubgen/test-framework/Android.bp19
-rw-r--r--tools/hoststubgen/hoststubgen/test-framework/AndroidHostTest.bp44
-rw-r--r--tools/hoststubgen/hoststubgen/test-framework/AndroidTest-host.xml29
-rw-r--r--tools/hoststubgen/hoststubgen/test-framework/README.md27
-rwxr-xr-xtools/hoststubgen/hoststubgen/test-framework/run-test-without-atest.sh85
-rw-r--r--tools/hoststubgen/hoststubgen/test-framework/src/com/android/hoststubgen/frameworktest/ArrayMapTest.java737
-rw-r--r--tools/hoststubgen/hoststubgen/test-framework/src/com/android/hoststubgen/frameworktest/LogTest.java48
-rw-r--r--tools/hoststubgen/hoststubgen/test-tiny-framework/Android.bp141
-rw-r--r--tools/hoststubgen/hoststubgen/test-tiny-framework/AndroidTest-host.xml29
-rw-r--r--tools/hoststubgen/hoststubgen/test-tiny-framework/README.md27
-rwxr-xr-xtools/hoststubgen/hoststubgen/test-tiny-framework/diff-and-update-golden.sh134
-rw-r--r--tools/hoststubgen/hoststubgen/test-tiny-framework/golden-output/01-hoststubgen-test-tiny-framework-orig-dump.txt1671
-rw-r--r--tools/hoststubgen/hoststubgen/test-tiny-framework/golden-output/02-hoststubgen-test-tiny-framework-host-stub-dump.txt837
-rw-r--r--tools/hoststubgen/hoststubgen/test-tiny-framework/golden-output/03-hoststubgen-test-tiny-framework-host-impl-dump.txt1774
-rw-r--r--tools/hoststubgen/hoststubgen/test-tiny-framework/policy-override-tiny-framework.txt17
-rwxr-xr-xtools/hoststubgen/hoststubgen/test-tiny-framework/run-test-manually.sh132
-rwxr-xr-xtools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework-dump-test.py64
-rw-r--r--tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck.java57
-rw-r--r--tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkClassAnnotations.java89
-rw-r--r--tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkClassClassWideAnnotations.java74
-rw-r--r--tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkClassLoadHook.java33
-rw-r--r--tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkClassWithInitializer.java30
-rw-r--r--tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkExceptionTester.java29
-rw-r--r--tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy.java66
-rw-r--r--tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkNative.java35
-rw-r--r--tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkNative_host.java31
-rw-r--r--tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses.java87
-rw-r--r--tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-test/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkBenchmark.java70
-rw-r--r--tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-test/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkClassTest.java143
-rw-r--r--tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-test/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkClassWithAnnotTest.java66
-rw-r--r--tools/hoststubgen/scripts/Android.bp26
-rwxr-xr-xtools/hoststubgen/scripts/build-framework-hostside-jars-and-extract.sh35
-rwxr-xr-xtools/hoststubgen/scripts/build-framework-hostside-jars-without-genrules.sh76
-rwxr-xr-xtools/hoststubgen/scripts/dump-jar163
-rwxr-xr-xtools/hoststubgen/scripts/run-all-tests.sh45
-rwxr-xr-xtools/hoststubgen/scripts/run-ravenwood-test129
1088 files changed, 28980 insertions, 10187 deletions
diff --git a/AconfigFlags.bp b/AconfigFlags.bp
index fd92979bd593..aabe87f9787e 100644
--- a/AconfigFlags.bp
+++ b/AconfigFlags.bp
@@ -18,12 +18,19 @@ java_defaults {
// Add java_aconfig_libraries to here to add them to the core framework
srcs: [
+ ":android.app.usage.flags-aconfig-java{.generated_srcjars}",
":android.os.flags-aconfig-java{.generated_srcjars}",
+ ":android.os.vibrator.flags-aconfig-java{.generated_srcjars}",
":android.security.flags-aconfig-java{.generated_srcjars}",
":camera_platform_flags_core_java_lib{.generated_srcjars}",
":com.android.window.flags.window-aconfig-java{.generated_srcjars}",
":com.android.text.flags-aconfig-java{.generated_srcjars}",
+ ":telecom_flags_core_java_lib{.generated_srcjars}",
+ ":android.companion.virtual.flags-aconfig-java{.generated_srcjars}",
+ ":android.view.inputmethod.flags-aconfig-java{.generated_srcjars}",
],
+ // Add aconfig-annotations-lib as a dependency for the optimization
+ libs: ["aconfig-annotations-lib"],
}
// Default flags for java_aconfig_libraries that go into framework-minus-apex
@@ -41,6 +48,13 @@ java_aconfig_library {
defaults: ["framework-minus-apex-aconfig-java-defaults"],
}
+// Telecom
+java_aconfig_library {
+ name: "telecom_flags_core_java_lib",
+ aconfig_declarations: "telecom_flags",
+ defaults: ["framework-minus-apex-aconfig-java-defaults"],
+}
+
// Window
aconfig_declarations {
name: "com.android.window.flags.window-aconfig",
@@ -67,6 +81,11 @@ java_aconfig_library {
defaults: ["framework-minus-apex-aconfig-java-defaults"],
}
+cc_aconfig_library {
+ name: "aconfig_text_flags_c_lib",
+ aconfig_declarations: "com.android.text.flags-aconfig",
+}
+
// Security
aconfig_declarations {
name: "android.security.flags-aconfig",
@@ -80,6 +99,27 @@ java_aconfig_library {
defaults: ["framework-minus-apex-aconfig-java-defaults"],
}
+java_aconfig_library {
+ name: "android.security.flags-aconfig-java-host",
+ aconfig_declarations: "android.security.flags-aconfig",
+ host_supported: true,
+ test: true,
+ defaults: ["framework-minus-apex-aconfig-java-defaults"],
+}
+
+// UsageStats
+aconfig_declarations {
+ name: "android.app.usage.flags-aconfig",
+ package: "android.app.usage",
+ srcs: ["core/java/android/app/usage/*.aconfig"],
+}
+
+java_aconfig_library {
+ name: "android.app.usage.flags-aconfig-java",
+ aconfig_declarations: "android.app.usage.flags-aconfig",
+ defaults: ["framework-minus-apex-aconfig-java-defaults"],
+}
+
// OS
aconfig_declarations {
name: "android.os.flags-aconfig",
@@ -92,3 +132,42 @@ java_aconfig_library {
aconfig_declarations: "android.os.flags-aconfig",
defaults: ["framework-minus-apex-aconfig-java-defaults"],
}
+
+// VirtualDeviceManager
+java_aconfig_library {
+ name: "android.companion.virtual.flags-aconfig-java",
+ aconfig_declarations: "android.companion.virtual.flags-aconfig",
+ defaults: ["framework-minus-apex-aconfig-java-defaults"],
+}
+
+aconfig_declarations {
+ name: "android.companion.virtual.flags-aconfig",
+ package: "android.companion.virtual.flags",
+ srcs: ["core/java/android/companion/virtual/*.aconfig"],
+}
+
+// InputMethod
+aconfig_declarations {
+ name: "android.view.inputmethod.flags-aconfig",
+ package: "android.view.inputmethod",
+ srcs: ["core/java/android/view/inputmethod/flags.aconfig"],
+}
+
+java_aconfig_library {
+ name: "android.view.inputmethod.flags-aconfig-java",
+ aconfig_declarations: "android.view.inputmethod.flags-aconfig",
+ defaults: ["framework-minus-apex-aconfig-java-defaults"],
+}
+
+// Vibrator
+aconfig_declarations {
+ name: "android.os.vibrator.flags-aconfig",
+ package: "android.os.vibrator",
+ srcs: ["core/java/android/os/vibrator/*.aconfig"],
+}
+
+java_aconfig_library {
+ name: "android.os.vibrator.flags-aconfig-java",
+ aconfig_declarations: "android.os.vibrator.flags-aconfig",
+ defaults: ["framework-minus-apex-aconfig-java-defaults"],
+}
diff --git a/Android.bp b/Android.bp
index 431f0b9317ac..57a5a3c6bff1 100644
--- a/Android.bp
+++ b/Android.bp
@@ -71,7 +71,6 @@ filegroup {
":framework-jobscheduler-sources", // jobscheduler is not a module for R
":framework-keystore-sources",
":framework-identity-sources",
- ":framework-location-sources",
":framework-mca-effect-sources",
":framework-mca-filterfw-sources",
":framework-mca-filterpacks-sources",
@@ -163,6 +162,12 @@ java_library {
//same purpose.
"//external/robolectric:__subpackages__",
"//frameworks/layoutlib:__subpackages__",
+
+ // This is for the same purpose as robolectric -- to build "framework.jar" for host-side
+ // testing.
+ // TODO: Once Ravenwood is stable, move the host side jar targets to this directory,
+ // and remove this line.
+ "//frameworks/base/tools/hoststubgen:__subpackages__",
],
}
@@ -177,7 +182,6 @@ java_defaults {
"graphics/java",
"identity/java",
"keystore/java",
- "location/java",
"media/java",
"media/mca/effect/java",
"media/mca/filterfw/java",
@@ -287,7 +291,6 @@ java_defaults {
":framework-jobscheduler-sources",
":framework-keystore-sources",
":framework-identity-sources",
- ":framework-location-sources",
":framework-mca-effect-sources",
":framework-mca-filterfw-sources",
":framework-mca-filterpacks-sources",
@@ -405,6 +408,7 @@ java_defaults {
"audiopolicy-aidl-java",
"sounddose-aidl-java",
"modules-utils-expresslog",
+ "hoststubgen-annotations",
],
}
diff --git a/apex/blobstore/service/java/com/android/server/blob/BlobStoreManagerService.java b/apex/blobstore/service/java/com/android/server/blob/BlobStoreManagerService.java
index 9d363c806f5f..3af36ebb08ca 100644
--- a/apex/blobstore/service/java/com/android/server/blob/BlobStoreManagerService.java
+++ b/apex/blobstore/service/java/com/android/server/blob/BlobStoreManagerService.java
@@ -28,6 +28,7 @@ import static android.content.pm.PackageManager.MATCH_UNINSTALLED_PACKAGES;
import static android.os.UserHandle.USER_CURRENT;
import static android.os.UserHandle.USER_NULL;
+import static com.android.internal.util.ConcurrentUtils.DIRECT_EXECUTOR;
import static com.android.server.blob.BlobStoreConfig.INVALID_BLOB_ID;
import static com.android.server.blob.BlobStoreConfig.INVALID_BLOB_SIZE;
import static com.android.server.blob.BlobStoreConfig.LOGV;
@@ -1915,7 +1916,7 @@ public class BlobStoreManagerService extends SystemService {
mStatsManager.setPullAtomCallback(
FrameworkStatsLog.BLOB_INFO,
null, // use default PullAtomMetadata values
- BackgroundThread.getExecutor(),
+ DIRECT_EXECUTOR,
mStatsCallbackImpl
);
}
diff --git a/apex/jobscheduler/framework/java/android/os/PowerExemptionManager.java b/apex/jobscheduler/framework/java/android/os/PowerExemptionManager.java
index 17076bc4eea4..66c1efca0000 100644
--- a/apex/jobscheduler/framework/java/android/os/PowerExemptionManager.java
+++ b/apex/jobscheduler/framework/java/android/os/PowerExemptionManager.java
@@ -419,6 +419,14 @@ public class PowerExemptionManager {
*/
public static final int REASON_SYSTEM_EXEMPT_APP_OP = 327;
+ /**
+ * Granted by {@link com.android.server.pm.PackageArchiverService} to the installer responsible
+ * for unarchiving an app.
+ *
+ * @hide
+ */
+ public static final int REASON_PACKAGE_UNARCHIVE = 328;
+
/** @hide The app requests out-out. */
public static final int REASON_OPT_OUT_REQUESTED = 1000;
@@ -502,6 +510,7 @@ public class PowerExemptionManager {
REASON_ACTIVE_DEVICE_ADMIN,
REASON_MEDIA_NOTIFICATION_TRANSFER,
REASON_PACKAGE_INSTALLER,
+ REASON_PACKAGE_UNARCHIVE,
})
@Retention(RetentionPolicy.SOURCE)
public @interface ReasonCode {}
diff --git a/apex/jobscheduler/service/java/com/android/server/DeviceIdleController.java b/apex/jobscheduler/service/java/com/android/server/DeviceIdleController.java
index 1be07fdfcceb..b8596d5a3926 100644
--- a/apex/jobscheduler/service/java/com/android/server/DeviceIdleController.java
+++ b/apex/jobscheduler/service/java/com/android/server/DeviceIdleController.java
@@ -538,7 +538,7 @@ public class DeviceIdleController extends SystemService
/**
* Package names the system has white-listed to opt out of power save restrictions,
- * except for device idle mode.
+ * except for device idle modes (light and full doze).
*/
private final ArrayMap<String, Integer> mPowerSaveWhitelistAppsExceptIdle = new ArrayMap<>();
diff --git a/apex/jobscheduler/service/java/com/android/server/alarm/MetricsHelper.java b/apex/jobscheduler/service/java/com/android/server/alarm/MetricsHelper.java
index 90a6455a4a8b..adb4d85101a3 100644
--- a/apex/jobscheduler/service/java/com/android/server/alarm/MetricsHelper.java
+++ b/apex/jobscheduler/service/java/com/android/server/alarm/MetricsHelper.java
@@ -16,6 +16,7 @@
package com.android.server.alarm;
+import static com.android.internal.util.ConcurrentUtils.DIRECT_EXECUTOR;
import static com.android.internal.util.FrameworkStatsLog.ALARM_SCHEDULED__EXACT_ALARM_ALLOWED_REASON__ALLOW_LIST;
import static com.android.internal.util.FrameworkStatsLog.ALARM_SCHEDULED__EXACT_ALARM_ALLOWED_REASON__CHANGE_DISABLED;
import static com.android.internal.util.FrameworkStatsLog.ALARM_SCHEDULED__EXACT_ALARM_ALLOWED_REASON__LISTENER;
@@ -31,7 +32,6 @@ import android.app.StatsManager;
import android.content.Context;
import android.os.SystemClock;
-import com.android.internal.os.BackgroundThread;
import com.android.internal.util.FrameworkStatsLog;
import java.util.function.Supplier;
@@ -51,7 +51,7 @@ class MetricsHelper {
void registerPuller(Supplier<AlarmStore> alarmStoreSupplier) {
final StatsManager statsManager = mContext.getSystemService(StatsManager.class);
statsManager.setPullAtomCallback(FrameworkStatsLog.PENDING_ALARM_INFO, null,
- BackgroundThread.getExecutor(), (atomTag, data) -> {
+ DIRECT_EXECUTOR, (atomTag, data) -> {
if (atomTag != FrameworkStatsLog.PENDING_ALARM_INFO) {
throw new UnsupportedOperationException("Unknown tag" + atomTag);
}
diff --git a/boot/preloaded-classes b/boot/preloaded-classes
index 2a9375caab51..19d6f04f4169 100644
--- a/boot/preloaded-classes
+++ b/boot/preloaded-classes
@@ -12682,7 +12682,6 @@ com.android.internal.util.LatencyTracker$$ExternalSyntheticLambda2
com.android.internal.util.LatencyTracker$Action
com.android.internal.util.LatencyTracker$ActionProperties
com.android.internal.util.LatencyTracker$FrameworkStatsLogEvent
-com.android.internal.util.LatencyTracker$SLatencyTrackerHolder
com.android.internal.util.LatencyTracker$Session$$ExternalSyntheticLambda0
com.android.internal.util.LatencyTracker$Session
com.android.internal.util.LatencyTracker
diff --git a/cmds/idmap2/libidmap2/RawPrintVisitor.cpp b/cmds/idmap2/libidmap2/RawPrintVisitor.cpp
index 174d85c71828..9d04a7f87400 100644
--- a/cmds/idmap2/libidmap2/RawPrintVisitor.cpp
+++ b/cmds/idmap2/libidmap2/RawPrintVisitor.cpp
@@ -96,7 +96,7 @@ void RawPrintVisitor::visit(const IdmapData& data ATTRIBUTE_UNUSED) {
auto value = target_entry_value.second;
print(target_entry_value.first.to_string(), false, "config: %s",
- target_entry_value.first.toString().string());
+ target_entry_value.first.toString().c_str());
print(value.data_type, "type: %s",
utils::DataTypeToString(value.data_type).data());
diff --git a/cmds/idmap2/libidmap2/XmlParser.cpp b/cmds/idmap2/libidmap2/XmlParser.cpp
index 1d784600459d..780715561006 100644
--- a/cmds/idmap2/libidmap2/XmlParser.cpp
+++ b/cmds/idmap2/libidmap2/XmlParser.cpp
@@ -130,11 +130,14 @@ Result<Res_value> XmlParser::Node::GetAttributeValue(ResourceId attr,
}
Result<Res_value> XmlParser::Node::GetAttributeValue(const std::string& name) const {
+ String16 name16;
return FindAttribute(parser_, name, [&](size_t index) -> bool {
- size_t len;
- const String16 key16(parser_.getAttributeName(index, &len));
- std::string key = String8(key16).c_str();
- return key == name;
+ if (name16.empty()) {
+ name16 = String16(name.c_str(), name.size());
+ }
+ size_t key_len;
+ const auto key16 = parser_.getAttributeName(index, &key_len);
+ return key16 && name16.size() == key_len && name16 == key16;
});
}
diff --git a/config/preloaded-classes b/config/preloaded-classes
index 214b12c0ad79..0351a0007a8b 100644
--- a/config/preloaded-classes
+++ b/config/preloaded-classes
@@ -12713,7 +12713,6 @@ com.android.internal.util.LatencyTracker$$ExternalSyntheticLambda2
com.android.internal.util.LatencyTracker$Action
com.android.internal.util.LatencyTracker$ActionProperties
com.android.internal.util.LatencyTracker$FrameworkStatsLogEvent
-com.android.internal.util.LatencyTracker$SLatencyTrackerHolder
com.android.internal.util.LatencyTracker$Session$$ExternalSyntheticLambda0
com.android.internal.util.LatencyTracker$Session
com.android.internal.util.LatencyTracker
diff --git a/core/api/current.txt b/core/api/current.txt
index e00362407fc7..0e5a5157c090 100644
--- a/core/api/current.txt
+++ b/core/api/current.txt
@@ -9681,14 +9681,24 @@ package android.companion.virtual {
public final class VirtualDevice implements android.os.Parcelable {
method public int describeContents();
method public int getDeviceId();
+ method @FlaggedApi(Flags.FLAG_VDM_PUBLIC_APIS) @NonNull public int[] getDisplayIds();
method @Nullable public String getName();
method @Nullable public String getPersistentDeviceId();
+ method @FlaggedApi(Flags.FLAG_VDM_PUBLIC_APIS) public boolean hasCustomSensorSupport();
method public void writeToParcel(@NonNull android.os.Parcel, int);
field @NonNull public static final android.os.Parcelable.Creator<android.companion.virtual.VirtualDevice> CREATOR;
}
public final class VirtualDeviceManager {
+ method @FlaggedApi(Flags.FLAG_VDM_PUBLIC_APIS) @Nullable public android.companion.virtual.VirtualDevice getVirtualDevice(int);
method @NonNull public java.util.List<android.companion.virtual.VirtualDevice> getVirtualDevices();
+ method @FlaggedApi(Flags.FLAG_VDM_PUBLIC_APIS) public void registerVirtualDeviceListener(@NonNull java.util.concurrent.Executor, @NonNull android.companion.virtual.VirtualDeviceManager.VirtualDeviceListener);
+ method @FlaggedApi(Flags.FLAG_VDM_PUBLIC_APIS) public void unregisterVirtualDeviceListener(@NonNull android.companion.virtual.VirtualDeviceManager.VirtualDeviceListener);
+ }
+
+ @FlaggedApi(Flags.FLAG_VDM_PUBLIC_APIS) public static interface VirtualDeviceManager.VirtualDeviceListener {
+ method public default void onVirtualDeviceClosed(int);
+ method public default void onVirtualDeviceCreated(int);
}
}
@@ -20405,513 +20415,6 @@ package android.inputmethodservice {
package android.location {
- public class Address implements android.os.Parcelable {
- ctor public Address(java.util.Locale);
- method public void clearLatitude();
- method public void clearLongitude();
- method public int describeContents();
- method public String getAddressLine(int);
- method public String getAdminArea();
- method public String getCountryCode();
- method public String getCountryName();
- method public android.os.Bundle getExtras();
- method public String getFeatureName();
- method public double getLatitude();
- method public java.util.Locale getLocale();
- method public String getLocality();
- method public double getLongitude();
- method public int getMaxAddressLineIndex();
- method public String getPhone();
- method public String getPostalCode();
- method public String getPremises();
- method public String getSubAdminArea();
- method public String getSubLocality();
- method public String getSubThoroughfare();
- method public String getThoroughfare();
- method public String getUrl();
- method public boolean hasLatitude();
- method public boolean hasLongitude();
- method public void setAddressLine(int, String);
- method public void setAdminArea(String);
- method public void setCountryCode(String);
- method public void setCountryName(String);
- method public void setExtras(android.os.Bundle);
- method public void setFeatureName(String);
- method public void setLatitude(double);
- method public void setLocality(String);
- method public void setLongitude(double);
- method public void setPhone(String);
- method public void setPostalCode(String);
- method public void setPremises(String);
- method public void setSubAdminArea(String);
- method public void setSubLocality(String);
- method public void setSubThoroughfare(String);
- method public void setThoroughfare(String);
- method public void setUrl(String);
- method public void writeToParcel(android.os.Parcel, int);
- field @NonNull public static final android.os.Parcelable.Creator<android.location.Address> CREATOR;
- }
-
- @Deprecated public class Criteria implements android.os.Parcelable {
- ctor @Deprecated public Criteria();
- ctor @Deprecated public Criteria(android.location.Criteria);
- method @Deprecated public int describeContents();
- method @Deprecated public int getAccuracy();
- method @Deprecated public int getBearingAccuracy();
- method @Deprecated public int getHorizontalAccuracy();
- method @Deprecated public int getPowerRequirement();
- method @Deprecated public int getSpeedAccuracy();
- method @Deprecated public int getVerticalAccuracy();
- method @Deprecated public boolean isAltitudeRequired();
- method @Deprecated public boolean isBearingRequired();
- method @Deprecated public boolean isCostAllowed();
- method @Deprecated public boolean isSpeedRequired();
- method @Deprecated public void setAccuracy(int);
- method @Deprecated public void setAltitudeRequired(boolean);
- method @Deprecated public void setBearingAccuracy(int);
- method @Deprecated public void setBearingRequired(boolean);
- method @Deprecated public void setCostAllowed(boolean);
- method @Deprecated public void setHorizontalAccuracy(int);
- method @Deprecated public void setPowerRequirement(int);
- method @Deprecated public void setSpeedAccuracy(int);
- method @Deprecated public void setSpeedRequired(boolean);
- method @Deprecated public void setVerticalAccuracy(int);
- method @Deprecated public void writeToParcel(android.os.Parcel, int);
- field @Deprecated public static final int ACCURACY_COARSE = 2; // 0x2
- field @Deprecated public static final int ACCURACY_FINE = 1; // 0x1
- field @Deprecated public static final int ACCURACY_HIGH = 3; // 0x3
- field @Deprecated public static final int ACCURACY_LOW = 1; // 0x1
- field @Deprecated public static final int ACCURACY_MEDIUM = 2; // 0x2
- field @Deprecated @NonNull public static final android.os.Parcelable.Creator<android.location.Criteria> CREATOR;
- field @Deprecated public static final int NO_REQUIREMENT = 0; // 0x0
- field @Deprecated public static final int POWER_HIGH = 3; // 0x3
- field @Deprecated public static final int POWER_LOW = 1; // 0x1
- field @Deprecated public static final int POWER_MEDIUM = 2; // 0x2
- }
-
- public final class Geocoder {
- ctor public Geocoder(@NonNull android.content.Context);
- ctor public Geocoder(@NonNull android.content.Context, @NonNull java.util.Locale);
- method @Deprecated @Nullable public java.util.List<android.location.Address> getFromLocation(@FloatRange(from=-90.0, to=90.0) double, @FloatRange(from=-180.0, to=180.0) double, @IntRange int) throws java.io.IOException;
- method public void getFromLocation(@FloatRange(from=-90.0, to=90.0) double, @FloatRange(from=-180.0, to=180.0) double, @IntRange int, @NonNull android.location.Geocoder.GeocodeListener);
- method @Deprecated @Nullable public java.util.List<android.location.Address> getFromLocationName(@NonNull String, @IntRange int) throws java.io.IOException;
- method public void getFromLocationName(@NonNull String, @IntRange int, @NonNull android.location.Geocoder.GeocodeListener);
- method @Deprecated @Nullable public java.util.List<android.location.Address> getFromLocationName(@NonNull String, @IntRange int, @FloatRange(from=-90.0, to=90.0) double, @FloatRange(from=-180.0, to=180.0) double, @FloatRange(from=-90.0, to=90.0) double, @FloatRange(from=-180.0, to=180.0) double) throws java.io.IOException;
- method public void getFromLocationName(@NonNull String, @IntRange int, @FloatRange(from=-90.0, to=90.0) double, @FloatRange(from=-180.0, to=180.0) double, @FloatRange(from=-90.0, to=90.0) double, @FloatRange(from=-180.0, to=180.0) double, @NonNull android.location.Geocoder.GeocodeListener);
- method public static boolean isPresent();
- }
-
- public static interface Geocoder.GeocodeListener {
- method public default void onError(@Nullable String);
- method public void onGeocode(@NonNull java.util.List<android.location.Address>);
- }
-
- public final class GnssAntennaInfo implements android.os.Parcelable {
- method public int describeContents();
- method @FloatRange(from=0.0f) public double getCarrierFrequencyMHz();
- method @NonNull public android.location.GnssAntennaInfo.PhaseCenterOffset getPhaseCenterOffset();
- method @Nullable public android.location.GnssAntennaInfo.SphericalCorrections getPhaseCenterVariationCorrections();
- method @Nullable public android.location.GnssAntennaInfo.SphericalCorrections getSignalGainCorrections();
- method public void writeToParcel(@NonNull android.os.Parcel, int);
- field @NonNull public static final android.os.Parcelable.Creator<android.location.GnssAntennaInfo> CREATOR;
- }
-
- public static class GnssAntennaInfo.Builder {
- ctor @Deprecated public GnssAntennaInfo.Builder();
- ctor public GnssAntennaInfo.Builder(double, @NonNull android.location.GnssAntennaInfo.PhaseCenterOffset);
- ctor public GnssAntennaInfo.Builder(@NonNull android.location.GnssAntennaInfo);
- method @NonNull public android.location.GnssAntennaInfo build();
- method @NonNull public android.location.GnssAntennaInfo.Builder setCarrierFrequencyMHz(@FloatRange(from=0.0f) double);
- method @NonNull public android.location.GnssAntennaInfo.Builder setPhaseCenterOffset(@NonNull android.location.GnssAntennaInfo.PhaseCenterOffset);
- method @NonNull public android.location.GnssAntennaInfo.Builder setPhaseCenterVariationCorrections(@Nullable android.location.GnssAntennaInfo.SphericalCorrections);
- method @NonNull public android.location.GnssAntennaInfo.Builder setSignalGainCorrections(@Nullable android.location.GnssAntennaInfo.SphericalCorrections);
- }
-
- public static interface GnssAntennaInfo.Listener {
- method public void onGnssAntennaInfoReceived(@NonNull java.util.List<android.location.GnssAntennaInfo>);
- }
-
- public static final class GnssAntennaInfo.PhaseCenterOffset implements android.os.Parcelable {
- ctor public GnssAntennaInfo.PhaseCenterOffset(double, double, double, double, double, double);
- method public int describeContents();
- method @FloatRange public double getXOffsetMm();
- method @FloatRange public double getXOffsetUncertaintyMm();
- method @FloatRange public double getYOffsetMm();
- method @FloatRange public double getYOffsetUncertaintyMm();
- method @FloatRange public double getZOffsetMm();
- method @FloatRange public double getZOffsetUncertaintyMm();
- method public void writeToParcel(@NonNull android.os.Parcel, int);
- field @NonNull public static final android.os.Parcelable.Creator<android.location.GnssAntennaInfo.PhaseCenterOffset> CREATOR;
- }
-
- public static final class GnssAntennaInfo.SphericalCorrections implements android.os.Parcelable {
- ctor public GnssAntennaInfo.SphericalCorrections(@NonNull double[][], @NonNull double[][]);
- method public int describeContents();
- method @NonNull public double[][] getCorrectionUncertaintiesArray();
- method @NonNull public double[][] getCorrectionsArray();
- method @FloatRange(from=0.0f, to=180.0f) public double getDeltaPhi();
- method @FloatRange(from=0.0f, to=360.0f) public double getDeltaTheta();
- method public void writeToParcel(@NonNull android.os.Parcel, int);
- field @NonNull public static final android.os.Parcelable.Creator<android.location.GnssAntennaInfo.SphericalCorrections> CREATOR;
- }
-
- public final class GnssAutomaticGainControl implements android.os.Parcelable {
- method public int describeContents();
- method @IntRange(from=0) public long getCarrierFrequencyHz();
- method public int getConstellationType();
- method @FloatRange(from=0xffffd8f0, to=10000) public double getLevelDb();
- method public void writeToParcel(@NonNull android.os.Parcel, int);
- field @NonNull public static final android.os.Parcelable.Creator<android.location.GnssAutomaticGainControl> CREATOR;
- }
-
- public static final class GnssAutomaticGainControl.Builder {
- ctor public GnssAutomaticGainControl.Builder();
- ctor public GnssAutomaticGainControl.Builder(@NonNull android.location.GnssAutomaticGainControl);
- method @NonNull public android.location.GnssAutomaticGainControl build();
- method @NonNull public android.location.GnssAutomaticGainControl.Builder setCarrierFrequencyHz(@IntRange(from=0) long);
- method @NonNull public android.location.GnssAutomaticGainControl.Builder setConstellationType(int);
- method @NonNull public android.location.GnssAutomaticGainControl.Builder setLevelDb(@FloatRange(from=0xffffd8f0, to=10000) double);
- }
-
- public final class GnssCapabilities implements android.os.Parcelable {
- method public int describeContents();
- method @NonNull public java.util.List<android.location.GnssSignalType> getGnssSignalTypes();
- method public int hasAccumulatedDeltaRange();
- method public boolean hasAntennaInfo();
- method public boolean hasGeofencing();
- method @Deprecated public boolean hasGnssAntennaInfo();
- method public boolean hasLowPowerMode();
- method public boolean hasMeasurementCorrections();
- method public boolean hasMeasurementCorrectionsExcessPathLength();
- method public boolean hasMeasurementCorrectionsForDriving();
- method public boolean hasMeasurementCorrectionsLosSats();
- method public boolean hasMeasurementCorrectionsReflectingPlane();
- method public boolean hasMeasurementCorrelationVectors();
- method public boolean hasMeasurements();
- method public boolean hasMsa();
- method public boolean hasMsb();
- method public boolean hasNavigationMessages();
- method public boolean hasOnDemandTime();
- method public boolean hasPowerMultibandAcquisition();
- method public boolean hasPowerMultibandTracking();
- method public boolean hasPowerOtherModes();
- method public boolean hasPowerSinglebandAcquisition();
- method public boolean hasPowerSinglebandTracking();
- method public boolean hasPowerTotal();
- method public boolean hasSatelliteBlocklist();
- method public boolean hasSatellitePvt();
- method public boolean hasScheduling();
- method public boolean hasSingleShotFix();
- method public void writeToParcel(@NonNull android.os.Parcel, int);
- field public static final int CAPABILITY_SUPPORTED = 1; // 0x1
- field public static final int CAPABILITY_UNKNOWN = 0; // 0x0
- field public static final int CAPABILITY_UNSUPPORTED = 2; // 0x2
- field @NonNull public static final android.os.Parcelable.Creator<android.location.GnssCapabilities> CREATOR;
- }
-
- public static final class GnssCapabilities.Builder {
- ctor public GnssCapabilities.Builder();
- ctor public GnssCapabilities.Builder(@NonNull android.location.GnssCapabilities);
- method @NonNull public android.location.GnssCapabilities build();
- method @NonNull public android.location.GnssCapabilities.Builder setGnssSignalTypes(@NonNull java.util.List<android.location.GnssSignalType>);
- method @NonNull public android.location.GnssCapabilities.Builder setHasAccumulatedDeltaRange(int);
- method @NonNull public android.location.GnssCapabilities.Builder setHasAntennaInfo(boolean);
- method @NonNull public android.location.GnssCapabilities.Builder setHasGeofencing(boolean);
- method @NonNull public android.location.GnssCapabilities.Builder setHasLowPowerMode(boolean);
- method @NonNull public android.location.GnssCapabilities.Builder setHasMeasurementCorrections(boolean);
- method @NonNull public android.location.GnssCapabilities.Builder setHasMeasurementCorrectionsExcessPathLength(boolean);
- method @NonNull public android.location.GnssCapabilities.Builder setHasMeasurementCorrectionsForDriving(boolean);
- method @NonNull public android.location.GnssCapabilities.Builder setHasMeasurementCorrectionsLosSats(boolean);
- method @NonNull public android.location.GnssCapabilities.Builder setHasMeasurementCorrectionsReflectingPlane(boolean);
- method @NonNull public android.location.GnssCapabilities.Builder setHasMeasurementCorrelationVectors(boolean);
- method @NonNull public android.location.GnssCapabilities.Builder setHasMeasurements(boolean);
- method @NonNull public android.location.GnssCapabilities.Builder setHasMsa(boolean);
- method @NonNull public android.location.GnssCapabilities.Builder setHasMsb(boolean);
- method @NonNull public android.location.GnssCapabilities.Builder setHasNavigationMessages(boolean);
- method @NonNull public android.location.GnssCapabilities.Builder setHasOnDemandTime(boolean);
- method @NonNull public android.location.GnssCapabilities.Builder setHasPowerMultibandAcquisition(boolean);
- method @NonNull public android.location.GnssCapabilities.Builder setHasPowerMultibandTracking(boolean);
- method @NonNull public android.location.GnssCapabilities.Builder setHasPowerOtherModes(boolean);
- method @NonNull public android.location.GnssCapabilities.Builder setHasPowerSinglebandAcquisition(boolean);
- method @NonNull public android.location.GnssCapabilities.Builder setHasPowerSinglebandTracking(boolean);
- method @NonNull public android.location.GnssCapabilities.Builder setHasPowerTotal(boolean);
- method @NonNull public android.location.GnssCapabilities.Builder setHasSatelliteBlocklist(boolean);
- method @NonNull public android.location.GnssCapabilities.Builder setHasSatellitePvt(boolean);
- method @NonNull public android.location.GnssCapabilities.Builder setHasScheduling(boolean);
- method @NonNull public android.location.GnssCapabilities.Builder setHasSingleShotFix(boolean);
- }
-
- public final class GnssClock implements android.os.Parcelable {
- method public int describeContents();
- method public double getBiasNanos();
- method @FloatRange(from=0.0f) public double getBiasUncertaintyNanos();
- method public double getDriftNanosPerSecond();
- method @FloatRange(from=0.0f) public double getDriftUncertaintyNanosPerSecond();
- method public long getElapsedRealtimeNanos();
- method @FloatRange(from=0.0f) public double getElapsedRealtimeUncertaintyNanos();
- method public long getFullBiasNanos();
- method public int getHardwareClockDiscontinuityCount();
- method public int getLeapSecond();
- method @FloatRange(from=0.0) public double getReferenceCarrierFrequencyHzForIsb();
- method @NonNull public String getReferenceCodeTypeForIsb();
- method public int getReferenceConstellationTypeForIsb();
- method public long getTimeNanos();
- method @FloatRange(from=0.0f) public double getTimeUncertaintyNanos();
- method public boolean hasBiasNanos();
- method public boolean hasBiasUncertaintyNanos();
- method public boolean hasDriftNanosPerSecond();
- method public boolean hasDriftUncertaintyNanosPerSecond();
- method public boolean hasElapsedRealtimeNanos();
- method public boolean hasElapsedRealtimeUncertaintyNanos();
- method public boolean hasFullBiasNanos();
- method public boolean hasLeapSecond();
- method public boolean hasReferenceCarrierFrequencyHzForIsb();
- method public boolean hasReferenceCodeTypeForIsb();
- method public boolean hasReferenceConstellationTypeForIsb();
- method public boolean hasTimeUncertaintyNanos();
- method public void writeToParcel(android.os.Parcel, int);
- field @NonNull public static final android.os.Parcelable.Creator<android.location.GnssClock> CREATOR;
- }
-
- public final class GnssMeasurement implements android.os.Parcelable {
- method public int describeContents();
- method public double getAccumulatedDeltaRangeMeters();
- method public int getAccumulatedDeltaRangeState();
- method public double getAccumulatedDeltaRangeUncertaintyMeters();
- method @Deprecated public double getAutomaticGainControlLevelDb();
- method @FloatRange(from=0, to=63) public double getBasebandCn0DbHz();
- method @Deprecated public long getCarrierCycles();
- method public float getCarrierFrequencyHz();
- method @Deprecated public double getCarrierPhase();
- method @Deprecated public double getCarrierPhaseUncertainty();
- method @FloatRange(from=0, to=63) public double getCn0DbHz();
- method @NonNull public String getCodeType();
- method public int getConstellationType();
- method public double getFullInterSignalBiasNanos();
- method @FloatRange(from=0.0) public double getFullInterSignalBiasUncertaintyNanos();
- method public int getMultipathIndicator();
- method public double getPseudorangeRateMetersPerSecond();
- method public double getPseudorangeRateUncertaintyMetersPerSecond();
- method public long getReceivedSvTimeNanos();
- method public long getReceivedSvTimeUncertaintyNanos();
- method public double getSatelliteInterSignalBiasNanos();
- method @FloatRange(from=0.0) public double getSatelliteInterSignalBiasUncertaintyNanos();
- method public double getSnrInDb();
- method public int getState();
- method public int getSvid();
- method public double getTimeOffsetNanos();
- method @Deprecated public boolean hasAutomaticGainControlLevelDb();
- method public boolean hasBasebandCn0DbHz();
- method @Deprecated public boolean hasCarrierCycles();
- method public boolean hasCarrierFrequencyHz();
- method @Deprecated public boolean hasCarrierPhase();
- method @Deprecated public boolean hasCarrierPhaseUncertainty();
- method public boolean hasCodeType();
- method public boolean hasFullInterSignalBiasNanos();
- method public boolean hasFullInterSignalBiasUncertaintyNanos();
- method public boolean hasSatelliteInterSignalBiasNanos();
- method public boolean hasSatelliteInterSignalBiasUncertaintyNanos();
- method public boolean hasSnrInDb();
- method public void writeToParcel(android.os.Parcel, int);
- field public static final int ADR_STATE_CYCLE_SLIP = 4; // 0x4
- field public static final int ADR_STATE_HALF_CYCLE_REPORTED = 16; // 0x10
- field public static final int ADR_STATE_HALF_CYCLE_RESOLVED = 8; // 0x8
- field public static final int ADR_STATE_RESET = 2; // 0x2
- field public static final int ADR_STATE_UNKNOWN = 0; // 0x0
- field public static final int ADR_STATE_VALID = 1; // 0x1
- field @NonNull public static final android.os.Parcelable.Creator<android.location.GnssMeasurement> CREATOR;
- field public static final int MULTIPATH_INDICATOR_DETECTED = 1; // 0x1
- field public static final int MULTIPATH_INDICATOR_NOT_DETECTED = 2; // 0x2
- field public static final int MULTIPATH_INDICATOR_UNKNOWN = 0; // 0x0
- field public static final int STATE_2ND_CODE_LOCK = 65536; // 0x10000
- field public static final int STATE_BDS_D2_BIT_SYNC = 256; // 0x100
- field public static final int STATE_BDS_D2_SUBFRAME_SYNC = 512; // 0x200
- field public static final int STATE_BIT_SYNC = 2; // 0x2
- field public static final int STATE_CODE_LOCK = 1; // 0x1
- field public static final int STATE_GAL_E1BC_CODE_LOCK = 1024; // 0x400
- field public static final int STATE_GAL_E1B_PAGE_SYNC = 4096; // 0x1000
- field public static final int STATE_GAL_E1C_2ND_CODE_LOCK = 2048; // 0x800
- field public static final int STATE_GLO_STRING_SYNC = 64; // 0x40
- field public static final int STATE_GLO_TOD_DECODED = 128; // 0x80
- field public static final int STATE_GLO_TOD_KNOWN = 32768; // 0x8000
- field public static final int STATE_MSEC_AMBIGUOUS = 16; // 0x10
- field public static final int STATE_SBAS_SYNC = 8192; // 0x2000
- field public static final int STATE_SUBFRAME_SYNC = 4; // 0x4
- field public static final int STATE_SYMBOL_SYNC = 32; // 0x20
- field public static final int STATE_TOW_DECODED = 8; // 0x8
- field public static final int STATE_TOW_KNOWN = 16384; // 0x4000
- field public static final int STATE_UNKNOWN = 0; // 0x0
- }
-
- public final class GnssMeasurementRequest implements android.os.Parcelable {
- method public int describeContents();
- method @IntRange(from=0) public int getIntervalMillis();
- method public boolean isFullTracking();
- method public void writeToParcel(@NonNull android.os.Parcel, int);
- field @NonNull public static final android.os.Parcelable.Creator<android.location.GnssMeasurementRequest> CREATOR;
- field public static final int PASSIVE_INTERVAL = 2147483647; // 0x7fffffff
- }
-
- public static final class GnssMeasurementRequest.Builder {
- ctor public GnssMeasurementRequest.Builder();
- ctor public GnssMeasurementRequest.Builder(@NonNull android.location.GnssMeasurementRequest);
- method @NonNull public android.location.GnssMeasurementRequest build();
- method @NonNull public android.location.GnssMeasurementRequest.Builder setFullTracking(boolean);
- method @NonNull public android.location.GnssMeasurementRequest.Builder setIntervalMillis(@IntRange(from=0) int);
- }
-
- public final class GnssMeasurementsEvent implements android.os.Parcelable {
- method public int describeContents();
- method @NonNull public android.location.GnssClock getClock();
- method @NonNull public java.util.Collection<android.location.GnssAutomaticGainControl> getGnssAutomaticGainControls();
- method @NonNull public java.util.Collection<android.location.GnssMeasurement> getMeasurements();
- method public boolean hasIsFullTracking();
- method public boolean isFullTracking();
- method public void writeToParcel(android.os.Parcel, int);
- field @NonNull public static final android.os.Parcelable.Creator<android.location.GnssMeasurementsEvent> CREATOR;
- }
-
- public static final class GnssMeasurementsEvent.Builder {
- ctor public GnssMeasurementsEvent.Builder();
- ctor public GnssMeasurementsEvent.Builder(@NonNull android.location.GnssMeasurementsEvent);
- method @NonNull public android.location.GnssMeasurementsEvent build();
- method @NonNull public android.location.GnssMeasurementsEvent.Builder clearIsFullTracking();
- method @NonNull public android.location.GnssMeasurementsEvent.Builder setClock(@NonNull android.location.GnssClock);
- method @NonNull public android.location.GnssMeasurementsEvent.Builder setGnssAutomaticGainControls(@NonNull java.util.Collection<android.location.GnssAutomaticGainControl>);
- method @NonNull public android.location.GnssMeasurementsEvent.Builder setIsFullTracking(boolean);
- method @NonNull public android.location.GnssMeasurementsEvent.Builder setMeasurements(@NonNull java.util.Collection<android.location.GnssMeasurement>);
- }
-
- public abstract static class GnssMeasurementsEvent.Callback {
- ctor public GnssMeasurementsEvent.Callback();
- method public void onGnssMeasurementsReceived(android.location.GnssMeasurementsEvent);
- method @Deprecated public void onStatusChanged(int);
- field @Deprecated public static final int STATUS_LOCATION_DISABLED = 2; // 0x2
- field @Deprecated public static final int STATUS_NOT_ALLOWED = 3; // 0x3
- field @Deprecated public static final int STATUS_NOT_SUPPORTED = 0; // 0x0
- field @Deprecated public static final int STATUS_READY = 1; // 0x1
- }
-
- public final class GnssNavigationMessage implements android.os.Parcelable {
- method public int describeContents();
- method @NonNull public byte[] getData();
- method @IntRange(from=0xffffffff, to=120) public int getMessageId();
- method public int getStatus();
- method @IntRange(from=1) public int getSubmessageId();
- method @IntRange(from=1, to=200) public int getSvid();
- method public int getType();
- method public void writeToParcel(android.os.Parcel, int);
- field @NonNull public static final android.os.Parcelable.Creator<android.location.GnssNavigationMessage> CREATOR;
- field public static final int STATUS_PARITY_PASSED = 1; // 0x1
- field public static final int STATUS_PARITY_REBUILT = 2; // 0x2
- field public static final int STATUS_UNKNOWN = 0; // 0x0
- field public static final int TYPE_BDS_CNAV1 = 1283; // 0x503
- field public static final int TYPE_BDS_CNAV2 = 1284; // 0x504
- field public static final int TYPE_BDS_D1 = 1281; // 0x501
- field public static final int TYPE_BDS_D2 = 1282; // 0x502
- field public static final int TYPE_GAL_F = 1538; // 0x602
- field public static final int TYPE_GAL_I = 1537; // 0x601
- field public static final int TYPE_GLO_L1CA = 769; // 0x301
- field public static final int TYPE_GPS_CNAV2 = 260; // 0x104
- field public static final int TYPE_GPS_L1CA = 257; // 0x101
- field public static final int TYPE_GPS_L2CNAV = 258; // 0x102
- field public static final int TYPE_GPS_L5CNAV = 259; // 0x103
- field public static final int TYPE_IRN_L5CA = 1793; // 0x701
- field public static final int TYPE_QZS_L1CA = 1025; // 0x401
- field public static final int TYPE_SBS = 513; // 0x201
- field public static final int TYPE_UNKNOWN = 0; // 0x0
- }
-
- public abstract static class GnssNavigationMessage.Callback {
- ctor public GnssNavigationMessage.Callback();
- method public void onGnssNavigationMessageReceived(android.location.GnssNavigationMessage);
- method @Deprecated public void onStatusChanged(int);
- field @Deprecated public static final int STATUS_LOCATION_DISABLED = 2; // 0x2
- field @Deprecated public static final int STATUS_NOT_SUPPORTED = 0; // 0x0
- field @Deprecated public static final int STATUS_READY = 1; // 0x1
- }
-
- public final class GnssSignalType implements android.os.Parcelable {
- method @NonNull public static android.location.GnssSignalType create(int, @FloatRange(from=0.0f, fromInclusive=false) double, @NonNull String);
- method public int describeContents();
- method @FloatRange(from=0.0f, fromInclusive=false) public double getCarrierFrequencyHz();
- method @NonNull public String getCodeType();
- method public int getConstellationType();
- method public void writeToParcel(@NonNull android.os.Parcel, int);
- field @NonNull public static final android.os.Parcelable.Creator<android.location.GnssSignalType> CREATOR;
- }
-
- public final class GnssStatus implements android.os.Parcelable {
- method public int describeContents();
- method @FloatRange(from=0, to=360) public float getAzimuthDegrees(@IntRange(from=0) int);
- method @FloatRange(from=0, to=63) public float getBasebandCn0DbHz(@IntRange(from=0) int);
- method @FloatRange(from=0) public float getCarrierFrequencyHz(@IntRange(from=0) int);
- method @FloatRange(from=0, to=63) public float getCn0DbHz(@IntRange(from=0) int);
- method public int getConstellationType(@IntRange(from=0) int);
- method @FloatRange(from=0xffffffa6, to=90) public float getElevationDegrees(@IntRange(from=0) int);
- method @IntRange(from=0) public int getSatelliteCount();
- method @IntRange(from=1, to=206) public int getSvid(@IntRange(from=0) int);
- method public boolean hasAlmanacData(@IntRange(from=0) int);
- method public boolean hasBasebandCn0DbHz(@IntRange(from=0) int);
- method public boolean hasCarrierFrequencyHz(@IntRange(from=0) int);
- method public boolean hasEphemerisData(@IntRange(from=0) int);
- method public boolean usedInFix(@IntRange(from=0) int);
- method public void writeToParcel(@NonNull android.os.Parcel, int);
- field public static final int CONSTELLATION_BEIDOU = 5; // 0x5
- field public static final int CONSTELLATION_GALILEO = 6; // 0x6
- field public static final int CONSTELLATION_GLONASS = 3; // 0x3
- field public static final int CONSTELLATION_GPS = 1; // 0x1
- field public static final int CONSTELLATION_IRNSS = 7; // 0x7
- field public static final int CONSTELLATION_QZSS = 4; // 0x4
- field public static final int CONSTELLATION_SBAS = 2; // 0x2
- field public static final int CONSTELLATION_UNKNOWN = 0; // 0x0
- field @NonNull public static final android.os.Parcelable.Creator<android.location.GnssStatus> CREATOR;
- }
-
- public static final class GnssStatus.Builder {
- ctor public GnssStatus.Builder();
- method @NonNull public android.location.GnssStatus.Builder addSatellite(int, @IntRange(from=1, to=200) int, @FloatRange(from=0, to=63) float, @FloatRange(from=0xffffffa6, to=90) float, @FloatRange(from=0, to=360) float, boolean, boolean, boolean, boolean, @FloatRange(from=0) float, boolean, @FloatRange(from=0, to=63) float);
- method @NonNull public android.location.GnssStatus build();
- method @NonNull public android.location.GnssStatus.Builder clearSatellites();
- }
-
- public abstract static class GnssStatus.Callback {
- ctor public GnssStatus.Callback();
- method public void onFirstFix(int);
- method public void onSatelliteStatusChanged(@NonNull android.location.GnssStatus);
- method public void onStarted();
- method public void onStopped();
- }
-
- @Deprecated public final class GpsSatellite {
- method @Deprecated public float getAzimuth();
- method @Deprecated public float getElevation();
- method @Deprecated public int getPrn();
- method @Deprecated public float getSnr();
- method @Deprecated public boolean hasAlmanac();
- method @Deprecated public boolean hasEphemeris();
- method @Deprecated public boolean usedInFix();
- }
-
- @Deprecated public final class GpsStatus {
- method @Deprecated @NonNull public static android.location.GpsStatus create(@NonNull android.location.GnssStatus, int);
- method @Deprecated public int getMaxSatellites();
- method @Deprecated public Iterable<android.location.GpsSatellite> getSatellites();
- method @Deprecated public int getTimeToFirstFix();
- field @Deprecated public static final int GPS_EVENT_FIRST_FIX = 3; // 0x3
- field @Deprecated public static final int GPS_EVENT_SATELLITE_STATUS = 4; // 0x4
- field @Deprecated public static final int GPS_EVENT_STARTED = 1; // 0x1
- field @Deprecated public static final int GPS_EVENT_STOPPED = 2; // 0x2
- }
-
- @Deprecated public static interface GpsStatus.Listener {
- method @Deprecated public void onGpsStatusChanged(int);
- }
-
- @Deprecated public static interface GpsStatus.NmeaListener {
- method @Deprecated public void onNmeaReceived(long, String);
- }
-
public class Location implements android.os.Parcelable {
ctor public Location(@Nullable String);
ctor public Location(@NonNull android.location.Location);
@@ -20990,219 +20493,6 @@ package android.location {
field public static final int FORMAT_SECONDS = 2; // 0x2
}
- public interface LocationListener {
- method public default void onFlushComplete(int);
- method public void onLocationChanged(@NonNull android.location.Location);
- method public default void onLocationChanged(@NonNull java.util.List<android.location.Location>);
- method public default void onProviderDisabled(@NonNull String);
- method public default void onProviderEnabled(@NonNull String);
- method @Deprecated public default void onStatusChanged(String, int, android.os.Bundle);
- }
-
- public class LocationManager {
- method @Deprecated @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) public boolean addGpsStatusListener(android.location.GpsStatus.Listener);
- method @Deprecated @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) public boolean addNmeaListener(@NonNull android.location.GpsStatus.NmeaListener);
- method @Deprecated @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) public boolean addNmeaListener(@NonNull android.location.OnNmeaMessageListener);
- method @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) public boolean addNmeaListener(@NonNull android.location.OnNmeaMessageListener, @Nullable android.os.Handler);
- method @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) public boolean addNmeaListener(@NonNull java.util.concurrent.Executor, @NonNull android.location.OnNmeaMessageListener);
- method @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public void addProximityAlert(double, double, float, long, @NonNull android.app.PendingIntent);
- method public void addTestProvider(@NonNull String, boolean, boolean, boolean, boolean, boolean, boolean, boolean, int, int);
- method public void addTestProvider(@NonNull String, @NonNull android.location.provider.ProviderProperties);
- method public void addTestProvider(@NonNull String, @NonNull android.location.provider.ProviderProperties, @NonNull java.util.Set<java.lang.String>);
- method @Deprecated public void clearTestProviderEnabled(@NonNull String);
- method @Deprecated public void clearTestProviderLocation(@NonNull String);
- method @Deprecated public void clearTestProviderStatus(@NonNull String);
- method @NonNull public java.util.List<java.lang.String> getAllProviders();
- method @Deprecated @Nullable public String getBestProvider(@NonNull android.location.Criteria, boolean);
- method @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public void getCurrentLocation(@NonNull String, @Nullable android.os.CancellationSignal, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<android.location.Location>);
- method @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public void getCurrentLocation(@NonNull String, @NonNull android.location.LocationRequest, @Nullable android.os.CancellationSignal, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<android.location.Location>);
- method @Nullable public java.util.List<android.location.GnssAntennaInfo> getGnssAntennaInfos();
- method @NonNull public android.location.GnssCapabilities getGnssCapabilities();
- method @Nullable public String getGnssHardwareModelName();
- method public int getGnssYearOfHardware();
- method @Deprecated @Nullable @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) public android.location.GpsStatus getGpsStatus(@Nullable android.location.GpsStatus);
- method @Nullable @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public android.location.Location getLastKnownLocation(@NonNull String);
- method @Deprecated @Nullable public android.location.LocationProvider getProvider(@NonNull String);
- method @Nullable public android.location.provider.ProviderProperties getProviderProperties(@NonNull String);
- method @NonNull public java.util.List<java.lang.String> getProviders(boolean);
- method @Deprecated @NonNull public java.util.List<java.lang.String> getProviders(@NonNull android.location.Criteria, boolean);
- method public boolean hasProvider(@NonNull String);
- method public boolean isLocationEnabled();
- method public boolean isProviderEnabled(@NonNull String);
- method public boolean registerAntennaInfoListener(@NonNull java.util.concurrent.Executor, @NonNull android.location.GnssAntennaInfo.Listener);
- method @Deprecated @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) public boolean registerGnssMeasurementsCallback(@NonNull android.location.GnssMeasurementsEvent.Callback);
- method @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) public boolean registerGnssMeasurementsCallback(@NonNull android.location.GnssMeasurementsEvent.Callback, @Nullable android.os.Handler);
- method @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) public boolean registerGnssMeasurementsCallback(@NonNull java.util.concurrent.Executor, @NonNull android.location.GnssMeasurementsEvent.Callback);
- method @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) public boolean registerGnssMeasurementsCallback(@NonNull android.location.GnssMeasurementRequest, @NonNull java.util.concurrent.Executor, @NonNull android.location.GnssMeasurementsEvent.Callback);
- method @Deprecated public boolean registerGnssNavigationMessageCallback(@NonNull android.location.GnssNavigationMessage.Callback);
- method @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) public boolean registerGnssNavigationMessageCallback(@NonNull android.location.GnssNavigationMessage.Callback, @Nullable android.os.Handler);
- method @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) public boolean registerGnssNavigationMessageCallback(@NonNull java.util.concurrent.Executor, @NonNull android.location.GnssNavigationMessage.Callback);
- method @Deprecated @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) public boolean registerGnssStatusCallback(@NonNull android.location.GnssStatus.Callback);
- method @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) public boolean registerGnssStatusCallback(@NonNull android.location.GnssStatus.Callback, @Nullable android.os.Handler);
- method @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) public boolean registerGnssStatusCallback(@NonNull java.util.concurrent.Executor, @NonNull android.location.GnssStatus.Callback);
- method @Deprecated public void removeGpsStatusListener(android.location.GpsStatus.Listener);
- method @Deprecated public void removeNmeaListener(@NonNull android.location.GpsStatus.NmeaListener);
- method public void removeNmeaListener(@NonNull android.location.OnNmeaMessageListener);
- method @RequiresPermission(anyOf={"android.permission.ACCESS_COARSE_LOCATION", "android.permission.ACCESS_FINE_LOCATION"}, apis="..22") public void removeProximityAlert(@NonNull android.app.PendingIntent);
- method public void removeTestProvider(@NonNull String);
- method @RequiresPermission(anyOf={"android.permission.ACCESS_COARSE_LOCATION", "android.permission.ACCESS_FINE_LOCATION"}, apis="..22") public void removeUpdates(@NonNull android.location.LocationListener);
- method public void removeUpdates(@NonNull android.app.PendingIntent);
- method public void requestFlush(@NonNull String, @NonNull android.location.LocationListener, int);
- method public void requestFlush(@NonNull String, @NonNull android.app.PendingIntent, int);
- method @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public void requestLocationUpdates(@NonNull String, long, float, @NonNull android.location.LocationListener);
- method @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public void requestLocationUpdates(@NonNull String, long, float, @NonNull android.location.LocationListener, @Nullable android.os.Looper);
- method @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public void requestLocationUpdates(@NonNull String, long, float, @NonNull java.util.concurrent.Executor, @NonNull android.location.LocationListener);
- method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public void requestLocationUpdates(long, float, @NonNull android.location.Criteria, @NonNull android.location.LocationListener, @Nullable android.os.Looper);
- method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public void requestLocationUpdates(long, float, @NonNull android.location.Criteria, @NonNull java.util.concurrent.Executor, @NonNull android.location.LocationListener);
- method @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public void requestLocationUpdates(@NonNull String, long, float, @NonNull android.app.PendingIntent);
- method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public void requestLocationUpdates(long, float, @NonNull android.location.Criteria, @NonNull android.app.PendingIntent);
- method @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public void requestLocationUpdates(@NonNull String, @NonNull android.location.LocationRequest, @NonNull java.util.concurrent.Executor, @NonNull android.location.LocationListener);
- method @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public void requestLocationUpdates(@NonNull String, @NonNull android.location.LocationRequest, @NonNull android.app.PendingIntent);
- method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public void requestSingleUpdate(@NonNull String, @NonNull android.location.LocationListener, @Nullable android.os.Looper);
- method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public void requestSingleUpdate(@NonNull android.location.Criteria, @NonNull android.location.LocationListener, @Nullable android.os.Looper);
- method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public void requestSingleUpdate(@NonNull String, @NonNull android.app.PendingIntent);
- method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public void requestSingleUpdate(@NonNull android.location.Criteria, @NonNull android.app.PendingIntent);
- method public boolean sendExtraCommand(@NonNull String, @NonNull String, @Nullable android.os.Bundle);
- method public void setTestProviderEnabled(@NonNull String, boolean);
- method public void setTestProviderLocation(@NonNull String, @NonNull android.location.Location);
- method @Deprecated public void setTestProviderStatus(@NonNull String, int, @Nullable android.os.Bundle, long);
- method public void unregisterAntennaInfoListener(@NonNull android.location.GnssAntennaInfo.Listener);
- method public void unregisterGnssMeasurementsCallback(@NonNull android.location.GnssMeasurementsEvent.Callback);
- method public void unregisterGnssNavigationMessageCallback(@NonNull android.location.GnssNavigationMessage.Callback);
- method public void unregisterGnssStatusCallback(@NonNull android.location.GnssStatus.Callback);
- field public static final String ACTION_GNSS_CAPABILITIES_CHANGED = "android.location.action.GNSS_CAPABILITIES_CHANGED";
- field public static final String EXTRA_GNSS_CAPABILITIES = "android.location.extra.GNSS_CAPABILITIES";
- field public static final String EXTRA_LOCATION_ENABLED = "android.location.extra.LOCATION_ENABLED";
- field public static final String EXTRA_PROVIDER_ENABLED = "android.location.extra.PROVIDER_ENABLED";
- field public static final String EXTRA_PROVIDER_NAME = "android.location.extra.PROVIDER_NAME";
- field public static final String FUSED_PROVIDER = "fused";
- field public static final String GPS_PROVIDER = "gps";
- field public static final String KEY_FLUSH_COMPLETE = "flushComplete";
- field public static final String KEY_LOCATIONS = "locations";
- field public static final String KEY_LOCATION_CHANGED = "location";
- field public static final String KEY_PROVIDER_ENABLED = "providerEnabled";
- field public static final String KEY_PROXIMITY_ENTERING = "entering";
- field @Deprecated public static final String KEY_STATUS_CHANGED = "status";
- field public static final String MODE_CHANGED_ACTION = "android.location.MODE_CHANGED";
- field public static final String NETWORK_PROVIDER = "network";
- field public static final String PASSIVE_PROVIDER = "passive";
- field public static final String PROVIDERS_CHANGED_ACTION = "android.location.PROVIDERS_CHANGED";
- }
-
- @Deprecated public class LocationProvider {
- method @Deprecated public int getAccuracy();
- method @Deprecated public String getName();
- method @Deprecated public int getPowerRequirement();
- method @Deprecated public boolean hasMonetaryCost();
- method @Deprecated public boolean meetsCriteria(android.location.Criteria);
- method @Deprecated public boolean requiresCell();
- method @Deprecated public boolean requiresNetwork();
- method @Deprecated public boolean requiresSatellite();
- method @Deprecated public boolean supportsAltitude();
- method @Deprecated public boolean supportsBearing();
- method @Deprecated public boolean supportsSpeed();
- field @Deprecated public static final int AVAILABLE = 2; // 0x2
- field @Deprecated public static final int OUT_OF_SERVICE = 0; // 0x0
- field @Deprecated public static final int TEMPORARILY_UNAVAILABLE = 1; // 0x1
- }
-
- public final class LocationRequest implements android.os.Parcelable {
- method public int describeContents();
- method @IntRange(from=1) public long getDurationMillis();
- method @IntRange(from=0) public long getIntervalMillis();
- method @IntRange(from=0) public long getMaxUpdateDelayMillis();
- method @IntRange(from=1, to=java.lang.Integer.MAX_VALUE) public int getMaxUpdates();
- method @FloatRange(from=0, to=java.lang.Float.MAX_VALUE) public float getMinUpdateDistanceMeters();
- method @IntRange(from=0) public long getMinUpdateIntervalMillis();
- method public int getQuality();
- method public void writeToParcel(@NonNull android.os.Parcel, int);
- field @NonNull public static final android.os.Parcelable.Creator<android.location.LocationRequest> CREATOR;
- field public static final long PASSIVE_INTERVAL = 9223372036854775807L; // 0x7fffffffffffffffL
- field public static final int QUALITY_BALANCED_POWER_ACCURACY = 102; // 0x66
- field public static final int QUALITY_HIGH_ACCURACY = 100; // 0x64
- field public static final int QUALITY_LOW_POWER = 104; // 0x68
- }
-
- public static final class LocationRequest.Builder {
- ctor public LocationRequest.Builder(long);
- ctor public LocationRequest.Builder(@NonNull android.location.LocationRequest);
- method @NonNull public android.location.LocationRequest build();
- method @NonNull public android.location.LocationRequest.Builder clearMinUpdateIntervalMillis();
- method @NonNull public android.location.LocationRequest.Builder setDurationMillis(@IntRange(from=1) long);
- method @NonNull public android.location.LocationRequest.Builder setIntervalMillis(@IntRange(from=0) long);
- method @NonNull public android.location.LocationRequest.Builder setMaxUpdateDelayMillis(@IntRange(from=0) long);
- method @NonNull public android.location.LocationRequest.Builder setMaxUpdates(@IntRange(from=1, to=java.lang.Integer.MAX_VALUE) int);
- method @NonNull public android.location.LocationRequest.Builder setMinUpdateDistanceMeters(@FloatRange(from=0, to=java.lang.Float.MAX_VALUE) float);
- method @NonNull public android.location.LocationRequest.Builder setMinUpdateIntervalMillis(@IntRange(from=0) long);
- method @NonNull public android.location.LocationRequest.Builder setQuality(int);
- }
-
- public interface OnNmeaMessageListener {
- method public void onNmeaMessage(String, long);
- }
-
- public abstract class SettingInjectorService extends android.app.Service {
- ctor public SettingInjectorService(String);
- method public final android.os.IBinder onBind(android.content.Intent);
- method protected abstract boolean onGetEnabled();
- method protected abstract String onGetSummary();
- method public final void onStart(android.content.Intent, int);
- method public final int onStartCommand(android.content.Intent, int, int);
- method public static final void refreshSettings(@NonNull android.content.Context);
- field public static final String ACTION_INJECTED_SETTING_CHANGED = "android.location.InjectedSettingChanged";
- field public static final String ACTION_SERVICE_INTENT = "android.location.SettingInjectorService";
- field public static final String ATTRIBUTES_NAME = "injected-location-setting";
- field public static final String META_DATA_NAME = "android.location.SettingInjectorService";
- }
-
-}
-
-package android.location.altitude {
-
- public final class AltitudeConverter {
- ctor public AltitudeConverter();
- method @WorkerThread public void addMslAltitudeToLocation(@NonNull android.content.Context, @NonNull android.location.Location) throws java.io.IOException;
- }
-
-}
-
-package android.location.provider {
-
- public final class ProviderProperties implements android.os.Parcelable {
- method public int describeContents();
- method public int getAccuracy();
- method public int getPowerUsage();
- method public boolean hasAltitudeSupport();
- method public boolean hasBearingSupport();
- method public boolean hasCellRequirement();
- method public boolean hasMonetaryCost();
- method public boolean hasNetworkRequirement();
- method public boolean hasSatelliteRequirement();
- method public boolean hasSpeedSupport();
- method public void writeToParcel(@NonNull android.os.Parcel, int);
- field public static final int ACCURACY_COARSE = 2; // 0x2
- field public static final int ACCURACY_FINE = 1; // 0x1
- field @NonNull public static final android.os.Parcelable.Creator<android.location.provider.ProviderProperties> CREATOR;
- field public static final int POWER_USAGE_HIGH = 3; // 0x3
- field public static final int POWER_USAGE_LOW = 1; // 0x1
- field public static final int POWER_USAGE_MEDIUM = 2; // 0x2
- }
-
- public static final class ProviderProperties.Builder {
- ctor public ProviderProperties.Builder();
- ctor public ProviderProperties.Builder(@NonNull android.location.provider.ProviderProperties);
- method @NonNull public android.location.provider.ProviderProperties build();
- method @NonNull public android.location.provider.ProviderProperties.Builder setAccuracy(int);
- method @NonNull public android.location.provider.ProviderProperties.Builder setHasAltitudeSupport(boolean);
- method @NonNull public android.location.provider.ProviderProperties.Builder setHasBearingSupport(boolean);
- method @NonNull public android.location.provider.ProviderProperties.Builder setHasCellRequirement(boolean);
- method @NonNull public android.location.provider.ProviderProperties.Builder setHasMonetaryCost(boolean);
- method @NonNull public android.location.provider.ProviderProperties.Builder setHasNetworkRequirement(boolean);
- method @NonNull public android.location.provider.ProviderProperties.Builder setHasSatelliteRequirement(boolean);
- method @NonNull public android.location.provider.ProviderProperties.Builder setHasSpeedSupport(boolean);
- method @NonNull public android.location.provider.ProviderProperties.Builder setPowerUsage(int);
- }
-
}
package android.media {
@@ -39351,10 +38641,10 @@ package android.security {
}
public final class FileIntegrityManager {
- method @FlaggedApi(Flags.FLAG_FSVERITY_API) @Nullable public byte[] getFsverityDigest(@NonNull java.io.File) throws java.io.IOException;
+ method @FlaggedApi(Flags.FLAG_FSVERITY_API) @Nullable public byte[] getFsVerityDigest(@NonNull java.io.File) throws java.io.IOException;
method public boolean isApkVeritySupported();
method @RequiresPermission(anyOf={android.Manifest.permission.INSTALL_PACKAGES, android.Manifest.permission.REQUEST_INSTALL_PACKAGES}) public boolean isAppSourceCertificateTrusted(@NonNull java.security.cert.X509Certificate) throws java.security.cert.CertificateEncodingException;
- method @FlaggedApi(Flags.FLAG_FSVERITY_API) public void setupFsverity(@NonNull java.io.File) throws java.io.IOException;
+ method @FlaggedApi(Flags.FLAG_FSVERITY_API) public void setupFsVerity(@NonNull java.io.File) throws java.io.IOException;
}
public final class KeyChain {
@@ -42273,7 +41563,7 @@ package android.telecom {
field public static final int PROPERTY_HIGH_DEF_AUDIO = 16; // 0x10
field public static final int PROPERTY_IS_ADHOC_CONFERENCE = 8192; // 0x2000
field public static final int PROPERTY_IS_EXTERNAL_CALL = 64; // 0x40
- field public static final int PROPERTY_IS_TRANSACTIONAL = 32768; // 0x8000
+ field @FlaggedApi(Flags.FLAG_VOIP_APP_ACTIONS_SUPPORT) public static final int PROPERTY_IS_TRANSACTIONAL = 32768; // 0x8000
field public static final int PROPERTY_NETWORK_IDENTIFIED_EMERGENCY_CALL = 2048; // 0x800
field public static final int PROPERTY_RTT = 1024; // 0x400
field public static final int PROPERTY_SELF_MANAGED = 256; // 0x100
diff --git a/core/api/module-lib-current.txt b/core/api/module-lib-current.txt
index 7f1e28961108..3de774868bb7 100644
--- a/core/api/module-lib-current.txt
+++ b/core/api/module-lib-current.txt
@@ -186,16 +186,6 @@ package android.hardware.usb {
}
-package android.location {
-
- public class LocationManager {
- method @RequiresPermission(allOf={android.Manifest.permission.LOCATION_HARDWARE, android.Manifest.permission.ACCESS_FINE_LOCATION}) public boolean injectLocation(@NonNull android.location.Location);
- method @RequiresPermission(android.Manifest.permission.CONTROL_AUTOMOTIVE_GNSS) public boolean isAutomotiveGnssSuspended();
- method @RequiresPermission(android.Manifest.permission.CONTROL_AUTOMOTIVE_GNSS) public void setAutomotiveGnssSuspended(boolean);
- }
-
-}
-
package android.media {
public class AudioManager {
@@ -529,6 +519,7 @@ package android.provider {
public static final class Settings.Config extends android.provider.Settings.NameValueTable {
method @RequiresPermission(android.Manifest.permission.MONITOR_DEVICE_CONFIG_ACCESS) public static void clearMonitorCallback(@NonNull android.content.ContentResolver);
method @RequiresPermission(android.Manifest.permission.WRITE_DEVICE_CONFIG) public static boolean deleteString(@NonNull String, @NonNull String);
+ method @NonNull public static java.util.Map<java.lang.String,java.lang.String> getAllStrings();
method @Nullable @RequiresPermission(android.Manifest.permission.READ_DEVICE_CONFIG) public static String getString(@NonNull String);
method @NonNull @RequiresPermission(android.Manifest.permission.READ_DEVICE_CONFIG) public static java.util.Map<java.lang.String,java.lang.String> getStrings(@NonNull String, @NonNull java.util.List<java.lang.String>);
method @RequiresPermission(android.Manifest.permission.WRITE_DEVICE_CONFIG) public static int getSyncDisabledMode();
diff --git a/core/api/module-lib-lint-baseline.txt b/core/api/module-lib-lint-baseline.txt
index 27436ce35867..471745ae0c50 100644
--- a/core/api/module-lib-lint-baseline.txt
+++ b/core/api/module-lib-lint-baseline.txt
@@ -17,18 +17,6 @@ SamShouldBeLast: android.content.pm.PackageItemInfo#dumpBack(android.util.Printe
SAM-compatible parameters (such as parameter 1, "pw", in android.content.pm.PackageItemInfo.dumpBack) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
SamShouldBeLast: android.content.pm.PackageItemInfo#dumpFront(android.util.Printer, String):
SAM-compatible parameters (such as parameter 1, "pw", in android.content.pm.PackageItemInfo.dumpFront) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
-SamShouldBeLast: android.location.LocationManager#addNmeaListener(android.location.OnNmeaMessageListener, android.os.Handler):
- SAM-compatible parameters (such as parameter 1, "listener", in android.location.LocationManager.addNmeaListener) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
-SamShouldBeLast: android.location.LocationManager#requestLocationUpdates(String, long, float, android.location.LocationListener, android.os.Looper):
- SAM-compatible parameters (such as parameter 4, "listener", in android.location.LocationManager.requestLocationUpdates) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
-SamShouldBeLast: android.location.LocationManager#requestLocationUpdates(android.location.LocationRequest, android.location.LocationListener, android.os.Looper):
- SAM-compatible parameters (such as parameter 2, "listener", in android.location.LocationManager.requestLocationUpdates) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
-SamShouldBeLast: android.location.LocationManager#requestLocationUpdates(long, float, android.location.Criteria, android.location.LocationListener, android.os.Looper):
- SAM-compatible parameters (such as parameter 4, "listener", in android.location.LocationManager.requestLocationUpdates) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
-SamShouldBeLast: android.location.LocationManager#requestSingleUpdate(String, android.location.LocationListener, android.os.Looper):
- SAM-compatible parameters (such as parameter 2, "listener", in android.location.LocationManager.requestSingleUpdate) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
-SamShouldBeLast: android.location.LocationManager#requestSingleUpdate(android.location.Criteria, android.location.LocationListener, android.os.Looper):
- SAM-compatible parameters (such as parameter 2, "listener", in android.location.LocationManager.requestSingleUpdate) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
SamShouldBeLast: android.media.AudioManager#abandonAudioFocus(android.media.AudioManager.OnAudioFocusChangeListener, android.media.AudioAttributes):
SAM-compatible parameters (such as parameter 1, "l", in android.media.AudioManager.abandonAudioFocus) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
SamShouldBeLast: android.media.AudioManager#requestAudioFocus(android.media.AudioManager.OnAudioFocusChangeListener, android.media.AudioAttributes, int, int):
diff --git a/core/api/system-current.txt b/core/api/system-current.txt
index adbd06c10f47..ff44a1b87e18 100644
--- a/core/api/system-current.txt
+++ b/core/api/system-current.txt
@@ -3213,6 +3213,7 @@ package android.companion.virtual {
method @RequiresPermission(android.Manifest.permission.CREATE_VIRTUAL_DEVICE) public void registerIntentInterceptor(@NonNull android.content.IntentFilter, @NonNull java.util.concurrent.Executor, @NonNull android.companion.virtual.VirtualDeviceManager.IntentInterceptorCallback);
method public void removeActivityListener(@NonNull android.companion.virtual.VirtualDeviceManager.ActivityListener);
method public void removeSoundEffectListener(@NonNull android.companion.virtual.VirtualDeviceManager.SoundEffectListener);
+ method @FlaggedApi(Flags.FLAG_DYNAMIC_POLICY) @RequiresPermission(android.Manifest.permission.CREATE_VIRTUAL_DEVICE) public void setDevicePolicy(int, int);
method @RequiresPermission(android.Manifest.permission.CREATE_VIRTUAL_DEVICE) public void setShowPointerIcon(boolean);
method @RequiresPermission(android.Manifest.permission.CREATE_VIRTUAL_DEVICE) public void unregisterIntentInterceptor(@NonNull android.companion.virtual.VirtualDeviceManager.IntentInterceptorCallback);
}
@@ -3546,6 +3547,7 @@ package android.content {
field public static final String ACTION_SHOW_SUSPENDED_APP_DETAILS = "android.intent.action.SHOW_SUSPENDED_APP_DETAILS";
field @Deprecated public static final String ACTION_SIM_STATE_CHANGED = "android.intent.action.SIM_STATE_CHANGED";
field public static final String ACTION_SPLIT_CONFIGURATION_CHANGED = "android.intent.action.SPLIT_CONFIGURATION_CHANGED";
+ field public static final String ACTION_UNARCHIVE_PACKAGE = "android.intent.action.UNARCHIVE_PACKAGE";
field public static final String ACTION_UPGRADE_SETUP = "android.intent.action.UPGRADE_SETUP";
field public static final String ACTION_USER_ADDED = "android.intent.action.USER_ADDED";
field public static final String ACTION_USER_REMOVED = "android.intent.action.USER_REMOVED";
@@ -3795,6 +3797,13 @@ package android.content.pm {
public class PackageArchiver {
method @RequiresPermission(anyOf={android.Manifest.permission.DELETE_PACKAGES, android.Manifest.permission.REQUEST_DELETE_PACKAGES}) public void requestArchive(@NonNull String, @NonNull android.content.IntentSender) throws android.content.pm.PackageManager.NameNotFoundException;
+ method @RequiresPermission(anyOf={android.Manifest.permission.INSTALL_PACKAGES, android.Manifest.permission.REQUEST_INSTALL_PACKAGES}) public void requestUnarchive(@NonNull String) throws android.content.pm.PackageManager.NameNotFoundException;
+ field public static final String EXTRA_UNARCHIVE_ALL_USERS = "android.content.pm.extra.UNARCHIVE_ALL_USERS";
+ field public static final String EXTRA_UNARCHIVE_PACKAGE_NAME = "android.content.pm.extra.UNARCHIVE_PACKAGE_NAME";
+ }
+
+ public class PackageInfo implements android.os.Parcelable {
+ field public boolean isArchived;
}
public class PackageInstaller {
@@ -4016,6 +4025,7 @@ package android.content.pm {
field @Deprecated public static final int INTENT_FILTER_VERIFICATION_SUCCESS = 1; // 0x1
field @Deprecated public static final int MASK_PERMISSION_FLAGS = 255; // 0xff
field public static final int MATCH_ANY_USER = 4194304; // 0x400000
+ field public static final long MATCH_ARCHIVED_PACKAGES = 4294967296L; // 0x100000000L
field public static final int MATCH_CLONE_PROFILE = 536870912; // 0x20000000
field public static final int MATCH_FACTORY_ONLY = 2097152; // 0x200000
field public static final int MATCH_HIDDEN_UNTIL_INSTALLED_COMPONENTS = 536870912; // 0x20000000
@@ -6172,653 +6182,12 @@ package android.hardware.usb {
package android.location {
- public abstract class BatchedLocationCallback {
- ctor public BatchedLocationCallback();
- method public void onLocationBatch(java.util.List<android.location.Location>);
- }
-
- public final class CorrelationVector implements android.os.Parcelable {
- method public int describeContents();
- method @FloatRange(from=0.0f) public double getFrequencyOffsetMetersPerSecond();
- method @NonNull public int[] getMagnitude();
- method @FloatRange(from=0.0f) public double getSamplingStartMeters();
- method @FloatRange(from=0.0f, fromInclusive=false) public double getSamplingWidthMeters();
- method public void writeToParcel(@NonNull android.os.Parcel, int);
- field @NonNull public static final android.os.Parcelable.Creator<android.location.CorrelationVector> CREATOR;
- }
-
- public static final class CorrelationVector.Builder {
- ctor public CorrelationVector.Builder();
- method @NonNull public android.location.CorrelationVector build();
- method @NonNull public android.location.CorrelationVector.Builder setFrequencyOffsetMetersPerSecond(@FloatRange(from=0.0f) double);
- method @NonNull public android.location.CorrelationVector.Builder setMagnitude(@NonNull int[]);
- method @NonNull public android.location.CorrelationVector.Builder setSamplingStartMeters(@FloatRange(from=0.0f) double);
- method @NonNull public android.location.CorrelationVector.Builder setSamplingWidthMeters(@FloatRange(from=0.0f, fromInclusive=false) double);
- }
-
- public final class Country implements android.os.Parcelable {
- ctor public Country(@NonNull String, int);
- method public int describeContents();
- method @NonNull public String getCountryCode();
- method public int getSource();
- method public void writeToParcel(@NonNull android.os.Parcel, int);
- field public static final int COUNTRY_SOURCE_LOCALE = 3; // 0x3
- field public static final int COUNTRY_SOURCE_LOCATION = 1; // 0x1
- field public static final int COUNTRY_SOURCE_NETWORK = 0; // 0x0
- field public static final int COUNTRY_SOURCE_SIM = 2; // 0x2
- field @NonNull public static final android.os.Parcelable.Creator<android.location.Country> CREATOR;
- }
-
- public class CountryDetector {
- method public void registerCountryDetectorCallback(@NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<android.location.Country>);
- method public void unregisterCountryDetectorCallback(@NonNull java.util.function.Consumer<android.location.Country>);
- }
-
- public final class GnssCapabilities implements android.os.Parcelable {
- method @Deprecated public boolean hasMeasurementCorrectionsReflectingPane();
- method @Deprecated public boolean hasNavMessages();
- method @Deprecated public boolean hasSatelliteBlacklist();
- }
-
- public final class GnssExcessPathInfo implements android.os.Parcelable {
- method public int describeContents();
- method @FloatRange(from=0.0f) public float getAttenuationDb();
- method @FloatRange(from=0.0f) public float getExcessPathLengthMeters();
- method @FloatRange(from=0.0f) public float getExcessPathLengthUncertaintyMeters();
- method @NonNull public android.location.GnssReflectingPlane getReflectingPlane();
- method public boolean hasAttenuation();
- method public boolean hasExcessPathLength();
- method public boolean hasExcessPathLengthUncertainty();
- method public boolean hasReflectingPlane();
- method public void writeToParcel(@NonNull android.os.Parcel, int);
- field @NonNull public static final android.os.Parcelable.Creator<android.location.GnssExcessPathInfo> CREATOR;
- }
-
- public static final class GnssExcessPathInfo.Builder {
- ctor public GnssExcessPathInfo.Builder();
- method @NonNull public android.location.GnssExcessPathInfo build();
- method @NonNull public android.location.GnssExcessPathInfo.Builder clearAttenuationDb();
- method @NonNull public android.location.GnssExcessPathInfo.Builder clearExcessPathLengthMeters();
- method @NonNull public android.location.GnssExcessPathInfo.Builder clearExcessPathLengthUncertaintyMeters();
- method @NonNull public android.location.GnssExcessPathInfo.Builder setAttenuationDb(@FloatRange(from=0.0f) float);
- method @NonNull public android.location.GnssExcessPathInfo.Builder setExcessPathLengthMeters(@FloatRange(from=0.0f) float);
- method @NonNull public android.location.GnssExcessPathInfo.Builder setExcessPathLengthUncertaintyMeters(@FloatRange(from=0.0f) float);
- method @NonNull public android.location.GnssExcessPathInfo.Builder setReflectingPlane(@Nullable android.location.GnssReflectingPlane);
- }
-
- public final class GnssMeasurement implements android.os.Parcelable {
- method @Nullable public java.util.Collection<android.location.CorrelationVector> getCorrelationVectors();
- method @Nullable public android.location.SatellitePvt getSatellitePvt();
- method public boolean hasCorrelationVectors();
- method public boolean hasSatellitePvt();
- }
-
- public final class GnssMeasurementCorrections implements android.os.Parcelable {
- method public int describeContents();
- method @FloatRange(from=-1000.0F, to=10000.0f) public double getAltitudeMeters();
- method @FloatRange(from=0.0f, to=360.0f) public float getEnvironmentBearingDegrees();
- method @FloatRange(from=0.0f, to=180.0f) public float getEnvironmentBearingUncertaintyDegrees();
- method @FloatRange(from=0.0f) public double getHorizontalPositionUncertaintyMeters();
- method @FloatRange(from=-90.0F, to=90.0f) public double getLatitudeDegrees();
- method @FloatRange(from=-180.0F, to=180.0f) public double getLongitudeDegrees();
- method @NonNull public java.util.List<android.location.GnssSingleSatCorrection> getSingleSatelliteCorrectionList();
- method @IntRange(from=0) public long getToaGpsNanosecondsOfWeek();
- method @FloatRange(from=0.0f) public double getVerticalPositionUncertaintyMeters();
- method public boolean hasEnvironmentBearing();
- method public void writeToParcel(@NonNull android.os.Parcel, int);
- field public static final android.os.Parcelable.Creator<android.location.GnssMeasurementCorrections> CREATOR;
- }
-
- public static final class GnssMeasurementCorrections.Builder {
- ctor public GnssMeasurementCorrections.Builder();
- method @NonNull public android.location.GnssMeasurementCorrections build();
- method @NonNull public android.location.GnssMeasurementCorrections.Builder setAltitudeMeters(@FloatRange(from=-1000.0F, to=10000.0f) double);
- method @NonNull public android.location.GnssMeasurementCorrections.Builder setEnvironmentBearingDegrees(@FloatRange(from=0.0f, to=360.0f) float);
- method @NonNull public android.location.GnssMeasurementCorrections.Builder setEnvironmentBearingUncertaintyDegrees(@FloatRange(from=0.0f, to=180.0f) float);
- method @NonNull public android.location.GnssMeasurementCorrections.Builder setHorizontalPositionUncertaintyMeters(@FloatRange(from=0.0f) double);
- method @NonNull public android.location.GnssMeasurementCorrections.Builder setLatitudeDegrees(@FloatRange(from=-90.0F, to=90.0f) double);
- method @NonNull public android.location.GnssMeasurementCorrections.Builder setLongitudeDegrees(@FloatRange(from=-180.0F, to=180.0f) double);
- method @NonNull public android.location.GnssMeasurementCorrections.Builder setSingleSatelliteCorrectionList(@NonNull java.util.List<android.location.GnssSingleSatCorrection>);
- method @NonNull public android.location.GnssMeasurementCorrections.Builder setToaGpsNanosecondsOfWeek(@IntRange(from=0) long);
- method @NonNull public android.location.GnssMeasurementCorrections.Builder setVerticalPositionUncertaintyMeters(@FloatRange(from=0.0f) double);
- }
-
- public final class GnssMeasurementRequest implements android.os.Parcelable {
- method @NonNull public android.os.WorkSource getWorkSource();
- method public boolean isCorrelationVectorOutputsEnabled();
- }
-
- public static final class GnssMeasurementRequest.Builder {
- method @NonNull public android.location.GnssMeasurementRequest.Builder setCorrelationVectorOutputsEnabled(boolean);
- method @NonNull @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS) public android.location.GnssMeasurementRequest.Builder setWorkSource(@Nullable android.os.WorkSource);
- }
-
- public final class GnssReflectingPlane implements android.os.Parcelable {
- method public int describeContents();
- method @FloatRange(from=-1000.0F, to=10000.0f) public double getAltitudeMeters();
- method @FloatRange(from=0.0f, to=360.0f) public double getAzimuthDegrees();
- method @FloatRange(from=-90.0F, to=90.0f) public double getLatitudeDegrees();
- method @FloatRange(from=-180.0F, to=180.0f) public double getLongitudeDegrees();
- method public void writeToParcel(@NonNull android.os.Parcel, int);
- field public static final android.os.Parcelable.Creator<android.location.GnssReflectingPlane> CREATOR;
- }
-
- public static final class GnssReflectingPlane.Builder {
- ctor public GnssReflectingPlane.Builder();
- method @NonNull public android.location.GnssReflectingPlane build();
- method @NonNull public android.location.GnssReflectingPlane.Builder setAltitudeMeters(@FloatRange(from=-1000.0F, to=10000.0f) double);
- method @NonNull public android.location.GnssReflectingPlane.Builder setAzimuthDegrees(@FloatRange(from=0.0f, to=360.0f) double);
- method @NonNull public android.location.GnssReflectingPlane.Builder setLatitudeDegrees(@FloatRange(from=-90.0F, to=90.0f) double);
- method @NonNull public android.location.GnssReflectingPlane.Builder setLongitudeDegrees(@FloatRange(from=-180.0F, to=180.0f) double);
- }
-
- public final class GnssRequest implements android.os.Parcelable {
- method public int describeContents();
- method public boolean isFullTracking();
- method public void writeToParcel(@NonNull android.os.Parcel, int);
- field @NonNull public static final android.os.Parcelable.Creator<android.location.GnssRequest> CREATOR;
- }
-
- public static final class GnssRequest.Builder {
- ctor public GnssRequest.Builder();
- ctor public GnssRequest.Builder(@NonNull android.location.GnssRequest);
- method @NonNull public android.location.GnssRequest build();
- method @NonNull public android.location.GnssRequest.Builder setFullTracking(boolean);
- }
-
- public final class GnssSingleSatCorrection implements android.os.Parcelable {
- method public int describeContents();
- method @FloatRange(from=0.0f, fromInclusive=false) public float getCarrierFrequencyHz();
- method @FloatRange(from=0.0f) public float getCombinedAttenuationDb();
- method public int getConstellationType();
- method @FloatRange(from=0.0f) public float getExcessPathLengthMeters();
- method @FloatRange(from=0.0f) public float getExcessPathLengthUncertaintyMeters();
- method @NonNull public java.util.List<android.location.GnssExcessPathInfo> getGnssExcessPathInfoList();
- method @FloatRange(from=0.0f, to=1.0f) public float getProbabilityLineOfSight();
- method @Deprecated @Nullable public android.location.GnssReflectingPlane getReflectingPlane();
- method @IntRange(from=0) public int getSatelliteId();
- method public boolean hasCombinedAttenuation();
- method public boolean hasExcessPathLength();
- method public boolean hasExcessPathLengthUncertainty();
- method @Deprecated public boolean hasReflectingPlane();
- method public boolean hasValidSatelliteLineOfSight();
- method public void writeToParcel(@NonNull android.os.Parcel, int);
- field public static final android.os.Parcelable.Creator<android.location.GnssSingleSatCorrection> CREATOR;
- }
-
- public static final class GnssSingleSatCorrection.Builder {
- ctor public GnssSingleSatCorrection.Builder();
- method @NonNull public android.location.GnssSingleSatCorrection build();
- method @NonNull public android.location.GnssSingleSatCorrection.Builder clearCombinedAttenuationDb();
- method @NonNull public android.location.GnssSingleSatCorrection.Builder clearExcessPathLengthMeters();
- method @NonNull public android.location.GnssSingleSatCorrection.Builder clearExcessPathLengthUncertaintyMeters();
- method @NonNull public android.location.GnssSingleSatCorrection.Builder clearProbabilityLineOfSight();
- method @NonNull public android.location.GnssSingleSatCorrection.Builder setCarrierFrequencyHz(@FloatRange(from=0.0f, fromInclusive=false) float);
- method @NonNull public android.location.GnssSingleSatCorrection.Builder setCombinedAttenuationDb(@FloatRange(from=0.0f) float);
- method @NonNull public android.location.GnssSingleSatCorrection.Builder setConstellationType(int);
- method @NonNull public android.location.GnssSingleSatCorrection.Builder setExcessPathLengthMeters(@FloatRange(from=0.0f) float);
- method @NonNull public android.location.GnssSingleSatCorrection.Builder setExcessPathLengthUncertaintyMeters(@FloatRange(from=0.0f) float);
- method @NonNull public android.location.GnssSingleSatCorrection.Builder setGnssExcessPathInfoList(@NonNull java.util.List<android.location.GnssExcessPathInfo>);
- method @NonNull public android.location.GnssSingleSatCorrection.Builder setProbabilityLineOfSight(@FloatRange(from=0.0f, to=1.0f) float);
- method @Deprecated @NonNull public android.location.GnssSingleSatCorrection.Builder setReflectingPlane(@Nullable android.location.GnssReflectingPlane);
- method @NonNull public android.location.GnssSingleSatCorrection.Builder setSatelliteId(@IntRange(from=0) int);
- }
-
- @Deprecated public class GpsClock implements android.os.Parcelable {
- method @Deprecated public int describeContents();
- method @Deprecated public double getBiasInNs();
- method @Deprecated public double getBiasUncertaintyInNs();
- method @Deprecated public double getDriftInNsPerSec();
- method @Deprecated public double getDriftUncertaintyInNsPerSec();
- method @Deprecated public long getFullBiasInNs();
- method @Deprecated public short getLeapSecond();
- method @Deprecated public long getTimeInNs();
- method @Deprecated public double getTimeUncertaintyInNs();
- method @Deprecated public byte getType();
- method @Deprecated public boolean hasBiasInNs();
- method @Deprecated public boolean hasBiasUncertaintyInNs();
- method @Deprecated public boolean hasDriftInNsPerSec();
- method @Deprecated public boolean hasDriftUncertaintyInNsPerSec();
- method @Deprecated public boolean hasFullBiasInNs();
- method @Deprecated public boolean hasLeapSecond();
- method @Deprecated public boolean hasTimeUncertaintyInNs();
- method @Deprecated public void reset();
- method @Deprecated public void resetBiasInNs();
- method @Deprecated public void resetBiasUncertaintyInNs();
- method @Deprecated public void resetDriftInNsPerSec();
- method @Deprecated public void resetDriftUncertaintyInNsPerSec();
- method @Deprecated public void resetFullBiasInNs();
- method @Deprecated public void resetLeapSecond();
- method @Deprecated public void resetTimeUncertaintyInNs();
- method @Deprecated public void set(android.location.GpsClock);
- method @Deprecated public void setBiasInNs(double);
- method @Deprecated public void setBiasUncertaintyInNs(double);
- method @Deprecated public void setDriftInNsPerSec(double);
- method @Deprecated public void setDriftUncertaintyInNsPerSec(double);
- method @Deprecated public void setFullBiasInNs(long);
- method @Deprecated public void setLeapSecond(short);
- method @Deprecated public void setTimeInNs(long);
- method @Deprecated public void setTimeUncertaintyInNs(double);
- method @Deprecated public void setType(byte);
- method @Deprecated public void writeToParcel(android.os.Parcel, int);
- field @Deprecated @NonNull public static final android.os.Parcelable.Creator<android.location.GpsClock> CREATOR;
- field @Deprecated public static final byte TYPE_GPS_TIME = 2; // 0x2
- field @Deprecated public static final byte TYPE_LOCAL_HW_TIME = 1; // 0x1
- field @Deprecated public static final byte TYPE_UNKNOWN = 0; // 0x0
- }
-
- @Deprecated public class GpsMeasurement implements android.os.Parcelable {
- method @Deprecated public int describeContents();
- method @Deprecated public double getAccumulatedDeltaRangeInMeters();
- method @Deprecated public short getAccumulatedDeltaRangeState();
- method @Deprecated public double getAccumulatedDeltaRangeUncertaintyInMeters();
- method @Deprecated public double getAzimuthInDeg();
- method @Deprecated public double getAzimuthUncertaintyInDeg();
- method @Deprecated public int getBitNumber();
- method @Deprecated public long getCarrierCycles();
- method @Deprecated public float getCarrierFrequencyInHz();
- method @Deprecated public double getCarrierPhase();
- method @Deprecated public double getCarrierPhaseUncertainty();
- method @Deprecated public double getCn0InDbHz();
- method @Deprecated public double getCodePhaseInChips();
- method @Deprecated public double getCodePhaseUncertaintyInChips();
- method @Deprecated public double getDopplerShiftInHz();
- method @Deprecated public double getDopplerShiftUncertaintyInHz();
- method @Deprecated public double getElevationInDeg();
- method @Deprecated public double getElevationUncertaintyInDeg();
- method @Deprecated public byte getLossOfLock();
- method @Deprecated public byte getMultipathIndicator();
- method @Deprecated public byte getPrn();
- method @Deprecated public double getPseudorangeInMeters();
- method @Deprecated public double getPseudorangeRateInMetersPerSec();
- method @Deprecated public double getPseudorangeRateUncertaintyInMetersPerSec();
- method @Deprecated public double getPseudorangeUncertaintyInMeters();
- method @Deprecated public long getReceivedGpsTowInNs();
- method @Deprecated public long getReceivedGpsTowUncertaintyInNs();
- method @Deprecated public double getSnrInDb();
- method @Deprecated public short getState();
- method @Deprecated public short getTimeFromLastBitInMs();
- method @Deprecated public double getTimeOffsetInNs();
- method @Deprecated public boolean hasAzimuthInDeg();
- method @Deprecated public boolean hasAzimuthUncertaintyInDeg();
- method @Deprecated public boolean hasBitNumber();
- method @Deprecated public boolean hasCarrierCycles();
- method @Deprecated public boolean hasCarrierFrequencyInHz();
- method @Deprecated public boolean hasCarrierPhase();
- method @Deprecated public boolean hasCarrierPhaseUncertainty();
- method @Deprecated public boolean hasCodePhaseInChips();
- method @Deprecated public boolean hasCodePhaseUncertaintyInChips();
- method @Deprecated public boolean hasDopplerShiftInHz();
- method @Deprecated public boolean hasDopplerShiftUncertaintyInHz();
- method @Deprecated public boolean hasElevationInDeg();
- method @Deprecated public boolean hasElevationUncertaintyInDeg();
- method @Deprecated public boolean hasPseudorangeInMeters();
- method @Deprecated public boolean hasPseudorangeUncertaintyInMeters();
- method @Deprecated public boolean hasSnrInDb();
- method @Deprecated public boolean hasTimeFromLastBitInMs();
- method @Deprecated public boolean isPseudorangeRateCorrected();
- method @Deprecated public boolean isUsedInFix();
- method @Deprecated public void reset();
- method @Deprecated public void resetAzimuthInDeg();
- method @Deprecated public void resetAzimuthUncertaintyInDeg();
- method @Deprecated public void resetBitNumber();
- method @Deprecated public void resetCarrierCycles();
- method @Deprecated public void resetCarrierFrequencyInHz();
- method @Deprecated public void resetCarrierPhase();
- method @Deprecated public void resetCarrierPhaseUncertainty();
- method @Deprecated public void resetCodePhaseInChips();
- method @Deprecated public void resetCodePhaseUncertaintyInChips();
- method @Deprecated public void resetDopplerShiftInHz();
- method @Deprecated public void resetDopplerShiftUncertaintyInHz();
- method @Deprecated public void resetElevationInDeg();
- method @Deprecated public void resetElevationUncertaintyInDeg();
- method @Deprecated public void resetPseudorangeInMeters();
- method @Deprecated public void resetPseudorangeUncertaintyInMeters();
- method @Deprecated public void resetSnrInDb();
- method @Deprecated public void resetTimeFromLastBitInMs();
- method @Deprecated public void set(android.location.GpsMeasurement);
- method @Deprecated public void setAccumulatedDeltaRangeInMeters(double);
- method @Deprecated public void setAccumulatedDeltaRangeState(short);
- method @Deprecated public void setAccumulatedDeltaRangeUncertaintyInMeters(double);
- method @Deprecated public void setAzimuthInDeg(double);
- method @Deprecated public void setAzimuthUncertaintyInDeg(double);
- method @Deprecated public void setBitNumber(int);
- method @Deprecated public void setCarrierCycles(long);
- method @Deprecated public void setCarrierFrequencyInHz(float);
- method @Deprecated public void setCarrierPhase(double);
- method @Deprecated public void setCarrierPhaseUncertainty(double);
- method @Deprecated public void setCn0InDbHz(double);
- method @Deprecated public void setCodePhaseInChips(double);
- method @Deprecated public void setCodePhaseUncertaintyInChips(double);
- method @Deprecated public void setDopplerShiftInHz(double);
- method @Deprecated public void setDopplerShiftUncertaintyInHz(double);
- method @Deprecated public void setElevationInDeg(double);
- method @Deprecated public void setElevationUncertaintyInDeg(double);
- method @Deprecated public void setLossOfLock(byte);
- method @Deprecated public void setMultipathIndicator(byte);
- method @Deprecated public void setPrn(byte);
- method @Deprecated public void setPseudorangeInMeters(double);
- method @Deprecated public void setPseudorangeRateInMetersPerSec(double);
- method @Deprecated public void setPseudorangeRateUncertaintyInMetersPerSec(double);
- method @Deprecated public void setPseudorangeUncertaintyInMeters(double);
- method @Deprecated public void setReceivedGpsTowInNs(long);
- method @Deprecated public void setReceivedGpsTowUncertaintyInNs(long);
- method @Deprecated public void setSnrInDb(double);
- method @Deprecated public void setState(short);
- method @Deprecated public void setTimeFromLastBitInMs(short);
- method @Deprecated public void setTimeOffsetInNs(double);
- method @Deprecated public void setUsedInFix(boolean);
- method @Deprecated public void writeToParcel(android.os.Parcel, int);
- field @Deprecated public static final short ADR_STATE_CYCLE_SLIP = 4; // 0x4
- field @Deprecated public static final short ADR_STATE_RESET = 2; // 0x2
- field @Deprecated public static final short ADR_STATE_UNKNOWN = 0; // 0x0
- field @Deprecated public static final short ADR_STATE_VALID = 1; // 0x1
- field @Deprecated @NonNull public static final android.os.Parcelable.Creator<android.location.GpsMeasurement> CREATOR;
- field @Deprecated public static final byte LOSS_OF_LOCK_CYCLE_SLIP = 2; // 0x2
- field @Deprecated public static final byte LOSS_OF_LOCK_OK = 1; // 0x1
- field @Deprecated public static final byte LOSS_OF_LOCK_UNKNOWN = 0; // 0x0
- field @Deprecated public static final byte MULTIPATH_INDICATOR_DETECTED = 1; // 0x1
- field @Deprecated public static final byte MULTIPATH_INDICATOR_NOT_USED = 2; // 0x2
- field @Deprecated public static final byte MULTIPATH_INDICATOR_UNKNOWN = 0; // 0x0
- field @Deprecated public static final short STATE_BIT_SYNC = 2; // 0x2
- field @Deprecated public static final short STATE_CODE_LOCK = 1; // 0x1
- field @Deprecated public static final short STATE_MSEC_AMBIGUOUS = 16; // 0x10
- field @Deprecated public static final short STATE_SUBFRAME_SYNC = 4; // 0x4
- field @Deprecated public static final short STATE_TOW_DECODED = 8; // 0x8
- field @Deprecated public static final short STATE_UNKNOWN = 0; // 0x0
- }
-
- @Deprecated public class GpsMeasurementsEvent implements android.os.Parcelable {
- ctor @Deprecated public GpsMeasurementsEvent(android.location.GpsClock, android.location.GpsMeasurement[]);
- method @Deprecated public int describeContents();
- method @Deprecated @NonNull public android.location.GpsClock getClock();
- method @Deprecated @NonNull public java.util.Collection<android.location.GpsMeasurement> getMeasurements();
- method @Deprecated public void writeToParcel(android.os.Parcel, int);
- field @Deprecated @NonNull public static final android.os.Parcelable.Creator<android.location.GpsMeasurementsEvent> CREATOR;
- field @Deprecated public static final int STATUS_GPS_LOCATION_DISABLED = 2; // 0x2
- field @Deprecated public static final int STATUS_NOT_SUPPORTED = 0; // 0x0
- field @Deprecated public static final int STATUS_READY = 1; // 0x1
- }
-
- @Deprecated public static interface GpsMeasurementsEvent.Listener {
- method @Deprecated public void onGpsMeasurementsReceived(android.location.GpsMeasurementsEvent);
- method @Deprecated public void onStatusChanged(int);
- }
-
- @Deprecated public class GpsNavigationMessage implements android.os.Parcelable {
- method @Deprecated public int describeContents();
- method @Deprecated @NonNull public byte[] getData();
- method @Deprecated public short getMessageId();
- method @Deprecated public byte getPrn();
- method @Deprecated public short getStatus();
- method @Deprecated public short getSubmessageId();
- method @Deprecated public byte getType();
- method @Deprecated public void reset();
- method @Deprecated public void set(android.location.GpsNavigationMessage);
- method @Deprecated public void setData(byte[]);
- method @Deprecated public void setMessageId(short);
- method @Deprecated public void setPrn(byte);
- method @Deprecated public void setStatus(short);
- method @Deprecated public void setSubmessageId(short);
- method @Deprecated public void setType(byte);
- method @Deprecated public void writeToParcel(android.os.Parcel, int);
- field @Deprecated @NonNull public static final android.os.Parcelable.Creator<android.location.GpsNavigationMessage> CREATOR;
- field @Deprecated public static final short STATUS_PARITY_PASSED = 1; // 0x1
- field @Deprecated public static final short STATUS_PARITY_REBUILT = 2; // 0x2
- field @Deprecated public static final short STATUS_UNKNOWN = 0; // 0x0
- field @Deprecated public static final byte TYPE_CNAV2 = 4; // 0x4
- field @Deprecated public static final byte TYPE_L1CA = 1; // 0x1
- field @Deprecated public static final byte TYPE_L2CNAV = 2; // 0x2
- field @Deprecated public static final byte TYPE_L5CNAV = 3; // 0x3
- field @Deprecated public static final byte TYPE_UNKNOWN = 0; // 0x0
- }
-
- @Deprecated public class GpsNavigationMessageEvent implements android.os.Parcelable {
- ctor @Deprecated public GpsNavigationMessageEvent(android.location.GpsNavigationMessage);
- method @Deprecated public int describeContents();
- method @Deprecated @NonNull public android.location.GpsNavigationMessage getNavigationMessage();
- method @Deprecated public void writeToParcel(android.os.Parcel, int);
- field @Deprecated @NonNull public static final android.os.Parcelable.Creator<android.location.GpsNavigationMessageEvent> CREATOR;
- field @Deprecated public static int STATUS_GPS_LOCATION_DISABLED;
- field @Deprecated public static int STATUS_NOT_SUPPORTED;
- field @Deprecated public static int STATUS_READY;
- }
-
- @Deprecated public static interface GpsNavigationMessageEvent.Listener {
- method @Deprecated public void onGpsNavigationMessageReceived(android.location.GpsNavigationMessageEvent);
- method @Deprecated public void onStatusChanged(int);
- }
-
- public final class LastLocationRequest implements android.os.Parcelable {
- method public int describeContents();
- method public boolean isAdasGnssBypass();
- method public boolean isHiddenFromAppOps();
- method public boolean isLocationSettingsIgnored();
- method public void writeToParcel(@NonNull android.os.Parcel, int);
- field @NonNull public static final android.os.Parcelable.Creator<android.location.LastLocationRequest> CREATOR;
- }
-
- public static final class LastLocationRequest.Builder {
- ctor public LastLocationRequest.Builder();
- ctor public LastLocationRequest.Builder(@NonNull android.location.LastLocationRequest);
- method @NonNull public android.location.LastLocationRequest build();
- method @NonNull @RequiresPermission(android.Manifest.permission.LOCATION_BYPASS) public android.location.LastLocationRequest.Builder setAdasGnssBypass(boolean);
- method @NonNull @RequiresPermission(android.Manifest.permission.UPDATE_APP_OPS_STATS) public android.location.LastLocationRequest.Builder setHiddenFromAppOps(boolean);
- method @NonNull @RequiresPermission(android.Manifest.permission.LOCATION_BYPASS) public android.location.LastLocationRequest.Builder setLocationSettingsIgnored(boolean);
- }
-
public class Location implements android.os.Parcelable {
method public void makeComplete();
method @Deprecated public void setIsFromMockProvider(boolean);
field @Deprecated public static final String EXTRA_NO_GPS_LOCATION = "noGPSLocation";
}
- public class LocationManager {
- method @RequiresPermission(allOf={android.Manifest.permission.LOCATION_HARDWARE, android.Manifest.permission.INTERACT_ACROSS_USERS}) public void addProviderRequestChangedListener(@NonNull java.util.concurrent.Executor, @NonNull android.location.provider.ProviderRequest.ChangedListener);
- method @Deprecated @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) public void flushGnssBatch();
- method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public void getCurrentLocation(@NonNull android.location.LocationRequest, @Nullable android.os.CancellationSignal, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<android.location.Location>);
- method @Nullable public String getExtraLocationControllerPackage();
- method @Deprecated public int getGnssBatchSize();
- method @Nullable @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public android.location.Location getLastKnownLocation(@NonNull String, @NonNull android.location.LastLocationRequest);
- method @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) public void injectGnssMeasurementCorrections(@NonNull android.location.GnssMeasurementCorrections);
- method public boolean isAdasGnssLocationEnabled();
- method public boolean isExtraLocationControllerPackageEnabled();
- method public boolean isLocationEnabledForUser(@NonNull android.os.UserHandle);
- method public boolean isProviderEnabledForUser(@NonNull String, @NonNull android.os.UserHandle);
- method @Deprecated @RequiresPermission(android.Manifest.permission.READ_DEVICE_CONFIG) public boolean isProviderPackage(@NonNull String);
- method @RequiresPermission(android.Manifest.permission.READ_DEVICE_CONFIG) public boolean isProviderPackage(@Nullable String, @NonNull String, @Nullable String);
- method @Deprecated @RequiresPermission(allOf={android.Manifest.permission.LOCATION_HARDWARE, android.Manifest.permission.UPDATE_APP_OPS_STATS}) public boolean registerGnssBatchedLocationCallback(long, boolean, @NonNull android.location.BatchedLocationCallback, @Nullable android.os.Handler);
- method @Deprecated @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) public boolean registerGnssMeasurementsCallback(@NonNull android.location.GnssRequest, @NonNull java.util.concurrent.Executor, @NonNull android.location.GnssMeasurementsEvent.Callback);
- method @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) public void removeProviderRequestChangedListener(@NonNull android.location.provider.ProviderRequest.ChangedListener);
- method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public void requestLocationUpdates(@Nullable android.location.LocationRequest, @NonNull android.location.LocationListener, @Nullable android.os.Looper);
- method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public void requestLocationUpdates(@Nullable android.location.LocationRequest, @NonNull java.util.concurrent.Executor, @NonNull android.location.LocationListener);
- method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public void requestLocationUpdates(@Nullable android.location.LocationRequest, @NonNull android.app.PendingIntent);
- method @RequiresPermission(android.Manifest.permission.LOCATION_BYPASS) public void setAdasGnssLocationEnabled(boolean);
- method @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) public void setExtraLocationControllerPackage(@Nullable String);
- method @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) public void setExtraLocationControllerPackageEnabled(boolean);
- method @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public void setLocationEnabledForUser(boolean, @NonNull android.os.UserHandle);
- method @Deprecated @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public boolean setProviderEnabledForUser(@NonNull String, boolean, @NonNull android.os.UserHandle);
- method @Deprecated @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) public boolean unregisterGnssBatchedLocationCallback(@NonNull android.location.BatchedLocationCallback);
- field public static final String ACTION_ADAS_GNSS_ENABLED_CHANGED = "android.location.action.ADAS_GNSS_ENABLED_CHANGED";
- field public static final String EXTRA_ADAS_GNSS_ENABLED = "android.location.extra.ADAS_GNSS_ENABLED";
- field @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) public static final String GPS_HARDWARE_PROVIDER = "gps_hardware";
- }
-
- public final class LocationRequest implements android.os.Parcelable {
- method @Deprecated @NonNull public static android.location.LocationRequest create();
- method @Deprecated @NonNull public static android.location.LocationRequest createFromDeprecatedCriteria(@NonNull android.location.Criteria, long, float, boolean);
- method @Deprecated @NonNull public static android.location.LocationRequest createFromDeprecatedProvider(@NonNull String, long, float, boolean);
- method @Deprecated public long getExpireAt();
- method @Deprecated public long getExpireIn();
- method @Deprecated public long getFastestInterval();
- method @Deprecated public boolean getHideFromAppOps();
- method @Deprecated public long getInterval();
- method @Deprecated public int getNumUpdates();
- method @Deprecated @NonNull public String getProvider();
- method @Deprecated public float getSmallestDisplacement();
- method @NonNull public android.os.WorkSource getWorkSource();
- method public boolean isAdasGnssBypass();
- method public boolean isHiddenFromAppOps();
- method public boolean isLocationSettingsIgnored();
- method public boolean isLowPower();
- method @Deprecated public boolean isLowPowerMode();
- method @Deprecated @NonNull public android.location.LocationRequest setExpireAt(long);
- method @Deprecated @NonNull public android.location.LocationRequest setExpireIn(long);
- method @Deprecated @NonNull public android.location.LocationRequest setFastestInterval(long);
- method @Deprecated public void setHideFromAppOps(boolean);
- method @Deprecated @NonNull public android.location.LocationRequest setInterval(long);
- method @Deprecated @NonNull @RequiresPermission(android.Manifest.permission.LOCATION_BYPASS) public android.location.LocationRequest setLocationSettingsIgnored(boolean);
- method @Deprecated @NonNull public android.location.LocationRequest setLowPowerMode(boolean);
- method @Deprecated @NonNull public android.location.LocationRequest setNumUpdates(int);
- method @Deprecated @NonNull public android.location.LocationRequest setProvider(@NonNull String);
- method @Deprecated @NonNull public android.location.LocationRequest setQuality(int);
- method @Deprecated @NonNull public android.location.LocationRequest setSmallestDisplacement(float);
- method @Deprecated public void setWorkSource(@Nullable android.os.WorkSource);
- field @Deprecated public static final int ACCURACY_BLOCK = 102; // 0x66
- field @Deprecated public static final int ACCURACY_CITY = 104; // 0x68
- field @Deprecated public static final int ACCURACY_FINE = 100; // 0x64
- field @Deprecated public static final int POWER_HIGH = 203; // 0xcb
- field @Deprecated public static final int POWER_LOW = 201; // 0xc9
- field @Deprecated public static final int POWER_NONE = 200; // 0xc8
- }
-
- public static final class LocationRequest.Builder {
- method @NonNull @RequiresPermission(android.Manifest.permission.LOCATION_BYPASS) public android.location.LocationRequest.Builder setAdasGnssBypass(boolean);
- method @NonNull @RequiresPermission(android.Manifest.permission.UPDATE_APP_OPS_STATS) public android.location.LocationRequest.Builder setHiddenFromAppOps(boolean);
- method @NonNull @RequiresPermission(android.Manifest.permission.LOCATION_BYPASS) public android.location.LocationRequest.Builder setLocationSettingsIgnored(boolean);
- method @NonNull @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) public android.location.LocationRequest.Builder setLowPower(boolean);
- method @NonNull @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS) public android.location.LocationRequest.Builder setWorkSource(@Nullable android.os.WorkSource);
- }
-
- public final class SatellitePvt implements android.os.Parcelable {
- method public int describeContents();
- method @Nullable public android.location.SatellitePvt.ClockInfo getClockInfo();
- method public int getEphemerisSource();
- method @FloatRange public double getIonoDelayMeters();
- method @IntRange(from=0, to=1023) public int getIssueOfDataClock();
- method @IntRange(from=0, to=1023) public int getIssueOfDataEphemeris();
- method @Nullable public android.location.SatellitePvt.PositionEcef getPositionEcef();
- method @IntRange(from=0) public long getTimeOfClockSeconds();
- method @IntRange(from=0) public long getTimeOfEphemerisSeconds();
- method @FloatRange public double getTropoDelayMeters();
- method @Nullable public android.location.SatellitePvt.VelocityEcef getVelocityEcef();
- method public boolean hasIono();
- method public boolean hasIssueOfDataClock();
- method public boolean hasIssueOfDataEphemeris();
- method public boolean hasPositionVelocityClockInfo();
- method public boolean hasTimeOfClockSeconds();
- method public boolean hasTimeOfEphemerisSeconds();
- method public boolean hasTropo();
- method public void writeToParcel(@NonNull android.os.Parcel, int);
- field @NonNull public static final android.os.Parcelable.Creator<android.location.SatellitePvt> CREATOR;
- field public static final int EPHEMERIS_SOURCE_DEMODULATED = 0; // 0x0
- field public static final int EPHEMERIS_SOURCE_OTHER = 3; // 0x3
- field public static final int EPHEMERIS_SOURCE_SERVER_LONG_TERM = 2; // 0x2
- field public static final int EPHEMERIS_SOURCE_SERVER_NORMAL = 1; // 0x1
- }
-
- public static final class SatellitePvt.Builder {
- ctor public SatellitePvt.Builder();
- method @NonNull public android.location.SatellitePvt build();
- method @NonNull public android.location.SatellitePvt.Builder setClockInfo(@NonNull android.location.SatellitePvt.ClockInfo);
- method @NonNull public android.location.SatellitePvt.Builder setEphemerisSource(int);
- method @NonNull public android.location.SatellitePvt.Builder setIonoDelayMeters(@FloatRange(from=0.0f, to=100.0f) double);
- method @NonNull public android.location.SatellitePvt.Builder setIssueOfDataClock(@IntRange(from=0, to=1023) int);
- method @NonNull public android.location.SatellitePvt.Builder setIssueOfDataEphemeris(@IntRange(from=0, to=1023) int);
- method @NonNull public android.location.SatellitePvt.Builder setPositionEcef(@NonNull android.location.SatellitePvt.PositionEcef);
- method @NonNull public android.location.SatellitePvt.Builder setTimeOfClockSeconds(@IntRange(from=0) long);
- method @NonNull public android.location.SatellitePvt.Builder setTimeOfEphemerisSeconds(@IntRange(from=0) long);
- method @NonNull public android.location.SatellitePvt.Builder setTropoDelayMeters(@FloatRange(from=0.0f, to=100.0f) double);
- method @NonNull public android.location.SatellitePvt.Builder setVelocityEcef(@NonNull android.location.SatellitePvt.VelocityEcef);
- }
-
- public static final class SatellitePvt.ClockInfo implements android.os.Parcelable {
- ctor public SatellitePvt.ClockInfo(double, double, double);
- method public int describeContents();
- method @FloatRange public double getClockDriftMetersPerSecond();
- method @FloatRange public double getHardwareCodeBiasMeters();
- method @FloatRange public double getTimeCorrectionMeters();
- method public void writeToParcel(@NonNull android.os.Parcel, int);
- field @NonNull public static final android.os.Parcelable.Creator<android.location.SatellitePvt.ClockInfo> CREATOR;
- }
-
- public static final class SatellitePvt.PositionEcef implements android.os.Parcelable {
- ctor public SatellitePvt.PositionEcef(double, double, double, double);
- method public int describeContents();
- method @FloatRange(from=0.0f, fromInclusive=false) public double getUreMeters();
- method @FloatRange public double getXMeters();
- method @FloatRange public double getYMeters();
- method @FloatRange public double getZMeters();
- method public void writeToParcel(@NonNull android.os.Parcel, int);
- field @NonNull public static final android.os.Parcelable.Creator<android.location.SatellitePvt.PositionEcef> CREATOR;
- }
-
- public static final class SatellitePvt.VelocityEcef implements android.os.Parcelable {
- ctor public SatellitePvt.VelocityEcef(double, double, double, double);
- method public int describeContents();
- method @FloatRange(from=0.0f, fromInclusive=false) public double getUreRateMetersPerSecond();
- method @FloatRange public double getXMetersPerSecond();
- method @FloatRange public double getYMetersPerSecond();
- method @FloatRange public double getZMetersPerSecond();
- method public void writeToParcel(@NonNull android.os.Parcel, int);
- field @NonNull public static final android.os.Parcelable.Creator<android.location.SatellitePvt.VelocityEcef> CREATOR;
- }
-
-}
-
-package android.location.provider {
-
- public abstract class LocationProviderBase {
- ctor public LocationProviderBase(@NonNull android.content.Context, @NonNull String, @NonNull android.location.provider.ProviderProperties);
- method @Nullable public final android.os.IBinder getBinder();
- method @NonNull public android.location.provider.ProviderProperties getProperties();
- method public boolean isAllowed();
- method public abstract void onFlush(@NonNull android.location.provider.LocationProviderBase.OnFlushCompleteCallback);
- method public abstract void onSendExtraCommand(@NonNull String, @Nullable android.os.Bundle);
- method public abstract void onSetRequest(@NonNull android.location.provider.ProviderRequest);
- method public void reportLocation(@NonNull android.location.Location);
- method public void reportLocations(@NonNull java.util.List<android.location.Location>);
- method public void setAllowed(boolean);
- method public void setProperties(@NonNull android.location.provider.ProviderProperties);
- field public static final String ACTION_FUSED_PROVIDER = "com.android.location.service.FusedLocationProvider";
- field public static final String ACTION_GNSS_PROVIDER = "android.location.provider.action.GNSS_PROVIDER";
- field public static final String ACTION_NETWORK_PROVIDER = "com.android.location.service.v3.NetworkLocationProvider";
- }
-
- public static interface LocationProviderBase.OnFlushCompleteCallback {
- method public void onFlushComplete();
- }
-
- public final class ProviderRequest implements android.os.Parcelable {
- method public int describeContents();
- method @IntRange(from=0) public long getIntervalMillis();
- method @IntRange(from=0) public long getMaxUpdateDelayMillis();
- method public int getQuality();
- method @NonNull public android.os.WorkSource getWorkSource();
- method public boolean isActive();
- method public boolean isLocationSettingsIgnored();
- method public boolean isLowPower();
- method public void writeToParcel(@NonNull android.os.Parcel, int);
- field @NonNull public static final android.os.Parcelable.Creator<android.location.provider.ProviderRequest> CREATOR;
- field @NonNull public static final android.location.provider.ProviderRequest EMPTY_REQUEST;
- field public static final long INTERVAL_DISABLED = 9223372036854775807L; // 0x7fffffffffffffffL
- }
-
- public static final class ProviderRequest.Builder {
- ctor public ProviderRequest.Builder();
- method @NonNull public android.location.provider.ProviderRequest build();
- method @NonNull public android.location.provider.ProviderRequest.Builder setIntervalMillis(@IntRange(from=0) long);
- method @NonNull public android.location.provider.ProviderRequest.Builder setLocationSettingsIgnored(boolean);
- method @NonNull public android.location.provider.ProviderRequest.Builder setLowPower(boolean);
- method @NonNull public android.location.provider.ProviderRequest.Builder setMaxUpdateDelayMillis(@IntRange(from=0) long);
- method @NonNull public android.location.provider.ProviderRequest.Builder setQuality(int);
- method @NonNull public android.location.provider.ProviderRequest.Builder setWorkSource(@NonNull android.os.WorkSource);
- }
-
- public static interface ProviderRequest.ChangedListener {
- method public void onProviderRequestChanged(@NonNull String, @NonNull android.location.provider.ProviderRequest);
- }
-
}
package android.media {
@@ -7281,8 +6650,11 @@ package android.media.audiofx {
package android.media.audiopolicy {
- public class AudioMix {
+ public class AudioMix implements android.os.Parcelable {
+ method public int describeContents();
method public int getMixState();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.media.audiopolicy.AudioMix> CREATOR;
field public static final int MIX_STATE_DISABLED = -1; // 0xffffffff
field public static final int MIX_STATE_IDLE = 0; // 0x0
field public static final int MIX_STATE_MIXING = 1; // 0x1
@@ -7291,15 +6663,18 @@ package android.media.audiopolicy {
}
public static class AudioMix.Builder {
- ctor public AudioMix.Builder(android.media.audiopolicy.AudioMixingRule) throws java.lang.IllegalArgumentException;
+ ctor public AudioMix.Builder(@NonNull android.media.audiopolicy.AudioMixingRule) throws java.lang.IllegalArgumentException;
method public android.media.audiopolicy.AudioMix build() throws java.lang.IllegalArgumentException;
method public android.media.audiopolicy.AudioMix.Builder setDevice(@NonNull android.media.AudioDeviceInfo) throws java.lang.IllegalArgumentException;
- method public android.media.audiopolicy.AudioMix.Builder setFormat(android.media.AudioFormat) throws java.lang.IllegalArgumentException;
+ method public android.media.audiopolicy.AudioMix.Builder setFormat(@NonNull android.media.AudioFormat) throws java.lang.IllegalArgumentException;
method public android.media.audiopolicy.AudioMix.Builder setRouteFlags(int) throws java.lang.IllegalArgumentException;
}
- public class AudioMixingRule {
+ public class AudioMixingRule implements android.os.Parcelable {
+ method public int describeContents();
method public int getTargetMixRole();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.media.audiopolicy.AudioMixingRule> CREATOR;
field public static final int MIX_ROLE_INJECTOR = 1; // 0x1
field public static final int MIX_ROLE_PLAYERS = 0; // 0x0
field public static final int RULE_MATCH_ATTRIBUTE_CAPTURE_PRESET = 2; // 0x2
@@ -7336,6 +6711,7 @@ package android.media.audiopolicy {
method public boolean setUidDeviceAffinity(int, @NonNull java.util.List<android.media.AudioDeviceInfo>);
method public boolean setUserIdDeviceAffinity(int, @NonNull java.util.List<android.media.AudioDeviceInfo>);
method public String toLogFriendlyString();
+ method @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public int updateMixingRules(@NonNull java.util.List<android.util.Pair<android.media.audiopolicy.AudioMix,android.media.audiopolicy.AudioMixingRule>>);
field public static final int FOCUS_POLICY_DUCKING_DEFAULT = 0; // 0x0
field public static final int FOCUS_POLICY_DUCKING_IN_APP = 0; // 0x0
field public static final int FOCUS_POLICY_DUCKING_IN_POLICY = 1; // 0x1
@@ -17321,7 +16697,6 @@ package android.telephony.satellite {
field public static final int NT_RADIO_TECHNOLOGY_NR_NTN = 2; // 0x2
field public static final int NT_RADIO_TECHNOLOGY_PROPRIETARY = 4; // 0x4
field public static final int NT_RADIO_TECHNOLOGY_UNKNOWN = 0; // 0x0
- field public static final int SATELLITE_ACCESS_BARRED = 16; // 0x10
field public static final int SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE = 0; // 0x0
field public static final int SATELLITE_DATAGRAM_TRANSFER_STATE_RECEIVE_FAILED = 7; // 0x7
field public static final int SATELLITE_DATAGRAM_TRANSFER_STATE_RECEIVE_NONE = 6; // 0x6
@@ -17331,13 +16706,6 @@ package android.telephony.satellite {
field public static final int SATELLITE_DATAGRAM_TRANSFER_STATE_SEND_FAILED = 3; // 0x3
field public static final int SATELLITE_DATAGRAM_TRANSFER_STATE_SEND_SUCCESS = 2; // 0x2
field public static final int SATELLITE_DATAGRAM_TRANSFER_STATE_UNKNOWN = -1; // 0xffffffff
- field public static final int SATELLITE_ERROR = 1; // 0x1
- field public static final int SATELLITE_ERROR_NONE = 0; // 0x0
- field public static final int SATELLITE_INVALID_ARGUMENTS = 8; // 0x8
- field public static final int SATELLITE_INVALID_MODEM_STATE = 7; // 0x7
- field public static final int SATELLITE_INVALID_TELEPHONY_STATE = 6; // 0x6
- field public static final int SATELLITE_MODEM_BUSY = 22; // 0x16
- field public static final int SATELLITE_MODEM_ERROR = 4; // 0x4
field public static final int SATELLITE_MODEM_STATE_DATAGRAM_RETRYING = 3; // 0x3
field public static final int SATELLITE_MODEM_STATE_DATAGRAM_TRANSFERRING = 2; // 0x2
field public static final int SATELLITE_MODEM_STATE_IDLE = 0; // 0x0
@@ -17345,21 +16713,29 @@ package android.telephony.satellite {
field public static final int SATELLITE_MODEM_STATE_OFF = 4; // 0x4
field public static final int SATELLITE_MODEM_STATE_UNAVAILABLE = 5; // 0x5
field public static final int SATELLITE_MODEM_STATE_UNKNOWN = -1; // 0xffffffff
- field public static final int SATELLITE_NETWORK_ERROR = 5; // 0x5
- field public static final int SATELLITE_NETWORK_TIMEOUT = 17; // 0x11
- field public static final int SATELLITE_NOT_AUTHORIZED = 19; // 0x13
- field public static final int SATELLITE_NOT_REACHABLE = 18; // 0x12
- field public static final int SATELLITE_NOT_SUPPORTED = 20; // 0x14
- field public static final int SATELLITE_NO_RESOURCES = 12; // 0xc
- field public static final int SATELLITE_RADIO_NOT_AVAILABLE = 10; // 0xa
- field public static final int SATELLITE_REQUEST_ABORTED = 15; // 0xf
- field public static final int SATELLITE_REQUEST_FAILED = 9; // 0x9
- field public static final int SATELLITE_REQUEST_IN_PROGRESS = 21; // 0x15
- field public static final int SATELLITE_REQUEST_NOT_SUPPORTED = 11; // 0xb
- field public static final int SATELLITE_SERVER_ERROR = 2; // 0x2
- field public static final int SATELLITE_SERVICE_ERROR = 3; // 0x3
- field public static final int SATELLITE_SERVICE_NOT_PROVISIONED = 13; // 0xd
- field public static final int SATELLITE_SERVICE_PROVISION_IN_PROGRESS = 14; // 0xe
+ field public static final int SATELLITE_RESULT_ACCESS_BARRED = 16; // 0x10
+ field public static final int SATELLITE_RESULT_ERROR = 1; // 0x1
+ field public static final int SATELLITE_RESULT_INVALID_ARGUMENTS = 8; // 0x8
+ field public static final int SATELLITE_RESULT_INVALID_MODEM_STATE = 7; // 0x7
+ field public static final int SATELLITE_RESULT_INVALID_TELEPHONY_STATE = 6; // 0x6
+ field public static final int SATELLITE_RESULT_MODEM_BUSY = 22; // 0x16
+ field public static final int SATELLITE_RESULT_MODEM_ERROR = 4; // 0x4
+ field public static final int SATELLITE_RESULT_NETWORK_ERROR = 5; // 0x5
+ field public static final int SATELLITE_RESULT_NETWORK_TIMEOUT = 17; // 0x11
+ field public static final int SATELLITE_RESULT_NOT_AUTHORIZED = 19; // 0x13
+ field public static final int SATELLITE_RESULT_NOT_REACHABLE = 18; // 0x12
+ field public static final int SATELLITE_RESULT_NOT_SUPPORTED = 20; // 0x14
+ field public static final int SATELLITE_RESULT_NO_RESOURCES = 12; // 0xc
+ field public static final int SATELLITE_RESULT_RADIO_NOT_AVAILABLE = 10; // 0xa
+ field public static final int SATELLITE_RESULT_REQUEST_ABORTED = 15; // 0xf
+ field public static final int SATELLITE_RESULT_REQUEST_FAILED = 9; // 0x9
+ field public static final int SATELLITE_RESULT_REQUEST_IN_PROGRESS = 21; // 0x15
+ field public static final int SATELLITE_RESULT_REQUEST_NOT_SUPPORTED = 11; // 0xb
+ field public static final int SATELLITE_RESULT_SERVER_ERROR = 2; // 0x2
+ field public static final int SATELLITE_RESULT_SERVICE_ERROR = 3; // 0x3
+ field public static final int SATELLITE_RESULT_SERVICE_NOT_PROVISIONED = 13; // 0xd
+ field public static final int SATELLITE_RESULT_SERVICE_PROVISION_IN_PROGRESS = 14; // 0xe
+ field public static final int SATELLITE_RESULT_SUCCESS = 0; // 0x0
}
public static class SatelliteManager.SatelliteException extends java.lang.Exception {
diff --git a/core/api/system-lint-baseline.txt b/core/api/system-lint-baseline.txt
index 6c233270bad5..e7c0a912383f 100644
--- a/core/api/system-lint-baseline.txt
+++ b/core/api/system-lint-baseline.txt
@@ -135,16 +135,6 @@ SamShouldBeLast: android.content.pm.ResolveInfo#dump(android.util.Printer, Strin
SAM-compatible parameters (such as parameter 1, "pw", in android.content.pm.ResolveInfo.dump) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
SamShouldBeLast: android.location.Location#dump(android.util.Printer, String):
SAM-compatible parameters (such as parameter 1, "pw", in android.location.Location.dump) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
-SamShouldBeLast: android.location.LocationManager#addNmeaListener(android.location.OnNmeaMessageListener, android.os.Handler):
- SAM-compatible parameters (such as parameter 1, "listener", in android.location.LocationManager.addNmeaListener) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
-SamShouldBeLast: android.location.LocationManager#requestLocationUpdates(String, long, float, android.location.LocationListener, android.os.Looper):
- SAM-compatible parameters (such as parameter 4, "listener", in android.location.LocationManager.requestLocationUpdates) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
-SamShouldBeLast: android.location.LocationManager#requestLocationUpdates(long, float, android.location.Criteria, android.location.LocationListener, android.os.Looper):
- SAM-compatible parameters (such as parameter 4, "listener", in android.location.LocationManager.requestLocationUpdates) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
-SamShouldBeLast: android.location.LocationManager#requestSingleUpdate(String, android.location.LocationListener, android.os.Looper):
- SAM-compatible parameters (such as parameter 2, "listener", in android.location.LocationManager.requestSingleUpdate) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
-SamShouldBeLast: android.location.LocationManager#requestSingleUpdate(android.location.Criteria, android.location.LocationListener, android.os.Looper):
- SAM-compatible parameters (such as parameter 2, "listener", in android.location.LocationManager.requestSingleUpdate) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
SamShouldBeLast: android.media.AudioFocusRequest.Builder#setOnAudioFocusChangeListener(android.media.AudioManager.OnAudioFocusChangeListener, android.os.Handler):
SAM-compatible parameters (such as parameter 1, "listener", in android.media.AudioFocusRequest.Builder.setOnAudioFocusChangeListener) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
SamShouldBeLast: android.media.AudioManager#requestAudioFocus(android.media.AudioManager.OnAudioFocusChangeListener, int, int):
diff --git a/core/api/system-removed.txt b/core/api/system-removed.txt
index 1c10356c6b03..aa17df3471d7 100644
--- a/core/api/system-removed.txt
+++ b/core/api/system-removed.txt
@@ -114,20 +114,6 @@ package android.hardware.hdmi {
}
-package android.location {
-
- public class LocationManager {
- method @Deprecated public boolean addGpsMeasurementListener(android.location.GpsMeasurementsEvent.Listener);
- method @Deprecated public boolean addGpsNavigationMessageListener(android.location.GpsNavigationMessageEvent.Listener);
- method @Deprecated @RequiresPermission(android.Manifest.permission.READ_DEVICE_CONFIG) public boolean isProviderPackage(@Nullable String, @NonNull String);
- method @Deprecated public void removeGpsMeasurementListener(android.location.GpsMeasurementsEvent.Listener);
- method @Deprecated public void removeGpsNavigationMessageListener(android.location.GpsNavigationMessageEvent.Listener);
- method @Deprecated @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) public void setLocationControllerExtraPackage(String);
- method @Deprecated @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) public void setLocationControllerExtraPackageEnabled(boolean);
- }
-
-}
-
package android.media.tv {
public final class TvInputManager {
diff --git a/core/api/test-current.txt b/core/api/test-current.txt
index 22d2999e9309..642813f36a58 100644
--- a/core/api/test-current.txt
+++ b/core/api/test-current.txt
@@ -499,14 +499,14 @@ package android.app {
method public int describeContents();
method public int getActivityType();
method @Nullable public android.graphics.Rect getAppBounds();
- method public android.graphics.Rect getBounds();
+ method @NonNull public android.graphics.Rect getBounds();
method @NonNull public android.graphics.Rect getMaxBounds();
method public int getRotation();
method public int getWindowingMode();
method public static boolean isFloating(int);
method public void setActivityType(int);
method public void setAppBounds(@Nullable android.graphics.Rect);
- method public void setBounds(android.graphics.Rect);
+ method public void setBounds(@Nullable android.graphics.Rect);
method public void setMaxBounds(@Nullable android.graphics.Rect);
method public void setRotation(int);
method public void setTo(android.app.WindowConfiguration);
@@ -1748,109 +1748,6 @@ package android.inputmethodservice {
}
-package android.location {
-
- public final class GnssClock implements android.os.Parcelable {
- ctor public GnssClock();
- method public void reset();
- method public void resetBiasNanos();
- method public void resetBiasUncertaintyNanos();
- method public void resetDriftNanosPerSecond();
- method public void resetDriftUncertaintyNanosPerSecond();
- method public void resetElapsedRealtimeNanos();
- method public void resetElapsedRealtimeUncertaintyNanos();
- method public void resetFullBiasNanos();
- method public void resetLeapSecond();
- method public void resetReferenceCarrierFrequencyHzForIsb();
- method public void resetReferenceCodeTypeForIsb();
- method public void resetReferenceConstellationTypeForIsb();
- method public void resetTimeUncertaintyNanos();
- method public void set(android.location.GnssClock);
- method public void setBiasNanos(double);
- method public void setBiasUncertaintyNanos(@FloatRange(from=0.0f) double);
- method public void setDriftNanosPerSecond(double);
- method public void setDriftUncertaintyNanosPerSecond(@FloatRange(from=0.0f) double);
- method public void setElapsedRealtimeNanos(long);
- method public void setElapsedRealtimeUncertaintyNanos(@FloatRange(from=0.0f) double);
- method public void setFullBiasNanos(long);
- method public void setHardwareClockDiscontinuityCount(int);
- method public void setLeapSecond(int);
- method public void setReferenceCarrierFrequencyHzForIsb(@FloatRange(from=0.0) double);
- method public void setReferenceCodeTypeForIsb(@NonNull String);
- method public void setReferenceConstellationTypeForIsb(int);
- method public void setTimeNanos(long);
- method public void setTimeUncertaintyNanos(@FloatRange(from=0.0f) double);
- }
-
- public final class GnssMeasurement implements android.os.Parcelable {
- ctor public GnssMeasurement();
- method public void reset();
- method public void resetAutomaticGainControlLevel();
- method public void resetBasebandCn0DbHz();
- method @Deprecated public void resetCarrierCycles();
- method public void resetCarrierFrequencyHz();
- method @Deprecated public void resetCarrierPhase();
- method @Deprecated public void resetCarrierPhaseUncertainty();
- method public void resetCodeType();
- method public void resetCorrelationVectors();
- method public void resetFullInterSignalBiasNanos();
- method public void resetFullInterSignalBiasUncertaintyNanos();
- method public void resetSatelliteInterSignalBiasNanos();
- method public void resetSatelliteInterSignalBiasUncertaintyNanos();
- method public void resetSatellitePvt();
- method public void resetSnrInDb();
- method public void set(android.location.GnssMeasurement);
- method public void setAccumulatedDeltaRangeMeters(double);
- method public void setAccumulatedDeltaRangeState(int);
- method public void setAccumulatedDeltaRangeUncertaintyMeters(double);
- method @Deprecated public void setAutomaticGainControlLevelInDb(double);
- method public void setBasebandCn0DbHz(double);
- method @Deprecated public void setCarrierCycles(long);
- method public void setCarrierFrequencyHz(float);
- method @Deprecated public void setCarrierPhase(double);
- method @Deprecated public void setCarrierPhaseUncertainty(double);
- method public void setCn0DbHz(double);
- method public void setCodeType(@NonNull String);
- method public void setConstellationType(int);
- method public void setCorrelationVectors(@Nullable java.util.Collection<android.location.CorrelationVector>);
- method public void setFullInterSignalBiasNanos(double);
- method public void setFullInterSignalBiasUncertaintyNanos(@FloatRange(from=0.0) double);
- method public void setMultipathIndicator(int);
- method public void setPseudorangeRateMetersPerSecond(double);
- method public void setPseudorangeRateUncertaintyMetersPerSecond(double);
- method public void setReceivedSvTimeNanos(long);
- method public void setReceivedSvTimeUncertaintyNanos(long);
- method public void setSatelliteInterSignalBiasNanos(double);
- method public void setSatelliteInterSignalBiasUncertaintyNanos(@FloatRange(from=0.0) double);
- method public void setSatellitePvt(@Nullable android.location.SatellitePvt);
- method public void setSnrInDb(double);
- method public void setState(int);
- method public void setSvid(int);
- method public void setTimeOffsetNanos(double);
- field public static final int ADR_STATE_ALL = 31; // 0x1f
- }
-
- public final class GnssNavigationMessage implements android.os.Parcelable {
- ctor public GnssNavigationMessage();
- method public void reset();
- method public void set(android.location.GnssNavigationMessage);
- method public void setData(byte[]);
- method public void setMessageId(@IntRange(from=0xffffffff, to=120) int);
- method public void setStatus(int);
- method public void setSubmessageId(@IntRange(from=1) int);
- method public void setSvid(@IntRange(from=1, to=200) int);
- method public void setType(int);
- }
-
- public class LocationManager {
- method @NonNull public String[] getBackgroundThrottlingWhitelist();
- method @NonNull public android.os.PackageTagsList getIgnoreSettingsAllowlist();
- method @Deprecated @NonNull public String[] getIgnoreSettingsWhitelist();
- method @Deprecated @Nullable @RequiresPermission(android.Manifest.permission.READ_DEVICE_CONFIG) public java.util.List<java.lang.String> getProviderPackages(@NonNull String);
- }
-
-}
-
package android.media {
public final class AudioAttributes implements android.os.Parcelable {
@@ -2247,6 +2144,10 @@ package android.os {
method @RequiresPermission(android.Manifest.permission.DEVICE_POWER) public void unplugBattery(boolean);
}
+ public final class BugreportParams {
+ field public static final int BUGREPORT_MODE_MAX_VALUE = 7; // 0x7
+ }
+
public class Build {
method public static boolean is64BitAbi(String);
method public static boolean isDebuggable();
@@ -2708,7 +2609,7 @@ package android.os.vibrator {
package android.os.vibrator.persistence {
public class ParsedVibration {
- method @NonNull public java.util.List<android.os.VibrationEffect> getVibrationEffectListForTesting();
+ method @NonNull public java.util.List<android.os.VibrationEffect> getVibrationEffects();
method @Nullable public android.os.VibrationEffect resolve(@NonNull android.os.Vibrator);
}
diff --git a/core/api/test-lint-baseline.txt b/core/api/test-lint-baseline.txt
index 4a972806b314..1aaedaba3f79 100644
--- a/core/api/test-lint-baseline.txt
+++ b/core/api/test-lint-baseline.txt
@@ -87,50 +87,6 @@ GenericException: android.service.autofill.ImageTransformation#apply(android.ser
Methods must not throw generic exceptions (`java.lang.Exception`)
-GetterSetterNames: android.location.GnssClock#setBiasNanos(double):
- Symmetric method for `hasBiasNanos` must be named `setHasBiasNanos`; was `setBiasNanos`
-GetterSetterNames: android.location.GnssClock#setBiasUncertaintyNanos(double):
- Symmetric method for `hasBiasUncertaintyNanos` must be named `setHasBiasUncertaintyNanos`; was `setBiasUncertaintyNanos`
-GetterSetterNames: android.location.GnssClock#setDriftNanosPerSecond(double):
- Symmetric method for `hasDriftNanosPerSecond` must be named `setHasDriftNanosPerSecond`; was `setDriftNanosPerSecond`
-GetterSetterNames: android.location.GnssClock#setDriftUncertaintyNanosPerSecond(double):
- Symmetric method for `hasDriftUncertaintyNanosPerSecond` must be named `setHasDriftUncertaintyNanosPerSecond`; was `setDriftUncertaintyNanosPerSecond`
-GetterSetterNames: android.location.GnssClock#setElapsedRealtimeNanos(long):
- Symmetric method for `hasElapsedRealtimeNanos` must be named `setHasElapsedRealtimeNanos`; was `setElapsedRealtimeNanos`
-GetterSetterNames: android.location.GnssClock#setElapsedRealtimeUncertaintyNanos(double):
- Symmetric method for `hasElapsedRealtimeUncertaintyNanos` must be named `setHasElapsedRealtimeUncertaintyNanos`; was `setElapsedRealtimeUncertaintyNanos`
-GetterSetterNames: android.location.GnssClock#setFullBiasNanos(long):
- Symmetric method for `hasFullBiasNanos` must be named `setHasFullBiasNanos`; was `setFullBiasNanos`
-GetterSetterNames: android.location.GnssClock#setLeapSecond(int):
- Symmetric method for `hasLeapSecond` must be named `setHasLeapSecond`; was `setLeapSecond`
-GetterSetterNames: android.location.GnssClock#setReferenceCarrierFrequencyHzForIsb(double):
- Symmetric method for `hasReferenceCarrierFrequencyHzForIsb` must be named `setHasReferenceCarrierFrequencyHzForIsb`; was `setReferenceCarrierFrequencyHzForIsb`
-GetterSetterNames: android.location.GnssClock#setReferenceCodeTypeForIsb(String):
- Symmetric method for `hasReferenceCodeTypeForIsb` must be named `setHasReferenceCodeTypeForIsb`; was `setReferenceCodeTypeForIsb`
-GetterSetterNames: android.location.GnssClock#setReferenceConstellationTypeForIsb(int):
- Symmetric method for `hasReferenceConstellationTypeForIsb` must be named `setHasReferenceConstellationTypeForIsb`; was `setReferenceConstellationTypeForIsb`
-GetterSetterNames: android.location.GnssClock#setTimeUncertaintyNanos(double):
- Symmetric method for `hasTimeUncertaintyNanos` must be named `setHasTimeUncertaintyNanos`; was `setTimeUncertaintyNanos`
-GetterSetterNames: android.location.GnssMeasurement#setBasebandCn0DbHz(double):
- Symmetric method for `hasBasebandCn0DbHz` must be named `setHasBasebandCn0DbHz`; was `setBasebandCn0DbHz`
-GetterSetterNames: android.location.GnssMeasurement#setCarrierFrequencyHz(float):
- Symmetric method for `hasCarrierFrequencyHz` must be named `setHasCarrierFrequencyHz`; was `setCarrierFrequencyHz`
-GetterSetterNames: android.location.GnssMeasurement#setCodeType(String):
- Symmetric method for `hasCodeType` must be named `setHasCodeType`; was `setCodeType`
-GetterSetterNames: android.location.GnssMeasurement#setCorrelationVectors(java.util.Collection<android.location.CorrelationVector>):
- Symmetric method for `hasCorrelationVectors` must be named `setHasCorrelationVectors`; was `setCorrelationVectors`
-GetterSetterNames: android.location.GnssMeasurement#setFullInterSignalBiasNanos(double):
- Symmetric method for `hasFullInterSignalBiasNanos` must be named `setHasFullInterSignalBiasNanos`; was `setFullInterSignalBiasNanos`
-GetterSetterNames: android.location.GnssMeasurement#setFullInterSignalBiasUncertaintyNanos(double):
- Symmetric method for `hasFullInterSignalBiasUncertaintyNanos` must be named `setHasFullInterSignalBiasUncertaintyNanos`; was `setFullInterSignalBiasUncertaintyNanos`
-GetterSetterNames: android.location.GnssMeasurement#setSatelliteInterSignalBiasNanos(double):
- Symmetric method for `hasSatelliteInterSignalBiasNanos` must be named `setHasSatelliteInterSignalBiasNanos`; was `setSatelliteInterSignalBiasNanos`
-GetterSetterNames: android.location.GnssMeasurement#setSatelliteInterSignalBiasUncertaintyNanos(double):
- Symmetric method for `hasSatelliteInterSignalBiasUncertaintyNanos` must be named `setHasSatelliteInterSignalBiasUncertaintyNanos`; was `setSatelliteInterSignalBiasUncertaintyNanos`
-GetterSetterNames: android.location.GnssMeasurement#setSatellitePvt(android.location.SatellitePvt):
- Symmetric method for `hasSatellitePvt` must be named `setHasSatellitePvt`; was `setSatellitePvt`
-GetterSetterNames: android.location.GnssMeasurement#setSnrInDb(double):
- Symmetric method for `hasSnrInDb` must be named `setHasSnrInDb`; was `setSnrInDb`
GetterSetterNames: android.net.NetworkPolicyManager#getRestrictBackground():
Symmetric method for `setRestrictBackground` must be named `isRestrictBackground`; was `getRestrictBackground`
@@ -343,14 +299,6 @@ MissingNullability: android.hardware.camera2.CameraManager#getCameraIdListNoLazy
Missing nullability on method `getCameraIdListNoLazy` return
MissingNullability: android.hardware.display.AmbientDisplayConfiguration#AmbientDisplayConfiguration(android.content.Context) parameter #0:
Missing nullability on parameter `context` in method `AmbientDisplayConfiguration`
-MissingNullability: android.location.GnssClock#set(android.location.GnssClock) parameter #0:
- Missing nullability on parameter `clock` in method `set`
-MissingNullability: android.location.GnssMeasurement#set(android.location.GnssMeasurement) parameter #0:
- Missing nullability on parameter `measurement` in method `set`
-MissingNullability: android.location.GnssNavigationMessage#set(android.location.GnssNavigationMessage) parameter #0:
- Missing nullability on parameter `navigationMessage` in method `set`
-MissingNullability: android.location.GnssNavigationMessage#setData(byte[]) parameter #0:
- Missing nullability on parameter `value` in method `setData`
MissingNullability: android.media.AudioAttributes#getSdkUsages():
Missing nullability on method `getSdkUsages` return
MissingNullability: android.media.AudioManager#getPublicStreamTypes():
diff --git a/core/java/android/app/AppOps.md b/core/java/android/app/AppOps.md
index 4589a71d5e5f..7b11a0351ebe 100644
--- a/core/java/android/app/AppOps.md
+++ b/core/java/android/app/AppOps.md
@@ -59,8 +59,8 @@ To control access the app-op can be set to:
: Throw a `SecurityException` on access. This can be suppressed by using a `...noThrow` method to
check the mode
-The initial state of an app-op is defined in `AppOpsManager.sOpDefaultMode`. Confusingly the
-initial state is often not `MODE_DEFAULT`
+The initial state of an app-op is defined in its `AppOpInfo`. Confusingly the initial state is not
+always `MODE_DEFAULT`, if `AppOpInfo.Builder.setDefaultMode()` is called with a different mode.
Per-package modes can be set using `AppOpsManager.setMode` and per-uid modes can be set using
`AppOpsManager.setUidMode`.
diff --git a/core/java/android/app/AppOpsManager.java b/core/java/android/app/AppOpsManager.java
index 56fef1aac36a..dab4110279fe 100644
--- a/core/java/android/app/AppOpsManager.java
+++ b/core/java/android/app/AppOpsManager.java
@@ -1486,13 +1486,13 @@ public class AppOpsManager {
AppProtoEnums.APP_OP_RECEIVE_SANDBOX_TRIGGER_AUDIO;
/**
- * Allows the assistant app to get the negative trigger data from the PCC sandbox to improve the
+ * Allows the assistant app to get the training data from the PCC sandbox to improve the
* hotword training model.
*
* @hide
*/
- public static final int OP_RECEIVE_SANDBOX_NEGATIVE_DATA_AUDIO =
- AppProtoEnums.APP_OP_RECEIVE_SANDBOX_NEGATIVE_DATA_AUDIO;
+ public static final int OP_RECEIVE_SANDBOX_TRAINING_DATA =
+ AppProtoEnums.APP_OP_RECEIVE_SANDBOX_TRAINING_DATA;
/** @hide */
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
@@ -1640,7 +1640,7 @@ public class AppOpsManager {
OPSTR_CAMERA_SANDBOXED,
OPSTR_RECORD_AUDIO_SANDBOXED,
OPSTR_RECEIVE_SANDBOX_TRIGGER_AUDIO,
- OPSTR_RECEIVE_SANDBOX_NEGATIVE_DATA_AUDIO
+ OPSTR_RECEIVE_SANDBOX_TRAINING_DATA
})
public @interface AppOpString {}
@@ -2261,13 +2261,13 @@ public class AppOpsManager {
"android:receive_sandbox_trigger_audio";
/**
- * Allows the assistant app to get the negative trigger data from the PCC sandbox to improve
+ * Allows the assistant app to get the training data from the PCC sandbox to improve
* the hotword training model.
*
* @hide
*/
- public static final String OPSTR_RECEIVE_SANDBOX_NEGATIVE_DATA_AUDIO =
- "android:receive_sandbox_negative_data_audio";
+ public static final String OPSTR_RECEIVE_SANDBOX_TRAINING_DATA =
+ "android:receive_sandbox_training_data";
/** {@link #sAppOpsToNote} not initialized yet for this op */
private static final byte SHOULD_COLLECT_NOTE_OP_NOT_INITIALIZED = 0;
@@ -2811,9 +2811,9 @@ public class AppOpsManager {
OPSTR_RECEIVE_SANDBOX_TRIGGER_AUDIO,
"RECEIVE_SANDBOX_TRIGGER_AUDIO")
.setDefaultMode(AppOpsManager.MODE_ALLOWED).build(),
- new AppOpInfo.Builder(OP_RECEIVE_SANDBOX_NEGATIVE_DATA_AUDIO,
- OPSTR_RECEIVE_SANDBOX_NEGATIVE_DATA_AUDIO,
- "RECEIVE_SANDBOX_NEGATIVE_DATA_AUDIO").build()
+ new AppOpInfo.Builder(OP_RECEIVE_SANDBOX_TRAINING_DATA,
+ OPSTR_RECEIVE_SANDBOX_TRAINING_DATA,
+ "RECEIVE_SANDBOX_TRAINING_DATA").build()
};
// The number of longs needed to form a full bitmask of app ops
diff --git a/core/java/android/app/IUriGrantsManager.aidl b/core/java/android/app/IUriGrantsManager.aidl
index 9e7f2fecfea0..b630d034dca9 100644
--- a/core/java/android/app/IUriGrantsManager.aidl
+++ b/core/java/android/app/IUriGrantsManager.aidl
@@ -39,4 +39,7 @@ interface IUriGrantsManager {
void clearGrantedUriPermissions(in String packageName, int userId);
ParceledListSlice getUriPermissions(in String packageName, boolean incoming,
boolean persistedOnly);
+
+ int checkGrantUriPermission_ignoreNonSystem(
+ int sourceUid, String targetPkg, in Uri uri, int modeFlags, int userId);
}
diff --git a/core/java/android/app/WindowConfiguration.java b/core/java/android/app/WindowConfiguration.java
index bf238c399ad3..019a1a8cb2a6 100644
--- a/core/java/android/app/WindowConfiguration.java
+++ b/core/java/android/app/WindowConfiguration.java
@@ -267,12 +267,13 @@ public class WindowConfiguration implements Parcelable, Comparable<WindowConfigu
}
};
- // TODO(b/297672475): make this take @Nullable
/**
* Sets the bounds to the provided {@link Rect}.
+ * Passing {@code null} sets the bounds {@link Rect} to empty.
+ *
* @param rect the new bounds value.
*/
- public void setBounds(Rect rect) {
+ public void setBounds(@Nullable Rect rect) {
if (rect == null) {
mBounds.setEmpty();
return;
@@ -282,8 +283,10 @@ public class WindowConfiguration implements Parcelable, Comparable<WindowConfigu
}
/**
- * Set {@link #mAppBounds} to the input Rect.
- * @param rect The rect value to set {@link #mAppBounds} to.
+ * Sets the app bounds to the provided {@link Rect}.
+ * Passing {@code null} sets the bounds to {@code null}.
+ *
+ * @param rect the new app bounds value.
* @see #getAppBounds()
*/
public void setAppBounds(@Nullable Rect rect) {
@@ -297,7 +300,9 @@ public class WindowConfiguration implements Parcelable, Comparable<WindowConfigu
/**
* Sets the maximum bounds to the provided {@link Rect}.
- * @param rect the new bounds value.
+ * Passing {@code null} sets the bounds {@link Rect} to empty.
+ *
+ * @param rect the new max bounds value.
* @see #getMaxBounds()
*/
public void setMaxBounds(@Nullable Rect rect) {
@@ -364,8 +369,8 @@ public class WindowConfiguration implements Parcelable, Comparable<WindowConfigu
return mAppBounds;
}
- // TODO(b/297672475): make this return @NonNull
/** @see #setBounds(Rect) */
+ @NonNull
public Rect getBounds() {
return mBounds;
}
diff --git a/core/java/android/app/assist/AssistStructure.java b/core/java/android/app/assist/AssistStructure.java
index d66fca8945f1..ed0f872bf9bc 100644
--- a/core/java/android/app/assist/AssistStructure.java
+++ b/core/java/android/app/assist/AssistStructure.java
@@ -2495,7 +2495,8 @@ public class AssistStructure implements Parcelable {
+ ", hints=" + Arrays.toString(node.getAutofillHints())
+ ", value=" + node.getAutofillValue()
+ ", sanitized=" + node.isSanitized()
- + ", important=" + node.getImportantForAutofill());
+ + ", important=" + node.getImportantForAutofill()
+ + ", visibility=" + node.getVisibility());
}
final int NCHILDREN = node.getChildCount();
diff --git a/core/java/android/app/usage/flags.aconfig b/core/java/android/app/usage/flags.aconfig
new file mode 100644
index 000000000000..afe87de1dbf5
--- /dev/null
+++ b/core/java/android/app/usage/flags.aconfig
@@ -0,0 +1,9 @@
+package: "android.app.usage"
+
+flag {
+ name: "user_interaction_type_api"
+ namespace: "power_optimization"
+ description: "Feature flag for user interaction event report/query API"
+ bug: "296061232"
+}
+
diff --git a/core/java/android/companion/virtual/IVirtualDevice.aidl b/core/java/android/companion/virtual/IVirtualDevice.aidl
index 4801d155eb33..c58561d0bb2e 100644
--- a/core/java/android/companion/virtual/IVirtualDevice.aidl
+++ b/core/java/android/companion/virtual/IVirtualDevice.aidl
@@ -64,12 +64,28 @@ interface IVirtualDevice {
String getPersistentDeviceId();
/**
+ * Returns the IDs of all virtual displays of this device.
+ */
+ int[] getDisplayIds();
+
+ /**
+ * Returns the device policy for the given policy type.
+ */
+ int getDevicePolicy(int policyType);
+
+ /**
* Closes the virtual device and frees all associated resources.
*/
@EnforcePermission("CREATE_VIRTUAL_DEVICE")
void close();
/**
+ * Specifies a policy for this virtual device.
+ */
+ @EnforcePermission("CREATE_VIRTUAL_DEVICE")
+ void setDevicePolicy(int policyType, int devicePolicy);
+
+ /**
* Notifies that an audio session being started.
*/
@EnforcePermission("CREATE_VIRTUAL_DEVICE")
diff --git a/core/java/android/companion/virtual/IVirtualDeviceListener.aidl b/core/java/android/companion/virtual/IVirtualDeviceListener.aidl
new file mode 100644
index 000000000000..c6dd227fe782
--- /dev/null
+++ b/core/java/android/companion/virtual/IVirtualDeviceListener.aidl
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.companion.virtual;
+
+/**
+ * Interface to listen for changes in the available virtual devices.
+ *
+ * @hide
+ */
+oneway interface IVirtualDeviceListener {
+
+ /**
+ * Called whenever a new virtual device has been added to the system.
+ */
+ void onVirtualDeviceCreated(int deviceId);
+
+ /**
+ * Called whenever a virtual device has been removed from the system.
+ */
+ void onVirtualDeviceClosed(int deviceId);
+}
diff --git a/core/java/android/companion/virtual/IVirtualDeviceManager.aidl b/core/java/android/companion/virtual/IVirtualDeviceManager.aidl
index ed8484fe7266..b665036c202f 100644
--- a/core/java/android/companion/virtual/IVirtualDeviceManager.aidl
+++ b/core/java/android/companion/virtual/IVirtualDeviceManager.aidl
@@ -18,6 +18,7 @@ package android.companion.virtual;
import android.companion.virtual.IVirtualDevice;
import android.companion.virtual.IVirtualDeviceActivityListener;
+import android.companion.virtual.IVirtualDeviceListener;
import android.companion.virtual.IVirtualDeviceSoundEffectListener;
import android.companion.virtual.VirtualDevice;
import android.companion.virtual.VirtualDeviceParams;
@@ -56,12 +57,27 @@ interface IVirtualDeviceManager {
*/
List<VirtualDevice> getVirtualDevices();
- /**
+ /**
+ * Returns the details of the virtual device with the given ID, if any.
+ */
+ VirtualDevice getVirtualDevice(int deviceId);
+
+ /**
+ * Registers a virtual device listener to receive notifications for virtual device events.
+ */
+ void registerVirtualDeviceListener(in IVirtualDeviceListener listener);
+
+ /**
+ * Unregisters a previously registered virtual device listener.
+ */
+ void unregisterVirtualDeviceListener(in IVirtualDeviceListener listener);
+
+ /**
* Returns the ID of the device which owns the display with the given ID.
*/
int getDeviceIdForDisplayId(int displayId);
- /**
+ /**
* Checks whether the passed {@code deviceId} is a valid virtual device ID or not.
* {@link VirtualDeviceManager#DEVICE_ID_DEFAULT} is not valid as it is the ID of the default
* device which is not a virtual device. {@code deviceId} must correspond to a virtual device
diff --git a/core/java/android/companion/virtual/VirtualDevice.java b/core/java/android/companion/virtual/VirtualDevice.java
index ceaf7e4f8317..4692f921beb2 100644
--- a/core/java/android/companion/virtual/VirtualDevice.java
+++ b/core/java/android/companion/virtual/VirtualDevice.java
@@ -16,13 +16,17 @@
package android.companion.virtual;
+import static android.companion.virtual.VirtualDeviceParams.DEVICE_POLICY_CUSTOM;
+import static android.companion.virtual.VirtualDeviceParams.POLICY_TYPE_SENSORS;
+
+import android.annotation.FlaggedApi;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.companion.virtual.flags.Flags;
import android.content.Context;
import android.os.Parcel;
import android.os.Parcelable;
-
-import java.util.Objects;
+import android.os.RemoteException;
/**
* Details of a particular virtual device.
@@ -31,9 +35,12 @@ import java.util.Objects;
*
* <p class="note">Not to be confused with {@link VirtualDeviceManager.VirtualDevice}, which is used
* by the virtual device creator and allows them to manage the device.
+ *
+ * @see VirtualDeviceManager#registerVirtualDeviceListener
*/
public final class VirtualDevice implements Parcelable {
+ private final @NonNull IVirtualDevice mVirtualDevice;
private final int mId;
private final @Nullable String mPersistentId;
private final @Nullable String mName;
@@ -44,17 +51,20 @@ public final class VirtualDevice implements Parcelable {
*
* @hide
*/
- public VirtualDevice(int id, @Nullable String persistentId, @Nullable String name) {
+ public VirtualDevice(@NonNull IVirtualDevice virtualDevice, int id,
+ @Nullable String persistentId, @Nullable String name) {
if (id <= Context.DEVICE_ID_DEFAULT) {
throw new IllegalArgumentException("VirtualDevice ID must be greater than "
+ Context.DEVICE_ID_DEFAULT);
}
+ mVirtualDevice = virtualDevice;
mId = id;
mPersistentId = persistentId;
mName = name;
}
private VirtualDevice(@NonNull Parcel parcel) {
+ mVirtualDevice = IVirtualDevice.Stub.asInterface(parcel.readStrongBinder());
mId = parcel.readInt();
mPersistentId = parcel.readString8();
mName = parcel.readString8();
@@ -101,6 +111,40 @@ public final class VirtualDevice implements Parcelable {
return mName;
}
+ /**
+ * Returns the IDs of all virtual displays that belong to this device, if any.
+ *
+ * <p>The actual {@link android.view.Display} objects can be obtained by passing the returned
+ * IDs to {@link android.hardware.display.DisplayManager#getDisplay(int)}.</p>
+ */
+ @FlaggedApi(Flags.FLAG_VDM_PUBLIC_APIS)
+ public @NonNull int[] getDisplayIds() {
+ try {
+ return mVirtualDevice.getDisplayIds();
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * Returns whether this device may have custom sensors.
+ *
+ * <p>Returning {@code true} does not necessarily mean that this device has sensors, it only
+ * means that a {@link android.hardware.SensorManager} instance created from a {@link Context}
+ * associated with this device will return this device's sensors, if any.</p>
+ *
+ * @see Context#getDeviceId()
+ * @see Context#createDeviceContext(int)
+ */
+ @FlaggedApi(Flags.FLAG_VDM_PUBLIC_APIS)
+ public boolean hasCustomSensorSupport() {
+ try {
+ return mVirtualDevice.getDevicePolicy(POLICY_TYPE_SENSORS) == DEVICE_POLICY_CUSTOM;
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
@Override
public int describeContents() {
return 0;
@@ -108,31 +152,13 @@ public final class VirtualDevice implements Parcelable {
@Override
public void writeToParcel(@NonNull Parcel dest, int flags) {
+ dest.writeStrongBinder(mVirtualDevice.asBinder());
dest.writeInt(mId);
dest.writeString8(mPersistentId);
dest.writeString8(mName);
}
@Override
- public boolean equals(Object o) {
- if (this == o) {
- return true;
- }
- if (!(o instanceof VirtualDevice)) {
- return false;
- }
- VirtualDevice that = (VirtualDevice) o;
- return mId == that.mId
- && Objects.equals(mPersistentId, that.mPersistentId)
- && Objects.equals(mName, that.mName);
- }
-
- @Override
- public int hashCode() {
- return Objects.hash(mId, mPersistentId, mName);
- }
-
- @Override
@NonNull
public String toString() {
return "VirtualDevice("
diff --git a/core/java/android/companion/virtual/VirtualDeviceInternal.java b/core/java/android/companion/virtual/VirtualDeviceInternal.java
index d13bfd4f6229..2e5c0f77de4a 100644
--- a/core/java/android/companion/virtual/VirtualDeviceInternal.java
+++ b/core/java/android/companion/virtual/VirtualDeviceInternal.java
@@ -238,6 +238,15 @@ public class VirtualDeviceInternal {
}
}
+ void setDevicePolicy(@VirtualDeviceParams.DynamicPolicyType int policyType,
+ @VirtualDeviceParams.DevicePolicy int devicePolicy) {
+ try {
+ mVirtualDevice.setDevicePolicy(policyType, devicePolicy);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
@NonNull
VirtualDpad createVirtualDpad(@NonNull VirtualDpadConfig config) {
try {
diff --git a/core/java/android/companion/virtual/VirtualDeviceManager.java b/core/java/android/companion/virtual/VirtualDeviceManager.java
index 060a5c85a713..29b0ff30f96f 100644
--- a/core/java/android/companion/virtual/VirtualDeviceManager.java
+++ b/core/java/android/companion/virtual/VirtualDeviceManager.java
@@ -19,6 +19,7 @@ package android.companion.virtual;
import static android.media.AudioManager.AUDIO_SESSION_ID_GENERATE;
import android.annotation.CallbackExecutor;
+import android.annotation.FlaggedApi;
import android.annotation.IntDef;
import android.annotation.IntRange;
import android.annotation.NonNull;
@@ -32,6 +33,7 @@ import android.app.PendingIntent;
import android.companion.AssociationInfo;
import android.companion.virtual.audio.VirtualAudioDevice;
import android.companion.virtual.audio.VirtualAudioDevice.AudioConfigurationChangeCallback;
+import android.companion.virtual.flags.Flags;
import android.companion.virtual.sensor.VirtualSensor;
import android.content.ComponentName;
import android.content.Context;
@@ -53,16 +55,21 @@ import android.hardware.input.VirtualNavigationTouchpadConfig;
import android.hardware.input.VirtualTouchscreen;
import android.hardware.input.VirtualTouchscreenConfig;
import android.media.AudioManager;
+import android.os.Binder;
import android.os.Looper;
import android.os.RemoteException;
import android.util.Log;
import android.view.Surface;
+import com.android.internal.annotations.GuardedBy;
+import com.android.internal.util.AnnotationValidations;
+
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.util.ArrayList;
+import java.util.Iterator;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.Executor;
@@ -143,6 +150,9 @@ public final class VirtualDeviceManager {
private final IVirtualDeviceManager mService;
private final Context mContext;
+ @GuardedBy("mVirtualDeviceListeners")
+ private final List<VirtualDeviceListenerDelegate> mVirtualDeviceListeners = new ArrayList<>();
+
/** @hide */
public VirtualDeviceManager(
@Nullable IVirtualDeviceManager service, @NonNull Context context) {
@@ -173,6 +183,9 @@ public final class VirtualDeviceManager {
int associationId,
@NonNull VirtualDeviceParams params) {
Objects.requireNonNull(params, "params must not be null");
+ if (Flags.moreLogs()) {
+ Log.i(TAG, "Creating VirtualDevice");
+ }
try {
return new VirtualDevice(mService, mContext, associationId, params);
} catch (RemoteException e) {
@@ -200,6 +213,88 @@ public final class VirtualDeviceManager {
}
/**
+ * Returns the details of the virtual device with the given ID, if any.
+ *
+ * <p>The returned object is a read-only representation of the virtual device that expose its
+ * properties.</p>
+ */
+ @FlaggedApi(Flags.FLAG_VDM_PUBLIC_APIS)
+ @Nullable
+ public android.companion.virtual.VirtualDevice getVirtualDevice(int deviceId) {
+ if (mService == null) {
+ Log.w(TAG, "Failed to retrieve virtual devices; no virtual device manager service.");
+ return null;
+ }
+ if (deviceId == Context.DEVICE_ID_INVALID || deviceId == Context.DEVICE_ID_DEFAULT) {
+ return null; // Don't even bother making a Binder call.
+ }
+ try {
+ return mService.getVirtualDevice(deviceId);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * Registers a virtual device listener to receive notifications when virtual devices are created
+ * or closed.
+ *
+ * @param executor The executor where the listener is executed on.
+ * @param listener The listener to add.
+ * @see #unregisterVirtualDeviceListener
+ */
+ @FlaggedApi(Flags.FLAG_VDM_PUBLIC_APIS)
+ public void registerVirtualDeviceListener(
+ @NonNull @CallbackExecutor Executor executor,
+ @NonNull VirtualDeviceListener listener) {
+ if (mService == null) {
+ Log.w(TAG, "Failed to register listener; no virtual device manager service.");
+ return;
+ }
+ final VirtualDeviceListenerDelegate delegate =
+ new VirtualDeviceListenerDelegate(Objects.requireNonNull(executor),
+ Objects.requireNonNull(listener));
+ synchronized (mVirtualDeviceListeners) {
+ try {
+ mService.registerVirtualDeviceListener(delegate);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ mVirtualDeviceListeners.add(delegate);
+ }
+ }
+
+ /**
+ * Unregisters a virtual device listener previously registered with
+ * {@link #registerVirtualDeviceListener}.
+ *
+ * @param listener The listener to unregister.
+ * @see #registerVirtualDeviceListener
+ */
+ @FlaggedApi(Flags.FLAG_VDM_PUBLIC_APIS)
+ public void unregisterVirtualDeviceListener(@NonNull VirtualDeviceListener listener) {
+ if (mService == null) {
+ Log.w(TAG, "Failed to unregister listener; no virtual device manager service.");
+ return;
+ }
+ Objects.requireNonNull(listener);
+ synchronized (mVirtualDeviceListeners) {
+ final Iterator<VirtualDeviceListenerDelegate> it = mVirtualDeviceListeners.iterator();
+ while (it.hasNext()) {
+ final VirtualDeviceListenerDelegate delegate = it.next();
+ if (delegate.mListener == listener) {
+ try {
+ mService.unregisterVirtualDeviceListener(delegate);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ it.remove();
+ }
+ }
+ }
+ }
+
+ /**
* Returns the device policy for the given virtual device and policy type.
*
* <p>In case the virtual device identifier is not valid, or there's no explicitly specified
@@ -509,6 +604,28 @@ public final class VirtualDeviceManager {
}
/**
+ * Specifies a policy for this virtual device.
+ *
+ * <p>Policies define the system behavior that may be specific for this virtual device. The
+ * given policy must be able to be changed dynamically during the lifetime of the device.
+ *
+ * @param policyType the type of policy, i.e. which behavior to specify a policy for.
+ * @param devicePolicy the value of the policy, i.e. how to interpret the device behavior.
+ *
+ * @see VirtualDeviceParams#POLICY_TYPE_RECENTS
+ */
+ @FlaggedApi(Flags.FLAG_DYNAMIC_POLICY)
+ @RequiresPermission(android.Manifest.permission.CREATE_VIRTUAL_DEVICE)
+ public void setDevicePolicy(@VirtualDeviceParams.DynamicPolicyType int policyType,
+ @VirtualDeviceParams.DevicePolicy int devicePolicy) {
+ AnnotationValidations.validate(
+ VirtualDeviceParams.DynamicPolicyType.class, null, policyType);
+ AnnotationValidations.validate(
+ VirtualDeviceParams.DevicePolicy.class, null, devicePolicy);
+ mVirtualDeviceInternal.setDevicePolicy(policyType, devicePolicy);
+ }
+
+ /**
* Creates a virtual dpad.
*
* @param config the configurations of the virtual dpad.
@@ -719,7 +836,7 @@ public final class VirtualDeviceManager {
*
* @param executor The executor where the listener is executed on.
* @param soundEffectListener The listener to add.
- * @see #removeActivityListener(ActivityListener)
+ * @see #removeSoundEffectListener(SoundEffectListener)
*/
public void addSoundEffectListener(@CallbackExecutor @NonNull Executor executor,
@NonNull SoundEffectListener soundEffectListener) {
@@ -848,4 +965,59 @@ public final class VirtualDeviceManager {
*/
void onPlaySoundEffect(@AudioManager.SystemSoundEffect int effectType);
}
+
+ /**
+ * Listener for changes in the available virtual devices.
+ */
+ @FlaggedApi(Flags.FLAG_VDM_PUBLIC_APIS)
+ public interface VirtualDeviceListener {
+ /**
+ * Called whenever a new virtual device has been added to the system.
+ * Use {@link VirtualDeviceManager#getVirtualDevice(int)} to get more information about
+ * the device.
+ *
+ * @param deviceId The id of the virtual device that was added.
+ */
+ default void onVirtualDeviceCreated(int deviceId) {}
+
+ /**
+ * Called whenever a virtual device has been removed from the system.
+ *
+ * @param deviceId The id of the virtual device that was removed.
+ */
+ default void onVirtualDeviceClosed(int deviceId) {}
+ }
+
+ /**
+ * A wrapper for {@link VirtualDeviceListener} that executes callbacks on the given executor.
+ */
+ private static class VirtualDeviceListenerDelegate extends IVirtualDeviceListener.Stub {
+ private final VirtualDeviceListener mListener;
+ private final Executor mExecutor;
+
+ private VirtualDeviceListenerDelegate(Executor executor, VirtualDeviceListener listener) {
+ mExecutor = executor;
+ mListener = listener;
+ }
+
+ @Override
+ public void onVirtualDeviceCreated(int deviceId) {
+ final long token = Binder.clearCallingIdentity();
+ try {
+ mExecutor.execute(() -> mListener.onVirtualDeviceCreated(deviceId));
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+
+ @Override
+ public void onVirtualDeviceClosed(int deviceId) {
+ final long token = Binder.clearCallingIdentity();
+ try {
+ mExecutor.execute(() -> mListener.onVirtualDeviceClosed(deviceId));
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+ }
}
diff --git a/core/java/android/companion/virtual/VirtualDeviceParams.java b/core/java/android/companion/virtual/VirtualDeviceParams.java
index b6d837589284..51df25723ef6 100644
--- a/core/java/android/companion/virtual/VirtualDeviceParams.java
+++ b/core/java/android/companion/virtual/VirtualDeviceParams.java
@@ -150,6 +150,17 @@ public final class VirtualDeviceParams implements Parcelable {
public @interface PolicyType {}
/**
+ * Policy types that can be dynamically changed during the virtual device's lifetime.
+ *
+ * @see VirtualDeviceManager.VirtualDevice#setDevicePolicy
+ * @hide
+ */
+ @IntDef(prefix = "POLICY_TYPE_", value = {POLICY_TYPE_RECENTS})
+ @Retention(RetentionPolicy.SOURCE)
+ @Target({ElementType.TYPE_PARAMETER, ElementType.TYPE_USE})
+ public @interface DynamicPolicyType {}
+
+ /**
* Tells the sensor framework how to handle sensor requests from contexts associated with this
* virtual device, namely the sensors returned by
* {@link android.hardware.SensorManager#getSensorList}:
@@ -191,14 +202,12 @@ public final class VirtualDeviceParams implements Parcelable {
private final int mLockState;
@NonNull private final ArraySet<UserHandle> mUsersWithMatchingAccounts;
- @NonNull private final ArraySet<ComponentName> mAllowedCrossTaskNavigations;
- @NonNull private final ArraySet<ComponentName> mBlockedCrossTaskNavigations;
@NavigationPolicy
private final int mDefaultNavigationPolicy;
- @NonNull private final ArraySet<ComponentName> mAllowedActivities;
- @NonNull private final ArraySet<ComponentName> mBlockedActivities;
+ @NonNull private final ArraySet<ComponentName> mCrossTaskNavigationExceptions;
@ActivityPolicy
private final int mDefaultActivityPolicy;
+ @NonNull private final ArraySet<ComponentName> mActivityPolicyExceptions;
@Nullable private final String mName;
// Mapping of @PolicyType to @DevicePolicy
@NonNull private final SparseIntArray mDevicePolicies;
@@ -210,12 +219,10 @@ public final class VirtualDeviceParams implements Parcelable {
private VirtualDeviceParams(
@LockState int lockState,
@NonNull Set<UserHandle> usersWithMatchingAccounts,
- @NonNull Set<ComponentName> allowedCrossTaskNavigations,
- @NonNull Set<ComponentName> blockedCrossTaskNavigations,
@NavigationPolicy int defaultNavigationPolicy,
- @NonNull Set<ComponentName> allowedActivities,
- @NonNull Set<ComponentName> blockedActivities,
+ @NonNull Set<ComponentName> crossTaskNavigationExceptions,
@ActivityPolicy int defaultActivityPolicy,
+ @NonNull Set<ComponentName> activityPolicyExceptions,
@Nullable String name,
@NonNull SparseIntArray devicePolicies,
@NonNull List<VirtualSensorConfig> virtualSensorConfigs,
@@ -225,14 +232,12 @@ public final class VirtualDeviceParams implements Parcelable {
mLockState = lockState;
mUsersWithMatchingAccounts =
new ArraySet<>(Objects.requireNonNull(usersWithMatchingAccounts));
- mAllowedCrossTaskNavigations =
- new ArraySet<>(Objects.requireNonNull(allowedCrossTaskNavigations));
- mBlockedCrossTaskNavigations =
- new ArraySet<>(Objects.requireNonNull(blockedCrossTaskNavigations));
mDefaultNavigationPolicy = defaultNavigationPolicy;
- mAllowedActivities = new ArraySet<>(Objects.requireNonNull(allowedActivities));
- mBlockedActivities = new ArraySet<>(Objects.requireNonNull(blockedActivities));
+ mCrossTaskNavigationExceptions =
+ new ArraySet<>(Objects.requireNonNull(crossTaskNavigationExceptions));
mDefaultActivityPolicy = defaultActivityPolicy;
+ mActivityPolicyExceptions =
+ new ArraySet<>(Objects.requireNonNull(activityPolicyExceptions));
mName = name;
mDevicePolicies = Objects.requireNonNull(devicePolicies);
mVirtualSensorConfigs = Objects.requireNonNull(virtualSensorConfigs);
@@ -245,12 +250,10 @@ public final class VirtualDeviceParams implements Parcelable {
private VirtualDeviceParams(Parcel parcel) {
mLockState = parcel.readInt();
mUsersWithMatchingAccounts = (ArraySet<UserHandle>) parcel.readArraySet(null);
- mAllowedCrossTaskNavigations = (ArraySet<ComponentName>) parcel.readArraySet(null);
- mBlockedCrossTaskNavigations = (ArraySet<ComponentName>) parcel.readArraySet(null);
mDefaultNavigationPolicy = parcel.readInt();
- mAllowedActivities = (ArraySet<ComponentName>) parcel.readArraySet(null);
- mBlockedActivities = (ArraySet<ComponentName>) parcel.readArraySet(null);
+ mCrossTaskNavigationExceptions = (ArraySet<ComponentName>) parcel.readArraySet(null);
mDefaultActivityPolicy = parcel.readInt();
+ mActivityPolicyExceptions = (ArraySet<ComponentName>) parcel.readArraySet(null);
mName = parcel.readString8();
mDevicePolicies = parcel.readSparseIntArray();
mVirtualSensorConfigs = new ArrayList<>();
@@ -290,7 +293,9 @@ public final class VirtualDeviceParams implements Parcelable {
*/
@NonNull
public Set<ComponentName> getAllowedCrossTaskNavigations() {
- return Collections.unmodifiableSet(mAllowedCrossTaskNavigations);
+ return mDefaultNavigationPolicy == NAVIGATION_POLICY_DEFAULT_ALLOWED
+ ? Collections.emptySet()
+ : Collections.unmodifiableSet(mCrossTaskNavigationExceptions);
}
/**
@@ -303,7 +308,9 @@ public final class VirtualDeviceParams implements Parcelable {
*/
@NonNull
public Set<ComponentName> getBlockedCrossTaskNavigations() {
- return Collections.unmodifiableSet(mBlockedCrossTaskNavigations);
+ return mDefaultNavigationPolicy == NAVIGATION_POLICY_DEFAULT_BLOCKED
+ ? Collections.emptySet()
+ : Collections.unmodifiableSet(mCrossTaskNavigationExceptions);
}
/**
@@ -327,7 +334,9 @@ public final class VirtualDeviceParams implements Parcelable {
*/
@NonNull
public Set<ComponentName> getAllowedActivities() {
- return Collections.unmodifiableSet(mAllowedActivities);
+ return mDefaultActivityPolicy == ACTIVITY_POLICY_DEFAULT_ALLOWED
+ ? Collections.emptySet()
+ : Collections.unmodifiableSet(mActivityPolicyExceptions);
}
/**
@@ -338,7 +347,9 @@ public final class VirtualDeviceParams implements Parcelable {
*/
@NonNull
public Set<ComponentName> getBlockedActivities() {
- return Collections.unmodifiableSet(mBlockedActivities);
+ return mDefaultActivityPolicy == ACTIVITY_POLICY_DEFAULT_BLOCKED
+ ? Collections.emptySet()
+ : Collections.unmodifiableSet(mActivityPolicyExceptions);
}
/**
@@ -375,6 +386,14 @@ public final class VirtualDeviceParams implements Parcelable {
}
/**
+ * Returns all device policies.
+ * @hide
+ */
+ public @NonNull SparseIntArray getDevicePolicies() {
+ return mDevicePolicies;
+ }
+
+ /**
* Returns the configurations for all sensors that should be created for this device.
*
* @see Builder#addVirtualSensorConfig
@@ -420,12 +439,10 @@ public final class VirtualDeviceParams implements Parcelable {
public void writeToParcel(@NonNull Parcel dest, int flags) {
dest.writeInt(mLockState);
dest.writeArraySet(mUsersWithMatchingAccounts);
- dest.writeArraySet(mAllowedCrossTaskNavigations);
- dest.writeArraySet(mBlockedCrossTaskNavigations);
dest.writeInt(mDefaultNavigationPolicy);
- dest.writeArraySet(mAllowedActivities);
- dest.writeArraySet(mBlockedActivities);
+ dest.writeArraySet(mCrossTaskNavigationExceptions);
dest.writeInt(mDefaultActivityPolicy);
+ dest.writeArraySet(mActivityPolicyExceptions);
dest.writeString8(mName);
dest.writeSparseIntArray(mDevicePolicies);
dest.writeTypedList(mVirtualSensorConfigs);
@@ -458,11 +475,10 @@ public final class VirtualDeviceParams implements Parcelable {
}
return mLockState == that.mLockState
&& mUsersWithMatchingAccounts.equals(that.mUsersWithMatchingAccounts)
- && Objects.equals(mAllowedCrossTaskNavigations, that.mAllowedCrossTaskNavigations)
- && Objects.equals(mBlockedCrossTaskNavigations, that.mBlockedCrossTaskNavigations)
+ && Objects.equals(
+ mCrossTaskNavigationExceptions, that.mCrossTaskNavigationExceptions)
&& mDefaultNavigationPolicy == that.mDefaultNavigationPolicy
- && Objects.equals(mAllowedActivities, that.mAllowedActivities)
- && Objects.equals(mBlockedActivities, that.mBlockedActivities)
+ && Objects.equals(mActivityPolicyExceptions, that.mActivityPolicyExceptions)
&& mDefaultActivityPolicy == that.mDefaultActivityPolicy
&& Objects.equals(mName, that.mName)
&& mAudioPlaybackSessionId == that.mAudioPlaybackSessionId
@@ -472,10 +488,9 @@ public final class VirtualDeviceParams implements Parcelable {
@Override
public int hashCode() {
int hashCode = Objects.hash(
- mLockState, mUsersWithMatchingAccounts, mAllowedCrossTaskNavigations,
- mBlockedCrossTaskNavigations, mDefaultNavigationPolicy, mAllowedActivities,
- mBlockedActivities, mDefaultActivityPolicy, mName, mDevicePolicies,
- mAudioPlaybackSessionId, mAudioRecordingSessionId);
+ mLockState, mUsersWithMatchingAccounts, mCrossTaskNavigationExceptions,
+ mDefaultNavigationPolicy, mActivityPolicyExceptions, mDefaultActivityPolicy, mName,
+ mDevicePolicies, mAudioPlaybackSessionId, mAudioRecordingSessionId);
for (int i = 0; i < mDevicePolicies.size(); i++) {
hashCode = 31 * hashCode + mDevicePolicies.keyAt(i);
hashCode = 31 * hashCode + mDevicePolicies.valueAt(i);
@@ -489,12 +504,10 @@ public final class VirtualDeviceParams implements Parcelable {
return "VirtualDeviceParams("
+ " mLockState=" + mLockState
+ " mUsersWithMatchingAccounts=" + mUsersWithMatchingAccounts
- + " mAllowedCrossTaskNavigations=" + mAllowedCrossTaskNavigations
- + " mBlockedCrossTaskNavigations=" + mBlockedCrossTaskNavigations
+ " mDefaultNavigationPolicy=" + mDefaultNavigationPolicy
- + " mAllowedActivities=" + mAllowedActivities
- + " mBlockedActivities=" + mBlockedActivities
+ + " mCrossTaskNavigationExceptions=" + mCrossTaskNavigationExceptions
+ " mDefaultActivityPolicy=" + mDefaultActivityPolicy
+ + " mActivityPolicyExceptions=" + mActivityPolicyExceptions
+ " mName=" + mName
+ " mDevicePolicies=" + mDevicePolicies
+ " mAudioPlaybackSessionId=" + mAudioPlaybackSessionId
@@ -510,13 +523,11 @@ public final class VirtualDeviceParams implements Parcelable {
pw.println(prefix + "mName=" + mName);
pw.println(prefix + "mLockState=" + mLockState);
pw.println(prefix + "mUsersWithMatchingAccounts=" + mUsersWithMatchingAccounts);
- pw.println(prefix + "mAllowedCrossTaskNavigations=" + mAllowedCrossTaskNavigations);
- pw.println(prefix + "mBlockedCrossTaskNavigations=" + mBlockedCrossTaskNavigations);
- pw.println(prefix + "mAllowedActivities=" + mAllowedActivities);
- pw.println(prefix + "mBlockedActivities=" + mBlockedActivities);
- pw.println(prefix + "mDevicePolicies=" + mDevicePolicies);
pw.println(prefix + "mDefaultNavigationPolicy=" + mDefaultNavigationPolicy);
+ pw.println(prefix + "mCrossTaskNavigationExceptions=" + mCrossTaskNavigationExceptions);
pw.println(prefix + "mDefaultActivityPolicy=" + mDefaultActivityPolicy);
+ pw.println(prefix + "mActivityPolicyExceptions=" + mActivityPolicyExceptions);
+ pw.println(prefix + "mDevicePolicies=" + mDevicePolicies);
pw.println(prefix + "mVirtualSensorConfigs=" + mVirtualSensorConfigs);
pw.println(prefix + "mAudioPlaybackSessionId=" + mAudioPlaybackSessionId);
pw.println(prefix + "mAudioRecordingSessionId=" + mAudioRecordingSessionId);
@@ -541,13 +552,11 @@ public final class VirtualDeviceParams implements Parcelable {
private @LockState int mLockState = LOCK_STATE_DEFAULT;
@NonNull private Set<UserHandle> mUsersWithMatchingAccounts = Collections.emptySet();
- @NonNull private Set<ComponentName> mAllowedCrossTaskNavigations = Collections.emptySet();
- @NonNull private Set<ComponentName> mBlockedCrossTaskNavigations = Collections.emptySet();
+ @NonNull private Set<ComponentName> mCrossTaskNavigationExceptions = Collections.emptySet();
@NavigationPolicy
private int mDefaultNavigationPolicy = NAVIGATION_POLICY_DEFAULT_ALLOWED;
private boolean mDefaultNavigationPolicyConfigured = false;
- @NonNull private Set<ComponentName> mBlockedActivities = Collections.emptySet();
- @NonNull private Set<ComponentName> mAllowedActivities = Collections.emptySet();
+ @NonNull private Set<ComponentName> mActivityPolicyExceptions = Collections.emptySet();
@ActivityPolicy
private int mDefaultActivityPolicy = ACTIVITY_POLICY_DEFAULT_ALLOWED;
private boolean mDefaultActivityPolicyConfigured = false;
@@ -686,12 +695,12 @@ public final class VirtualDeviceParams implements Parcelable {
if (mDefaultNavigationPolicyConfigured
&& mDefaultNavigationPolicy != NAVIGATION_POLICY_DEFAULT_BLOCKED) {
throw new IllegalArgumentException(
- "Allowed cross task navigation and blocked task navigation cannot "
+ "Allowed cross task navigations and blocked cross task navigations cannot "
+ " both be set.");
}
mDefaultNavigationPolicy = NAVIGATION_POLICY_DEFAULT_BLOCKED;
mDefaultNavigationPolicyConfigured = true;
- mAllowedCrossTaskNavigations = Objects.requireNonNull(allowedCrossTaskNavigations);
+ mCrossTaskNavigationExceptions = Objects.requireNonNull(allowedCrossTaskNavigations);
return this;
}
@@ -722,7 +731,7 @@ public final class VirtualDeviceParams implements Parcelable {
}
mDefaultNavigationPolicy = NAVIGATION_POLICY_DEFAULT_ALLOWED;
mDefaultNavigationPolicyConfigured = true;
- mBlockedCrossTaskNavigations = Objects.requireNonNull(blockedCrossTaskNavigations);
+ mCrossTaskNavigationExceptions = Objects.requireNonNull(blockedCrossTaskNavigations);
return this;
}
@@ -748,7 +757,7 @@ public final class VirtualDeviceParams implements Parcelable {
}
mDefaultActivityPolicy = ACTIVITY_POLICY_DEFAULT_BLOCKED;
mDefaultActivityPolicyConfigured = true;
- mAllowedActivities = Objects.requireNonNull(allowedActivities);
+ mActivityPolicyExceptions = Objects.requireNonNull(allowedActivities);
return this;
}
@@ -774,7 +783,7 @@ public final class VirtualDeviceParams implements Parcelable {
}
mDefaultActivityPolicy = ACTIVITY_POLICY_DEFAULT_ALLOWED;
mDefaultActivityPolicyConfigured = true;
- mBlockedActivities = Objects.requireNonNull(blockedActivities);
+ mActivityPolicyExceptions = Objects.requireNonNull(blockedActivities);
return this;
}
@@ -969,12 +978,10 @@ public final class VirtualDeviceParams implements Parcelable {
return new VirtualDeviceParams(
mLockState,
mUsersWithMatchingAccounts,
- mAllowedCrossTaskNavigations,
- mBlockedCrossTaskNavigations,
mDefaultNavigationPolicy,
- mAllowedActivities,
- mBlockedActivities,
+ mCrossTaskNavigationExceptions,
mDefaultActivityPolicy,
+ mActivityPolicyExceptions,
mName,
mDevicePolicies,
mVirtualSensorConfigs,
diff --git a/core/java/android/companion/virtual/flags.aconfig b/core/java/android/companion/virtual/flags.aconfig
new file mode 100644
index 000000000000..9ab3be6863d0
--- /dev/null
+++ b/core/java/android/companion/virtual/flags.aconfig
@@ -0,0 +1,22 @@
+package: "android.companion.virtual.flags"
+
+flag {
+ name: "more_logs"
+ namespace: "virtual_devices"
+ description: "More logs to test flags with"
+ bug: "291725823"
+}
+
+flag {
+ name: "dynamic_policy"
+ namespace: "virtual_devices"
+ description: "Enable dynamic policy API"
+ bug: "298401780"
+}
+
+flag {
+ name: "vdm_public_apis"
+ namespace: "virtual_devices"
+ description: "Enable public VDM API for device capabilities"
+ bug: "297253526"
+}
diff --git a/core/java/android/content/AttributionSource.java b/core/java/android/content/AttributionSource.java
index 8f35ca25ab22..15678a772ef4 100644
--- a/core/java/android/content/AttributionSource.java
+++ b/core/java/android/content/AttributionSource.java
@@ -226,6 +226,11 @@ public final class AttributionSource implements Parcelable {
}
/** @hide */
+ public AttributionSource withDefaultToken() {
+ return withToken(sDefaultToken);
+ }
+
+ /** @hide */
public AttributionSource withPid(int pid) {
return new AttributionSource(getUid(), pid, getPackageName(), getAttributionTag(),
getToken(), mAttributionSourceState.renouncedPermissions, getDeviceId(), getNext());
@@ -552,16 +557,28 @@ public final class AttributionSource implements Parcelable {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
AttributionSource that = (AttributionSource) o;
- return mAttributionSourceState.uid == that.mAttributionSourceState.uid
+ return equalsExceptToken(that) && Objects.equals(
+ mAttributionSourceState.token, that.mAttributionSourceState.token);
+ }
+
+ /**
+ * We store trusted attribution sources without their token (the token is the key to the map)
+ * to avoid having a strong reference to the token. This means, when checking the equality of a
+ * supplied AttributionSource in PermissionManagerService.isTrustedAttributionSource, we want to
+ * compare everything except the token.
+ *
+ * @hide
+ */
+ public boolean equalsExceptToken(@Nullable AttributionSource o) {
+ if (o == null) return false;
+ return mAttributionSourceState.uid == o.mAttributionSourceState.uid
&& Objects.equals(mAttributionSourceState.packageName,
- that.mAttributionSourceState.packageName)
+ o.mAttributionSourceState.packageName)
&& Objects.equals(mAttributionSourceState.attributionTag,
- that.mAttributionSourceState.attributionTag)
- && Objects.equals(mAttributionSourceState.token,
- that.mAttributionSourceState.token)
+ o.mAttributionSourceState.attributionTag)
&& Arrays.equals(mAttributionSourceState.renouncedPermissions,
- that.mAttributionSourceState.renouncedPermissions)
- && Objects.equals(getNext(), that.getNext());
+ o.mAttributionSourceState.renouncedPermissions)
+ && Objects.equals(getNext(), o.getNext());
}
@Override
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index 31f6418ac3d0..fe7d1e6fb232 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -5270,6 +5270,16 @@ public class Intent implements Parcelable, Cloneable {
public static final String ACTION_SHOW_FOREGROUND_SERVICE_MANAGER =
"android.intent.action.SHOW_FOREGROUND_SERVICE_MANAGER";
+ /**
+ * Broadcast Action: Sent to the responsible installer of an archived package when unarchival
+ * is requested.
+ *
+ * @see android.content.pm.PackageArchiver
+ * @hide
+ */
+ @SystemApi
+ public static final String ACTION_UNARCHIVE_PACKAGE = "android.intent.action.UNARCHIVE_PACKAGE";
+
// ---------------------------------------------------------------------
// ---------------------------------------------------------------------
// Standard intent categories (see addCategory()).
diff --git a/core/java/android/content/pm/ArchivedPackageParcel.aidl b/core/java/android/content/pm/ArchivedPackageParcel.aidl
new file mode 100644
index 000000000000..6aeee895301a
--- /dev/null
+++ b/core/java/android/content/pm/ArchivedPackageParcel.aidl
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.content.pm;
+
+import android.content.pm.SigningDetails;
+
+/**
+ * Contains fields required for archived package installation,
+ * i.e. installation without an APK.
+ * @hide
+ */
+parcelable ArchivedPackageParcel {
+ String packageName;
+ SigningDetails signingDetails;
+ int versionCode;
+ int versionCodeMajor;
+ int targetSdkVersion;
+ boolean backupAllowed;
+ boolean defaultToDeviceProtectedStorage;
+ boolean requestLegacyExternalStorage;
+ boolean userDataFragile;
+ boolean clearUserDataOnFailedRestoreAllowed;
+}
diff --git a/core/java/android/content/pm/IPackageArchiverService.aidl b/core/java/android/content/pm/IPackageArchiverService.aidl
index fc471c451370..dc6491d6d97e 100644
--- a/core/java/android/content/pm/IPackageArchiverService.aidl
+++ b/core/java/android/content/pm/IPackageArchiverService.aidl
@@ -23,4 +23,7 @@ interface IPackageArchiverService {
@JavaPassthrough(annotation="@android.annotation.RequiresPermission(anyOf={android.Manifest.permission.DELETE_PACKAGES,android.Manifest.permission.REQUEST_DELETE_PACKAGES})")
void requestArchive(String packageName, String callerPackageName, in IntentSender statusReceiver, in UserHandle userHandle);
+
+ @JavaPassthrough(annotation="@android.annotation.RequiresPermission(anyOf={android.Manifest.permission.INSTALL_PACKAGES,android.Manifest.permission.REQUEST_INSTALL_PACKAGES})")
+ void requestUnarchive(String packageName, String callerPackageName, in UserHandle userHandle);
} \ No newline at end of file
diff --git a/core/java/android/content/pm/IPackageManager.aidl b/core/java/android/content/pm/IPackageManager.aidl
index 4ed4dd3c015a..916c249019a7 100644
--- a/core/java/android/content/pm/IPackageManager.aidl
+++ b/core/java/android/content/pm/IPackageManager.aidl
@@ -22,6 +22,7 @@ import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.ActivityInfo;
import android.content.pm.ApplicationInfo;
+import android.content.pm.ArchivedPackageParcel;
import android.content.pm.ChangedPackages;
import android.content.pm.InstantAppInfo;
import android.content.pm.FeatureInfo;
@@ -833,4 +834,6 @@ interface IPackageManager {
void registerPackageMonitorCallback(IRemoteCallback callback, int userId);
void unregisterPackageMonitorCallback(IRemoteCallback callback);
+
+ ArchivedPackageParcel getArchivedPackage(in String apkPath);
}
diff --git a/core/java/android/content/pm/PackageArchiver.java b/core/java/android/content/pm/PackageArchiver.java
index d739d5054800..b06523160b92 100644
--- a/core/java/android/content/pm/PackageArchiver.java
+++ b/core/java/android/content/pm/PackageArchiver.java
@@ -42,6 +42,26 @@ import android.os.RemoteException;
@SystemApi
public class PackageArchiver {
+ /**
+ * Extra field for the package name of a package that is requested to be unarchived. Sent as
+ * part of the {@link android.content.Intent#ACTION_UNARCHIVE_PACKAGE} intent.
+ *
+ * @hide
+ */
+ @SystemApi
+ public static final String EXTRA_UNARCHIVE_PACKAGE_NAME =
+ "android.content.pm.extra.UNARCHIVE_PACKAGE_NAME";
+
+ /**
+ * If true, the requestor of the unarchival has specified that the app should be unarchived
+ * for {@link android.os.UserHandle#ALL}.
+ *
+ * @hide
+ */
+ @SystemApi
+ public static final String EXTRA_UNARCHIVE_ALL_USERS =
+ "android.content.pm.extra.UNARCHIVE_ALL_USERS";
+
private final Context mContext;
private final IPackageArchiverService mService;
@@ -58,7 +78,7 @@ public class PackageArchiver {
*
* @param statusReceiver Callback used to notify when the operation is completed.
* @throws NameNotFoundException If {@code packageName} isn't found or not available to the
- * caller.
+ * caller or isn't archived.
* @hide
*/
@RequiresPermission(anyOf = {
@@ -76,4 +96,34 @@ public class PackageArchiver {
throw e.rethrowFromSystemServer();
}
}
+
+ /**
+ * Requests to unarchive a currently archived package.
+ *
+ * <p> Sends a request to unarchive an app to the responsible installer. The installer is
+ * determined by {@link InstallSourceInfo#getUpdateOwnerPackageName()}, or
+ * {@link InstallSourceInfo#getInstallingPackageName()} if the former value is null.
+ *
+ * <p> The installation will happen asynchronously and can be observed through
+ * {@link android.content.Intent#ACTION_PACKAGE_ADDED}.
+ *
+ * @throws NameNotFoundException If {@code packageName} isn't found or not visible to the
+ * caller or if the package has no installer on the device
+ * anymore to unarchive it.
+ * @hide
+ */
+ @RequiresPermission(anyOf = {
+ Manifest.permission.INSTALL_PACKAGES,
+ Manifest.permission.REQUEST_INSTALL_PACKAGES})
+ @SystemApi
+ public void requestUnarchive(@NonNull String packageName)
+ throws NameNotFoundException {
+ try {
+ mService.requestUnarchive(packageName, mContext.getPackageName(), mContext.getUser());
+ } catch (ParcelableException e) {
+ e.maybeRethrow(NameNotFoundException.class);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
}
diff --git a/core/java/android/content/pm/PackageInfo.java b/core/java/android/content/pm/PackageInfo.java
index 63c11b779641..cdb8b46ba41a 100644
--- a/core/java/android/content/pm/PackageInfo.java
+++ b/core/java/android/content/pm/PackageInfo.java
@@ -18,6 +18,7 @@ package android.content.pm;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.SystemApi;
import android.compat.annotation.UnsupportedAppUsage;
import android.os.Build;
import android.os.Parcel;
@@ -488,6 +489,17 @@ public class PackageInfo implements Parcelable {
*/
public boolean isActiveApex;
+ /**
+ * Whether the package is currently in an archived state.
+ *
+ * <p>Packages can be archived through {@link PackageArchiver} and do not have any APKs stored
+ * on the device, but do keep the data directory.
+ * @hide
+ */
+ // TODO(b/278553670) Unhide and update @links before launch.
+ @SystemApi
+ public boolean isArchived;
+
public PackageInfo() {
}
@@ -575,6 +587,7 @@ public class PackageInfo implements Parcelable {
}
dest.writeBoolean(isApex);
dest.writeBoolean(isActiveApex);
+ dest.writeBoolean(isArchived);
dest.restoreAllowSquashing(prevAllowSquashing);
}
@@ -640,5 +653,6 @@ public class PackageInfo implements Parcelable {
}
isApex = source.readBoolean();
isActiveApex = source.readBoolean();
+ isArchived = source.readBoolean();
}
}
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index d2173a6d44bd..9a53a2a60076 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -787,6 +787,7 @@ public abstract class PackageManager {
MATCH_DEBUG_TRIAGED_MISSING,
MATCH_INSTANT,
MATCH_APEX,
+ MATCH_ARCHIVED_PACKAGES,
GET_DISABLED_COMPONENTS,
GET_DISABLED_UNTIL_USED_COMPONENTS,
GET_UNINSTALLED_PACKAGES,
@@ -811,6 +812,7 @@ public abstract class PackageManager {
GET_UNINSTALLED_PACKAGES,
MATCH_HIDDEN_UNTIL_INSTALLED_COMPONENTS,
MATCH_APEX,
+ MATCH_ARCHIVED_PACKAGES,
})
@Retention(RetentionPolicy.SOURCE)
public @interface ApplicationInfoFlagsBits {}
@@ -1235,6 +1237,21 @@ public abstract class PackageManager {
public static final long GET_ATTRIBUTIONS_LONG = 0x80000000L;
/**
+ * Flag parameter to also retrieve some information about archived packages.
+ * Packages can be archived through {@link PackageArchiver} and do not have any APKs stored on
+ * the device, but do keep the data directory.
+ * <p> Note: Archived apps are a subset of apps returned by {@link #MATCH_UNINSTALLED_PACKAGES}.
+ * <p> Note: this flag may cause less information about currently installed
+ * applications to be returned.
+ * <p> Note: use of this flag requires the android.permission.QUERY_ALL_PACKAGES
+ * permission to see uninstalled packages.
+ * @hide
+ */
+ // TODO(b/278553670) Unhide and update @links before launch.
+ @SystemApi
+ public static final long MATCH_ARCHIVED_PACKAGES = 1L << 32;
+
+ /**
* @hide
*/
public static final long FILTER_OUT_QUARANTINED_COMPONENTS = 0x100000000L;
@@ -1682,6 +1699,13 @@ public abstract class PackageManager {
public static final int INSTALL_FROM_MANAGED_USER_OR_PROFILE = 1 << 26;
/**
+ * Flag parameter for {@link PackageInstaller.SessionParams} to indicate that this
+ * session is for archived package installation.
+ * @hide
+ */
+ public static final int INSTALL_ARCHIVED = 1 << 27;
+
+ /**
* Flag parameter for {@link #installPackage} to force a non-staged update of an APEX. This is
* a development-only feature and should not be used on end user devices.
*
diff --git a/packages/SystemUI/compose/facade/disabled/src/com/android/systemui/scene/ui/composable/SceneModule.kt b/core/java/android/content/pm/SigningDetails.aidl
index 24064b1261b7..95f3ca786c03 100644
--- a/packages/SystemUI/compose/facade/disabled/src/com/android/systemui/scene/ui/composable/SceneModule.kt
+++ b/core/java/android/content/pm/SigningDetails.aidl
@@ -13,14 +13,6 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+package android.content.pm;
-package com.android.systemui.scene.ui.composable
-
-import com.android.systemui.scene.shared.model.Scene
-import dagger.Module
-import dagger.multibindings.Multibinds
-
-@Module
-interface SceneModule {
- @Multibinds fun scenes(): Set<Scene>
-}
+parcelable SigningDetails;
diff --git a/core/java/android/content/pm/TEST_MAPPING b/core/java/android/content/pm/TEST_MAPPING
index ea21d51b0e9e..ab669cc141f1 100644
--- a/core/java/android/content/pm/TEST_MAPPING
+++ b/core/java/android/content/pm/TEST_MAPPING
@@ -48,9 +48,6 @@
"name":"CarrierAppIntegrationTestCases"
},
{
- "name":"ApkVerityTest"
- },
- {
"name":"CtsSilentUpdateHostTestCases"
},
{
diff --git a/core/java/android/content/pm/parsing/ApkLite.java b/core/java/android/content/pm/parsing/ApkLite.java
index 269bec256282..8e7592a1eb73 100644
--- a/core/java/android/content/pm/parsing/ApkLite.java
+++ b/core/java/android/content/pm/parsing/ApkLite.java
@@ -18,6 +18,7 @@ package android.content.pm.parsing;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.content.pm.ArchivedPackageParcel;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.SigningDetails;
@@ -138,6 +139,34 @@ public class ApkLite {
*/
private final boolean mIsSdkLibrary;
+ /**
+ * Set to <code>false</code> if the application does not wish to permit any OS-driven
+ * backups of its data; <code>true</code> otherwise.
+ */
+ private final boolean mBackupAllowed;
+
+ /**
+ * When set, the default data storage directory for this app is pointed at
+ * the device-protected location.
+ */
+ private final boolean mDefaultToDeviceProtectedStorage;
+
+ /**
+ * If {@code true} this app requests full external storage access.
+ */
+ private final boolean mRequestLegacyExternalStorage;
+
+ /**
+ * Indicates whether this application has declared its user data as fragile, causing the
+ * system to prompt the user on whether to keep the user data on uninstall.
+ */
+ private final boolean mUserDataFragile;
+
+ /**
+ * Indicates whether this application's data will be cleared on a failed restore.
+ */
+ private final boolean mClearUserDataOnFailedRestoreAllowed;
+
public ApkLite(String path, String packageName, String splitName, boolean isFeatureSplit,
String configForSplit, String usesSplitName, boolean isSplitRequired, int versionCode,
int versionCodeMajor, int revisionCode, int installLocation,
@@ -148,7 +177,10 @@ public class ApkLite {
String requiredSystemPropertyName, String requiredSystemPropertyValue,
int minSdkVersion, int targetSdkVersion, int rollbackDataPolicy,
Set<String> requiredSplitTypes, Set<String> splitTypes,
- boolean hasDeviceAdminReceiver, boolean isSdkLibrary) {
+ boolean hasDeviceAdminReceiver, boolean isSdkLibrary, boolean clearUserDataAllowed,
+ boolean backupAllowed, boolean defaultToDeviceProtectedStorage,
+ boolean requestLegacyExternalStorage, boolean userDataFragile,
+ boolean clearUserDataOnFailedRestoreAllowed) {
mPath = path;
mPackageName = packageName;
mSplitName = splitName;
@@ -182,6 +214,52 @@ public class ApkLite {
mRollbackDataPolicy = rollbackDataPolicy;
mHasDeviceAdminReceiver = hasDeviceAdminReceiver;
mIsSdkLibrary = isSdkLibrary;
+ mBackupAllowed = backupAllowed;
+ mDefaultToDeviceProtectedStorage = defaultToDeviceProtectedStorage;
+ mRequestLegacyExternalStorage = requestLegacyExternalStorage;
+ mUserDataFragile = userDataFragile;
+ mClearUserDataOnFailedRestoreAllowed = clearUserDataOnFailedRestoreAllowed;
+ }
+
+ public ApkLite(String path, ArchivedPackageParcel archivedPackage) {
+ mPath = path;
+ mPackageName = archivedPackage.packageName;
+ mSplitName = null; // base.apk
+ mSplitTypes = null;
+ mFeatureSplit = false;
+ mConfigForSplit = null;
+ mUsesSplitName = null;
+ mRequiredSplitTypes = null;
+ mSplitRequired = hasAnyRequiredSplitTypes();
+ mVersionCode = archivedPackage.versionCode;
+ mVersionCodeMajor = archivedPackage.versionCodeMajor;
+ mRevisionCode = 0;
+ mInstallLocation = PackageInfo.INSTALL_LOCATION_UNSPECIFIED;
+ mVerifiers = new VerifierInfo[]{};
+ mSigningDetails = archivedPackage.signingDetails;
+ mCoreApp = false;
+ mDebuggable = false;
+ mProfileableByShell = false;
+ mMultiArch = false;
+ mUse32bitAbi = false;
+ mUseEmbeddedDex = false;
+ mExtractNativeLibs = false;
+ mIsolatedSplits = false;
+ mTargetPackageName = null;
+ mOverlayIsStatic = false;
+ mOverlayPriority = 0;
+ mRequiredSystemPropertyName = null;
+ mRequiredSystemPropertyValue = null;
+ mMinSdkVersion = ApkLiteParseUtils.DEFAULT_MIN_SDK_VERSION;
+ mTargetSdkVersion = archivedPackage.targetSdkVersion;
+ mRollbackDataPolicy = 0;
+ mHasDeviceAdminReceiver = false;
+ mIsSdkLibrary = false;
+ mBackupAllowed = archivedPackage.backupAllowed;
+ mDefaultToDeviceProtectedStorage = archivedPackage.defaultToDeviceProtectedStorage;
+ mRequestLegacyExternalStorage = archivedPackage.requestLegacyExternalStorage;
+ mUserDataFragile = archivedPackage.userDataFragile;
+ mClearUserDataOnFailedRestoreAllowed = archivedPackage.clearUserDataOnFailedRestoreAllowed;
}
/**
@@ -474,6 +552,9 @@ public class ApkLite {
return mRollbackDataPolicy;
}
+ /**
+ * Indicates if this app contains a {@link android.app.admin.DeviceAdminReceiver}.
+ */
@DataClass.Generated.Member
public boolean isHasDeviceAdminReceiver() {
return mHasDeviceAdminReceiver;
@@ -487,11 +568,54 @@ public class ApkLite {
return mIsSdkLibrary;
}
+ /**
+ * Set to <code>false</code> if the application does not wish to permit any OS-driven
+ * backups of its data; <code>true</code> otherwise.
+ */
+ @DataClass.Generated.Member
+ public boolean isBackupAllowed() {
+ return mBackupAllowed;
+ }
+
+ /**
+ * When set, the default data storage directory for this app is pointed at
+ * the device-protected location.
+ */
+ @DataClass.Generated.Member
+ public boolean isDefaultToDeviceProtectedStorage() {
+ return mDefaultToDeviceProtectedStorage;
+ }
+
+ /**
+ * If {@code true} this app requests full external storage access.
+ */
+ @DataClass.Generated.Member
+ public boolean isRequestLegacyExternalStorage() {
+ return mRequestLegacyExternalStorage;
+ }
+
+ /**
+ * Indicates whether this application has declared its user data as fragile, causing the
+ * system to prompt the user on whether to keep the user data on uninstall.
+ */
+ @DataClass.Generated.Member
+ public boolean isUserDataFragile() {
+ return mUserDataFragile;
+ }
+
+ /**
+ * Indicates whether this application's data will be cleared on a failed restore.
+ */
+ @DataClass.Generated.Member
+ public boolean isClearUserDataOnFailedRestoreAllowed() {
+ return mClearUserDataOnFailedRestoreAllowed;
+ }
+
@DataClass.Generated(
- time = 1643063342990L,
+ time = 1693513509013L,
codegenVersion = "1.0.23",
sourceFile = "frameworks/base/core/java/android/content/pm/parsing/ApkLite.java",
- inputSignatures = "private final @android.annotation.NonNull java.lang.String mPackageName\nprivate final @android.annotation.NonNull java.lang.String mPath\nprivate final @android.annotation.Nullable java.lang.String mSplitName\nprivate final @android.annotation.Nullable java.lang.String mUsesSplitName\nprivate final @android.annotation.Nullable java.lang.String mConfigForSplit\nprivate final @android.annotation.Nullable java.util.Set<java.lang.String> mRequiredSplitTypes\nprivate final @android.annotation.Nullable java.util.Set<java.lang.String> mSplitTypes\nprivate final int mVersionCodeMajor\nprivate final int mVersionCode\nprivate final int mRevisionCode\nprivate final int mInstallLocation\nprivate final int mMinSdkVersion\nprivate final int mTargetSdkVersion\nprivate final @android.annotation.NonNull android.content.pm.VerifierInfo[] mVerifiers\nprivate final @android.annotation.NonNull android.content.pm.SigningDetails mSigningDetails\nprivate final boolean mFeatureSplit\nprivate final boolean mIsolatedSplits\nprivate final boolean mSplitRequired\nprivate final boolean mCoreApp\nprivate final boolean mDebuggable\nprivate final boolean mProfileableByShell\nprivate final boolean mMultiArch\nprivate final boolean mUse32bitAbi\nprivate final boolean mExtractNativeLibs\nprivate final boolean mUseEmbeddedDex\nprivate final @android.annotation.Nullable java.lang.String mTargetPackageName\nprivate final boolean mOverlayIsStatic\nprivate final int mOverlayPriority\nprivate final @android.annotation.Nullable java.lang.String mRequiredSystemPropertyName\nprivate final @android.annotation.Nullable java.lang.String mRequiredSystemPropertyValue\nprivate final int mRollbackDataPolicy\nprivate final boolean mHasDeviceAdminReceiver\nprivate final boolean mIsSdkLibrary\npublic long getLongVersionCode()\nprivate boolean hasAnyRequiredSplitTypes()\nclass ApkLite extends java.lang.Object implements []\n@com.android.internal.util.DataClass(genConstructor=false, genConstDefs=false)")
+ inputSignatures = "private final @android.annotation.NonNull java.lang.String mPackageName\nprivate final @android.annotation.NonNull java.lang.String mPath\nprivate final @android.annotation.Nullable java.lang.String mSplitName\nprivate final @android.annotation.Nullable java.lang.String mUsesSplitName\nprivate final @android.annotation.Nullable java.lang.String mConfigForSplit\nprivate final @android.annotation.Nullable java.util.Set<java.lang.String> mRequiredSplitTypes\nprivate final @android.annotation.Nullable java.util.Set<java.lang.String> mSplitTypes\nprivate final int mVersionCodeMajor\nprivate final int mVersionCode\nprivate final int mRevisionCode\nprivate final int mInstallLocation\nprivate final int mMinSdkVersion\nprivate final int mTargetSdkVersion\nprivate final @android.annotation.NonNull android.content.pm.VerifierInfo[] mVerifiers\nprivate final @android.annotation.NonNull android.content.pm.SigningDetails mSigningDetails\nprivate final boolean mFeatureSplit\nprivate final boolean mIsolatedSplits\nprivate final boolean mSplitRequired\nprivate final boolean mCoreApp\nprivate final boolean mDebuggable\nprivate final boolean mProfileableByShell\nprivate final boolean mMultiArch\nprivate final boolean mUse32bitAbi\nprivate final boolean mExtractNativeLibs\nprivate final boolean mUseEmbeddedDex\nprivate final @android.annotation.Nullable java.lang.String mTargetPackageName\nprivate final boolean mOverlayIsStatic\nprivate final int mOverlayPriority\nprivate final @android.annotation.Nullable java.lang.String mRequiredSystemPropertyName\nprivate final @android.annotation.Nullable java.lang.String mRequiredSystemPropertyValue\nprivate final int mRollbackDataPolicy\nprivate final boolean mHasDeviceAdminReceiver\nprivate final boolean mIsSdkLibrary\nprivate final boolean mBackupAllowed\nprivate final boolean mDefaultToDeviceProtectedStorage\nprivate final boolean mRequestLegacyExternalStorage\nprivate final boolean mUserDataFragile\nprivate final boolean mClearUserDataOnFailedRestoreAllowed\npublic long getLongVersionCode()\nprivate boolean hasAnyRequiredSplitTypes()\nclass ApkLite extends java.lang.Object implements []\n@com.android.internal.util.DataClass(genConstructor=false, genConstDefs=false)")
@Deprecated
private void __metadata() {}
diff --git a/core/java/android/content/pm/parsing/ApkLiteParseUtils.java b/core/java/android/content/pm/parsing/ApkLiteParseUtils.java
index 4f6bcb6f0be5..066ff6896ac8 100644
--- a/core/java/android/content/pm/parsing/ApkLiteParseUtils.java
+++ b/core/java/android/content/pm/parsing/ApkLiteParseUtils.java
@@ -40,6 +40,7 @@ import android.util.Pair;
import android.util.Slog;
import com.android.internal.util.ArrayUtils;
+import com.android.internal.util.XmlUtils;
import libcore.io.IoUtils;
@@ -73,7 +74,7 @@ public class ApkLiteParseUtils {
// Constants copied from services.jar side since they're not accessible
private static final String ANDROID_RES_NAMESPACE =
"http://schemas.android.com/apk/res/android";
- private static final int DEFAULT_MIN_SDK_VERSION = 1;
+ public static final int DEFAULT_MIN_SDK_VERSION = 1;
private static final int DEFAULT_TARGET_SDK_VERSION = 0;
public static final String ANDROID_MANIFEST_FILENAME = "AndroidManifest.xml";
private static final int PARSE_IS_SYSTEM_DIR = 1 << 4;
@@ -446,6 +447,13 @@ public class ApkLiteParseUtils {
int overlayPriority = 0;
int rollbackDataPolicy = 0;
+ boolean clearUserDataAllowed = true;
+ boolean backupAllowed = true;
+ boolean defaultToDeviceProtectedStorage = false;
+ String requestLegacyExternalStorage = null;
+ boolean userDataFragile = false;
+ boolean clearUserDataOnFailedRestoreAllowed = true;
+
String requiredSystemPropertyName = null;
String requiredSystemPropertyValue = null;
@@ -484,6 +492,23 @@ public class ApkLiteParseUtils {
"extractNativeLibs", true);
useEmbeddedDex = parser.getAttributeBooleanValue(ANDROID_RES_NAMESPACE,
"useEmbeddedDex", false);
+
+ clearUserDataAllowed = parser.getAttributeBooleanValue(ANDROID_RES_NAMESPACE,
+ "allowClearUserDataOnFailedRestore", true);
+ backupAllowed = parser.getAttributeBooleanValue(ANDROID_RES_NAMESPACE,
+ "allowBackup", true);
+ defaultToDeviceProtectedStorage = parser.getAttributeBooleanValue(
+ ANDROID_RES_NAMESPACE,
+ "defaultToDeviceProtectedStorage", false);
+ userDataFragile = parser.getAttributeBooleanValue(ANDROID_RES_NAMESPACE,
+ "hasFragileUserData", false);
+ clearUserDataOnFailedRestoreAllowed = parser.getAttributeBooleanValue(
+ ANDROID_RES_NAMESPACE,
+ "allowClearUserDataOnFailedRestore", true);
+
+ requestLegacyExternalStorage = parser.getAttributeValue(ANDROID_RES_NAMESPACE,
+ "requestLegacyExternalStorage");
+
rollbackDataPolicy = parser.getAttributeIntValue(ANDROID_RES_NAMESPACE,
"rollbackDataPolicy", 0);
String permission = parser.getAttributeValue(ANDROID_RES_NAMESPACE,
@@ -604,6 +629,9 @@ public class ApkLiteParseUtils {
return input.skip(message);
}
+ boolean isRequestLegacyExternalStorage = XmlUtils.convertValueToBoolean(
+ requestLegacyExternalStorage, targetSdkVersion < Build.VERSION_CODES.Q);
+
return input.success(
new ApkLite(codePath, packageSplit.first, packageSplit.second, isFeatureSplit,
configForSplit, usesSplitName, isSplitRequired, versionCode,
@@ -613,7 +641,9 @@ public class ApkLiteParseUtils {
overlayIsStatic, overlayPriority, requiredSystemPropertyName,
requiredSystemPropertyValue, minSdkVersion, targetSdkVersion,
rollbackDataPolicy, requiredSplitTypes.first, requiredSplitTypes.second,
- hasDeviceAdminReceiver, isSdkLibrary));
+ hasDeviceAdminReceiver, isSdkLibrary, clearUserDataAllowed, backupAllowed,
+ defaultToDeviceProtectedStorage, isRequestLegacyExternalStorage,
+ userDataFragile, clearUserDataOnFailedRestoreAllowed));
}
private static boolean isDeviceAdminReceiver(
diff --git a/core/java/android/content/pm/parsing/PackageLite.java b/core/java/android/content/pm/parsing/PackageLite.java
index e2789c93516f..ccef9def609e 100644
--- a/core/java/android/content/pm/parsing/PackageLite.java
+++ b/core/java/android/content/pm/parsing/PackageLite.java
@@ -19,6 +19,7 @@ package android.content.pm.parsing;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.pm.PackageInfo;
+import android.content.pm.SigningDetails;
import android.content.pm.VerifierInfo;
import com.android.internal.util.ArrayUtils;
@@ -78,6 +79,8 @@ public class PackageLite {
private final int mInstallLocation;
/** Information about a package verifiers as used during package verification */
private final @NonNull VerifierInfo[] mVerifiers;
+ /** Signing-related data of an application package */
+ private final @NonNull SigningDetails mSigningDetails;
/** Indicate whether any split APKs that are features. Ordered by splitName */
private final @Nullable boolean[] mIsFeatureSplits;
@@ -109,6 +112,29 @@ public class PackageLite {
* Indicates if this package is a sdk.
*/
private final boolean mIsSdkLibrary;
+ /**
+ * Set to <code>false</code> if the application does not wish to permit any OS-driven
+ * backups of its data; <code>true</code> otherwise.
+ */
+ private final boolean mBackupAllowed;
+ /**
+ * When set, the default data storage directory for this app is pointed at
+ * the device-protected location.
+ */
+ private final boolean mDefaultToDeviceProtectedStorage;
+ /**
+ * If {@code true} this app requests full external storage access.
+ */
+ private final boolean mRequestLegacyExternalStorage;
+ /**
+ * Indicates whether this application has declared its user data as fragile, causing the
+ * system to prompt the user on whether to keep the user data on uninstall.
+ */
+ private final boolean mUserDataFragile;
+ /**
+ * Indicates whether this application's data will be cleared on a failed restore.
+ */
+ private final boolean mClearUserDataOnFailedRestoreAllowed;
public PackageLite(String path, String baseApkPath, ApkLite baseApk,
String[] splitNames, boolean[] isFeatureSplits, String[] usesSplitNames,
@@ -123,6 +149,7 @@ public class PackageLite {
mVersionCodeMajor = baseApk.getVersionCodeMajor();
mInstallLocation = baseApk.getInstallLocation();
mVerifiers = baseApk.getVerifiers();
+ mSigningDetails = baseApk.getSigningDetails();
mBaseRevisionCode = baseApk.getRevisionCode();
mCoreApp = baseApk.isCoreApp();
mDebuggable = baseApk.isDebuggable();
@@ -144,6 +171,11 @@ public class PackageLite {
mSplitApkPaths = splitApkPaths;
mSplitRevisionCodes = splitRevisionCodes;
mTargetSdk = targetSdk;
+ mBackupAllowed = baseApk.isBackupAllowed();
+ mDefaultToDeviceProtectedStorage = baseApk.isDefaultToDeviceProtectedStorage();
+ mRequestLegacyExternalStorage = baseApk.isRequestLegacyExternalStorage();
+ mUserDataFragile = baseApk.isUserDataFragile();
+ mClearUserDataOnFailedRestoreAllowed = baseApk.isClearUserDataOnFailedRestoreAllowed();
}
/**
@@ -325,6 +357,14 @@ public class PackageLite {
}
/**
+ * Signing-related data of an application package
+ */
+ @DataClass.Generated.Member
+ public @NonNull SigningDetails getSigningDetails() {
+ return mSigningDetails;
+ }
+
+ /**
* Indicate whether any split APKs that are features. Ordered by splitName
*/
@DataClass.Generated.Member
@@ -414,12 +454,54 @@ public class PackageLite {
return mIsSdkLibrary;
}
+ /**
+ * Set to <code>false</code> if the application does not wish to permit any OS-driven
+ * backups of its data; <code>true</code> otherwise.
+ */
+ @DataClass.Generated.Member
+ public boolean isBackupAllowed() {
+ return mBackupAllowed;
+ }
+
+ /**
+ * When set, the default data storage directory for this app is pointed at
+ * the device-protected location.
+ */
+ @DataClass.Generated.Member
+ public boolean isDefaultToDeviceProtectedStorage() {
+ return mDefaultToDeviceProtectedStorage;
+ }
+
+ /**
+ * If {@code true} this app requests full external storage access.
+ */
+ @DataClass.Generated.Member
+ public boolean isRequestLegacyExternalStorage() {
+ return mRequestLegacyExternalStorage;
+ }
+
+ /**
+ * Indicates whether this application has declared its user data as fragile, causing the
+ * system to prompt the user on whether to keep the user data on uninstall.
+ */
+ @DataClass.Generated.Member
+ public boolean isUserDataFragile() {
+ return mUserDataFragile;
+ }
+
+ /**
+ * Indicates whether this application's data will be cleared on a failed restore.
+ */
+ @DataClass.Generated.Member
+ public boolean isClearUserDataOnFailedRestoreAllowed() {
+ return mClearUserDataOnFailedRestoreAllowed;
+ }
+
@DataClass.Generated(
- time = 1643132127068L,
+ time = 1693513525097L,
codegenVersion = "1.0.23",
sourceFile = "frameworks/base/core/java/android/content/pm/parsing/PackageLite.java",
- inputSignatures =
- "private final @android.annotation.NonNull java.lang.String mPackageName\nprivate final @android.annotation.NonNull java.lang.String mPath\nprivate final @android.annotation.NonNull java.lang.String mBaseApkPath\nprivate final @android.annotation.Nullable java.lang.String[] mSplitApkPaths\nprivate final @android.annotation.Nullable java.lang.String[] mSplitNames\nprivate final @android.annotation.Nullable java.lang.String[] mUsesSplitNames\nprivate final @android.annotation.Nullable java.lang.String[] mConfigForSplit\nprivate final @android.annotation.Nullable java.util.Set<java.lang.String> mBaseRequiredSplitTypes\nprivate final @android.annotation.Nullable java.util.Set<java.lang.String>[] mRequiredSplitTypes\nprivate final @android.annotation.Nullable java.util.Set<java.lang.String>[] mSplitTypes\nprivate final int mVersionCodeMajor\nprivate final int mVersionCode\nprivate final int mTargetSdk\nprivate final int mBaseRevisionCode\nprivate final @android.annotation.Nullable int[] mSplitRevisionCodes\nprivate final int mInstallLocation\nprivate final @android.annotation.NonNull android.content.pm.VerifierInfo[] mVerifiers\nprivate final @android.annotation.Nullable boolean[] mIsFeatureSplits\nprivate final boolean mIsolatedSplits\nprivate final boolean mSplitRequired\nprivate final boolean mCoreApp\nprivate final boolean mDebuggable\nprivate final boolean mMultiArch\nprivate final boolean mUse32bitAbi\nprivate final boolean mExtractNativeLibs\nprivate final boolean mProfileableByShell\nprivate final boolean mUseEmbeddedDex\nprivate final boolean mIsSdkLibrary\npublic java.util.List<java.lang.String> getAllApkPaths()\npublic long getLongVersionCode()\nprivate boolean hasAnyRequiredSplitTypes()\nclass PackageLite extends java.lang.Object implements []\n@com.android.internal.util.DataClass(genConstructor=false, genConstDefs=false)")
+ inputSignatures = "private final @android.annotation.NonNull java.lang.String mPackageName\nprivate final @android.annotation.NonNull java.lang.String mPath\nprivate final @android.annotation.NonNull java.lang.String mBaseApkPath\nprivate final @android.annotation.Nullable java.lang.String[] mSplitApkPaths\nprivate final @android.annotation.Nullable java.lang.String[] mSplitNames\nprivate final @android.annotation.Nullable java.lang.String[] mUsesSplitNames\nprivate final @android.annotation.Nullable java.lang.String[] mConfigForSplit\nprivate final @android.annotation.Nullable java.util.Set<java.lang.String> mBaseRequiredSplitTypes\nprivate final @android.annotation.Nullable java.util.Set<java.lang.String>[] mRequiredSplitTypes\nprivate final @android.annotation.Nullable java.util.Set<java.lang.String>[] mSplitTypes\nprivate final int mVersionCodeMajor\nprivate final int mVersionCode\nprivate final int mTargetSdk\nprivate final int mBaseRevisionCode\nprivate final @android.annotation.Nullable int[] mSplitRevisionCodes\nprivate final int mInstallLocation\nprivate final @android.annotation.NonNull android.content.pm.VerifierInfo[] mVerifiers\nprivate final @android.annotation.NonNull android.content.pm.SigningDetails mSigningDetails\nprivate final @android.annotation.Nullable boolean[] mIsFeatureSplits\nprivate final boolean mIsolatedSplits\nprivate final boolean mSplitRequired\nprivate final boolean mCoreApp\nprivate final boolean mDebuggable\nprivate final boolean mMultiArch\nprivate final boolean mUse32bitAbi\nprivate final boolean mExtractNativeLibs\nprivate final boolean mProfileableByShell\nprivate final boolean mUseEmbeddedDex\nprivate final boolean mIsSdkLibrary\nprivate final boolean mBackupAllowed\nprivate final boolean mDefaultToDeviceProtectedStorage\nprivate final boolean mRequestLegacyExternalStorage\nprivate final boolean mUserDataFragile\nprivate final boolean mClearUserDataOnFailedRestoreAllowed\npublic java.util.List<java.lang.String> getAllApkPaths()\npublic long getLongVersionCode()\nprivate boolean hasAnyRequiredSplitTypes()\nclass PackageLite extends java.lang.Object implements []\n@com.android.internal.util.DataClass(genConstructor=false, genConstDefs=false)")
@Deprecated
private void __metadata() {}
diff --git a/core/java/android/content/res/ResourcesImpl.java b/core/java/android/content/res/ResourcesImpl.java
index 76b29e683312..5cc3b92da305 100644
--- a/core/java/android/content/res/ResourcesImpl.java
+++ b/core/java/android/content/res/ResourcesImpl.java
@@ -27,7 +27,6 @@ import android.annotation.PluralsRes;
import android.annotation.RawRes;
import android.annotation.StyleRes;
import android.annotation.StyleableRes;
-import android.app.ResourcesManager;
import android.compat.annotation.UnsupportedAppUsage;
import android.content.pm.ActivityInfo;
import android.content.pm.ActivityInfo.Config;
@@ -430,49 +429,35 @@ public class ResourcesImpl {
if ((configChanges & ActivityInfo.CONFIG_LOCALE) != 0) {
if (locales.size() > 1) {
String[] availableLocales;
- if (ResourcesManager.getInstance().getLocaleList().isEmpty()) {
- // The LocaleList has changed. We must query the AssetManager's
- // available Locales and figure out the best matching Locale in the new
- // LocaleList.
- availableLocales = mAssets.getNonSystemLocales();
+ // The LocaleList has changed. We must query the AssetManager's
+ // available Locales and figure out the best matching Locale in the new
+ // LocaleList.
+ availableLocales = mAssets.getNonSystemLocales();
+ if (LocaleList.isPseudoLocalesOnly(availableLocales)) {
+ // No app defined locales, so grab the system locales.
+ availableLocales = mAssets.getLocales();
if (LocaleList.isPseudoLocalesOnly(availableLocales)) {
- // No app defined locales, so grab the system locales.
- availableLocales = mAssets.getLocales();
- if (LocaleList.isPseudoLocalesOnly(availableLocales)) {
- availableLocales = null;
- }
+ availableLocales = null;
}
+ }
- if (availableLocales != null) {
- final Locale bestLocale = locales.getFirstMatchWithEnglishSupported(
- availableLocales);
- if (bestLocale != null) {
- selectedLocales = new String[]{
- adjustLanguageTag(bestLocale.toLanguageTag())};
- if (!bestLocale.equals(locales.get(0))) {
- mConfiguration.setLocales(
- new LocaleList(bestLocale, locales));
- }
+ if (availableLocales != null) {
+ final Locale bestLocale = locales.getFirstMatchWithEnglishSupported(
+ availableLocales);
+ if (bestLocale != null) {
+ selectedLocales = new String[]{
+ adjustLanguageTag(bestLocale.toLanguageTag())};
+ if (!bestLocale.equals(locales.get(0))) {
+ mConfiguration.setLocales(
+ new LocaleList(bestLocale, locales));
}
}
- } else {
- selectedLocales = locales.getIntersection(
- ResourcesManager.getInstance().getLocaleList());
- defaultLocale = ResourcesManager.getInstance()
- .getLocaleList().get(0).toLanguageTag();
}
}
}
if (selectedLocales == null) {
- if (ResourcesManager.getInstance().getLocaleList().isEmpty()) {
- selectedLocales = new String[]{
- adjustLanguageTag(locales.get(0).toLanguageTag())};
- } else {
- selectedLocales = new String[locales.size()];
- for (int i = 0; i < locales.size(); i++) {
- selectedLocales[i] = adjustLanguageTag(locales.get(i).toLanguageTag());
- }
- }
+ selectedLocales = new String[]{
+ adjustLanguageTag(locales.get(0).toLanguageTag())};
}
if (mConfiguration.densityDpi != Configuration.DENSITY_DPI_UNDEFINED) {
diff --git a/core/java/android/hardware/camera2/CameraDevice.java b/core/java/android/hardware/camera2/CameraDevice.java
index 082a3361be4e..f4d783a7c2b7 100644
--- a/core/java/android/hardware/camera2/CameraDevice.java
+++ b/core/java/android/hardware/camera2/CameraDevice.java
@@ -625,12 +625,13 @@ public abstract class CameraDevice implements AutoCloseable {
* <style scoped>
* #rb { border-right-width: thick; }
* </style>
+ *
+ * <h5>LEGACY-level guaranteed configurations</h5>
+ *
* <p>Legacy devices ({@link CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL}
* {@code == }{@link CameraMetadata#INFO_SUPPORTED_HARDWARE_LEVEL_LEGACY LEGACY}) support at
* least the following stream combinations:
*
- * <h5>LEGACY-level guaranteed configurations</h5>
- *
* <table>
* <tr> <th colspan="2" id="rb">Target 1</th> <th colspan="2" id="rb">Target 2</th> <th colspan="2" id="rb">Target 3</th> <th rowspan="2">Sample use case(s)</th> </tr>
* <tr> <th>Type</th><th id="rb">Max size</th> <th>Type</th><th id="rb">Max size</th> <th>Type</th><th id="rb">Max size</th></tr>
@@ -645,13 +646,13 @@ public abstract class CameraDevice implements AutoCloseable {
* </table><br>
* </p>
*
+ * <h5>LIMITED-level additional guaranteed configurations</h5>
+ *
* <p>Limited-level ({@link CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL}
* {@code == }{@link CameraMetadata#INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED LIMITED}) devices
* support at least the following stream combinations in addition to those for
* {@link CameraMetadata#INFO_SUPPORTED_HARDWARE_LEVEL_LEGACY LEGACY} devices:
*
- * <h5>LIMITED-level additional guaranteed configurations</h5>
- *
* <table>
* <tr><th colspan="2" id="rb">Target 1</th><th colspan="2" id="rb">Target 2</th><th colspan="2" id="rb">Target 3</th> <th rowspan="2">Sample use case(s)</th> </tr>
* <tr><th>Type</th><th id="rb">Max size</th><th>Type</th><th id="rb">Max size</th><th>Type</th><th id="rb">Max size</th></tr>
@@ -664,13 +665,13 @@ public abstract class CameraDevice implements AutoCloseable {
* </table><br>
* </p>
*
+ * <h5>FULL-level additional guaranteed configurations</h5>
+ *
* <p>FULL-level ({@link CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL}
* {@code == }{@link CameraMetadata#INFO_SUPPORTED_HARDWARE_LEVEL_FULL FULL}) devices
* support at least the following stream combinations in addition to those for
* {@link CameraMetadata#INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED LIMITED} devices:
*
- * <h5>FULL-level additional guaranteed configurations</h5>
- *
* <table>
* <tr><th colspan="2" id="rb">Target 1</th><th colspan="2" id="rb">Target 2</th><th colspan="2" id="rb">Target 3</th> <th rowspan="2">Sample use case(s)</th> </tr>
* <tr><th>Type</th><th id="rb">Max size</th><th>Type</th><th id="rb">Max size</th><th>Type</th><th id="rb">Max size</th> </tr>
@@ -683,14 +684,14 @@ public abstract class CameraDevice implements AutoCloseable {
* </table><br>
* </p>
*
+ * <h5>RAW-capability additional guaranteed configurations</h5>
+ *
* <p>RAW-capability ({@link CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES} includes
* {@link CameraMetadata#REQUEST_AVAILABLE_CAPABILITIES_RAW RAW}) devices additionally support
* at least the following stream combinations on both
* {@link CameraMetadata#INFO_SUPPORTED_HARDWARE_LEVEL_FULL FULL} and
* {@link CameraMetadata#INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED LIMITED} devices:
*
- * <h5>RAW-capability additional guaranteed configurations</h5>
- *
* <table>
* <tr><th colspan="2" id="rb">Target 1</th><th colspan="2" id="rb">Target 2</th><th colspan="2" id="rb">Target 3</th> <th rowspan="2">Sample use case(s)</th> </tr>
* <tr><th>Type</th><th id="rb">Max size</th><th>Type</th><th id="rb">Max size</th><th>Type</th><th id="rb">Max size</th> </tr>
@@ -705,6 +706,8 @@ public abstract class CameraDevice implements AutoCloseable {
* </table><br>
* </p>
*
+ * <h5>BURST-capability additional guaranteed configurations</h5>
+ *
* <p>BURST-capability ({@link CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES} includes
* {@link CameraMetadata#REQUEST_AVAILABLE_CAPABILITIES_BURST_CAPTURE BURST_CAPTURE}) devices
* support at least the below stream combinations in addition to those for
@@ -713,8 +716,6 @@ public abstract class CameraDevice implements AutoCloseable {
* list for FULL-level devices, so this table is only relevant for LIMITED-level devices that
* support the BURST_CAPTURE capability.
*
- * <h5>BURST-capability additional guaranteed configurations</h5>
- *
* <table>
* <tr><th colspan="2" id="rb">Target 1</th><th colspan="2" id="rb">Target 2</th><th rowspan="2">Sample use case(s)</th> </tr>
* <tr><th>Type</th><th id="rb">Max size</th><th>Type</th><th id="rb">Max size</th> </tr>
@@ -724,6 +725,8 @@ public abstract class CameraDevice implements AutoCloseable {
* </table><br>
* </p>
*
+ * <h5>LEVEL-3 additional guaranteed configurations</h5>
+ *
* <p>LEVEL-3 ({@link CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL}
* {@code == }{@link CameraMetadata#INFO_SUPPORTED_HARDWARE_LEVEL_3 LEVEL_3})
* support at least the following stream combinations in addition to the combinations for
@@ -731,8 +734,6 @@ public abstract class CameraDevice implements AutoCloseable {
* RAW capability ({@link CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES} includes
* {@link CameraMetadata#REQUEST_AVAILABLE_CAPABILITIES_RAW RAW}):
*
- * <h5>LEVEL-3 additional guaranteed configurations</h5>
- *
* <table>
* <tr><th colspan="2" id="rb">Target 1</th><th colspan="2" id="rb">Target 2</th><th colspan="2" id="rb">Target 3</th><th colspan="2" id="rb">Target 4</th><th rowspan="2">Sample use case(s)</th> </tr>
* <tr><th>Type</th><th id="rb">Max size</th><th>Type</th><th id="rb">Max size</th><th>Type</th><th id="rb">Max size</th><th>Type</th><th id="rb">Max size</th> </tr>
@@ -741,14 +742,16 @@ public abstract class CameraDevice implements AutoCloseable {
* </table><br>
* </p>
*
- *<p>BACKWARD_COMPATIBLE devices capable of streaming concurrently with other devices as described by
- * {@link android.hardware.camera2.CameraManager#getConcurrentCameraIds} have the
+ * <h5>Concurrent stream guaranteed configurations</h5>
+ *
+ * <p>BACKWARD_COMPATIBLE devices capable of streaming concurrently with other devices as
+ * described by {@link android.hardware.camera2.CameraManager#getConcurrentCameraIds} have the
* following guaranteed streams (when streaming concurrently with other devices)</p>
+ *
* <p> Note: The sizes mentioned for these concurrent streams are the maximum sizes guaranteed
* to be supported. Sizes smaller than these, obtained by {@link StreamConfigurationMap#getOutputSizes} for a particular format, are supported as well. </p>
*
- * <h5>Concurrent stream guaranteed configurations</h5>
- *
+ * <p>
* <table>
* <tr><th colspan="2" id="rb">Target 1</th><th colspan="2" id="rb">Target 2</th><th rowspan="2">Sample use case(s)</th> </tr>
* <tr><th>Type</th><th id="rb">Max size</th><th>Type</th><th id="rb">Max size</th> </tr>
@@ -784,6 +787,8 @@ public abstract class CameraDevice implements AutoCloseable {
* level and capabilities. Calling createCaptureSession with both JPEG and HEIC outputs is not
* supported.</p>
*
+ * <h5>LEGACY-level additional guaranteed combinations with multi-resolution outputs</h5>
+ *
* <p>Devices capable of multi-resolution output for a particular format (
* {@link android.hardware.camera2.params.MultiResolutionStreamConfigurationMap#getOutputInfo}
* returns a non-empty list) support using {@link MultiResolutionImageReader} for MAXIMUM
@@ -794,8 +799,6 @@ public abstract class CameraDevice implements AutoCloseable {
* stream combinations ({@code MULTI_RES} in the Max size column refers to a {@link
* MultiResolutionImageReader} created based on the variable max resolutions supported):
*
- * <h5>LEGACY-level additional guaranteed combinations with MultiResolutionoutputs</h5>
- *
* <table>
* <tr> <th colspan="2" id="rb">Target 1</th> <th colspan="2" id="rb">Target 2</th> <th colspan="2" id="rb">Target 3</th> <th rowspan="2">Sample use case(s)</th> </tr>
* <tr> <th>Type</th><th id="rb">Max size</th> <th>Type</th><th id="rb">Max size</th> <th>Type</th><th id="rb">Max size</th></tr>
@@ -804,8 +807,12 @@ public abstract class CameraDevice implements AutoCloseable {
* <tr> <td>{@code PRIV}</td><td id="rb">{@code PREVIEW}</td> <td>{@code JPEG}</td><td id="rb">{@code MULTI_RES}</td> <td colspan="2" id="rb"></td> <td>Standard still imaging.</td> </tr>
* <tr> <td>{@code PRIV}</td><td id="rb">{@code PREVIEW}</td> <td>{@code YUV }</td><td id="rb">{@code PREVIEW}</td> <td>{@code JPEG}</td><td id="rb">{@code MULTI_RES}</td> <td>Still capture plus in-app processing.</td> </tr>
* </table><br>
+ * </p>
+ *
+ * <h5>LIMITED-level additional guaranteed configurations with multi-resolution outputs</h5>
+ *
+ * <p>
* <table>
- * <tr><th colspan="7">LIMITED-level additional guaranteed configurations with MultiResolutionoutputs</th></tr>
* <tr><th colspan="2" id="rb">Target 1</th><th colspan="2" id="rb">Target 2</th><th colspan="2" id="rb">Target 3</th> <th rowspan="2">Sample use case(s)</th> </tr>
* <tr><th>Type</th><th id="rb">Max size</th><th>Type</th><th id="rb">Max size</th><th>Type</th><th id="rb">Max size</th></tr>
* <tr> <td>{@code YUV }</td><td id="rb">{@code PREVIEW}</td> <td>{@code YUV }</td><td id="rb">{@code PREVIEW}</td> <td>{@code JPEG}</td><td id="rb">{@code MULTI_RES}</td> <td>Two-input in-app processing with still capture.</td> </tr>
@@ -813,11 +820,11 @@ public abstract class CameraDevice implements AutoCloseable {
* The same logic applies to other hardware levels and capabilities.
* </p>
*
- * <p> Devices with the ULTRA_HIGH_RESOLUTION_SENSOR capability have some additional guarantees
- * which clients can take advantage of : </p>
- *
* <h5>Additional guaranteed combinations for ULTRA_HIGH_RESOLUTION sensors</h5>
*
+ * <p> Devices with the ULTRA_HIGH_RESOLUTION_SENSOR capability have some additional guarantees
+ * which clients can take advantage of:
+ *
* <table>
* <tr> <th colspan="3" id="rb">Target 1</th> <th colspan="3" id="rb">Target 2</th> <th colspan="3" id="rb">Target 3</th> <th rowspan="2">Sample use case(s)</th> </tr>
* <tr> <th>Type</th><th id="rb"> SC Map</th><th id="rb">Max size</th> <th>Type</th><th id="rb"> SC Map</th><th id="rb">Max size</th> <th>Type</th><th id="rb"> SC Map</th><th id="rb">Max size</th></tr>
@@ -825,6 +832,7 @@ public abstract class CameraDevice implements AutoCloseable {
* <tr> <td>{@code YUV / JPEG / RAW}</td><td id="rb">{@code MAX_RES}</td><td id="rb">{@code MAX}</td><td id="rb">{@code PRIV}</td><td id="rb">{@code DEFAULT}</td><td id="rb">{@code PREVIEW}</td><td id="rb">{@code PRIV / YUV}</td><td id="rb">{@code DEFAULT}</td><td id="rb">{@code RECORD}</td> <td>Ultra high res still capture with preview + app based RECORD size analysis</td> </tr>
* <tr> <td>{@code YUV / JPEG / RAW}</td><td id="rb">{@code MAX_RES}</td><td id="rb">{@code MAX}</td><td id="rb">{@code PRIV}</td><td id="rb">{@code DEFAULT}</td><td id="rb">{@code PREVIEW}</td><td id="rb">{@code JPEG / YUV / RAW}</td><td id="rb">{@code DEFAULT}</td><td id="rb">{@code MAX}</td> <td>Ultra high res still image capture with preview + default sensor pixel mode analysis stream</td> </tr>
* </table><br>
+ * </p>
*
* <p> Here, SC Map, refers to the {@link StreamConfigurationMap}, the target stream sizes must
* be chosen from. {@code DEFAULT} refers to the default sensor pixel mode {@link
@@ -834,17 +842,17 @@ public abstract class CameraDevice implements AutoCloseable {
* Note: The same capture request must not mix targets from
* {@link StreamConfigurationMap}s corresponding to different sensor pixel modes. </p>
*
- * <p> 10-bit output capable
- * {@link CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES_DYNAMIC_RANGE_TEN_BIT}
- * devices support at least the following stream combinations: </p>
- *
* <h5>10-bit output additional guaranteed configurations</h5>
*
+ * <p>10-bit output capable
+ * {@link CameraMetadata#REQUEST_AVAILABLE_CAPABILITIES_DYNAMIC_RANGE_TEN_BIT}
+ * devices support at least the following stream combinations:
+ *
* <table>
* <tr><th colspan="2" id="rb">Target 1</th><th colspan="2" id="rb">Target 2</th><th colspan="2" id="rb">Target 3</th> <th rowspan="2">Sample use case(s)</th> </tr>
* <tr><th>Type</th><th id="rb">Max size</th><th>Type</th><th id="rb">Max size</th><th>Type</th><th id="rb">Max size</th></tr>
- * <tr> <td>{@code PRIV}</td><td id="rb">{@code MAXIMUM}</td> }</td> <td colspan="4" id="rb"></td> <td>Simple preview, GPU video processing, or no-preview video recording.</td> </tr>
- * <tr> <td>{@code YUV}</td><td id="rb">{@code MAXIMUM}</td> }</td> <td colspan="4" id="rb"></td> <td>In-application video/image processing.</td> </tr>
+ * <tr> <td>{@code PRIV}</td><td id="rb">{@code MAXIMUM}</td> </td> <td colspan="4" id="rb"></td> <td>Simple preview, GPU video processing, or no-preview video recording.</td> </tr>
+ * <tr> <td>{@code YUV}</td><td id="rb">{@code MAXIMUM}</td> </td> <td colspan="4" id="rb"></td> <td>In-application video/image processing.</td> </tr>
* <tr> <td>{@code PRIV}</td><td id="rb">{@code PREVIEW}</td> <td>{@code JPEG}</td><td id="rb">{@code MAXIMUM }</td> <td colspan="2" id="rb"></td> <td>Standard still imaging.</td> </tr>
* <tr> <td>{@code PRIV}</td><td id="rb">{@code PREVIEW}</td> <td>{@code YUV }</td><td id="rb">{@code MAXIMUM }</td> <td colspan="2" id="rb"></td> <td>Maximum-resolution in-app processing with preview.</td> </tr>
* <tr> <td>{@code YUV}</td><td id="rb">{@code PREVIEW}</td> <td>{@code YUV}</td><td id="rb">{@code MAXIMUM }</td> <td colspan="2" id="rb"></td> <td>Maximum-resolution two-input in-app processing.</td> </tr>
@@ -852,6 +860,8 @@ public abstract class CameraDevice implements AutoCloseable {
* <tr> <td>{@code PRIV}</td><td id="rb">{@code PREVIEW}</td> <td>{@code PRIV}</td><td id="rb">{@code RECORD }</td> <td>{@code YUV}</td><td id="rb">{@code RECORD }</td> <td>High-resolution recording with in-app snapshot.</td> </tr>
* <tr> <td>{@code PRIV}</td><td id="rb">{@code PREVIEW}</td> <td>{@code PRIV }</td><td id="rb">{@code RECORD }</td> <td>{@code JPEG}</td><td id="rb">{@code RECORD }</td> <td>High-resolution recording with video snapshot.</td> </tr>
* </table><br>
+ * </p>
+ *
* <p>Here PRIV can be either 8 or 10-bit {@link android.graphics.ImageFormat#PRIVATE} pixel
* format. YUV can be either {@link android.graphics.ImageFormat#YUV_420_888} or
* {@link android.graphics.ImageFormat#YCBCR_P010}.
@@ -887,13 +897,13 @@ public abstract class CameraDevice implements AutoCloseable {
* {@link CameraDevice#isSessionConfigurationSupported} to ensure that this particular
* configuration is supported.</p>
*
+ * <h5>STREAM_USE_CASE capability additional guaranteed configurations</h5>
+ *
* <p>Devices with the STREAM_USE_CASE capability ({@link
* CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES} includes {@link
* CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES_STREAM_USE_CASE}) support below additional
* stream combinations:
*
- * <h5>STREAM_USE_CASE capability additional guaranteed configurations</h5>
- *
* <table>
* <tr><th colspan="3" id="rb">Target 1</th><th colspan="3" id="rb">Target 2</th><th colspan="3" id="rb">Target 3</th> <th rowspan="2">Sample use case(s)</th> </tr>
* <tr><th>Type</th><th id="rb">Max size</th><th>Usecase</th><th>Type</th><th id="rb">Max size</th><th>Usecase</th><th>Type</th><th id="rb">Max size</th><th>Usecase</th> </tr>
@@ -913,12 +923,12 @@ public abstract class CameraDevice implements AutoCloseable {
* </table><br>
* </p>
*
+ * <h5>STREAM_USE_CASE_CROPPED_RAW capability additional guaranteed configurations</h5>
+ *
* <p>Devices that include the {@link CameraMetadata#SCALER_AVAILABLE_STREAM_USE_CASES_CROPPED_RAW}
* stream use-case in {@link CameraCharacteristics#SCALER_AVAILABLE_STREAM_USE_CASES},
* support the additional stream combinations below:
*
- * <h5>STREAM_USE_CASE_CROPPED_RAW capability additional guaranteed configurations</h5>
- *
* <table>
* <tr><th colspan="3" id="rb">Target 1</th><th colspan="3" id="rb">Target 2</th><th colspan="3" id="rb">Target 3</th> <th rowspan="2">Sample use case(s)</th> </tr>
* <tr><th>Type</th><th id="rb">Max size</th><th>Usecase</th><th>Type</th><th id="rb">Max size</th><th>Usecase</th><th>Type</th><th id="rb">Max size</th><th>Usecase</th> </tr>
@@ -926,15 +936,17 @@ public abstract class CameraDevice implements AutoCloseable {
* <tr> <td>{@code PRIV / YUV}</td><td id="rb">{@code PREVIEW}</td><td id="rb">{@code PREVIEW}</td> <td>{@code RAW}</td><td id="rb">{@code MAXIMUM}</td><td id="rb">{@code CROPPED_RAW}</td> <td colspan="3" id="rb"></td> <td>Preview with cropped RAW still capture</td> </tr>
* <tr> <td>{@code PRIV / YUV}</td><td id="rb">{@code PREVIEW}</td><td id="rb">{@code PREVIEW}</td> <td>{@code YUV / JPEG}</td><td id="rb">{@code MAXIMUM}</td><td id="rb">{@code STILL_CAPTURE}</td> <td>{@code RAW}</td><td id="rb">{@code MAXIMUM}</td><td id="rb">{@code CROPPED_RAW}</td> <td>Preview with YUV / JPEG and cropped RAW still capture</td> </tr>
* <tr> <td>{@code PRIV / YUV}</td><td id="rb">{@code PREVIEW}</td><td id="rb">{@code PREVIEW}</td> <td>{@code PRIV / YUV}</td><td id="rb">{@code PREVIEW}</td><td id="rb">{@code VIDEO_RECORD / PREVIEW}</td> <td>{@code RAW}</td><td id="rb">{@code MAXIMUM}</td><td id="rb">{@code CROPPED_RAW}</td> <td>Video recording with preview and cropped RAW still capture</td> </tr>
+ * </table><br>
+ * </p>
*
+ * <h5>Preview stabilization guaranteed stream configurations</h5>
*
- *<p> For devices where {@link CameraCharacteristics#CONTROL_AVAILABLE_VIDEO_STABILIZATION_MODES}
- * includes {@link CameraMetadata#CONTROL_VIDEO_STABILIZATION_MODE_PREVIEW_STABILIZATION},
+ * <p>For devices where
+ * {@link CameraCharacteristics#CONTROL_AVAILABLE_VIDEO_STABILIZATION_MODES} includes
+ * {@link CameraMetadata#CONTROL_VIDEO_STABILIZATION_MODE_PREVIEW_STABILIZATION},
* the following stream combinations are guaranteed,
* for CaptureRequests where {@link CaptureRequest#CONTROL_VIDEO_STABILIZATION_MODE} is set to
- * {@link CameraMetadata#CONTROL_VIDEO_STABILIZATION_MODE_PREVIEW_STABILIZATION} <p>
- *
- * <h5>Preview stabilization guaranteed stream configurations</h5>
+ * {@link CameraMetadata#CONTROL_VIDEO_STABILIZATION_MODE_PREVIEW_STABILIZATION}
*
* <table>
* <tr><th colspan="2" id="rb">Target 1</th><th colspan="2" id="rb">Target 2</th><th rowspan="2">Sample use case(s)</th> </tr>
@@ -943,6 +955,8 @@ public abstract class CameraDevice implements AutoCloseable {
* <tr> <td>{@code PRIV / YUV}</td><td id="rb">{@code s1440p}</td> <td>{@code JPEG / YUV}</td><td id="rb">{@code MAXIMUM }</td><td>Standard still imaging with stabilized preview.</td> </tr>
* <tr> <td>{@code PRIV / YUV}</td><td id="rb">{@code PREVIEW}</td> <td>{@code PRIV / YUV}</td><td id="rb">{@code s1440p }</td><td>High-resolution recording with stabilized preview and recording stream.</td> </tr>
* </table><br>
+ * </p>
+ *
* <p>
* For the maximum size column, PREVIEW refers to the best size match to the device's screen
* resolution, or to 1080p (1920x1080), whichever is smaller. RECORD refers to the camera
diff --git a/core/java/android/inputmethodservice/InputMethodService.java b/core/java/android/inputmethodservice/InputMethodService.java
index c0a44b178b66..f1ae9be8528d 100644
--- a/core/java/android/inputmethodservice/InputMethodService.java
+++ b/core/java/android/inputmethodservice/InputMethodService.java
@@ -890,10 +890,13 @@ public class InputMethodService extends AbstractInputMethodService {
mSystemCallingHideSoftInput = true;
mCurHideInputToken = hideInputToken;
mCurStatsToken = statsToken;
- hideSoftInput(flags, resultReceiver);
- mCurStatsToken = null;
- mCurHideInputToken = null;
- mSystemCallingHideSoftInput = false;
+ try {
+ hideSoftInput(flags, resultReceiver);
+ } finally {
+ mCurStatsToken = null;
+ mCurHideInputToken = null;
+ mSystemCallingHideSoftInput = false;
+ }
}
/**
diff --git a/core/java/android/inputmethodservice/NavigationBarController.java b/core/java/android/inputmethodservice/NavigationBarController.java
index c01664e55744..8be4c5858694 100644
--- a/core/java/android/inputmethodservice/NavigationBarController.java
+++ b/core/java/android/inputmethodservice/NavigationBarController.java
@@ -237,7 +237,7 @@ final class NavigationBarController {
mNavigationBarFrame.setOnApplyWindowInsetsListener((view, insets) -> {
if (mNavigationBarFrame != null) {
boolean visible = insets.isVisible(captionBar());
- mNavigationBarFrame.setVisibility(visible ? View.VISIBLE : View.INVISIBLE);
+ mNavigationBarFrame.setVisibility(visible ? View.VISIBLE : View.GONE);
}
return view.onApplyWindowInsets(insets);
});
diff --git a/location/java/android/location/GeocoderParams.java b/core/java/android/location/GeocoderParams.java
index 3ea6364e07c5..3ea6364e07c5 100644
--- a/location/java/android/location/GeocoderParams.java
+++ b/core/java/android/location/GeocoderParams.java
diff --git a/location/java/android/location/Geofence.java b/core/java/android/location/Geofence.java
index 10773f82fa43..10773f82fa43 100644
--- a/location/java/android/location/Geofence.java
+++ b/core/java/android/location/Geofence.java
diff --git a/location/java/android/location/GnssSignalQuality.java b/core/java/android/location/GnssSignalQuality.java
index 7945f3ecf841..7945f3ecf841 100644
--- a/location/java/android/location/GnssSignalQuality.java
+++ b/core/java/android/location/GnssSignalQuality.java
diff --git a/location/java/android/location/IFusedGeofenceHardware.aidl b/core/java/android/location/IFusedGeofenceHardware.aidl
index d8c35851b160..d8c35851b160 100644
--- a/location/java/android/location/IFusedGeofenceHardware.aidl
+++ b/core/java/android/location/IFusedGeofenceHardware.aidl
diff --git a/location/java/android/location/IGpsGeofenceHardware.aidl b/core/java/android/location/IGpsGeofenceHardware.aidl
index 764bf8e86fc2..764bf8e86fc2 100644
--- a/location/java/android/location/IGpsGeofenceHardware.aidl
+++ b/core/java/android/location/IGpsGeofenceHardware.aidl
diff --git a/location/java/android/location/Location.aidl b/core/java/android/location/Location.aidl
index f47b4886e3c0..f47b4886e3c0 100644
--- a/location/java/android/location/Location.aidl
+++ b/core/java/android/location/Location.aidl
diff --git a/location/java/android/location/Location.java b/core/java/android/location/Location.java
index 0eb657aba033..fd3e5a22e969 100644
--- a/location/java/android/location/Location.java
+++ b/core/java/android/location/Location.java
@@ -709,11 +709,9 @@ public class Location implements Parcelable {
/**
* Returns the Mean Sea Level altitude of this location in meters.
*
- * @throws IllegalStateException if {@link #hasMslAltitude()} is false.
+ * <p>This is only valid if {@link #hasMslAltitude()} is true.
*/
public @FloatRange double getMslAltitudeMeters() {
- Preconditions.checkState(hasMslAltitude(),
- "The Mean Sea Level altitude of this location is not set.");
return mMslAltitudeMeters;
}
@@ -744,11 +742,9 @@ public class Location implements Parcelable {
* percentile confidence level. This means that there is 68% chance that the true Mean Sea Level
* altitude of this location falls within {@link #getMslAltitudeMeters()} +/- this uncertainty.
*
- * @throws IllegalStateException if {@link #hasMslAltitudeAccuracy()} is false.
+ * <p>This is only valid if {@link #hasMslAltitudeAccuracy()} is true.
*/
public @FloatRange(from = 0.0) float getMslAltitudeAccuracyMeters() {
- Preconditions.checkState(hasMslAltitudeAccuracy(),
- "The Mean Sea Level altitude accuracy of this location is not set.");
return mMslAltitudeAccuracyMeters;
}
diff --git a/location/java/android/location/LocationTime.java b/core/java/android/location/LocationTime.java
index 2f03508fbb15..2f03508fbb15 100644
--- a/location/java/android/location/LocationTime.java
+++ b/core/java/android/location/LocationTime.java
diff --git a/core/java/android/os/AggregateBatteryConsumer.java b/core/java/android/os/AggregateBatteryConsumer.java
index 7a153ef9c6f3..c5f56144c29c 100644
--- a/core/java/android/os/AggregateBatteryConsumer.java
+++ b/core/java/android/os/AggregateBatteryConsumer.java
@@ -116,8 +116,9 @@ public final class AggregateBatteryConsumer extends BatteryConsumer {
* Builder for DeviceBatteryConsumer.
*/
public static final class Builder extends BaseBuilder<AggregateBatteryConsumer.Builder> {
- public Builder(BatteryConsumer.BatteryConsumerData data, int scope) {
- super(data, CONSUMER_TYPE_AGGREGATE);
+ public Builder(BatteryConsumer.BatteryConsumerData data, int scope,
+ double minConsumedPowerThreshold) {
+ super(data, CONSUMER_TYPE_AGGREGATE, minConsumedPowerThreshold);
data.putInt(COLUMN_INDEX_SCOPE, scope);
}
diff --git a/core/java/android/os/BatteryConsumer.java b/core/java/android/os/BatteryConsumer.java
index 0ba8d51e820f..ca84b3563561 100644
--- a/core/java/android/os/BatteryConsumer.java
+++ b/core/java/android/os/BatteryConsumer.java
@@ -795,11 +795,12 @@ public abstract class BatteryConsumer {
protected final BatteryConsumer.BatteryConsumerData mData;
protected final PowerComponents.Builder mPowerComponentsBuilder;
- public BaseBuilder(BatteryConsumer.BatteryConsumerData data, int consumerType) {
+ public BaseBuilder(BatteryConsumer.BatteryConsumerData data, int consumerType,
+ double minConsumedPowerThreshold) {
mData = data;
data.putLong(COLUMN_INDEX_BATTERY_CONSUMER_TYPE, consumerType);
- mPowerComponentsBuilder = new PowerComponents.Builder(data);
+ mPowerComponentsBuilder = new PowerComponents.Builder(data, minConsumedPowerThreshold);
}
@Nullable
diff --git a/core/java/android/os/BatteryUsageStats.java b/core/java/android/os/BatteryUsageStats.java
index 7586bf7700d9..a5f8844a2921 100644
--- a/core/java/android/os/BatteryUsageStats.java
+++ b/core/java/android/os/BatteryUsageStats.java
@@ -707,7 +707,7 @@ public final class BatteryUsageStats implements Parcelable, Closeable {
XML_ATTR_PREFIX_INCLUDES_PROC_STATE_DATA, false);
builder = new Builder(customComponentNames.toArray(new String[0]), true,
- includesProcStateData);
+ includesProcStateData, 0);
builder.setStatsStartTimestamp(
parser.getAttributeLong(null, XML_ATTR_START_TIMESTAMP));
@@ -782,6 +782,7 @@ public final class BatteryUsageStats implements Parcelable, Closeable {
private final String[] mCustomPowerComponentNames;
private final boolean mIncludePowerModels;
private final boolean mIncludesProcessStateData;
+ private final double mMinConsumedPowerThreshold;
private final BatteryConsumer.BatteryConsumerDataLayout mBatteryConsumerDataLayout;
private long mStatsStartTimestampMs;
private long mStatsEndTimestampMs;
@@ -802,11 +803,11 @@ public final class BatteryUsageStats implements Parcelable, Closeable {
private BatteryStatsHistory mBatteryStatsHistory;
public Builder(@NonNull String[] customPowerComponentNames) {
- this(customPowerComponentNames, false, false);
+ this(customPowerComponentNames, false, false, 0);
}
public Builder(@NonNull String[] customPowerComponentNames, boolean includePowerModels,
- boolean includeProcessStateData) {
+ boolean includeProcessStateData, double minConsumedPowerThreshold) {
mBatteryConsumersCursorWindow =
new CursorWindow(null, BATTERY_CONSUMER_CURSOR_WINDOW_SIZE);
mBatteryConsumerDataLayout =
@@ -817,12 +818,14 @@ public final class BatteryUsageStats implements Parcelable, Closeable {
mCustomPowerComponentNames = customPowerComponentNames;
mIncludePowerModels = includePowerModels;
mIncludesProcessStateData = includeProcessStateData;
+ mMinConsumedPowerThreshold = minConsumedPowerThreshold;
for (int scope = 0; scope < AGGREGATE_BATTERY_CONSUMER_SCOPE_COUNT; scope++) {
final BatteryConsumer.BatteryConsumerData data =
BatteryConsumer.BatteryConsumerData.create(mBatteryConsumersCursorWindow,
mBatteryConsumerDataLayout);
mAggregateBatteryConsumersBuilders[scope] =
- new AggregateBatteryConsumer.Builder(data, scope);
+ new AggregateBatteryConsumer.Builder(
+ data, scope, mMinConsumedPowerThreshold);
}
}
@@ -961,7 +964,8 @@ public final class BatteryUsageStats implements Parcelable, Closeable {
final BatteryConsumer.BatteryConsumerData data =
BatteryConsumer.BatteryConsumerData.create(mBatteryConsumersCursorWindow,
mBatteryConsumerDataLayout);
- builder = new UidBatteryConsumer.Builder(data, batteryStatsUid);
+ builder = new UidBatteryConsumer.Builder(data, batteryStatsUid,
+ mMinConsumedPowerThreshold);
mUidBatteryConsumerBuilders.put(uid, builder);
}
return builder;
@@ -979,7 +983,7 @@ public final class BatteryUsageStats implements Parcelable, Closeable {
final BatteryConsumer.BatteryConsumerData data =
BatteryConsumer.BatteryConsumerData.create(mBatteryConsumersCursorWindow,
mBatteryConsumerDataLayout);
- builder = new UidBatteryConsumer.Builder(data, uid);
+ builder = new UidBatteryConsumer.Builder(data, uid, mMinConsumedPowerThreshold);
mUidBatteryConsumerBuilders.put(uid, builder);
}
return builder;
@@ -996,7 +1000,7 @@ public final class BatteryUsageStats implements Parcelable, Closeable {
final BatteryConsumer.BatteryConsumerData data =
BatteryConsumer.BatteryConsumerData.create(mBatteryConsumersCursorWindow,
mBatteryConsumerDataLayout);
- builder = new UserBatteryConsumer.Builder(data, userId);
+ builder = new UserBatteryConsumer.Builder(data, userId, mMinConsumedPowerThreshold);
mUserBatteryConsumerBuilders.put(userId, builder);
}
return builder;
diff --git a/core/java/android/os/BatteryUsageStatsQuery.java b/core/java/android/os/BatteryUsageStatsQuery.java
index b3f4d9874f4e..49d7e8bc5632 100644
--- a/core/java/android/os/BatteryUsageStatsQuery.java
+++ b/core/java/android/os/BatteryUsageStatsQuery.java
@@ -80,6 +80,7 @@ public final class BatteryUsageStatsQuery implements Parcelable {
private final long mMaxStatsAgeMs;
private final long mFromTimestamp;
private final long mToTimestamp;
+ private final double mMinConsumedPowerThreshold;
private final @BatteryConsumer.PowerComponent int[] mPowerComponents;
private BatteryUsageStatsQuery(@NonNull Builder builder) {
@@ -87,6 +88,7 @@ public final class BatteryUsageStatsQuery implements Parcelable {
mUserIds = builder.mUserIds != null ? builder.mUserIds.toArray()
: new int[]{UserHandle.USER_ALL};
mMaxStatsAgeMs = builder.mMaxStatsAgeMs;
+ mMinConsumedPowerThreshold = builder.mMinConsumedPowerThreshold;
mFromTimestamp = builder.mFromTimestamp;
mToTimestamp = builder.mToTimestamp;
mPowerComponents = builder.mPowerComponents;
@@ -137,6 +139,14 @@ public final class BatteryUsageStatsQuery implements Parcelable {
}
/**
+ * Returns the minimal power component consumed power threshold. The small power consuming
+ * components will be reported as zero.
+ */
+ public double getMinConsumedPowerThreshold() {
+ return mMinConsumedPowerThreshold;
+ }
+
+ /**
* Returns the exclusive lower bound of the stored snapshot timestamps that should be included
* in the aggregation. Ignored if {@link #getToTimestamp()} is zero.
*/
@@ -158,6 +168,7 @@ public final class BatteryUsageStatsQuery implements Parcelable {
mUserIds = new int[in.readInt()];
in.readIntArray(mUserIds);
mMaxStatsAgeMs = in.readLong();
+ mMinConsumedPowerThreshold = in.readDouble();
mFromTimestamp = in.readLong();
mToTimestamp = in.readLong();
mPowerComponents = in.createIntArray();
@@ -169,6 +180,7 @@ public final class BatteryUsageStatsQuery implements Parcelable {
dest.writeInt(mUserIds.length);
dest.writeIntArray(mUserIds);
dest.writeLong(mMaxStatsAgeMs);
+ dest.writeDouble(mMinConsumedPowerThreshold);
dest.writeLong(mFromTimestamp);
dest.writeLong(mToTimestamp);
dest.writeIntArray(mPowerComponents);
@@ -202,6 +214,7 @@ public final class BatteryUsageStatsQuery implements Parcelable {
private long mMaxStatsAgeMs = DEFAULT_MAX_STATS_AGE_MS;
private long mFromTimestamp;
private long mToTimestamp;
+ private double mMinConsumedPowerThreshold = 0;
private @BatteryConsumer.PowerComponent int[] mPowerComponents;
/**
@@ -301,5 +314,14 @@ public final class BatteryUsageStatsQuery implements Parcelable {
mMaxStatsAgeMs = maxStatsAgeMs;
return this;
}
+
+ /**
+ * Set the minimal power component consumed power threshold. The small power consuming
+ * components will be reported as zero.
+ */
+ public Builder setMinConsumedPowerThreshold(double minConsumedPowerThreshold) {
+ mMinConsumedPowerThreshold = minConsumedPowerThreshold;
+ return this;
+ }
}
}
diff --git a/core/java/android/os/BugreportParams.java b/core/java/android/os/BugreportParams.java
index 0456a33580cf..f10467f0760e 100644
--- a/core/java/android/os/BugreportParams.java
+++ b/core/java/android/os/BugreportParams.java
@@ -18,6 +18,7 @@ package android.os;
import android.annotation.IntDef;
import android.annotation.SystemApi;
+import android.annotation.TestApi;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -127,6 +128,13 @@ public final class BugreportParams {
public static final int BUGREPORT_MODE_ONBOARDING = IDumpstate.BUGREPORT_MODE_ONBOARDING;
/**
+ * The maximum value of supported bugreport mode.
+ * @hide
+ */
+ @TestApi
+ public static final int BUGREPORT_MODE_MAX_VALUE = BUGREPORT_MODE_ONBOARDING;
+
+ /**
* Defines acceptable flags for customizing bugreport requests.
* @hide
*/
diff --git a/core/java/android/os/IVibratorManagerService.aidl b/core/java/android/os/IVibratorManagerService.aidl
index 62753527929c..f30dd20d7087 100644
--- a/core/java/android/os/IVibratorManagerService.aidl
+++ b/core/java/android/os/IVibratorManagerService.aidl
@@ -36,4 +36,10 @@ interface IVibratorManagerService {
void vibrate(int uid, int displayId, String opPkg, in CombinedVibration vibration,
in VibrationAttributes attributes, String reason, IBinder token);
void cancelVibrate(int usageFilter, IBinder token);
+
+ // Async oneway APIs.
+ // There is no order guarantee with respect to the two-way APIs above like
+ // vibrate/isVibrating/cancel.
+ oneway void performHapticFeedback(int uid, int displayId, String opPkg, int constant,
+ boolean always, String reason, IBinder token);
}
diff --git a/core/java/android/os/PowerComponents.java b/core/java/android/os/PowerComponents.java
index 5dffa0a0ac34..9e5f5399301c 100644
--- a/core/java/android/os/PowerComponents.java
+++ b/core/java/android/os/PowerComponents.java
@@ -461,9 +461,11 @@ class PowerComponents {
private static final byte POWER_MODEL_UNINITIALIZED = -1;
private final BatteryConsumer.BatteryConsumerData mData;
+ private final double mMinConsumedPowerThreshold;
- Builder(BatteryConsumer.BatteryConsumerData data) {
+ Builder(BatteryConsumer.BatteryConsumerData data, double minConsumedPowerThreshold) {
mData = data;
+ mMinConsumedPowerThreshold = minConsumedPowerThreshold;
for (BatteryConsumer.Key[] keys : mData.layout.keys) {
for (BatteryConsumer.Key key : keys) {
if (key.mPowerModelColumnIndex != -1) {
@@ -476,6 +478,9 @@ class PowerComponents {
@NonNull
public Builder setConsumedPower(BatteryConsumer.Key key, double componentPower,
int powerModel) {
+ if (Math.abs(componentPower) < mMinConsumedPowerThreshold) {
+ componentPower = 0;
+ }
mData.putDouble(key.mPowerColumnIndex, componentPower);
if (key.mPowerModelColumnIndex != -1) {
mData.putInt(key.mPowerModelColumnIndex, powerModel);
@@ -491,6 +496,9 @@ class PowerComponents {
*/
@NonNull
public Builder setConsumedPowerForCustomComponent(int componentId, double componentPower) {
+ if (Math.abs(componentPower) < mMinConsumedPowerThreshold) {
+ componentPower = 0;
+ }
final int index = componentId - BatteryConsumer.FIRST_CUSTOM_POWER_COMPONENT_ID;
if (index < 0 || index >= mData.layout.customPowerComponentCount) {
throw new IllegalArgumentException(
diff --git a/core/java/android/os/SystemVibrator.java b/core/java/android/os/SystemVibrator.java
index 1cd0f3b156c2..04c257b92e29 100644
--- a/core/java/android/os/SystemVibrator.java
+++ b/core/java/android/os/SystemVibrator.java
@@ -206,6 +206,15 @@ public class SystemVibrator extends Vibrator {
}
@Override
+ public void performHapticFeedback(int constant, boolean always, String reason) {
+ if (mVibratorManager == null) {
+ Log.w(TAG, "Failed to perform haptic feedback; no vibrator manager.");
+ return;
+ }
+ mVibratorManager.performHapticFeedback(constant, always, reason);
+ }
+
+ @Override
public void cancel() {
if (mVibratorManager == null) {
Log.w(TAG, "Failed to cancel vibrate; no vibrator manager.");
diff --git a/core/java/android/os/SystemVibratorManager.java b/core/java/android/os/SystemVibratorManager.java
index 284b2464c468..ee90834c15ef 100644
--- a/core/java/android/os/SystemVibratorManager.java
+++ b/core/java/android/os/SystemVibratorManager.java
@@ -145,6 +145,21 @@ public class SystemVibratorManager extends VibratorManager {
}
@Override
+ public void performHapticFeedback(int constant, boolean always, String reason) {
+ if (mService == null) {
+ Log.w(TAG, "Failed to perform haptic feedback; no vibrator manager service.");
+ return;
+ }
+ try {
+ mService.performHapticFeedback(
+ Process.myUid(), mContext.getAssociatedDisplayId(), mPackageName, constant,
+ always, reason, mToken);
+ } catch (RemoteException e) {
+ Log.w(TAG, "Failed to perform haptic feedback.", e);
+ }
+ }
+
+ @Override
public void cancel() {
cancelVibration(VibrationAttributes.USAGE_FILTER_MATCH_ALL);
}
@@ -228,6 +243,11 @@ public class SystemVibratorManager extends VibratorManager {
}
@Override
+ public void performHapticFeedback(int effectId, boolean always, String reason) {
+ SystemVibratorManager.this.performHapticFeedback(effectId, always, reason);
+ }
+
+ @Override
public void cancel() {
SystemVibratorManager.this.cancel();
}
diff --git a/core/java/android/os/UidBatteryConsumer.java b/core/java/android/os/UidBatteryConsumer.java
index 103452d255a7..03a1b6f7fe01 100644
--- a/core/java/android/os/UidBatteryConsumer.java
+++ b/core/java/android/os/UidBatteryConsumer.java
@@ -207,17 +207,18 @@ public final class UidBatteryConsumer extends BatteryConsumer {
private String mPackageWithHighestDrain = PACKAGE_NAME_UNINITIALIZED;
private boolean mExcludeFromBatteryUsageStats;
- public Builder(BatteryConsumerData data, @NonNull BatteryStats.Uid batteryStatsUid) {
- this(data, batteryStatsUid, batteryStatsUid.getUid());
+ public Builder(BatteryConsumerData data, @NonNull BatteryStats.Uid batteryStatsUid,
+ double minConsumedPowerThreshold) {
+ this(data, batteryStatsUid, batteryStatsUid.getUid(), minConsumedPowerThreshold);
}
- public Builder(BatteryConsumerData data, int uid) {
- this(data, null, uid);
+ public Builder(BatteryConsumerData data, int uid, double minConsumedPowerThreshold) {
+ this(data, null, uid, minConsumedPowerThreshold);
}
private Builder(BatteryConsumerData data, @Nullable BatteryStats.Uid batteryStatsUid,
- int uid) {
- super(data, CONSUMER_TYPE_UID);
+ int uid, double minConsumedPowerThreshold) {
+ super(data, CONSUMER_TYPE_UID, minConsumedPowerThreshold);
mBatteryStatsUid = batteryStatsUid;
mUid = uid;
mIsVirtualUid = mUid == Process.SDK_SANDBOX_VIRTUAL_UID;
diff --git a/core/java/android/os/UserBatteryConsumer.java b/core/java/android/os/UserBatteryConsumer.java
index 6b4a5cfc836f..a2ff078263ca 100644
--- a/core/java/android/os/UserBatteryConsumer.java
+++ b/core/java/android/os/UserBatteryConsumer.java
@@ -107,8 +107,8 @@ public class UserBatteryConsumer extends BatteryConsumer {
public static final class Builder extends BaseBuilder<Builder> {
private List<UidBatteryConsumer.Builder> mUidBatteryConsumers;
- Builder(BatteryConsumerData data, int userId) {
- super(data, CONSUMER_TYPE_USER);
+ Builder(BatteryConsumerData data, int userId, double minConsumedPowerThreshold) {
+ super(data, CONSUMER_TYPE_USER, minConsumedPowerThreshold);
data.putLong(COLUMN_INDEX_USER_ID, userId);
}
diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java
index bcde31acda2e..c6cb604d4039 100644
--- a/core/java/android/os/UserManager.java
+++ b/core/java/android/os/UserManager.java
@@ -1002,6 +1002,24 @@ public class UserManager {
public static final String DISALLOW_ADD_CLONE_PROFILE = "no_add_clone_profile";
/**
+ * Specifies if a user is disallowed from creating a private profile.
+ * <p>The default value for an unmanaged user is <code>false</code>.
+ * For users with a device owner set, the default is <code>true</code>.
+ *
+ * <p>Holders of the permission
+ * {@link android.Manifest.permission#MANAGE_DEVICE_POLICY_PROFILES}
+ * can set this restriction using the DevicePolicyManager APIs mentioned below.
+ *
+ * <p>Key for user restrictions.
+ * <p>Type: Boolean
+ * @see DevicePolicyManager#addUserRestriction(ComponentName, String)
+ * @see DevicePolicyManager#clearUserRestriction(ComponentName, String)
+ * @see #getUserRestrictions()
+ * @hide
+ */
+ public static final String DISALLOW_ADD_PRIVATE_PROFILE = "no_add_private_profile";
+
+ /**
* Specifies if a user is disallowed from disabling application verification. The default
* value is <code>false</code>.
*
@@ -1895,6 +1913,7 @@ public class UserManager {
DISALLOW_ADD_USER,
DISALLOW_ADD_MANAGED_PROFILE,
DISALLOW_ADD_CLONE_PROFILE,
+ DISALLOW_ADD_PRIVATE_PROFILE,
ENSURE_VERIFY_APPS,
DISALLOW_CONFIG_CELL_BROADCASTS,
DISALLOW_CONFIG_MOBILE_NETWORKS,
diff --git a/core/java/android/os/Vibrator.java b/core/java/android/os/Vibrator.java
index aafa5018af10..99c9925d9cb7 100644
--- a/core/java/android/os/Vibrator.java
+++ b/core/java/android/os/Vibrator.java
@@ -510,6 +510,28 @@ public abstract class Vibrator {
String reason, @NonNull VibrationAttributes attributes);
/**
+ * Performs a haptic feedback.
+ *
+ * <p>A haptic feedback is a short vibration feedback. The type of feedback is identified via
+ * the {@code constant}, which should be one of the effect constants provided in
+ * {@link HapticFeedbackConstants}. The haptic feedback provided for a given effect ID is
+ * consistent across all usages on the same device.
+ *
+ * @param constant the ID for the haptic feedback. This should be one of the constants defined
+ * in {@link HapticFeedbackConstants}.
+ * @param always {@code true} if the haptic feedback should be played regardless of the user
+ * vibration intensity settings applicable to the corresponding vibration.
+ * {@code false} if the vibration for the haptic feedback should respect the applicable
+ * vibration intensity settings.
+ * @param reason the reason for this haptic feedback.
+ *
+ * @hide
+ */
+ public void performHapticFeedback(int constant, boolean always, String reason) {
+ Log.w(TAG, "performHapticFeedback is not supported");
+ }
+
+ /**
* Query whether the vibrator natively supports the given effects.
*
* <p>If an effect is not supported, the system may still automatically fall back to playing
diff --git a/core/java/android/os/VibratorManager.java b/core/java/android/os/VibratorManager.java
index f506ef8955d4..e0b6a9fd28f0 100644
--- a/core/java/android/os/VibratorManager.java
+++ b/core/java/android/os/VibratorManager.java
@@ -35,7 +35,8 @@ import android.util.Log;
public abstract class VibratorManager {
private static final String TAG = "VibratorManager";
- private final String mPackageName;
+ /** @hide */
+ protected final String mPackageName;
/**
* @hide to prevent subclassing from outside of the framework
@@ -137,6 +138,21 @@ public abstract class VibratorManager {
String reason, @Nullable VibrationAttributes attributes);
/**
+ * Performs a haptic feedback.
+ *
+ * @param constant the ID of the requested haptic feedback. Should be one of the constants
+ * defined in {@link HapticFeedbackConstants}.
+ * @param always {@code true} if the haptic feedback should be played regardless of the user
+ * vibration intensity settings applicable to the corresponding vibration.
+ * {@code false} otherwise.
+ * @param reason the reason for this haptic feedback.
+ * @hide
+ */
+ public void performHapticFeedback(int constant, boolean always, String reason) {
+ Log.w(TAG, "performHapticFeedback is not supported");
+ }
+
+ /**
* Turn all the vibrators off.
*/
@RequiresPermission(android.Manifest.permission.VIBRATE)
diff --git a/core/java/android/os/vibrator/flags.aconfig b/core/java/android/os/vibrator/flags.aconfig
new file mode 100644
index 000000000000..c01ef3d79bb9
--- /dev/null
+++ b/core/java/android/os/vibrator/flags.aconfig
@@ -0,0 +1,15 @@
+package: "android.os.vibrator"
+
+flag {
+ namespace: "haptics"
+ name: "use_vibrator_haptic_feedback"
+ description: "Enables performHapticFeedback to directly use the vibrator service instead of going through the window session"
+ bug: "295459081"
+}
+
+flag {
+ namespace: "haptics"
+ name: "haptics_customization_enabled"
+ description: "Enables the haptics customization feature"
+ bug: "241918098"
+} \ No newline at end of file
diff --git a/core/java/android/os/vibrator/persistence/ParsedVibration.java b/core/java/android/os/vibrator/persistence/ParsedVibration.java
index a76f597252ec..ded74eab149e 100644
--- a/core/java/android/os/vibrator/persistence/ParsedVibration.java
+++ b/core/java/android/os/vibrator/persistence/ParsedVibration.java
@@ -70,7 +70,7 @@ public class ParsedVibration {
@TestApi
@VisibleForTesting
@NonNull
- public List<VibrationEffect> getVibrationEffectListForTesting() {
+ public List<VibrationEffect> getVibrationEffects() {
return Collections.unmodifiableList(mEffects);
}
diff --git a/core/java/android/permission/PermissionUsageHelper.java b/core/java/android/permission/PermissionUsageHelper.java
index 2a4c01e1c46e..1f798baf1bd6 100644
--- a/core/java/android/permission/PermissionUsageHelper.java
+++ b/core/java/android/permission/PermissionUsageHelper.java
@@ -87,11 +87,6 @@ public class PermissionUsageHelper implements AppOpsManager.OnOpActiveChangedLis
"location_indicators_enabled";
/**
- * Whether to show the Permissions Hub.
- */
- private static final String PROPERTY_PERMISSIONS_HUB_2_ENABLED = "permissions_hub_2_enabled";
-
- /**
* How long after an access to show it as "recent"
*/
private static final String RECENT_ACCESS_TIME_MS = "recent_access_time_ms";
@@ -106,14 +101,9 @@ public class PermissionUsageHelper implements AppOpsManager.OnOpActiveChangedLis
private static final long DEFAULT_RUNNING_TIME_MS = 5000L;
private static final long DEFAULT_RECENT_TIME_MS = 15000L;
- private static boolean shouldShowPermissionsHub() {
- return DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_PRIVACY,
- PROPERTY_PERMISSIONS_HUB_2_ENABLED, false);
- }
-
private static boolean shouldShowIndicators() {
return DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_PRIVACY,
- PROPERTY_CAMERA_MIC_ICONS_ENABLED, true) || shouldShowPermissionsHub();
+ PROPERTY_CAMERA_MIC_ICONS_ENABLED, true);
}
private static boolean shouldShowLocationIndicator() {
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 522caac9f627..f823dbcec7f2 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -2831,7 +2831,7 @@ public final class Settings {
/** @hide - Private call() method to query the 'global' table */
public static final String CALL_METHOD_LIST_GLOBAL = "LIST_global";
- /** @hide - Private call() method to reset to defaults the 'configuration' table */
+ /** @hide - Private call() method to query the 'configuration' table */
public static final String CALL_METHOD_LIST_CONFIG = "LIST_config";
/** @hide - Private call() method to disable / re-enable syncs to the 'configuration' table */
@@ -4871,13 +4871,13 @@ public final class Settings {
public static final String PEAK_REFRESH_RATE = "peak_refresh_rate";
/**
- * Control whether to stay awake on fold
+ * Control lock behavior on fold
*
* If this isn't set, the system falls back to a device specific default.
* @hide
*/
@Readable
- public static final String STAY_AWAKE_ON_FOLD = "stay_awake_on_fold";
+ public static final String FOLD_LOCK_BEHAVIOR = "fold_lock_behavior_setting";
/**
* The amount of time in milliseconds before the device goes to sleep or begins
@@ -5885,15 +5885,6 @@ public final class Settings {
public static final String MULTI_AUDIO_FOCUS_ENABLED = "multi_audio_focus_enabled";
/**
- * Whether desktop mode is enabled or not.
- * 0 = off
- * 1 = on
- * @hide
- */
- @Readable
- public static final String DESKTOP_MODE = "desktop_mode";
-
- /**
* The information of locale preference. This records user's preference to avoid
* unsynchronized and existing locale preference in
* {@link Locale#getDefault(Locale.Category)}.
@@ -6066,7 +6057,6 @@ public final class Settings {
PRIVATE_SETTINGS.add(SHOW_BATTERY_PERCENT);
PRIVATE_SETTINGS.add(DISPLAY_COLOR_MODE);
PRIVATE_SETTINGS.add(DISPLAY_COLOR_MODE_VENDOR_HINT);
- PRIVATE_SETTINGS.add(DESKTOP_MODE);
PRIVATE_SETTINGS.add(LOCALE_PREFERENCES);
PRIVATE_SETTINGS.add(TOUCHPAD_POINTER_SPEED);
PRIVATE_SETTINGS.add(TOUCHPAD_NATURAL_SCROLLING);
@@ -10674,20 +10664,6 @@ public final class Settings {
"search_press_hold_nav_handle_enabled";
/**
- * Control whether Trust Agents are in active unlock or extend unlock mode.
- * @hide
- */
- @Readable
- public static final String TRUST_AGENTS_EXTEND_UNLOCK = "trust_agents_extend_unlock";
-
- /**
- * Control whether the screen locks when trust is lost.
- * @hide
- */
- @Readable
- public static final String LOCK_SCREEN_WHEN_TRUST_LOST = "lock_screen_when_trust_lost";
-
- /**
* Control whether Night display is currently activated.
* @hide
*/
@@ -18370,24 +18346,28 @@ public final class Settings {
* If hotword detection should be enabled.
* @hide
*/
+ @Readable(maxTargetSdk = Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
public static final String HOTWORD_DETECTION_ENABLED = "hotword_detection_enabled";
/**
* Whether Smart Replies are enabled within Wear.
* @hide
*/
+ @Readable(maxTargetSdk = Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
public static final String SMART_REPLIES_ENABLED = "smart_replies_enabled";
/**
* The default vibration pattern.
* @hide
*/
+ @Readable(maxTargetSdk = Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
public static final String DEFAULT_VIBRATION = "default_vibration";
/**
* If FLP should obtain location data from the paired device.
* @hide
*/
+ @Readable(maxTargetSdk = Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
public static final String OBTAIN_PAIRED_DEVICE_LOCATION =
"obtain_paired_device_location";
@@ -18395,6 +18375,7 @@ public final class Settings {
* The play store availability on companion phone.
* @hide
*/
+ @Readable(maxTargetSdk = Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
public static final String PHONE_PLAY_STORE_AVAILABILITY =
"phone_play_store_availability";
@@ -18410,6 +18391,7 @@ public final class Settings {
* Whether the bug report is enabled.
* @hide
*/
+ @Readable(maxTargetSdk = Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
public static final String BUG_REPORT = "bug_report";
// Possible bug report states
@@ -18422,12 +18404,14 @@ public final class Settings {
* The enabled/disabled state of the SmartIlluminate.
* @hide
*/
+ @Readable(maxTargetSdk = Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
public static final String SMART_ILLUMINATE_ENABLED = "smart_illuminate_enabled";
/**
* Whether automatic time is enabled on the watch.
* @hide
*/
+ @Readable(maxTargetSdk = Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
public static final String CLOCKWORK_AUTO_TIME = "clockwork_auto_time";
// Possible clockwork auto time states
@@ -18445,6 +18429,7 @@ public final class Settings {
* Whether automatic time zone is enabled on the watch.
* @hide
*/
+ @Readable(maxTargetSdk = Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
public static final String CLOCKWORK_AUTO_TIME_ZONE = "clockwork_auto_time_zone";
// Possible clockwork auto time zone states
@@ -18461,12 +18446,14 @@ public final class Settings {
* Whether 24 hour time format is enabled on the watch.
* @hide
*/
+ @Readable(maxTargetSdk = Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
public static final String CLOCKWORK_24HR_TIME = "clockwork_24hr_time";
/**
* Whether the auto wifi toggle setting is enabled.
* @hide
*/
+ @Readable(maxTargetSdk = Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
public static final String AUTO_WIFI = "auto_wifi";
// Possible force wifi on states
@@ -18486,6 +18473,7 @@ public final class Settings {
* wifi requirement until this time). The time is in millis since epoch.
* @hide
*/
+ @Readable(maxTargetSdk = Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
public static final String ALT_BYPASS_WIFI_REQUIREMENT_TIME_MILLIS =
"alt_bypass_wifi_requirement_time_millis";
@@ -18493,6 +18481,7 @@ public final class Settings {
* Whether the setup was skipped.
* @hide
*/
+ @Readable(maxTargetSdk = Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
public static final String SETUP_SKIPPED = "setup_skipped";
// Possible setup_skipped states
@@ -18507,6 +18496,7 @@ public final class Settings {
* The last requested call forwarding action.
* @hide
*/
+ @Readable(maxTargetSdk = Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
public static final String LAST_CALL_FORWARD_ACTION = "last_call_forward_action";
// Possible call forwarding actions
@@ -18519,22 +18509,31 @@ public final class Settings {
// Stem button settings.
/** @hide */
+ @Readable(maxTargetSdk = Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
public static final String STEM_1_TYPE = "STEM_1_TYPE";
/** @hide */
+ @Readable(maxTargetSdk = Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
public static final String STEM_1_DATA = "STEM_1_DATA";
/** @hide */
+ @Readable(maxTargetSdk = Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
public static final String STEM_1_DEFAULT_DATA = "STEM_1_DEFAULT_DATA";
/** @hide */
+ @Readable(maxTargetSdk = Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
public static final String STEM_2_TYPE = "STEM_2_TYPE";
/** @hide */
+ @Readable(maxTargetSdk = Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
public static final String STEM_2_DATA = "STEM_2_DATA";
/** @hide */
+ @Readable(maxTargetSdk = Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
public static final String STEM_2_DEFAULT_DATA = "STEM_2_DEFAULT_DATA";
/** @hide */
+ @Readable(maxTargetSdk = Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
public static final String STEM_3_TYPE = "STEM_3_TYPE";
/** @hide */
+ @Readable(maxTargetSdk = Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
public static final String STEM_3_DATA = "STEM_3_DATA";
/** @hide */
+ @Readable(maxTargetSdk = Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
public static final String STEM_3_DEFAULT_DATA = "STEM_3_DEFAULT_DATA";
// Stem types
@@ -18549,12 +18548,14 @@ public final class Settings {
* If the device should be muted when off body.
* @hide
*/
+ @Readable(maxTargetSdk = Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
public static final String MUTE_WHEN_OFF_BODY_ENABLED = "obtain_mute_when_off_body";
/**
* Wear OS version string.
* @hide
*/
+ @Readable(maxTargetSdk = Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
public static final String WEAR_OS_VERSION_STRING = "wear_os_version_string";
/**
@@ -18567,24 +18568,28 @@ public final class Settings {
* The android wear system version.
* @hide
*/
+ @Readable(maxTargetSdk = Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
public static final String ANDROID_WEAR_VERSION = "android_wear_version";
/**
* The wear system capabiltiies.
* @hide
*/
+ @Readable(maxTargetSdk = Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
public static final String SYSTEM_CAPABILITIES = "system_capabilities";
/**
* The android wear system edition.
* @hide
*/
+ @Readable(maxTargetSdk = Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
public static final String SYSTEM_EDITION = "android_wear_system_edition";
/**
* The Wear platform MR number.
* @hide
*/
+ @Readable(maxTargetSdk = Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
public static final String WEAR_PLATFORM_MR_NUMBER = "wear_platform_mr_number";
/**
@@ -18598,36 +18603,42 @@ public final class Settings {
* Whether ambient is currently enabled.
* @hide
*/
+ @Readable(maxTargetSdk = Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
public static final String AMBIENT_ENABLED = "ambient_enabled";
/**
* Whether ambient tilt to wake is enabled.
* @hide
*/
+ @Readable(maxTargetSdk = Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
public static final String AMBIENT_TILT_TO_WAKE = "ambient_tilt_to_wake";
/**
* Whether ambient low bit mode is enabled by developer options.
* @hide
*/
+ @Readable(maxTargetSdk = Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
public static final String AMBIENT_LOW_BIT_ENABLED_DEV = "ambient_low_bit_enabled_dev";
/**
* Whether ambient touch to wake is enabled.
* @hide
*/
+ @Readable(maxTargetSdk = Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
public static final String AMBIENT_TOUCH_TO_WAKE = "ambient_touch_to_wake";
/**
* Whether ambient tilt to bright is enabled.
* @hide
*/
+ @Readable(maxTargetSdk = Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
public static final String AMBIENT_TILT_TO_BRIGHT = "ambient_tilt_to_bright";
/**
* Whether touch and hold to edit WF is enabled
* @hide
*/
+ @Readable(maxTargetSdk = Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
public static final String GESTURE_TOUCH_AND_HOLD_WATCH_FACE_ENABLED =
"gesture_touch_and_hold_watchface_enabled";
@@ -18641,6 +18652,7 @@ public final class Settings {
* Whether bedtime mode is enabled.
* @hide
*/
+ @Readable(maxTargetSdk = Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
public static final String BEDTIME_MODE = "bedtime_mode";
/**
@@ -18652,31 +18664,35 @@ public final class Settings {
* Whether the current watchface is decomposable.
* @hide
*/
+ @Readable(maxTargetSdk = Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
public static final String DECOMPOSABLE_WATCHFACE = "current_watchface_decomposable";
/**
* Whether to force ambient when docked.
* @hide
*/
+ @Readable(maxTargetSdk = Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
public static final String AMBIENT_FORCE_WHEN_DOCKED = "ambient_force_when_docked";
/**
* Whether the ambient low bit mode is enabled.
* @hide
*/
+ @Readable(maxTargetSdk = Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
public static final String AMBIENT_LOW_BIT_ENABLED = "ambient_low_bit_enabled";
/**
* The timeout duration in minutes of ambient mode when plugged in.
* @hide
*/
+ @Readable(maxTargetSdk = Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
public static final String AMBIENT_PLUGGED_TIMEOUT_MIN = "ambient_plugged_timeout_min";
/**
* What OS does paired device has.
* @hide
*/
- @Readable
+ @Readable(maxTargetSdk = Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
public static final String PAIRED_DEVICE_OS_TYPE = "paired_device_os_type";
// Possible values of PAIRED_DEVICE_OS_TYPE
@@ -18709,6 +18725,7 @@ public final class Settings {
* The user's last setting for hfp client.
* @hide
*/
+ @Readable(maxTargetSdk = Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
public static final String USER_HFP_CLIENT_SETTING = "user_hfp_client_setting";
// Possible hfp client user setting values
@@ -18733,6 +18750,7 @@ public final class Settings {
* The companion App name.
* @hide
*/
+ @Readable(maxTargetSdk = Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
public static final String COMPANION_APP_NAME = "wear_companion_app_name";
/**
@@ -18740,18 +18758,21 @@ public final class Settings {
* wear. 1 for supporting, 0 for not supporting.
* @hide
*/
+ @Readable(maxTargetSdk = Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
public static final String ENABLE_ALL_LANGUAGES = "enable_all_languages";
/**
* The Locale (as language tag) the user chose at startup.
* @hide
*/
+ @Readable(maxTargetSdk = Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
public static final String SETUP_LOCALE = "setup_locale";
/**
* The version of oem setup present.
* @hide
*/
+ @Readable(maxTargetSdk = Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
public static final String OEM_SETUP_VERSION = "oem_setup_version";
/**
@@ -18797,6 +18818,7 @@ public final class Settings {
* -{@link BATTERY_SAVER_MODE_CUSTOM}
* @hide
*/
+ @Readable(maxTargetSdk = Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
public static final String BATTERY_SAVER_MODE = "battery_saver_mode";
/**
@@ -18829,6 +18851,7 @@ public final class Settings {
* The maximum ambient mode duration when an activity is allowed to auto resume.
* @hide
*/
+ @Readable(maxTargetSdk = Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
public static final String WEAR_ACTIVITY_AUTO_RESUME_TIMEOUT_MS =
"wear_activity_auto_resume_timeout_ms";
@@ -18844,6 +18867,7 @@ public final class Settings {
* If burn in protection is enabled.
* @hide
*/
+ @Readable(maxTargetSdk = Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
public static final String BURN_IN_PROTECTION_ENABLED = "burn_in_protection";
/**
@@ -18862,6 +18886,7 @@ public final class Settings {
* RIGHT_WRIST_ROTATION_0 = "2", RIGHT_WRIST_ROTATION_180 = "3"
* @hide
*/
+ @Readable(maxTargetSdk = Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
public static final String WRIST_ORIENTATION_MODE = "wear_wrist_orientation_mode";
/**
@@ -18900,6 +18925,7 @@ public final class Settings {
*
* @hide
*/
+ @Readable(maxTargetSdk = Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
public static final String CLOCKWORK_SYSUI_PACKAGE = "clockwork_sysui_package";
/**
@@ -18929,6 +18955,7 @@ public final class Settings {
* Whether the device has Wet Mode/ Touch Lock Mode enabled.
* @hide
*/
+ @Readable(maxTargetSdk = Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
public static final String WET_MODE_ON = "wet_mode_on";
/**
@@ -18947,6 +18974,7 @@ public final class Settings {
* Whether charging sounds are enabled.
* @hide
*/
+ @Readable(maxTargetSdk = Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
public static final String CHARGING_SOUNDS_ENABLED = "wear_charging_sounds_enabled";
/**
@@ -18955,6 +18983,7 @@ public final class Settings {
*
* @hide
*/
+ @Readable(maxTargetSdk = Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
public static final String DYNAMIC_COLOR_THEME_ENABLED = "dynamic_color_theme_enabled";
/**
@@ -19046,6 +19075,7 @@ public final class Settings {
* The key to indicate the data migration status on device upgrade in Wear Services.
* @hide
*/
+ @Readable(maxTargetSdk = Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
public static final String UPGRADE_DATA_MIGRATION_STATUS =
"upgrade_data_migration_status";
@@ -19096,17 +19126,20 @@ public final class Settings {
* The custom foreground color.
* @hide
*/
+ @Readable(maxTargetSdk = Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
public static final String CUSTOM_COLOR_FOREGROUND = "custom_foreground_color";
/**
* The custom background color.
* @hide
*/
+ @Readable(maxTargetSdk = Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
public static final String CUSTOM_COLOR_BACKGROUND = "custom_background_color";
/** The status of the phone switching process.
* @hide
*/
+ @Readable(maxTargetSdk = Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
public static final String PHONE_SWITCHING_STATUS = "phone_switching_status";
/**
@@ -19187,6 +19220,7 @@ public final class Settings {
* (0 = false, 1 = true)
* @hide
*/
+ @Readable(maxTargetSdk = Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
public static final String REDUCE_MOTION = "reduce_motion";
/**
@@ -19248,6 +19282,7 @@ public final class Settings {
* Controls the launcher ui mode on wearable devices.
* @hide
*/
+ @Readable(maxTargetSdk = Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
public static final String WEAR_LAUNCHER_UI_MODE = "wear_launcher_ui_mode";
/** Whether Wear Power Anomaly Service is enabled.
@@ -19374,6 +19409,36 @@ public final class Settings {
}
/**
+ * Return all stored flags.
+ *
+ * The keys take the form {@code namespace/flag}, and the values are the flag values.
+ *
+ * @hide
+ */
+ @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
+ @NonNull
+ public static Map<String, String> getAllStrings() {
+ HashMap<String, String> allFlags = new HashMap<String, String>();
+ try {
+ ContentResolver resolver = getContentResolver();
+ Bundle arg = new Bundle();
+ arg.putInt(Settings.CALL_METHOD_USER_KEY, resolver.getUserId());
+ IContentProvider cp = sProviderHolder.getProvider(resolver);
+ Bundle b = cp.call(resolver.getAttributionSource(),
+ sProviderHolder.mUri.getAuthority(), CALL_METHOD_LIST_CONFIG, null, arg);
+ if (b != null) {
+ Map<String, String> flagsToValues =
+ (HashMap) b.getSerializable(Settings.NameValueTable.VALUE,
+ java.util.HashMap.class);
+ allFlags.putAll(flagsToValues);
+ }
+ } catch (RemoteException e) {
+ Log.w(TAG, "Can't query configuration table for " + CONTENT_URI, e);
+ }
+ return allFlags;
+ }
+
+ /**
* Look up a list of names in the database, within the specified namespace.
*
* @param resolver to access the database with
diff --git a/core/java/android/security/FileIntegrityManager.java b/core/java/android/security/FileIntegrityManager.java
index 7869404c265f..132700d289b8 100644
--- a/core/java/android/security/FileIntegrityManager.java
+++ b/core/java/android/security/FileIntegrityManager.java
@@ -78,7 +78,7 @@ public final class FileIntegrityManager {
* as a separate file and stored next to the targeting file in the filesystem. The public key of
* the signer (normally the same app developer) can be put in the APK, and the app can use the
* public key to verify the signature to the file's actual fs-verity digest (from {@link
- * #getFsverityDigest}) before using the file. The exact format is not prescribed by the
+ * #getFsVerityDigest}) before using the file. The exact format is not prescribed by the
* framework. App developers may choose to use common practices like JCA for the signing and
* verification, or their own preferred approach.
*
@@ -87,7 +87,7 @@ public final class FileIntegrityManager {
* @see <a href="https://www.kernel.org/doc/html/next/filesystems/fsverity.html">Kernel doc</a>
*/
@FlaggedApi(Flags.FLAG_FSVERITY_API)
- public void setupFsverity(@NonNull File file) throws IOException {
+ public void setupFsVerity(@NonNull File file) throws IOException {
if (!file.isAbsolute()) {
throw new IllegalArgumentException("Expect an absolute path");
}
@@ -104,7 +104,7 @@ public final class FileIntegrityManager {
int errno = mService.setupFsverity(authToken, file.getPath(),
mContext.getPackageName());
if (errno != 0) {
- new ErrnoException("setupFsverity", errno).rethrowAsIOException();
+ new ErrnoException("setupFsVerity", errno).rethrowAsIOException();
}
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
@@ -120,7 +120,7 @@ public final class FileIntegrityManager {
* @see <a href="https://www.kernel.org/doc/html/next/filesystems/fsverity.html">Kernel doc</a>
*/
@FlaggedApi(Flags.FLAG_FSVERITY_API)
- public @Nullable byte[] getFsverityDigest(@NonNull File file) throws IOException {
+ public @Nullable byte[] getFsVerityDigest(@NonNull File file) throws IOException {
return VerityUtils.getFsverityDigest(file.getPath());
}
diff --git a/core/java/android/service/trust/OWNERS b/core/java/android/service/trust/OWNERS
index 16eb19a58952..d3525250ebb6 100644
--- a/core/java/android/service/trust/OWNERS
+++ b/core/java/android/service/trust/OWNERS
@@ -1,3 +1,4 @@
# Bug component: 36824
jacobhobbie@google.com
+dlm@google.com
diff --git a/core/java/android/service/wallpaper/WallpaperService.java b/core/java/android/service/wallpaper/WallpaperService.java
index c7e54537703b..637770c4fb21 100644
--- a/core/java/android/service/wallpaper/WallpaperService.java
+++ b/core/java/android/service/wallpaper/WallpaperService.java
@@ -1307,9 +1307,9 @@ public abstract class WallpaperService extends Service {
visibleFrame.intersect(mInsetsState.getDisplayFrame());
WindowInsets windowInsets = mInsetsState.calculateInsets(visibleFrame,
null /* ignoringVisibilityState */, config.isScreenRound(),
- false /* alwaysConsumeSystemBars */, mLayout.softInputMode,
- mLayout.flags, SYSTEM_UI_FLAG_VISIBLE, mLayout.type,
- config.windowConfiguration.getWindowingMode(), null /* idSideMap */);
+ mLayout.softInputMode, mLayout.flags, SYSTEM_UI_FLAG_VISIBLE,
+ mLayout.type, config.windowConfiguration.getActivityType(),
+ null /* idSideMap */);
if (!fixedSize) {
final Rect padding = mIWallpaperEngine.mDisplayPadding;
diff --git a/core/java/android/text/flags/deprecate_fonts_xml.aconfig b/core/java/android/text/flags/deprecate_fonts_xml.aconfig
new file mode 100644
index 000000000000..58dc210af581
--- /dev/null
+++ b/core/java/android/text/flags/deprecate_fonts_xml.aconfig
@@ -0,0 +1,8 @@
+package: "com.android.text.flags"
+
+flag {
+ name: "deprecate_fonts_xml"
+ namespace: "text"
+ description: "Feature flag for deprecating fonts.xml. By setting true for this feature flag, the new font configuration XML, /system/etc/font_fallback.xml is used. The new XML has a new syntax and flexibility of variable font declarations, but it is not compatible with the apps that reads fonts.xml. So, fonts.xml is maintained as a subset of the font_fallback.xml"
+ bug: "281769620"
+}
diff --git a/core/java/android/text/flags/phrase_strict_fallback.aconfig b/core/java/android/text/flags/phrase_strict_fallback.aconfig
new file mode 100644
index 000000000000..c67a21bca0b4
--- /dev/null
+++ b/core/java/android/text/flags/phrase_strict_fallback.aconfig
@@ -0,0 +1,8 @@
+package: "com.android.text.flags"
+
+flag {
+ name: "phrase_strict_fallback"
+ namespace: "text"
+ description: "Feature flag for automatic fallback from phrase based line break to strict line break."
+ bug: "281970875"
+}
diff --git a/core/java/android/util/FeatureFlagUtils.java b/core/java/android/util/FeatureFlagUtils.java
index 85f5395f2657..12527e91a87c 100644
--- a/core/java/android/util/FeatureFlagUtils.java
+++ b/core/java/android/util/FeatureFlagUtils.java
@@ -156,6 +156,13 @@ public class FeatureFlagUtils {
public static final String SETTINGS_BIOMETRICS2_FINGERPRINT_SETTINGS =
"settings_biometrics2_fingerprint";
+ /**
+ * Flag to enable/disable remote auth enrollment and settings
+ * @hide
+ */
+ public static final String SETTINGS_REMOTEAUTH_ENROLLMENT_SETTINGS =
+ "settings_remoteauth_enrollment";
+
/** Flag to enable/disable entire page in Accessibility -> Hearing aids
* @hide
*/
@@ -247,7 +254,8 @@ public class FeatureFlagUtils {
DEFAULT_FLAGS.put(SETTINGS_ENABLE_LOCKSCREEN_TRANSFER_API, "true");
DEFAULT_FLAGS.put(SETTINGS_REMOTE_DEVICE_CREDENTIAL_VALIDATION, "true");
DEFAULT_FLAGS.put(SETTINGS_BIOMETRICS2_FINGERPRINT_SETTINGS, "false");
- DEFAULT_FLAGS.put("settings_press_hold_nav_handle_to_search", "false");
+ // TODO: b/298454866 Replace with Trunk Stable Feature Flag
+ DEFAULT_FLAGS.put(SETTINGS_REMOTEAUTH_ENROLLMENT_SETTINGS, "false");
}
private static final Set<String> PERSISTENT_FLAGS;
diff --git a/core/java/android/view/HandwritingInitiator.java b/core/java/android/view/HandwritingInitiator.java
index 23afb03569ce..a208d1f1a558 100644
--- a/core/java/android/view/HandwritingInitiator.java
+++ b/core/java/android/view/HandwritingInitiator.java
@@ -81,6 +81,8 @@ public class HandwritingInitiator {
private int mConnectionCount = 0;
private final InputMethodManager mImm;
+ private final Rect mTempRect = new Rect();
+
private final RectF mTempRectF = new RectF();
private final Region mTempRegion = new Region();
@@ -401,8 +403,9 @@ public class HandwritingInitiator {
final View cachedHoverTarget = getCachedHoverTarget();
if (cachedHoverTarget != null) {
- final Rect handwritingArea = getViewHandwritingArea(cachedHoverTarget);
- if (isInHandwritingArea(handwritingArea, hoverX, hoverY, cachedHoverTarget,
+ final Rect handwritingArea = mTempRect;
+ if (getViewHandwritingArea(cachedHoverTarget, handwritingArea)
+ && isInHandwritingArea(handwritingArea, hoverX, hoverY, cachedHoverTarget,
/* isHover */ true)
&& shouldTriggerStylusHandwritingForView(cachedHoverTarget)) {
return cachedHoverTarget;
@@ -445,8 +448,9 @@ public class HandwritingInitiator {
// directly return the connectedView.
final View connectedView = getConnectedView();
if (connectedView != null) {
- Rect handwritingArea = getViewHandwritingArea(connectedView);
- if (isInHandwritingArea(handwritingArea, x, y, connectedView, isHover)
+ Rect handwritingArea = mTempRect;
+ if (getViewHandwritingArea(connectedView, handwritingArea)
+ && isInHandwritingArea(handwritingArea, x, y, connectedView, isHover)
&& shouldTriggerStylusHandwritingForView(connectedView)) {
return connectedView;
}
@@ -528,28 +532,30 @@ public class HandwritingInitiator {
/**
* Return the handwriting area of the given view, represented in the window's coordinate.
* If the view didn't set any handwriting area, it will return the view's boundary.
- * It will return null if the view or its handwriting area is not visible.
*
- * The handwriting area is clipped to its visible part.
+ * <p> The handwriting area is clipped to its visible part.
* Notice that the returned rectangle is the view's original handwriting area without the
- * view's handwriting area extends.
+ * view's handwriting area extends. </p>
+ *
+ * @param view the {@link View} whose handwriting area we want to compute.
+ * @param rect the {@link Rect} to receive the result.
+ *
+ * @return true if the view's handwriting area is still visible, or false if it's clipped and
+ * fully invisible. This method only consider the clip by given view's parents, but not the case
+ * where a view is covered by its sibling view.
*/
- @Nullable
- private static Rect getViewHandwritingArea(@NonNull View view) {
+ private static boolean getViewHandwritingArea(@NonNull View view, @NonNull Rect rect) {
final ViewParent viewParent = view.getParent();
if (viewParent != null && view.isAttachedToWindow() && view.isAggregatedVisible()) {
final Rect localHandwritingArea = view.getHandwritingArea();
- final Rect globalHandwritingArea = new Rect();
if (localHandwritingArea != null) {
- globalHandwritingArea.set(localHandwritingArea);
+ rect.set(localHandwritingArea);
} else {
- globalHandwritingArea.set(0, 0, view.getWidth(), view.getHeight());
- }
- if (viewParent.getChildVisibleRect(view, globalHandwritingArea, null)) {
- return globalHandwritingArea;
+ rect.set(0, 0, view.getWidth(), view.getHeight());
}
+ return viewParent.getChildVisibleRect(view, rect, null);
}
- return null;
+ return false;
}
/**
diff --git a/core/java/android/view/InsetsAnimationControlImpl.java b/core/java/android/view/InsetsAnimationControlImpl.java
index fabfed39a913..1ec7c41e4395 100644
--- a/core/java/android/view/InsetsAnimationControlImpl.java
+++ b/core/java/android/view/InsetsAnimationControlImpl.java
@@ -16,7 +16,7 @@
package android.view;
-import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
+import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
import static android.view.EventLogTags.IMF_IME_ANIM_CANCEL;
import static android.view.EventLogTags.IMF_IME_ANIM_FINISH;
import static android.view.EventLogTags.IMF_IME_ANIM_START;
@@ -39,6 +39,7 @@ import static android.view.InsetsState.ISIDE_LEFT;
import static android.view.InsetsState.ISIDE_RIGHT;
import static android.view.InsetsState.ISIDE_TOP;
import static android.view.WindowInsets.Type.ime;
+import static android.view.WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
import static android.view.inputmethod.ImeTracker.DEBUG_IME_VISIBILITY;
import static android.view.inputmethod.ImeTracker.TOKEN_NONE;
@@ -62,7 +63,6 @@ import android.view.InsetsState.InternalInsetsSide;
import android.view.SyncRtSurfaceTransactionApplier.SurfaceParams;
import android.view.WindowInsets.Type.InsetsType;
import android.view.WindowInsetsAnimation.Bounds;
-import android.view.WindowManager.LayoutParams;
import android.view.animation.Interpolator;
import android.view.inputmethod.ImeTracker;
@@ -396,10 +396,9 @@ public class InsetsAnimationControlImpl implements InternalInsetsAnimationContro
private Insets getInsetsFromState(InsetsState state, Rect frame,
@Nullable @InternalInsetsSide SparseIntArray idSideMap) {
return state.calculateInsets(frame, null /* ignoringVisibilityState */,
- false /* isScreenRound */, false /* alwaysConsumeSystemBars */,
- LayoutParams.SOFT_INPUT_ADJUST_RESIZE /* legacySoftInputMode*/,
+ false /* isScreenRound */, SOFT_INPUT_ADJUST_RESIZE /* legacySoftInputMode */,
0 /* legacyWindowFlags */, 0 /* legacySystemUiFlags */, TYPE_APPLICATION,
- WINDOWING_MODE_UNDEFINED, idSideMap).getInsets(mTypes);
+ ACTIVITY_TYPE_UNDEFINED, idSideMap).getInsets(mTypes);
}
/** Computes the insets relative to the given frame. */
diff --git a/core/java/android/view/InsetsController.java b/core/java/android/view/InsetsController.java
index 8ec7d6779392..fb24211e591a 100644
--- a/core/java/android/view/InsetsController.java
+++ b/core/java/android/view/InsetsController.java
@@ -652,7 +652,7 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation
private int mLastLegacySoftInputMode;
private int mLastLegacyWindowFlags;
private int mLastLegacySystemUiFlags;
- private int mLastWindowingMode;
+ private int mLastActivityType;
private boolean mStartingAnimation;
private int mCaptionInsetsHeight = 0;
private int mImeCaptionBarInsetsHeight = 0;
@@ -800,10 +800,10 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation
}
}
- WindowInsets insets = state.calculateInsets(mFrame, mState /* ignoringVisibilityState*/,
- mLastInsets.isRound(), false /* alwaysConsumeSystemBars */,
+ WindowInsets insets = state.calculateInsets(mFrame,
+ mState /* ignoringVisibilityState */, mLastInsets.isRound(),
mLastLegacySoftInputMode, mLastLegacyWindowFlags, mLastLegacySystemUiFlags,
- mWindowType, mLastWindowingMode, null /* idSideMap */);
+ mWindowType, mLastActivityType, null /* idSideMap */);
mHost.dispatchWindowInsetsAnimationProgress(insets,
Collections.unmodifiableList(runningAnimations));
if (DEBUG) {
@@ -939,30 +939,29 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation
}
/**
- * @see InsetsState#calculateInsets(Rect, InsetsState, boolean, boolean, int, int, int, int,
- * int, android.util.SparseIntArray)
+ * @see InsetsState#calculateInsets(Rect, InsetsState, boolean, int, int, int, int, int,
+ * android.util.SparseIntArray)
*/
@VisibleForTesting
- public WindowInsets calculateInsets(boolean isScreenRound, boolean alwaysConsumeSystemBars,
- int windowType, int windowingMode, int legacySoftInputMode, int legacyWindowFlags,
- int legacySystemUiFlags) {
+ public WindowInsets calculateInsets(boolean isScreenRound, int windowType, int activityType,
+ int legacySoftInputMode, int legacyWindowFlags, int legacySystemUiFlags) {
mWindowType = windowType;
- mLastWindowingMode = windowingMode;
+ mLastActivityType = activityType;
mLastLegacySoftInputMode = legacySoftInputMode;
mLastLegacyWindowFlags = legacyWindowFlags;
mLastLegacySystemUiFlags = legacySystemUiFlags;
- mLastInsets = mState.calculateInsets(mFrame, null /* ignoringVisibilityState*/,
- isScreenRound, alwaysConsumeSystemBars, legacySoftInputMode, legacyWindowFlags,
- legacySystemUiFlags, windowType, windowingMode, null /* idSideMap */);
+ mLastInsets = mState.calculateInsets(mFrame, null /* ignoringVisibilityState */,
+ isScreenRound, legacySoftInputMode, legacyWindowFlags,
+ legacySystemUiFlags, windowType, activityType, null /* idSideMap */);
return mLastInsets;
}
/**
* @see InsetsState#calculateVisibleInsets(Rect, int, int, int, int)
*/
- public Insets calculateVisibleInsets(int windowType, int windowingMode,
+ public Insets calculateVisibleInsets(int windowType, int activityType,
@SoftInputModeFlags int softInputMode, int windowFlags) {
- return mState.calculateVisibleInsets(mFrame, windowType, windowingMode, softInputMode,
+ return mState.calculateVisibleInsets(mFrame, windowType, activityType, softInputMode,
windowFlags);
}
diff --git a/core/java/android/view/InsetsState.java b/core/java/android/view/InsetsState.java
index af24140086ed..59e0932ecd80 100644
--- a/core/java/android/view/InsetsState.java
+++ b/core/java/android/view/InsetsState.java
@@ -16,6 +16,7 @@
package android.view;
+import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
import static android.view.InsetsSource.FLAG_FORCE_CONSUMING;
import static android.view.InsetsSource.FLAG_INSETS_ROUNDED_CORNER;
import static android.view.InsetsStateProto.DISPLAY_CUTOUT;
@@ -39,7 +40,7 @@ import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.app.WindowConfiguration;
+import android.app.WindowConfiguration.ActivityType;
import android.graphics.Insets;
import android.graphics.Rect;
import android.os.Parcel;
@@ -136,9 +137,8 @@ public class InsetsState implements Parcelable {
* @return The calculated insets.
*/
public WindowInsets calculateInsets(Rect frame, @Nullable InsetsState ignoringVisibilityState,
- boolean isScreenRound, boolean alwaysConsumeSystemBars,
- int legacySoftInputMode, int legacyWindowFlags, int legacySystemUiFlags,
- int windowType, @WindowConfiguration.WindowingMode int windowingMode,
+ boolean isScreenRound, int legacySoftInputMode, int legacyWindowFlags,
+ int legacySystemUiFlags, int windowType, @ActivityType int activityType,
@Nullable @InternalInsetsSide SparseIntArray idSideMap) {
Insets[] typeInsetsMap = new Insets[Type.SIZE];
Insets[] typeMaxInsetsMap = new Insets[Type.SIZE];
@@ -185,9 +185,8 @@ public class InsetsState implements Parcelable {
if ((legacyWindowFlags & FLAG_FULLSCREEN) != 0) {
compatInsetsTypes &= ~statusBars();
}
- if (clearsCompatInsets(windowType, legacyWindowFlags, windowingMode)) {
- // Clear all types but forceConsumingTypes.
- compatInsetsTypes &= forceConsumingTypes;
+ if (clearsCompatInsets(windowType, legacyWindowFlags, activityType, forceConsumingTypes)) {
+ compatInsetsTypes = 0;
}
return new WindowInsets(typeInsetsMap, typeMaxInsetsMap, typeVisibilityMap, isScreenRound,
@@ -295,26 +294,27 @@ public class InsetsState implements Parcelable {
return insets;
}
- public Insets calculateVisibleInsets(Rect frame, int windowType, int windowingMode,
+ public Insets calculateVisibleInsets(Rect frame, int windowType, @ActivityType int activityType,
@SoftInputModeFlags int softInputMode, int windowFlags) {
- final boolean clearsCompatInsets = clearsCompatInsets(
- windowType, windowFlags, windowingMode);
final int softInputAdjustMode = softInputMode & SOFT_INPUT_MASK_ADJUST;
final int visibleInsetsTypes = softInputAdjustMode != SOFT_INPUT_ADJUST_NOTHING
? systemBars() | ime()
: systemBars();
+ @InsetsType int forceConsumingTypes = 0;
Insets insets = Insets.NONE;
for (int i = mSources.size() - 1; i >= 0; i--) {
final InsetsSource source = mSources.valueAt(i);
if ((source.getType() & visibleInsetsTypes) == 0) {
continue;
}
- if (clearsCompatInsets && !source.hasFlags(FLAG_FORCE_CONSUMING)) {
- continue;
+ if (source.hasFlags(FLAG_FORCE_CONSUMING)) {
+ forceConsumingTypes |= source.getType();
}
insets = Insets.max(source.calculateVisibleInsets(frame), insets);
}
- return insets;
+ return clearsCompatInsets(windowType, windowFlags, activityType, forceConsumingTypes)
+ ? Insets.NONE
+ : insets;
}
/**
@@ -662,10 +662,15 @@ public class InsetsState implements Parcelable {
mSources.put(source.getId(), source);
}
- public static boolean clearsCompatInsets(int windowType, int windowFlags, int windowingMode) {
+ public static boolean clearsCompatInsets(int windowType, int windowFlags,
+ @ActivityType int activityType, @InsetsType int forceConsumingTypes) {
return (windowFlags & FLAG_LAYOUT_NO_LIMITS) != 0
+ // For compatibility reasons, this excludes the wallpaper, the system error windows,
+ // and the app windows while any system bar is forcibly consumed.
&& windowType != TYPE_WALLPAPER && windowType != TYPE_SYSTEM_ERROR
- && !WindowConfiguration.inMultiWindowMode(windowingMode);
+ // This ensures the app content won't be obscured by compat insets even if the app
+ // has FLAG_LAYOUT_NO_LIMITS.
+ && (forceConsumingTypes == 0 || activityType != ACTIVITY_TYPE_STANDARD);
}
public void dump(String prefix, PrintWriter pw) {
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 9a4cb7298ee6..81edd3c5b811 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -105,6 +105,8 @@ import android.os.RemoteCallback;
import android.os.RemoteException;
import android.os.SystemClock;
import android.os.Trace;
+import android.os.Vibrator;
+import android.os.vibrator.Flags;
import android.sysprop.DisplayProperties;
import android.text.InputType;
import android.text.TextUtils;
@@ -2447,7 +2449,6 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
* @see #getId()
*/
@IdRes
- @ViewDebug.ExportedProperty(resolveId = true)
int mID = NO_ID;
/** The ID of this view for autofill purposes.
@@ -4298,71 +4299,6 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
* This view's request for the visibility of the status bar.
* @hide
*/
- @ViewDebug.ExportedProperty(flagMapping = {
- @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_LOW_PROFILE,
- equals = SYSTEM_UI_FLAG_LOW_PROFILE,
- name = "LOW_PROFILE"),
- @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_HIDE_NAVIGATION,
- equals = SYSTEM_UI_FLAG_HIDE_NAVIGATION,
- name = "HIDE_NAVIGATION"),
- @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_FULLSCREEN,
- equals = SYSTEM_UI_FLAG_FULLSCREEN,
- name = "FULLSCREEN"),
- @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_LAYOUT_STABLE,
- equals = SYSTEM_UI_FLAG_LAYOUT_STABLE,
- name = "LAYOUT_STABLE"),
- @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION,
- equals = SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION,
- name = "LAYOUT_HIDE_NAVIGATION"),
- @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN,
- equals = SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN,
- name = "LAYOUT_FULLSCREEN"),
- @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_IMMERSIVE,
- equals = SYSTEM_UI_FLAG_IMMERSIVE,
- name = "IMMERSIVE"),
- @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_IMMERSIVE_STICKY,
- equals = SYSTEM_UI_FLAG_IMMERSIVE_STICKY,
- name = "IMMERSIVE_STICKY"),
- @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_LIGHT_STATUS_BAR,
- equals = SYSTEM_UI_FLAG_LIGHT_STATUS_BAR,
- name = "LIGHT_STATUS_BAR"),
- @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR,
- equals = SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR,
- name = "LIGHT_NAVIGATION_BAR"),
- @ViewDebug.FlagToString(mask = STATUS_BAR_DISABLE_EXPAND,
- equals = STATUS_BAR_DISABLE_EXPAND,
- name = "STATUS_BAR_DISABLE_EXPAND"),
- @ViewDebug.FlagToString(mask = STATUS_BAR_DISABLE_NOTIFICATION_ICONS,
- equals = STATUS_BAR_DISABLE_NOTIFICATION_ICONS,
- name = "STATUS_BAR_DISABLE_NOTIFICATION_ICONS"),
- @ViewDebug.FlagToString(mask = STATUS_BAR_DISABLE_NOTIFICATION_ALERTS,
- equals = STATUS_BAR_DISABLE_NOTIFICATION_ALERTS,
- name = "STATUS_BAR_DISABLE_NOTIFICATION_ALERTS"),
- @ViewDebug.FlagToString(mask = STATUS_BAR_DISABLE_NOTIFICATION_TICKER,
- equals = STATUS_BAR_DISABLE_NOTIFICATION_TICKER,
- name = "STATUS_BAR_DISABLE_NOTIFICATION_TICKER"),
- @ViewDebug.FlagToString(mask = STATUS_BAR_DISABLE_SYSTEM_INFO,
- equals = STATUS_BAR_DISABLE_SYSTEM_INFO,
- name = "STATUS_BAR_DISABLE_SYSTEM_INFO"),
- @ViewDebug.FlagToString(mask = STATUS_BAR_DISABLE_HOME,
- equals = STATUS_BAR_DISABLE_HOME,
- name = "STATUS_BAR_DISABLE_HOME"),
- @ViewDebug.FlagToString(mask = STATUS_BAR_DISABLE_BACK,
- equals = STATUS_BAR_DISABLE_BACK,
- name = "STATUS_BAR_DISABLE_BACK"),
- @ViewDebug.FlagToString(mask = STATUS_BAR_DISABLE_CLOCK,
- equals = STATUS_BAR_DISABLE_CLOCK,
- name = "STATUS_BAR_DISABLE_CLOCK"),
- @ViewDebug.FlagToString(mask = STATUS_BAR_DISABLE_RECENT,
- equals = STATUS_BAR_DISABLE_RECENT,
- name = "STATUS_BAR_DISABLE_RECENT"),
- @ViewDebug.FlagToString(mask = STATUS_BAR_DISABLE_SEARCH,
- equals = STATUS_BAR_DISABLE_SEARCH,
- name = "STATUS_BAR_DISABLE_SEARCH"),
- @ViewDebug.FlagToString(mask = STATUS_BAR_DISABLE_ONGOING_CALL_CHIP,
- equals = STATUS_BAR_DISABLE_ONGOING_CALL_CHIP,
- name = "STATUS_BAR_DISABLE_ONGOING_CALL_CHIP")
- }, formatToHexString = true)
@SystemUiVisibility
int mSystemUiVisibility;
@@ -4481,7 +4417,6 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
* to the left edge of this view.
* {@hide}
*/
- @ViewDebug.ExportedProperty(category = "layout")
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
protected int mLeft;
/**
@@ -4489,7 +4424,6 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
* to the right edge of this view.
* {@hide}
*/
- @ViewDebug.ExportedProperty(category = "layout")
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
protected int mRight;
/**
@@ -4497,7 +4431,6 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
* to the top edge of this view.
* {@hide}
*/
- @ViewDebug.ExportedProperty(category = "layout")
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
protected int mTop;
/**
@@ -4505,7 +4438,6 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
* to the bottom edge of this view.
* {@hide}
*/
- @ViewDebug.ExportedProperty(category = "layout")
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
protected int mBottom;
@@ -4516,7 +4448,6 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
* accessing these directly.
* {@hide}
*/
- @ViewDebug.ExportedProperty(category = "scrolling")
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
protected int mScrollX;
/**
@@ -4526,7 +4457,6 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
* accessing these directly.
* {@hide}
*/
- @ViewDebug.ExportedProperty(category = "scrolling")
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
protected int mScrollY;
@@ -4535,7 +4465,6 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
* pixels between the left edge of this view and the left edge of its content.
* {@hide}
*/
- @ViewDebug.ExportedProperty(category = "padding")
@UnsupportedAppUsage
protected int mPaddingLeft = 0;
/**
@@ -4543,7 +4472,6 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
* pixels between the right edge of this view and the right edge of its content.
* {@hide}
*/
- @ViewDebug.ExportedProperty(category = "padding")
@UnsupportedAppUsage
protected int mPaddingRight = 0;
/**
@@ -4551,7 +4479,6 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
* pixels between the top edge of this view and the top edge of its content.
* {@hide}
*/
- @ViewDebug.ExportedProperty(category = "padding")
@UnsupportedAppUsage
protected int mPaddingTop;
/**
@@ -4559,7 +4486,6 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
* pixels between the bottom edge of this view and the bottom edge of its content.
* {@hide}
*/
- @ViewDebug.ExportedProperty(category = "padding")
@UnsupportedAppUsage
protected int mPaddingBottom;
@@ -5411,6 +5337,9 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
*/
private PointerIcon mMousePointerIcon;
+ /** Vibrator for haptic feedback. */
+ private Vibrator mVibrator;
+
/**
* @hide
*/
@@ -17918,6 +17847,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
* @return The left edge of the displayed part of your view, in pixels.
*/
@InspectableProperty
+ @ViewDebug.ExportedProperty(category = "scrolling")
public final int getScrollX() {
return mScrollX;
}
@@ -17930,6 +17860,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
* @return The top edge of the displayed part of your view, in pixels.
*/
@InspectableProperty
+ @ViewDebug.ExportedProperty(category = "scrolling")
public final int getScrollY() {
return mScrollY;
}
@@ -18720,6 +18651,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
* @return The top of this view, in pixels.
*/
@ViewDebug.CapturedViewProperty
+ @ViewDebug.ExportedProperty(category = "layout")
public final int getTop() {
return mTop;
}
@@ -18779,6 +18711,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
* @return The bottom of this view, in pixels.
*/
@ViewDebug.CapturedViewProperty
+ @ViewDebug.ExportedProperty(category = "layout")
public final int getBottom() {
return mBottom;
}
@@ -18844,6 +18777,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
* @return The left edge of this view, in pixels.
*/
@ViewDebug.CapturedViewProperty
+ @ViewDebug.ExportedProperty(category = "layout")
public final int getLeft() {
return mLeft;
}
@@ -18903,6 +18837,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
* @return The right edge of this view, in pixels.
*/
@ViewDebug.CapturedViewProperty
+ @ViewDebug.ExportedProperty(category = "layout")
public final int getRight() {
return mRight;
}
@@ -26130,6 +26065,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
* @return the top padding in pixels
*/
@InspectableProperty
+ @ViewDebug.ExportedProperty(category = "padding")
public int getPaddingTop() {
return mPaddingTop;
}
@@ -26142,6 +26078,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
* @return the bottom padding in pixels
*/
@InspectableProperty
+ @ViewDebug.ExportedProperty(category = "padding")
public int getPaddingBottom() {
return mPaddingBottom;
}
@@ -26154,6 +26091,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
* @return the left padding in pixels
*/
@InspectableProperty
+ @ViewDebug.ExportedProperty(category = "padding")
public int getPaddingLeft() {
if (!isPaddingResolved()) {
resolvePadding();
@@ -26184,6 +26122,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
* @return the right padding in pixels
*/
@InspectableProperty
+ @ViewDebug.ExportedProperty(category = "padding")
public int getPaddingRight() {
if (!isPaddingResolved()) {
resolvePadding();
@@ -26869,6 +26808,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
*/
@IdRes
@ViewDebug.CapturedViewProperty
+ @ViewDebug.ExportedProperty(resolveId = true)
@InspectableProperty
public int getId() {
return mID;
@@ -27758,8 +27698,24 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
&& !isHapticFeedbackEnabled()) {
return false;
}
- return mAttachInfo.mRootCallbacks.performHapticFeedback(feedbackConstant,
- (flags & HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING) != 0);
+
+ final boolean always = (flags & HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING) != 0;
+ if (Flags.useVibratorHapticFeedback()) {
+ if (!mAttachInfo.canPerformHapticFeedback()) {
+ return false;
+ }
+ getSystemVibrator().performHapticFeedback(
+ feedbackConstant, always, "View#performHapticFeedback");
+ return true;
+ }
+ return mAttachInfo.mRootCallbacks.performHapticFeedback(feedbackConstant, always);
+ }
+
+ private Vibrator getSystemVibrator() {
+ if (mVibrator != null) {
+ return mVibrator;
+ }
+ return mVibrator = mContext.getSystemService(Vibrator.class);
}
/**
@@ -27832,6 +27788,71 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
* @deprecated SystemUiVisibility flags are deprecated. Use {@link WindowInsetsController}
* instead.
*/
+ @ViewDebug.ExportedProperty(flagMapping = {
+ @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_LOW_PROFILE,
+ equals = SYSTEM_UI_FLAG_LOW_PROFILE,
+ name = "LOW_PROFILE"),
+ @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_HIDE_NAVIGATION,
+ equals = SYSTEM_UI_FLAG_HIDE_NAVIGATION,
+ name = "HIDE_NAVIGATION"),
+ @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_FULLSCREEN,
+ equals = SYSTEM_UI_FLAG_FULLSCREEN,
+ name = "FULLSCREEN"),
+ @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_LAYOUT_STABLE,
+ equals = SYSTEM_UI_FLAG_LAYOUT_STABLE,
+ name = "LAYOUT_STABLE"),
+ @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION,
+ equals = SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION,
+ name = "LAYOUT_HIDE_NAVIGATION"),
+ @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN,
+ equals = SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN,
+ name = "LAYOUT_FULLSCREEN"),
+ @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_IMMERSIVE,
+ equals = SYSTEM_UI_FLAG_IMMERSIVE,
+ name = "IMMERSIVE"),
+ @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_IMMERSIVE_STICKY,
+ equals = SYSTEM_UI_FLAG_IMMERSIVE_STICKY,
+ name = "IMMERSIVE_STICKY"),
+ @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_LIGHT_STATUS_BAR,
+ equals = SYSTEM_UI_FLAG_LIGHT_STATUS_BAR,
+ name = "LIGHT_STATUS_BAR"),
+ @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR,
+ equals = SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR,
+ name = "LIGHT_NAVIGATION_BAR"),
+ @ViewDebug.FlagToString(mask = STATUS_BAR_DISABLE_EXPAND,
+ equals = STATUS_BAR_DISABLE_EXPAND,
+ name = "STATUS_BAR_DISABLE_EXPAND"),
+ @ViewDebug.FlagToString(mask = STATUS_BAR_DISABLE_NOTIFICATION_ICONS,
+ equals = STATUS_BAR_DISABLE_NOTIFICATION_ICONS,
+ name = "STATUS_BAR_DISABLE_NOTIFICATION_ICONS"),
+ @ViewDebug.FlagToString(mask = STATUS_BAR_DISABLE_NOTIFICATION_ALERTS,
+ equals = STATUS_BAR_DISABLE_NOTIFICATION_ALERTS,
+ name = "STATUS_BAR_DISABLE_NOTIFICATION_ALERTS"),
+ @ViewDebug.FlagToString(mask = STATUS_BAR_DISABLE_NOTIFICATION_TICKER,
+ equals = STATUS_BAR_DISABLE_NOTIFICATION_TICKER,
+ name = "STATUS_BAR_DISABLE_NOTIFICATION_TICKER"),
+ @ViewDebug.FlagToString(mask = STATUS_BAR_DISABLE_SYSTEM_INFO,
+ equals = STATUS_BAR_DISABLE_SYSTEM_INFO,
+ name = "STATUS_BAR_DISABLE_SYSTEM_INFO"),
+ @ViewDebug.FlagToString(mask = STATUS_BAR_DISABLE_HOME,
+ equals = STATUS_BAR_DISABLE_HOME,
+ name = "STATUS_BAR_DISABLE_HOME"),
+ @ViewDebug.FlagToString(mask = STATUS_BAR_DISABLE_BACK,
+ equals = STATUS_BAR_DISABLE_BACK,
+ name = "STATUS_BAR_DISABLE_BACK"),
+ @ViewDebug.FlagToString(mask = STATUS_BAR_DISABLE_CLOCK,
+ equals = STATUS_BAR_DISABLE_CLOCK,
+ name = "STATUS_BAR_DISABLE_CLOCK"),
+ @ViewDebug.FlagToString(mask = STATUS_BAR_DISABLE_RECENT,
+ equals = STATUS_BAR_DISABLE_RECENT,
+ name = "STATUS_BAR_DISABLE_RECENT"),
+ @ViewDebug.FlagToString(mask = STATUS_BAR_DISABLE_SEARCH,
+ equals = STATUS_BAR_DISABLE_SEARCH,
+ name = "STATUS_BAR_DISABLE_SEARCH"),
+ @ViewDebug.FlagToString(mask = STATUS_BAR_DISABLE_ONGOING_CALL_CHIP,
+ equals = STATUS_BAR_DISABLE_ONGOING_CALL_CHIP,
+ name = "STATUS_BAR_DISABLE_ONGOING_CALL_CHIP")
+ }, formatToHexString = true)
@Deprecated
public int getSystemUiVisibility() {
return mSystemUiVisibility;
@@ -31239,6 +31260,11 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
return events;
}
+ private boolean canPerformHapticFeedback() {
+ return mSession != null
+ && (mDisplay.getFlags() & Display.FLAG_TOUCH_FEEDBACK_DISABLED) == 0;
+ }
+
@Nullable
ScrollCaptureInternal getScrollCaptureInternal() {
if (mScrollCaptureInternal != null) {
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index e0fda7e51c33..60d964e32f6f 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -2848,16 +2848,15 @@ public final class ViewRootImpl implements ViewParent,
if (mLastWindowInsets == null || forceConstruct) {
final Configuration config = getConfiguration();
mLastWindowInsets = mInsetsController.calculateInsets(
- config.isScreenRound(), mAttachInfo.mAlwaysConsumeSystemBars,
- mWindowAttributes.type, config.windowConfiguration.getWindowingMode(),
- mWindowAttributes.softInputMode, mWindowAttributes.flags,
- (mWindowAttributes.systemUiVisibility
+ config.isScreenRound(), mWindowAttributes.type,
+ config.windowConfiguration.getActivityType(), mWindowAttributes.softInputMode,
+ mWindowAttributes.flags, (mWindowAttributes.systemUiVisibility
| mWindowAttributes.subtreeSystemUiVisibility));
mAttachInfo.mContentInsets.set(mLastWindowInsets.getSystemWindowInsets().toRect());
mAttachInfo.mStableInsets.set(mLastWindowInsets.getStableInsets().toRect());
mAttachInfo.mVisibleInsets.set(mInsetsController.calculateVisibleInsets(
- mWindowAttributes.type, config.windowConfiguration.getWindowingMode(),
+ mWindowAttributes.type, config.windowConfiguration.getActivityType(),
mWindowAttributes.softInputMode, mWindowAttributes.flags).toRect());
}
return mLastWindowInsets;
diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java
index 62e37a4f50d2..b8385c6ecba9 100644
--- a/core/java/android/view/WindowManager.java
+++ b/core/java/android/view/WindowManager.java
@@ -1318,8 +1318,8 @@ public interface WindowManager extends ViewManager {
* that have the ignore orientation request display setting enabled by OEMs
* (enables compatibility mode for fixed orientation on Android 12 (API
* level 31) or higher; see
- * <a href="https://developer.android.com/guide/topics/large-screens/large-screen-app-compatibility">
- * Large screen app compatibility</a>
+ * <a href="https://developer.android.com/guide/topics/large-screens/large-screen-compatibility-mode">
+ * Large screen compatibility mode</a>
* for more details).
*
* <p>To opt out of the user aspect ratio compatibility override, add this property
@@ -1358,8 +1358,8 @@ public interface WindowManager extends ViewManager {
* that have the ignore orientation request display setting enabled by OEMs
* (enables compatibility mode for fixed orientation on Android 12 (API
* level 31) or higher; see
- * <a href="https://developer.android.com/guide/topics/large-screens/large-screen-app-compatibility">
- * Large screen app compatibility</a>
+ * <a href="https://developer.android.com/guide/topics/large-screens/large-screen-compatibility-mode">
+ * Large screen compatibility mode</a>
* for more details).
*
* <p>To opt out of the full-screen option of the user aspect ratio compatibility
diff --git a/core/java/android/view/inputmethod/RemoteInputConnectionImpl.java b/core/java/android/view/inputmethod/RemoteInputConnectionImpl.java
index f67a61be5879..61470f2bc71a 100644
--- a/core/java/android/view/inputmethod/RemoteInputConnectionImpl.java
+++ b/core/java/android/view/inputmethod/RemoteInputConnectionImpl.java
@@ -28,7 +28,13 @@ import static java.lang.annotation.RetentionPolicy.SOURCE;
import android.annotation.AnyThread;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.UiThread;
+import android.app.UriGrantsManager;
+import android.content.ContentProvider;
+import android.content.Intent;
import android.graphics.RectF;
+import android.net.Uri;
+import android.os.Binder;
import android.os.Bundle;
import android.os.CancellationSignal;
import android.os.CancellationSignalBeamer;
@@ -37,6 +43,7 @@ import android.os.IBinder;
import android.os.Looper;
import android.os.ResultReceiver;
import android.os.Trace;
+import android.os.UserHandle;
import android.util.Log;
import android.util.proto.ProtoOutputStream;
import android.view.KeyEvent;
@@ -1143,7 +1150,22 @@ final class RemoteInputConnectionImpl extends IRemoteInputConnection.Stub {
public void commitContent(InputConnectionCommandHeader header,
InputContentInfo inputContentInfo, int flags, Bundle opts,
AndroidFuture future /* T=Boolean */) {
+ final int imeUid = Binder.getCallingUid();
dispatchWithTracing("commitContent", future, () -> {
+ // Check if the originator IME has the right permissions
+ try {
+ final int contentUriOwnerUserId = ContentProvider.getUserIdFromUri(
+ inputContentInfo.getContentUri(), UserHandle.getUserId(imeUid));
+ final Uri contentUriWithoutUserId = ContentProvider.getUriWithoutUserId(
+ inputContentInfo.getContentUri());
+ UriGrantsManager.getService().checkGrantUriPermission_ignoreNonSystem(imeUid, null,
+ contentUriWithoutUserId, Intent.FLAG_GRANT_READ_URI_PERMISSION,
+ contentUriOwnerUserId);
+ } catch (Exception e) {
+ Log.w(TAG, "commitContent with invalid Uri permission from IME:", e);
+ return false;
+ }
+
if (header.mSessionId != mCurrentSessionId.get()) {
return false; // cancelled
}
diff --git a/core/java/android/view/inputmethod/flags.aconfig b/core/java/android/view/inputmethod/flags.aconfig
new file mode 100644
index 000000000000..92d34089cb22
--- /dev/null
+++ b/core/java/android/view/inputmethod/flags.aconfig
@@ -0,0 +1,8 @@
+package: "android.view.inputmethod"
+
+flag {
+ name: "refactor_insets_controller"
+ namespace: "inputmethod"
+ description: "Feature flag for refactoring InsetsController and removing ImeInsetsSourceConsumer"
+ bug: "298172246"
+} \ No newline at end of file
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index 6523fffc4b91..f5b81b027134 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -50,6 +50,7 @@ import android.util.SparseArray;
import android.view.DragEvent;
import android.view.KeyEvent;
import android.view.MotionEvent;
+import android.view.PointerIcon;
import android.view.View;
import android.view.ViewDebug;
import android.view.ViewGroup;
@@ -3139,4 +3140,15 @@ public class WebView extends AbsoluteLayout
if (result == null) return super.onApplyWindowInsets(insets);
return result;
}
+
+ @Override
+ @Nullable
+ public PointerIcon onResolvePointerIcon(@NonNull MotionEvent event, int pointerIndex) {
+ PointerIcon icon =
+ mProvider.getViewDelegate().onResolvePointerIcon(event, pointerIndex);
+ if (icon != null) {
+ return icon;
+ }
+ return super.onResolvePointerIcon(event, pointerIndex);
+ }
}
diff --git a/core/java/android/webkit/WebViewProvider.java b/core/java/android/webkit/WebViewProvider.java
index 26579c5dec68..ca423e030044 100644
--- a/core/java/android/webkit/WebViewProvider.java
+++ b/core/java/android/webkit/WebViewProvider.java
@@ -39,6 +39,7 @@ import android.util.SparseArray;
import android.view.DragEvent;
import android.view.KeyEvent;
import android.view.MotionEvent;
+import android.view.PointerIcon;
import android.view.View;
import android.view.ViewGroup.LayoutParams;
import android.view.WindowInsets;
@@ -496,6 +497,15 @@ public interface WebViewProvider {
default WindowInsets onApplyWindowInsets(@Nullable WindowInsets insets) {
return null;
}
+
+ /**
+ * @hide Only used by WebView.
+ */
+ @SuppressWarnings("unused")
+ @Nullable
+ default PointerIcon onResolvePointerIcon(@NonNull MotionEvent event, int pointerIndex) {
+ return null;
+ }
}
interface ScrollDelegate {
diff --git a/core/java/android/widget/Editor.java b/core/java/android/widget/Editor.java
index f99f13843bd7..ddcfb40e00ce 100644
--- a/core/java/android/widget/Editor.java
+++ b/core/java/android/widget/Editor.java
@@ -2098,17 +2098,14 @@ public class Editor {
final int selectionEnd = mTextView.getSelectionEnd();
final InputMethodState ims = mInputMethodState;
- if (ims != null && ims.mBatchEditNesting == 0) {
+ if (ims != null && ims.mBatchEditNesting == 0
+ && (ims.mContentChanged || ims.mSelectionModeChanged)) {
InputMethodManager imm = getInputMethodManager();
- if (imm != null) {
- if (imm.isActive(mTextView)) {
- if (ims.mContentChanged || ims.mSelectionModeChanged) {
- // We are in extract mode and the content has changed
- // in some way... just report complete new text to the
- // input method.
- reportExtractedText();
- }
- }
+ if (imm != null && imm.hasActiveInputConnection(mTextView)) {
+ // We are in extract mode and the content has changed
+ // in some way... just report complete new text to the
+ // input method.
+ reportExtractedText();
}
}
@@ -4830,7 +4827,7 @@ public class Editor {
if (null == imm) {
return;
}
- if (!imm.isActive(mTextView)) {
+ if (!imm.hasActiveInputConnection(mTextView)) {
return;
}
// Skip if the IME has not requested the cursor/anchor position.
diff --git a/core/java/android/widget/SearchView.java b/core/java/android/widget/SearchView.java
index da094893abb9..b4d7a943ff17 100755
--- a/core/java/android/widget/SearchView.java
+++ b/core/java/android/widget/SearchView.java
@@ -2109,7 +2109,7 @@ public class SearchView extends LinearLayout implements CollapsibleActionView {
return;
}
- if (imm.isActive(this)) {
+ if (imm.hasActiveInputConnection(this)) {
// This means that SearchAutoComplete is already connected to the IME.
// InputMethodManager#showSoftInput() is guaranteed to pass client-side focus check.
mHasPendingShowSoftInputRequest = false;
diff --git a/core/java/android/window/DisplayWindowPolicyController.java b/core/java/android/window/DisplayWindowPolicyController.java
index c2700536f849..2747233a4bf1 100644
--- a/core/java/android/window/DisplayWindowPolicyController.java
+++ b/core/java/android/window/DisplayWindowPolicyController.java
@@ -17,8 +17,10 @@
package android.window;
import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
+import static android.view.Display.INVALID_DISPLAY;
import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.annotation.UserIdInt;
import android.app.WindowConfiguration;
import android.content.ComponentName;
@@ -107,18 +109,38 @@ public abstract class DisplayWindowPolicyController {
}
/**
- * Returns {@code true} if the given activities can be displayed on this virtual display and
- * the windowing mode is supported.
+ * Returns {@code true} if all of the given activities can be launched on this virtual display
+ * in the configuration defined by the rest of the arguments.
+ *
+ * @see #canContainActivity
+ */
+ public boolean canContainActivities(@NonNull List<ActivityInfo> activities,
+ @WindowConfiguration.WindowingMode int windowingMode) {
+ for (int i = 0; i < activities.size(); i++) {
+ if (!canContainActivity(activities.get(i), windowingMode,
+ /*launchingFromDisplayId=*/ INVALID_DISPLAY, /*isNewTask=*/ false)) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Returns {@code true} if the given activity can be launched on this virtual display in the
+ * configuration defined by the rest of the arguments. If the given intent would be intercepted
+ * by the display owner then this means that the activity cannot be launched.
*/
- public abstract boolean canContainActivities(@NonNull List<ActivityInfo> activities,
- @WindowConfiguration.WindowingMode int windowingMode);
+ public abstract boolean canActivityBeLaunched(@NonNull ActivityInfo activityInfo,
+ @Nullable Intent intent, @WindowConfiguration.WindowingMode int windowingMode,
+ int launchingFromDisplayId, boolean isNewTask);
/**
- * Returns {@code true} if the given new task can be launched on this virtual display.
+ * Returns {@code true} if the given activity can be launched on this virtual display in the
+ * configuration defined by the rest of the arguments.
*/
- public abstract boolean canActivityBeLaunched(@NonNull ActivityInfo activityInfo, Intent intent,
- @WindowConfiguration.WindowingMode int windowingMode, int launchingFromDisplayId,
- boolean isNewTask);
+ protected abstract boolean canContainActivity(@NonNull ActivityInfo activityInfo,
+ @WindowConfiguration.WindowingMode int windowingMode,
+ int launchingFromDisplayId, boolean isNewTask);
/**
* Called when an Activity window is layouted with the new changes where contains the
diff --git a/core/java/android/window/WindowMetricsController.java b/core/java/android/window/WindowMetricsController.java
index 2858f0a1a725..e32c8e58bb21 100644
--- a/core/java/android/window/WindowMetricsController.java
+++ b/core/java/android/window/WindowMetricsController.java
@@ -16,7 +16,7 @@
package android.window;
-import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
+import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
import static android.view.View.SYSTEM_UI_FLAG_VISIBLE;
import static android.view.WindowManager.LayoutParams.SOFT_INPUT_ADJUST_NOTHING;
@@ -80,7 +80,7 @@ public final class WindowMetricsController {
final Rect bounds;
final float density;
final boolean isScreenRound;
- final int windowingMode;
+ final int activityType;
synchronized (ResourcesManager.getInstance()) {
final Configuration config = mContext.getResources().getConfiguration();
final WindowConfiguration winConfig = config.windowConfiguration;
@@ -90,11 +90,11 @@ public final class WindowMetricsController {
// as DisplayMetrics#density
density = config.densityDpi * DisplayMetrics.DENSITY_DEFAULT_SCALE;
isScreenRound = config.isScreenRound();
- windowingMode = winConfig.getWindowingMode();
+ activityType = winConfig.getActivityType();
}
final IBinder token = Context.getToken(mContext);
final Supplier<WindowInsets> insetsSupplier = () -> getWindowInsetsFromServerForDisplay(
- mContext.getDisplayId(), token, bounds, isScreenRound, windowingMode);
+ mContext.getDisplayId(), token, bounds, isScreenRound, activityType);
return new WindowMetrics(new Rect(bounds), insetsSupplier, density);
}
@@ -105,23 +105,22 @@ public final class WindowMetricsController {
* @param token the token of Activity or WindowContext
* @param bounds the window bounds to calculate insets for
* @param isScreenRound if the display identified by displayId is round
- * @param windowingMode the windowing mode of the window to calculate insets for
+ * @param activityType the activity type of the window to calculate insets for
* @return WindowInsets calculated for the given window bounds, on the given display
*/
private static WindowInsets getWindowInsetsFromServerForDisplay(int displayId, IBinder token,
- Rect bounds, boolean isScreenRound, int windowingMode) {
+ Rect bounds, boolean isScreenRound, int activityType) {
try {
final InsetsState insetsState = new InsetsState();
- final boolean alwaysConsumeSystemBars = WindowManagerGlobal.getWindowManagerService()
- .getWindowInsets(displayId, token, insetsState);
+ WindowManagerGlobal.getWindowManagerService().getWindowInsets(
+ displayId, token, insetsState);
final float overrideInvScale = CompatibilityInfo.getOverrideInvertedScale();
if (overrideInvScale != 1f) {
insetsState.scale(overrideInvScale);
}
return insetsState.calculateInsets(bounds, null /* ignoringVisibilityState */,
- isScreenRound, alwaysConsumeSystemBars, SOFT_INPUT_ADJUST_NOTHING,
- 0 /* flags */, SYSTEM_UI_FLAG_VISIBLE,
- WindowManager.LayoutParams.INVALID_WINDOW_TYPE, windowingMode,
+ isScreenRound, SOFT_INPUT_ADJUST_NOTHING, 0 /* flags */, SYSTEM_UI_FLAG_VISIBLE,
+ WindowManager.LayoutParams.INVALID_WINDOW_TYPE, activityType,
null /* idSideMap */);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
@@ -157,7 +156,7 @@ public final class WindowMetricsController {
currentDisplayInfo.displayId, null /* token */,
new Rect(0, 0, currentDisplayInfo.getNaturalWidth(),
currentDisplayInfo.getNaturalHeight()), isScreenRound,
- WINDOWING_MODE_FULLSCREEN);
+ ACTIVITY_TYPE_UNDEFINED);
// Set the hardware-provided insets.
windowInsets = new WindowInsets.Builder(windowInsets).setRoundedCorners(
currentDisplayInfo.roundedCorners)
diff --git a/core/java/android/window/flags/windowing_sdk.aconfig b/core/java/android/window/flags/windowing_sdk.aconfig
index 560e41b1aa33..b8d251fc5cc5 100644
--- a/core/java/android/window/flags/windowing_sdk.aconfig
+++ b/core/java/android/window/flags/windowing_sdk.aconfig
@@ -8,3 +8,10 @@ flag {
description: "Whether the feature to sync different window-related config updates is enabled"
bug: "260873529"
}
+
+flag {
+ namespace: "windowing_sdk"
+ name: "activity_embedding_overlay_presentation_flag"
+ description: "Whether the overlay presentation feature is enabled"
+ bug: "243518738"
+}
diff --git a/core/java/com/android/internal/config/sysui/SystemUiDeviceConfigFlags.java b/core/java/com/android/internal/config/sysui/SystemUiDeviceConfigFlags.java
index 048912c0b2e2..2909b6a488b8 100644
--- a/core/java/com/android/internal/config/sysui/SystemUiDeviceConfigFlags.java
+++ b/core/java/com/android/internal/config/sysui/SystemUiDeviceConfigFlags.java
@@ -128,11 +128,6 @@ public final class SystemUiDeviceConfigFlags {
// Flag related to Privacy Indicators
/**
- * Whether to show the complete ongoing app ops chip.
- */
- public static final String PROPERTY_PERMISSIONS_HUB_ENABLED = "permissions_hub_2_enabled";
-
- /**
* Whether to show app ops chip for just microphone + camera.
*/
public static final String PROPERTY_MIC_CAMERA_ENABLED = "camera_mic_icons_enabled";
diff --git a/core/java/com/android/internal/content/InstallLocationUtils.java b/core/java/com/android/internal/content/InstallLocationUtils.java
index a173ce16feea..f3dd0f8f6993 100644
--- a/core/java/com/android/internal/content/InstallLocationUtils.java
+++ b/core/java/com/android/internal/content/InstallLocationUtils.java
@@ -454,8 +454,10 @@ public class InstallLocationUtils {
// Include raw dex metadata files
sizeBytes += DexMetadataHelper.getPackageDexMetadataSize(pkg);
- // Include all relevant native code
- sizeBytes += NativeLibraryHelper.sumNativeBinariesWithOverride(handle, abiOverride);
+ if (pkg.isExtractNativeLibs()) {
+ // Include all relevant native code
+ sizeBytes += NativeLibraryHelper.sumNativeBinariesWithOverride(handle, abiOverride);
+ }
return sizeBytes;
}
diff --git a/core/java/com/android/internal/policy/DecorView.java b/core/java/com/android/internal/policy/DecorView.java
index bb868018bc95..3e16df4d7f67 100644
--- a/core/java/com/android/internal/policy/DecorView.java
+++ b/core/java/com/android/internal/policy/DecorView.java
@@ -1113,15 +1113,14 @@ public class DecorView extends FrameLayout implements RootViewSurfaceTaker, Wind
if (insets != null) {
mLastForceConsumingTypes = insets.getForceConsumingTypes();
- @InsetsType int compatInsetsTypes =
+ final boolean clearsCompatInsets = clearsCompatInsets(attrs.type, attrs.flags,
+ getResources().getConfiguration().windowConfiguration.getActivityType(),
+ mLastForceConsumingTypes);
+ final @InsetsType int compatInsetsTypes =
WindowInsets.Type.systemBars() | WindowInsets.Type.displayCutout();
- if (clearsCompatInsets(attrs.type, attrs.flags,
- getResources().getConfiguration().windowConfiguration.getWindowingMode())) {
- compatInsetsTypes &= mLastForceConsumingTypes;
- }
final Insets stableBarInsets = insets.getInsetsIgnoringVisibility(
WindowInsets.Type.systemBars());
- final Insets systemInsets = compatInsetsTypes == 0
+ final Insets systemInsets = clearsCompatInsets
? Insets.NONE
: Insets.min(insets.getInsets(compatInsetsTypes), stableBarInsets);
mLastTopInset = systemInsets.top;
@@ -2625,8 +2624,7 @@ public class DecorView extends FrameLayout implements RootViewSurfaceTaker, Wind
@Override
public String toString() {
- return "DecorView@" + Integer.toHexString(this.hashCode()) + "["
- + getTitleSuffix(mWindow.getAttributes()) + "]";
+ return super.toString() + "[" + getTitleSuffix(mWindow.getAttributes()) + "]";
}
private static class ColorViewState {
diff --git a/core/java/com/android/internal/policy/TransitionAnimation.java b/core/java/com/android/internal/policy/TransitionAnimation.java
index aa2318d219f8..483a184a7ba2 100644
--- a/core/java/com/android/internal/policy/TransitionAnimation.java
+++ b/core/java/com/android/internal/policy/TransitionAnimation.java
@@ -1303,10 +1303,9 @@ public class TransitionAnimation {
ScreenCapture.ScreenshotHardwareBuffer buffer) {
t.setBuffer(layer, buffer.getHardwareBuffer());
t.setDataSpace(layer, buffer.getColorSpace().getDataSpace());
- // Avoid showing dimming effect for HDR content when running animation.
- if (buffer.containsHdrLayers()) {
- t.setDimmingEnabled(layer, false);
- }
+ // Avoid showing dimming effect for HDR content when running animations.
+ // TODO(b/298219334): Only do this if we know we already dimmed in the screenshot
+ t.setDimmingEnabled(layer, false);
}
/** Returns whether the hardware buffer passed in is marked as protected. */
diff --git a/core/java/com/android/internal/security/TEST_MAPPING b/core/java/com/android/internal/security/TEST_MAPPING
index 2d598dc57613..0af3b03edefc 100644
--- a/core/java/com/android/internal/security/TEST_MAPPING
+++ b/core/java/com/android/internal/security/TEST_MAPPING
@@ -12,10 +12,6 @@
]
},
{
- "name": "ApkVerityTest",
- "file_patterns": ["VerityUtils\\.java"]
- },
- {
"name": "UpdatableSystemFontTest",
"file_patterns": ["VerityUtils\\.java"]
},
@@ -23,5 +19,11 @@
"name": "CtsApkVerityInstallHostTestCases",
"file_patterns": ["VerityUtils\\.java"]
}
+ ],
+ "postsubmit": [
+ {
+ "name": "FsVerityTest",
+ "file_patterns": ["VerityUtils\\.java"]
+ }
]
}
diff --git a/core/java/com/android/internal/util/SettingsWrapper.java b/core/java/com/android/internal/util/SettingsWrapper.java
new file mode 100644
index 000000000000..8cf6c18adb3a
--- /dev/null
+++ b/core/java/com/android/internal/util/SettingsWrapper.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.util;
+
+import android.content.ContentResolver;
+import android.provider.Settings;
+
+/**
+ * A wrapper class for accessing and modifying system settings that would help with testing.
+ */
+public class SettingsWrapper {
+
+ /** Retrieves the string value of a system setting */
+ public String getStringForUser(ContentResolver contentResolver, String name, int userHandle) {
+ return Settings.System.getStringForUser(contentResolver, name, userHandle);
+ }
+
+ /** Updates the string value of a system setting */
+ public String putStringForUser(ContentResolver contentResolver, String name, int userHandle) {
+ return Settings.System.getStringForUser(contentResolver, name, userHandle);
+ }
+}
diff --git a/core/jni/android_media_AudioSystem.cpp b/core/jni/android_media_AudioSystem.cpp
index ccae67f3e953..6440cc3952f8 100644
--- a/core/jni/android_media_AudioSystem.cpp
+++ b/core/jni/android_media_AudioSystem.cpp
@@ -2071,10 +2071,67 @@ jobject convertAudioMixerAttributesFromNative(JNIEnv *env,
mixerBehavior);
}
-static jint convertAudioMixToNative(JNIEnv *env,
- AudioMix *nAudioMix,
- const jobject jAudioMix)
-{
+static jint convertAudioMixingRuleToNative(JNIEnv *env, const jobject audioMixingRule,
+ std::vector<AudioMixMatchCriterion> *nCriteria) {
+ jobject jRuleCriteria = env->GetObjectField(audioMixingRule, gAudioMixingRuleFields.mCriteria);
+
+ jobjectArray jCriteria = static_cast<jobjectArray>(
+ env->CallObjectMethod(jRuleCriteria, gArrayListMethods.toArray));
+ env->DeleteLocalRef(jRuleCriteria);
+
+ jint numCriteria = env->GetArrayLength(jCriteria);
+ if (numCriteria > MAX_CRITERIA_PER_MIX) {
+ numCriteria = MAX_CRITERIA_PER_MIX;
+ }
+
+ nCriteria->resize(numCriteria);
+ for (jint i = 0; i < numCriteria; i++) {
+ AudioMixMatchCriterion &nCriterion = (*nCriteria)[i];
+
+ jobject jCriterion = env->GetObjectArrayElement(jCriteria, i);
+
+ nCriterion.mRule = env->GetIntField(jCriterion, gAudioMixMatchCriterionFields.mRule);
+
+ const uint32_t match_rule = nCriterion.mRule & ~RULE_EXCLUSION_MASK;
+ switch (match_rule) {
+ case RULE_MATCH_UID:
+ nCriterion.mValue.mUid =
+ env->GetIntField(jCriterion, gAudioMixMatchCriterionFields.mIntProp);
+ break;
+ case RULE_MATCH_USERID:
+ nCriterion.mValue.mUserId =
+ env->GetIntField(jCriterion, gAudioMixMatchCriterionFields.mIntProp);
+ break;
+ case RULE_MATCH_AUDIO_SESSION_ID: {
+ jint jAudioSessionId =
+ env->GetIntField(jCriterion, gAudioMixMatchCriterionFields.mIntProp);
+ nCriterion.mValue.mAudioSessionId = static_cast<audio_session_t>(jAudioSessionId);
+ } break;
+ case RULE_MATCH_ATTRIBUTE_USAGE:
+ case RULE_MATCH_ATTRIBUTE_CAPTURE_PRESET: {
+ jobject jAttributes =
+ env->GetObjectField(jCriterion, gAudioMixMatchCriterionFields.mAttr);
+
+ auto paa = JNIAudioAttributeHelper::makeUnique();
+ jint jStatus = JNIAudioAttributeHelper::nativeFromJava(env, jAttributes, paa.get());
+ if (jStatus != AUDIO_JAVA_SUCCESS) {
+ return jStatus;
+ }
+ if (match_rule == RULE_MATCH_ATTRIBUTE_USAGE) {
+ nCriterion.mValue.mUsage = paa->usage;
+ } else {
+ nCriterion.mValue.mSource = paa->source;
+ }
+ env->DeleteLocalRef(jAttributes);
+ } break;
+ }
+ env->DeleteLocalRef(jCriterion);
+ }
+ env->DeleteLocalRef(jCriteria);
+ return AUDIO_JAVA_SUCCESS;
+}
+
+static jint convertAudioMixToNative(JNIEnv *env, AudioMix *nAudioMix, const jobject jAudioMix) {
nAudioMix->mMixType = env->GetIntField(jAudioMix, gAudioMixFields.mMixType);
nAudioMix->mRouteFlags = env->GetIntField(jAudioMix, gAudioMixFields.mRouteFlags);
nAudioMix->mDeviceType =
@@ -2094,69 +2151,16 @@ static jint convertAudioMixToNative(JNIEnv *env,
env->DeleteLocalRef(jFormat);
jobject jRule = env->GetObjectField(jAudioMix, gAudioMixFields.mRule);
- jobject jRuleCriteria = env->GetObjectField(jRule, gAudioMixingRuleFields.mCriteria);
nAudioMix->mAllowPrivilegedMediaPlaybackCapture =
env->GetBooleanField(jRule, gAudioMixingRuleFields.mAllowPrivilegedPlaybackCapture);
nAudioMix->mVoiceCommunicationCaptureAllowed =
env->GetBooleanField(jRule, gAudioMixingRuleFields.mVoiceCommunicationCaptureAllowed);
- env->DeleteLocalRef(jRule);
- jobjectArray jCriteria = static_cast<jobjectArray>(
- env->CallObjectMethod(jRuleCriteria, gArrayListMethods.toArray));
- env->DeleteLocalRef(jRuleCriteria);
-
- jint numCriteria = env->GetArrayLength(jCriteria);
- if (numCriteria > MAX_CRITERIA_PER_MIX) {
- numCriteria = MAX_CRITERIA_PER_MIX;
- }
- for (jint i = 0; i < numCriteria; i++) {
- AudioMixMatchCriterion nCriterion;
+ jint status = convertAudioMixingRuleToNative(env, jRule, &(nAudioMix->mCriteria));
- jobject jCriterion = env->GetObjectArrayElement(jCriteria, i);
-
- nCriterion.mRule = env->GetIntField(jCriterion, gAudioMixMatchCriterionFields.mRule);
-
- const uint32_t match_rule = nCriterion.mRule & ~RULE_EXCLUSION_MASK;
- switch (match_rule) {
- case RULE_MATCH_UID:
- nCriterion.mValue.mUid = env->GetIntField(jCriterion,
- gAudioMixMatchCriterionFields.mIntProp);
- break;
- case RULE_MATCH_USERID:
- nCriterion.mValue.mUserId =
- env->GetIntField(jCriterion, gAudioMixMatchCriterionFields.mIntProp);
- break;
- case RULE_MATCH_AUDIO_SESSION_ID: {
- jint jAudioSessionId =
- env->GetIntField(jCriterion, gAudioMixMatchCriterionFields.mIntProp);
- nCriterion.mValue.mAudioSessionId = static_cast<audio_session_t>(jAudioSessionId);
- } break;
- case RULE_MATCH_ATTRIBUTE_USAGE:
- case RULE_MATCH_ATTRIBUTE_CAPTURE_PRESET: {
- jobject jAttributes = env->GetObjectField(jCriterion, gAudioMixMatchCriterionFields.mAttr);
-
- auto paa = JNIAudioAttributeHelper::makeUnique();
- jint jStatus = JNIAudioAttributeHelper::nativeFromJava(env, jAttributes, paa.get());
- if (jStatus != AUDIO_JAVA_SUCCESS) {
- return jStatus;
- }
- if (match_rule == RULE_MATCH_ATTRIBUTE_USAGE) {
- nCriterion.mValue.mUsage = paa->usage;
- } else {
- nCriterion.mValue.mSource = paa->source;
- }
- env->DeleteLocalRef(jAttributes);
- }
- break;
- }
-
- nAudioMix->mCriteria.push_back(nCriterion);
- env->DeleteLocalRef(jCriterion);
- }
-
- env->DeleteLocalRef(jCriteria);
+ env->DeleteLocalRef(jRule);
- return AUDIO_JAVA_SUCCESS;
+ return status;
}
static jint
@@ -2200,6 +2204,45 @@ android_media_AudioSystem_registerPolicyMixes(JNIEnv *env, jobject clazz,
return nativeToJavaStatus(status);
}
+static jint android_media_AudioSystem_updatePolicyMixes(JNIEnv *env, jobject clazz,
+ jobjectArray mixes,
+ jobjectArray updatedMixingRules) {
+ if (mixes == nullptr || updatedMixingRules == nullptr) {
+ return AUDIO_JAVA_BAD_VALUE;
+ }
+
+ jsize updatesCount = env->GetArrayLength(mixes);
+ if (updatesCount == 0 || updatesCount != env->GetArrayLength(updatedMixingRules)) {
+ return AUDIO_JAVA_BAD_VALUE;
+ }
+
+ std::vector<std::pair<AudioMix, std::vector<AudioMixMatchCriterion>>> updates(updatesCount);
+ for (int i = 0; i < updatesCount; i++) {
+ jobject jAudioMix = env->GetObjectArrayElement(mixes, i);
+ jobject jAudioMixingRule = env->GetObjectArrayElement(updatedMixingRules, i);
+ if (!env->IsInstanceOf(jAudioMix, gAudioMixClass) ||
+ !env->IsInstanceOf(jAudioMixingRule, gAudioMixingRuleClass)) {
+ return AUDIO_JAVA_BAD_VALUE;
+ }
+
+ jint ret;
+ if ((ret = convertAudioMixToNative(env, &updates[i].first, jAudioMix)) !=
+ AUDIO_JAVA_SUCCESS) {
+ return ret;
+ }
+ if ((ret = convertAudioMixingRuleToNative(env, jAudioMixingRule, &updates[i].second)) !=
+ AUDIO_JAVA_SUCCESS) {
+ return ret;
+ }
+ }
+
+ ALOGV("AudioSystem::updatePolicyMixes numMixes %d", updatesCount);
+ int status = AudioSystem::updatePolicyMixes(updates);
+ ALOGV("AudioSystem::updatePolicyMixes returned %d", status);
+
+ return nativeToJavaStatus(status);
+}
+
static jint android_media_AudioSystem_setUidDeviceAffinities(JNIEnv *env, jobject clazz,
jint uid, jintArray deviceTypes, jobjectArray deviceAddresses) {
AudioDeviceTypeAddrVector deviceVector;
@@ -3158,6 +3201,10 @@ static const JNINativeMethod gMethods[] =
MAKE_AUDIO_SYSTEM_METHOD(getAudioHwSyncForSession),
MAKE_JNI_NATIVE_METHOD("registerPolicyMixes", "(Ljava/util/ArrayList;Z)I",
android_media_AudioSystem_registerPolicyMixes),
+ MAKE_JNI_NATIVE_METHOD("updatePolicyMixes",
+ "([Landroid/media/audiopolicy/AudioMix;[Landroid/media/audiopolicy/"
+ "AudioMixingRule;)I",
+ android_media_AudioSystem_updatePolicyMixes),
MAKE_JNI_NATIVE_METHOD("setUidDeviceAffinities", "(I[I[Ljava/lang/String;)I",
android_media_AudioSystem_setUidDeviceAffinities),
MAKE_AUDIO_SYSTEM_METHOD(removeUidDeviceAffinities),
diff --git a/core/res/OWNERS b/core/res/OWNERS
index b46902e3a8e9..0df7c2047bc1 100644
--- a/core/res/OWNERS
+++ b/core/res/OWNERS
@@ -52,3 +52,6 @@ per-file res/xml/power_profile_test.xml = file:/BATTERY_STATS_OWNERS
# Telephony
per-file res/values/config_telephony.xml = file:/platform/frameworks/opt/telephony:/OWNERS
per-file res/xml/sms_short_codes.xml = file:/platform/frameworks/opt/telephony:/OWNERS
+
+# TV Input Framework
+per-file res/values/config_tv_external_input_logging.xml = file:/services/core/java/com/android/server/tv/OWNERS
diff --git a/core/res/res/layout/autofill_fill_dialog.xml b/core/res/res/layout/autofill_fill_dialog.xml
index d1a4935633cb..37d2fa0540f0 100644
--- a/core/res/res/layout/autofill_fill_dialog.xml
+++ b/core/res/res/layout/autofill_fill_dialog.xml
@@ -85,14 +85,18 @@
android:layout_marginStart="24dp"
android:layout_marginEnd="24dp"
android:theme="@style/Theme.DeviceDefault.AutofillHalfScreenDialogButton"
- android:orientation="horizontal">
+ android:orientation="horizontal"
+ android:gravity="center_vertical">
<Button
android:id="@+id/autofill_dialog_no"
android:layout_width="wrap_content"
- android:layout_height="36dp"
- android:layout_marginTop="6dp"
- android:layout_marginBottom="6dp"
+ android:layout_height="40dp"
+ android:paddingStart="12dp"
+ android:paddingEnd="12dp"
+ android:paddingTop="0dp"
+ android:paddingBottom="0dp"
+ android:minWidth="0dp"
style="?android:attr/borderlessButtonStyle"
android:text="@string/autofill_save_no">
</Button>
@@ -107,9 +111,8 @@
<Button
android:id="@+id/autofill_dialog_yes"
android:layout_width="wrap_content"
- android:layout_height="36dp"
- android:layout_marginTop="6dp"
- android:layout_marginBottom="6dp"
+ android:layout_height="40dp"
+ android:minWidth="0dp"
style="@style/AutofillHalfSheetTonalButton"
android:text="@string/autofill_save_yes"
android:visibility="gone" >
diff --git a/core/res/res/layout/autofill_save.xml b/core/res/res/layout/autofill_save.xml
index 85529d6a4b3b..bed19a87eb16 100644
--- a/core/res/res/layout/autofill_save.xml
+++ b/core/res/res/layout/autofill_save.xml
@@ -72,14 +72,18 @@
android:layout_marginTop="32dp"
android:layout_marginBottom="18dp"
android:theme="@style/Theme.DeviceDefault.AutofillHalfScreenDialogButton"
- android:orientation="horizontal">
+ android:orientation="horizontal"
+ android:gravity="center_vertical">
<Button
android:id="@+id/autofill_save_no"
android:layout_width="wrap_content"
- android:layout_height="36dp"
- android:layout_marginTop="6dp"
- android:layout_marginBottom="6dp"
+ android:layout_height="40dp"
+ android:paddingStart="12dp"
+ android:paddingEnd="12dp"
+ android:paddingTop="0dp"
+ android:paddingBottom="0dp"
+ android:minWidth="0dp"
style="?android:attr/borderlessButtonStyle"
android:text="@string/autofill_save_no">
</Button>
@@ -94,9 +98,8 @@
<Button
android:id="@+id/autofill_save_yes"
android:layout_width="wrap_content"
- android:layout_height="36dp"
- android:layout_marginTop="6dp"
- android:layout_marginBottom="6dp"
+ android:layout_height="40dp"
+ android:minWidth="0dp"
style="@style/AutofillHalfSheetTonalButton"
android:text="@string/autofill_save_yes">
</Button>
diff --git a/core/res/res/values-af/strings.xml b/core/res/res/values-af/strings.xml
index 46fb80c77841..b1caec253949 100644
--- a/core/res/res/values-af/strings.xml
+++ b/core/res/res/values-af/strings.xml
@@ -1867,6 +1867,7 @@
<string name="managed_profile_label_badge_2" msgid="5673187309555352550">"2e werk-<xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="managed_profile_label_badge_3" msgid="6882151970556391957">"3e werk-<xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="clone_profile_label_badge" msgid="1871997694718793964">"Kloon <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+ <string name="private_profile_label_badge" msgid="1712086003787839183">"Privaat <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"Vra PIN voordat jy ontspeld"</string>
<string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"Vra ontsluitpatroon voordat jy ontspeld"</string>
<string name="lock_to_app_unlock_password" msgid="9126722403506560473">"Vra wagwoord voordat jy ontspeld"</string>
@@ -2031,8 +2032,7 @@
<string name="autofill_update_title" msgid="3630695947047069136">"Dateer op in "<b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>"?"</string>
<string name="autofill_update_title_with_type" msgid="5264152633488495704">"Dateer <xliff:g id="TYPE">%1$s</xliff:g> op in "<b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>"?"</string>
<string name="autofill_update_title_with_2types" msgid="1797514386321086273">"Dateer <xliff:g id="TYPE_0">%1$s</xliff:g> en <xliff:g id="TYPE_1">%2$s</xliff:g> op in "<b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>"?"</string>
- <!-- no translation found for autofill_update_title_with_3types (8285767070604652626) -->
- <skip />
+ <string name="autofill_update_title_with_3types" msgid="8285767070604652626">"Dateer hierdie items op in "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>": <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> en <xliff:g id="TYPE_2">%3$s</xliff:g>?"</string>
<string name="autofill_save_yes" msgid="8035743017382012850">"Stoor"</string>
<string name="autofill_save_no" msgid="9212826374207023544">"Nee, dankie"</string>
<string name="autofill_save_notnow" msgid="2853932672029024195">"Nie nou nie"</string>
diff --git a/core/res/res/values-am/strings.xml b/core/res/res/values-am/strings.xml
index 40246beffbf2..8109e9ab4cae 100644
--- a/core/res/res/values-am/strings.xml
+++ b/core/res/res/values-am/strings.xml
@@ -1867,6 +1867,8 @@
<string name="managed_profile_label_badge_2" msgid="5673187309555352550">"2ኛ ሥራ <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="managed_profile_label_badge_3" msgid="6882151970556391957">"3ኛ ሥራ <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="clone_profile_label_badge" msgid="1871997694718793964">"<xliff:g id="LABEL">%1$s</xliff:g>ን አባዛ"</string>
+ <!-- no translation found for private_profile_label_badge (1712086003787839183) -->
+ <skip />
<string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"ከመንቀል በፊት ፒን ጠይቅ"</string>
<string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"ከመንቀል በፊት የማስከፈቻ ስርዓተ-ጥለት ጠይቅ"</string>
<string name="lock_to_app_unlock_password" msgid="9126722403506560473">"ከመንቀል በፊት የይለፍ ቃል ጠይቅ"</string>
@@ -2031,8 +2033,7 @@
<string name="autofill_update_title" msgid="3630695947047069136">"በ"<b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>" ውስጥ ይዘመን?"</string>
<string name="autofill_update_title_with_type" msgid="5264152633488495704">"<xliff:g id="TYPE">%1$s</xliff:g> በ"<b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>" ውስጥ ይዘመን?"</string>
<string name="autofill_update_title_with_2types" msgid="1797514386321086273">"<xliff:g id="TYPE_0">%1$s</xliff:g> እና <xliff:g id="TYPE_1">%2$s</xliff:g> በ"<b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>" ውስጥ ይዘመኑ?"</string>
- <!-- no translation found for autofill_update_title_with_3types (8285767070604652626) -->
- <skip />
+ <string name="autofill_update_title_with_3types" msgid="8285767070604652626">"እነዚህ ንጥሎች በ"<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>" ውስጥ ይዘመኑ፦ <xliff:g id="TYPE_0">%1$s</xliff:g>፣ <xliff:g id="TYPE_1">%2$s</xliff:g> እና <xliff:g id="TYPE_2">%3$s</xliff:g>?"</string>
<string name="autofill_save_yes" msgid="8035743017382012850">"አስቀምጥ"</string>
<string name="autofill_save_no" msgid="9212826374207023544">"አይ፣ አመሰግናለሁ"</string>
<string name="autofill_save_notnow" msgid="2853932672029024195">"አሁን አይደለም"</string>
diff --git a/core/res/res/values-ar/strings.xml b/core/res/res/values-ar/strings.xml
index 0286d42611dc..ff1ecdca11da 100644
--- a/core/res/res/values-ar/strings.xml
+++ b/core/res/res/values-ar/strings.xml
@@ -1871,6 +1871,7 @@
<string name="managed_profile_label_badge_2" msgid="5673187309555352550">"العمل الثاني <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="managed_profile_label_badge_3" msgid="6882151970556391957">"العمل الثالث <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="clone_profile_label_badge" msgid="1871997694718793964">"نسخة طبق الأصل عن \"<xliff:g id="LABEL">%1$s</xliff:g>\""</string>
+ <string name="private_profile_label_badge" msgid="1712086003787839183">"ملف شخصي خاص على <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"طلب إدخال رقم التعريف الشخصي قبل إزالة التثبيت"</string>
<string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"طلب إدخال النقش الخاص بإلغاء القفل قبل إزالة التثبيت"</string>
<string name="lock_to_app_unlock_password" msgid="9126722403506560473">"طلب إدخال كلمة المرور قبل إزالة التثبيت"</string>
@@ -2035,8 +2036,7 @@
<string name="autofill_update_title" msgid="3630695947047069136">"هل تريد التحديث في "<b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>"؟"</string>
<string name="autofill_update_title_with_type" msgid="5264152633488495704">"هل تريد تحديث <xliff:g id="TYPE">%1$s</xliff:g> في "<b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>"؟"</string>
<string name="autofill_update_title_with_2types" msgid="1797514386321086273">"هل تريد تحديث <xliff:g id="TYPE_0">%1$s</xliff:g> و<xliff:g id="TYPE_1">%2$s</xliff:g> في "<b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>"؟"</string>
- <!-- no translation found for autofill_update_title_with_3types (8285767070604652626) -->
- <skip />
+ <string name="autofill_update_title_with_3types" msgid="8285767070604652626">"هل تريد تعديل هذه العناصر في "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>": <xliff:g id="TYPE_0">%1$s</xliff:g> و<xliff:g id="TYPE_1">%2$s</xliff:g> و<xliff:g id="TYPE_2">%3$s</xliff:g>؟"</string>
<string name="autofill_save_yes" msgid="8035743017382012850">"حفظ"</string>
<string name="autofill_save_no" msgid="9212826374207023544">"لا، شكرًا"</string>
<string name="autofill_save_notnow" msgid="2853932672029024195">"ليس الآن"</string>
diff --git a/core/res/res/values-as/strings.xml b/core/res/res/values-as/strings.xml
index a1679b3bdc38..f2aee4063cc9 100644
--- a/core/res/res/values-as/strings.xml
+++ b/core/res/res/values-as/strings.xml
@@ -1867,6 +1867,8 @@
<string name="managed_profile_label_badge_2" msgid="5673187309555352550">"২য় কার্য <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="managed_profile_label_badge_3" msgid="6882151970556391957">"৩য় কার্য <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="clone_profile_label_badge" msgid="1871997694718793964">"ক্ল’ন <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+ <!-- no translation found for private_profile_label_badge (1712086003787839183) -->
+ <skip />
<string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"আনপিন কৰাৰ পূৰ্বে পিন দিবলৈ কওক"</string>
<string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"আনপিন কৰাৰ পূৰ্বে আনলক আৰ্হি দিবলৈ কওক"</string>
<string name="lock_to_app_unlock_password" msgid="9126722403506560473">"আনপিন কৰাৰ পূৰ্বে পাছৱৰ্ড দিবলৈ কওক"</string>
@@ -2031,8 +2033,7 @@
<string name="autofill_update_title" msgid="3630695947047069136"><b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>"ত আপডে’ট কৰিবনে?"</string>
<string name="autofill_update_title_with_type" msgid="5264152633488495704"><b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>"ত <xliff:g id="TYPE">%1$s</xliff:g> আপডে’ট কৰিবনে?"</string>
<string name="autofill_update_title_with_2types" msgid="1797514386321086273"><b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>"ত <xliff:g id="TYPE_0">%1$s</xliff:g> আৰু <xliff:g id="TYPE_1">%2$s</xliff:g> আপডে’ট কৰিবনে?"</string>
- <!-- no translation found for autofill_update_title_with_3types (8285767070604652626) -->
- <skip />
+ <string name="autofill_update_title_with_3types" msgid="8285767070604652626">"এই তথ্যবোৰ "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>": <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> আৰু <xliff:g id="TYPE_2">%3$s</xliff:g>ত আপডে’ট কৰিবনে?"</string>
<string name="autofill_save_yes" msgid="8035743017382012850">"ছেভ কৰক"</string>
<string name="autofill_save_no" msgid="9212826374207023544">"নালাগে, ধন্যবাদ"</string>
<string name="autofill_save_notnow" msgid="2853932672029024195">"এতিয়া নহয়"</string>
diff --git a/core/res/res/values-az/strings.xml b/core/res/res/values-az/strings.xml
index 49a599e5dd09..0004ba87d9fd 100644
--- a/core/res/res/values-az/strings.xml
+++ b/core/res/res/values-az/strings.xml
@@ -1867,6 +1867,7 @@
<string name="managed_profile_label_badge_2" msgid="5673187309555352550">"2-ci İş <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="managed_profile_label_badge_3" msgid="6882151970556391957">"3-cü İş <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="clone_profile_label_badge" msgid="1871997694718793964">"Kopyalayın: <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+ <string name="private_profile_label_badge" msgid="1712086003787839183">"Şəxsi <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"Ayırmadan öncə PIN istənilsin"</string>
<string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"Qrafik açar istənilsin"</string>
<string name="lock_to_app_unlock_password" msgid="9126722403506560473">"Ayırmadan öncə parol istənilsin"</string>
@@ -2031,8 +2032,7 @@
<string name="autofill_update_title" msgid="3630695947047069136"><b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>" ünvanında yenilənsin?"</string>
<string name="autofill_update_title_with_type" msgid="5264152633488495704">"<xliff:g id="TYPE">%1$s</xliff:g> "<b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>" ünvanında yenilənsin?"</string>
<string name="autofill_update_title_with_2types" msgid="1797514386321086273">"<xliff:g id="TYPE_0">%1$s</xliff:g> və <xliff:g id="TYPE_1">%2$s</xliff:g> "<b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>" ünvanında yenilənsin?"</string>
- <!-- no translation found for autofill_update_title_with_3types (8285767070604652626) -->
- <skip />
+ <string name="autofill_update_title_with_3types" msgid="8285767070604652626"><b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>": <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> və <xliff:g id="TYPE_2">%3$s</xliff:g> bölmələrində bu elementlər yenilənsin?"</string>
<string name="autofill_save_yes" msgid="8035743017382012850">"Yadda saxlayın"</string>
<string name="autofill_save_no" msgid="9212826374207023544">"Xeyr, çox sağ olun"</string>
<string name="autofill_save_notnow" msgid="2853932672029024195">"İndi yox"</string>
diff --git a/core/res/res/values-b+sr+Latn/strings.xml b/core/res/res/values-b+sr+Latn/strings.xml
index 97483a4df1ae..592c3440c7e1 100644
--- a/core/res/res/values-b+sr+Latn/strings.xml
+++ b/core/res/res/values-b+sr+Latn/strings.xml
@@ -494,7 +494,7 @@
<string name="permdesc_sim_communication" msgid="4179799296415957960">"Omogućava aplikaciji da šalje komande SIM kartici. To je veoma opasno."</string>
<string name="permlab_activityRecognition" msgid="1782303296053990884">"prepoznavanje fizičkih aktivnosti"</string>
<string name="permdesc_activityRecognition" msgid="8667484762991357519">"Ova aplikacija može da prepozna fizičke aktivnosti."</string>
- <string name="permlab_camera" msgid="6320282492904119413">"snimanje fotografija i video snimaka"</string>
+ <string name="permlab_camera" msgid="6320282492904119413">"snimanje fotografija i videa"</string>
<string name="permdesc_camera" msgid="5240801376168647151">"Ova aplikacija može da snima slike i video snimke pomoću kamere dok se aplikacija koristi."</string>
<string name="permlab_backgroundCamera" msgid="7549917926079731681">"da snima slike i video snimke u pozadini"</string>
<string name="permdesc_backgroundCamera" msgid="1615291686191138250">"Ova aplikacija može da snima fotografije i video snimke pomoću kamere u bilo kom trenutku."</string>
@@ -745,8 +745,8 @@
<string name="permdesc_readMediaVideo" msgid="3846400073770403528">"Omogućava aplikaciji da čita video fajlove iz deljenog memorijskog prostora."</string>
<string name="permlab_readMediaImages" msgid="4057590631020986789">"čitanje fajlova slika iz deljenog memorijskog prostora"</string>
<string name="permdesc_readMediaImages" msgid="5836219373138469259">"Omogućava aplikaciji da čita fajlove slika iz deljenog memorijskog prostora."</string>
- <string name="permlab_readVisualUserSelect" msgid="5516204215354667586">"čitanje fajlova slika i video snimaka koje korisnik bira iz deljenog memorijskog prostora"</string>
- <string name="permdesc_readVisualUserSelect" msgid="8027174717714968217">"Omogućava aplikaciji da čita fajlove slika i video snimaka koje izaberete iz deljenog memorijskog prostora."</string>
+ <string name="permlab_readVisualUserSelect" msgid="5516204215354667586">"čitanje fajlova slika i videa koje korisnik bira iz deljenog memorijskog prostora"</string>
+ <string name="permdesc_readVisualUserSelect" msgid="8027174717714968217">"Omogućava aplikaciji da čita fajlove slika i videa koje izaberete iz deljenog memorijskog prostora."</string>
<string name="permlab_sdcardWrite" msgid="4863021819671416668">"menjanje ili brisanje sadržaja deljenog memorijskog prostora"</string>
<string name="permdesc_sdcardWrite" msgid="8376047679331387102">"Dozvoljava aplikaciji da upisuje sadržaj deljenog memorijskog prostora."</string>
<string name="permlab_use_sip" msgid="8250774565189337477">"upućivanje/prijem SIP poziva"</string>
@@ -1172,7 +1172,7 @@
<string name="app_running_notification_text" msgid="5120815883400228566">"Dodirnite za više informacija ili zaustavljanje aplikacije."</string>
<string name="ok" msgid="2646370155170753815">"Potvrdi"</string>
<string name="cancel" msgid="6908697720451760115">"Otkaži"</string>
- <string name="yes" msgid="9069828999585032361">"Potvrdi"</string>
+ <string name="yes" msgid="9069828999585032361">"U redu"</string>
<string name="no" msgid="5122037903299899715">"Otkaži"</string>
<string name="dialog_alert_title" msgid="651856561974090712">"Pažnja"</string>
<string name="loading" msgid="3138021523725055037">"Učitava se…"</string>
@@ -1417,7 +1417,7 @@
<string name="ext_media_new_notification_message" msgid="6095403121990786986">"Dodirnite da biste podesili"</string>
<string name="ext_media_new_notification_message" product="tv" msgid="216863352100263668">"Izaberite da biste podesili"</string>
<string name="ext_media_new_notification_message" product="automotive" msgid="5140127881613227162">"Možda morate da reformatirate uređaj. Dodirnite da biste izbacili."</string>
- <string name="ext_media_ready_notification_message" msgid="7509496364380197369">"Za čuvanje slika, video snimaka, muzike i drugog sadržaja"</string>
+ <string name="ext_media_ready_notification_message" msgid="7509496364380197369">"Za čuvanje slika, videa, muzike i drugog sadržaja"</string>
<string name="ext_media_ready_notification_message" product="tv" msgid="8847134811163165935">"Pregledajte medijske fajlove"</string>
<string name="ext_media_unmountable_notification_title" msgid="4895444667278979910">"Problem sa: <xliff:g id="NAME">%s</xliff:g>"</string>
<string name="ext_media_unmountable_notification_title" product="automotive" msgid="3142723758949023280">"<xliff:g id="NAME">%s</xliff:g> ne radi"</string>
@@ -1868,6 +1868,7 @@
<string name="managed_profile_label_badge_2" msgid="5673187309555352550">"2. poslovni <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="managed_profile_label_badge_3" msgid="6882151970556391957">"3. poslovni imejl <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="clone_profile_label_badge" msgid="1871997694718793964">"Kloniraj <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+ <string name="private_profile_label_badge" msgid="1712086003787839183">"Privatni <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"Traži PIN pre otkačinjanja"</string>
<string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"Traži šablon za otključavanje pre otkačinjanja"</string>
<string name="lock_to_app_unlock_password" msgid="9126722403506560473">"Traži lozinku pre otkačinjanja"</string>
@@ -2032,8 +2033,7 @@
<string name="autofill_update_title" msgid="3630695947047069136">"Želite li da ažurirate u usluzi "<b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>"?"</string>
<string name="autofill_update_title_with_type" msgid="5264152633488495704">"Želite li da ažurirate stavku <xliff:g id="TYPE">%1$s</xliff:g> u usluzi "<b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>"?"</string>
<string name="autofill_update_title_with_2types" msgid="1797514386321086273">"Želite li da ažurirate stavke <xliff:g id="TYPE_0">%1$s</xliff:g> i <xliff:g id="TYPE_1">%2$s</xliff:g> u usluzi "<b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>"?"</string>
- <!-- no translation found for autofill_update_title_with_3types (8285767070604652626) -->
- <skip />
+ <string name="autofill_update_title_with_3types" msgid="8285767070604652626">"Želite li da ažurirate ove stavke u usluzi "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>": <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> i <xliff:g id="TYPE_2">%3$s</xliff:g>?"</string>
<string name="autofill_save_yes" msgid="8035743017382012850">"Sačuvaj"</string>
<string name="autofill_save_no" msgid="9212826374207023544">"Ne, hvala"</string>
<string name="autofill_save_notnow" msgid="2853932672029024195">"Ne sada"</string>
diff --git a/core/res/res/values-be/strings.xml b/core/res/res/values-be/strings.xml
index cd87b5291fbb..4cd8aa589d65 100644
--- a/core/res/res/values-be/strings.xml
+++ b/core/res/res/values-be/strings.xml
@@ -671,14 +671,10 @@
</string-array>
<string name="fingerprint_error_vendor_unknown" msgid="4170002184907291065">"Нешта пайшло не так. Паўтарыце спробу."</string>
<string name="fingerprint_icon_content_description" msgid="4741068463175388817">"Значок адбіткаў пальцаў"</string>
- <!-- no translation found for device_unlock_notification_name (2632928999862915709) -->
- <skip />
- <!-- no translation found for alternative_unlock_setup_notification_title (6241508547901933544) -->
- <skip />
- <!-- no translation found for alternative_face_setup_notification_content (3384959224091897331) -->
- <skip />
- <!-- no translation found for alternative_fp_setup_notification_content (7454096947415721639) -->
- <skip />
+ <string name="device_unlock_notification_name" msgid="2632928999862915709">"Разблакіроўка прылады"</string>
+ <string name="alternative_unlock_setup_notification_title" msgid="6241508547901933544">"Паспрабуйце іншы спосаб разблакіроўкі"</string>
+ <string name="alternative_face_setup_notification_content" msgid="3384959224091897331">"Выкарыстоўвайце распазнаванне твару, калі прылада не распазнае ваш адбітак пальца. Гэта функцыя можа прыдацца, напрыклад, калі ў вас мокрыя пальцы."</string>
+ <string name="alternative_fp_setup_notification_content" msgid="7454096947415721639">"Выкарыстоўвайце разблакіроўку адбіткам пальца, калі прылада не распазнае ваш твар. Гэта функцыя можа прыдацца, напрыклад, ва ўмовах недастатковай асветленасці."</string>
<string name="face_recalibrate_notification_name" msgid="7311163114750748686">"Распазнаванне твару"</string>
<string name="face_recalibrate_notification_title" msgid="2524791952735579082">"Праблема з распазнаваннем твару"</string>
<string name="face_recalibrate_notification_content" msgid="3064513770251355594">"Націсніце, каб выдаліць мадэль твару, пасля дадайце твар яшчэ раз"</string>
@@ -1873,6 +1869,8 @@
<string name="managed_profile_label_badge_2" msgid="5673187309555352550">"Другая праца <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="managed_profile_label_badge_3" msgid="6882151970556391957">"Трэцяя праца <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="clone_profile_label_badge" msgid="1871997694718793964">"Кланіраваць \"<xliff:g id="LABEL">%1$s</xliff:g>\""</string>
+ <!-- no translation found for private_profile_label_badge (1712086003787839183) -->
+ <skip />
<string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"Запытваць PIN-код перад адмацаваннем"</string>
<string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"Запытваць узор разблакіроўкі перад адмацаваннем"</string>
<string name="lock_to_app_unlock_password" msgid="9126722403506560473">"Запытваць пароль перад адмацаваннем"</string>
@@ -2037,8 +2035,7 @@
<string name="autofill_update_title" msgid="3630695947047069136">"Абнавіць у сэрвісе "<b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>"?"</string>
<string name="autofill_update_title_with_type" msgid="5264152633488495704">"Абнавіць даныя \"<xliff:g id="TYPE">%1$s</xliff:g>\" у сэрвісе "<b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>"?"</string>
<string name="autofill_update_title_with_2types" msgid="1797514386321086273">"Абнавіць даныя \"<xliff:g id="TYPE_0">%1$s</xliff:g>\" і \"<xliff:g id="TYPE_1">%2$s</xliff:g>\" у сэрвісе "<b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>"?"</string>
- <!-- no translation found for autofill_update_title_with_3types (8285767070604652626) -->
- <skip />
+ <string name="autofill_update_title_with_3types" msgid="8285767070604652626">"Абнавіць наступныя даныя ў сэрвісе "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>": <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> і <xliff:g id="TYPE_2">%3$s</xliff:g>?"</string>
<string name="autofill_save_yes" msgid="8035743017382012850">"Захаваць"</string>
<string name="autofill_save_no" msgid="9212826374207023544">"Не, дзякуй"</string>
<string name="autofill_save_notnow" msgid="2853932672029024195">"Не зараз"</string>
diff --git a/core/res/res/values-bg/strings.xml b/core/res/res/values-bg/strings.xml
index 7810776bed92..97345fcf4b3d 100644
--- a/core/res/res/values-bg/strings.xml
+++ b/core/res/res/values-bg/strings.xml
@@ -1867,6 +1867,7 @@
<string name="managed_profile_label_badge_2" msgid="5673187309555352550">"Втори служебен профил (<xliff:g id="LABEL">%1$s</xliff:g>)"</string>
<string name="managed_profile_label_badge_3" msgid="6882151970556391957">"Трети служебен профил (<xliff:g id="LABEL">%1$s</xliff:g>)"</string>
<string name="clone_profile_label_badge" msgid="1871997694718793964">"Копие на <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+ <string name="private_profile_label_badge" msgid="1712086003787839183">"Частен <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"Запитване за ПИН код преди освобождаване"</string>
<string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"Запитване за фигура за отключване преди освобождаване"</string>
<string name="lock_to_app_unlock_password" msgid="9126722403506560473">"Запитване за парола преди освобождаване"</string>
@@ -2031,8 +2032,7 @@
<string name="autofill_update_title" msgid="3630695947047069136">"Искате ли да актуализирате в(ъв) "<b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>"?"</string>
<string name="autofill_update_title_with_type" msgid="5264152633488495704">"Искате ли да актуализирате <xliff:g id="TYPE">%1$s</xliff:g> в(ъв) "<b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>"?"</string>
<string name="autofill_update_title_with_2types" msgid="1797514386321086273">"Искате ли да актуализирате <xliff:g id="TYPE_0">%1$s</xliff:g> и <xliff:g id="TYPE_1">%2$s</xliff:g> в(ъв) "<b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>"?"</string>
- <!-- no translation found for autofill_update_title_with_3types (8285767070604652626) -->
- <skip />
+ <string name="autofill_update_title_with_3types" msgid="8285767070604652626">"Искате ли да актуализирате тези елементи в(ъв) "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>": <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> и <xliff:g id="TYPE_2">%3$s</xliff:g>?"</string>
<string name="autofill_save_yes" msgid="8035743017382012850">"Запазване"</string>
<string name="autofill_save_no" msgid="9212826374207023544">"Не, благодаря"</string>
<string name="autofill_save_notnow" msgid="2853932672029024195">"Не сега"</string>
diff --git a/core/res/res/values-bn/strings.xml b/core/res/res/values-bn/strings.xml
index 02bfaae2cfe9..1d1e29c9d517 100644
--- a/core/res/res/values-bn/strings.xml
+++ b/core/res/res/values-bn/strings.xml
@@ -1867,6 +1867,8 @@
<string name="managed_profile_label_badge_2" msgid="5673187309555352550">"দ্বিতীয় কার্যক্ষেত্র <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="managed_profile_label_badge_3" msgid="6882151970556391957">"তৃতীয় কার্যক্ষেত্র <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="clone_profile_label_badge" msgid="1871997694718793964">"<xliff:g id="LABEL">%1$s</xliff:g> ক্লোন"</string>
+ <!-- no translation found for private_profile_label_badge (1712086003787839183) -->
+ <skip />
<string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"আনপিন করার আগে পিন চান"</string>
<string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"আনপিন করার আগে আনলক প্যাটার্ন চান"</string>
<string name="lock_to_app_unlock_password" msgid="9126722403506560473">"আনপিন করার আগে পাসওয়ার্ড চান"</string>
@@ -2031,8 +2033,7 @@
<string name="autofill_update_title" msgid="3630695947047069136"><b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>"-এ আপডেট করতে চান?"</string>
<string name="autofill_update_title_with_type" msgid="5264152633488495704"><b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>"-এ <xliff:g id="TYPE">%1$s</xliff:g> আপডেট করতে চান?"</string>
<string name="autofill_update_title_with_2types" msgid="1797514386321086273"><b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>"-এ <xliff:g id="TYPE_0">%1$s</xliff:g> এবং <xliff:g id="TYPE_1">%2$s</xliff:g> আপডেট করতে চান?"</string>
- <!-- no translation found for autofill_update_title_with_3types (8285767070604652626) -->
- <skip />
+ <string name="autofill_update_title_with_3types" msgid="8285767070604652626">"এইসব আইটেম "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>"-এ আপডেট করতে চান: <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> ও <xliff:g id="TYPE_2">%3$s</xliff:g>?"</string>
<string name="autofill_save_yes" msgid="8035743017382012850">"সেভ করুন"</string>
<string name="autofill_save_no" msgid="9212826374207023544">"না থাক"</string>
<string name="autofill_save_notnow" msgid="2853932672029024195">"এখনই নয়"</string>
diff --git a/core/res/res/values-bs/strings.xml b/core/res/res/values-bs/strings.xml
index 00aa3073a761..3fd0637d27f9 100644
--- a/core/res/res/values-bs/strings.xml
+++ b/core/res/res/values-bs/strings.xml
@@ -1868,6 +1868,7 @@
<string name="managed_profile_label_badge_2" msgid="5673187309555352550">"2. poslovni <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="managed_profile_label_badge_3" msgid="6882151970556391957">"3. poslovni <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="clone_profile_label_badge" msgid="1871997694718793964">"Kloniranje aplikacije <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+ <string name="private_profile_label_badge" msgid="1712086003787839183">"<xliff:g id="LABEL">%1$s</xliff:g> – privatno"</string>
<string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"Traži PIN prije nego se otkači"</string>
<string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"Traži uzorak za otključavanje prije poništavanja kačenja"</string>
<string name="lock_to_app_unlock_password" msgid="9126722403506560473">"Traži lozinku prije nego se otkači"</string>
@@ -2032,8 +2033,7 @@
<string name="autofill_update_title" msgid="3630695947047069136">"Ažurirati u "<b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>"?"</string>
<string name="autofill_update_title_with_type" msgid="5264152633488495704">"Ažurirati <xliff:g id="TYPE">%1$s</xliff:g> u "<b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>"?"</string>
<string name="autofill_update_title_with_2types" msgid="1797514386321086273">"Ažurirati <xliff:g id="TYPE_0">%1$s</xliff:g> i <xliff:g id="TYPE_1">%2$s</xliff:g> u "<b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>"?"</string>
- <!-- no translation found for autofill_update_title_with_3types (8285767070604652626) -->
- <skip />
+ <string name="autofill_update_title_with_3types" msgid="8285767070604652626">"Ažurirati ove stavke u oznaci "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>": <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> i <xliff:g id="TYPE_2">%3$s</xliff:g>?"</string>
<string name="autofill_save_yes" msgid="8035743017382012850">"Sačuvaj"</string>
<string name="autofill_save_no" msgid="9212826374207023544">"Ne, hvala"</string>
<string name="autofill_save_notnow" msgid="2853932672029024195">"Ne sada"</string>
diff --git a/core/res/res/values-ca/strings.xml b/core/res/res/values-ca/strings.xml
index 42e631b78805..5ec91f5ebce8 100644
--- a/core/res/res/values-ca/strings.xml
+++ b/core/res/res/values-ca/strings.xml
@@ -1868,6 +1868,8 @@
<string name="managed_profile_label_badge_2" msgid="5673187309555352550">"2n <xliff:g id="LABEL">%1$s</xliff:g> de la feina"</string>
<string name="managed_profile_label_badge_3" msgid="6882151970556391957">"3r <xliff:g id="LABEL">%1$s</xliff:g> de la feina"</string>
<string name="clone_profile_label_badge" msgid="1871997694718793964">"Clon de <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+ <!-- no translation found for private_profile_label_badge (1712086003787839183) -->
+ <skip />
<string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"Sol·licita el PIN per deixar de fixar"</string>
<string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"Sol·licita el patró de desbloqueig per deixar de fixar"</string>
<string name="lock_to_app_unlock_password" msgid="9126722403506560473">"Demana la contrasenya per deixar de fixar"</string>
@@ -2032,8 +2034,7 @@
<string name="autofill_update_title" msgid="3630695947047069136">"Vols actualitzar-ho a "<b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>"?"</string>
<string name="autofill_update_title_with_type" msgid="5264152633488495704">"Vols actualitzar <xliff:g id="TYPE">%1$s</xliff:g> a "<b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>"?"</string>
<string name="autofill_update_title_with_2types" msgid="1797514386321086273">"Vols actualitzar <xliff:g id="TYPE_0">%1$s</xliff:g> i <xliff:g id="TYPE_1">%2$s</xliff:g> a "<b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>"?"</string>
- <!-- no translation found for autofill_update_title_with_3types (8285767070604652626) -->
- <skip />
+ <string name="autofill_update_title_with_3types" msgid="8285767070604652626">"Vols actualitzar aquests elements a "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>": <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> i <xliff:g id="TYPE_2">%3$s</xliff:g>?"</string>
<string name="autofill_save_yes" msgid="8035743017382012850">"Desa"</string>
<string name="autofill_save_no" msgid="9212826374207023544">"No, gràcies"</string>
<string name="autofill_save_notnow" msgid="2853932672029024195">"Ara no"</string>
diff --git a/core/res/res/values-cs/strings.xml b/core/res/res/values-cs/strings.xml
index 772ef5334f82..89d25015d4db 100644
--- a/core/res/res/values-cs/strings.xml
+++ b/core/res/res/values-cs/strings.xml
@@ -1869,6 +1869,7 @@
<string name="managed_profile_label_badge_2" msgid="5673187309555352550">"2. <xliff:g id="LABEL">%1$s</xliff:g> do práce"</string>
<string name="managed_profile_label_badge_3" msgid="6882151970556391957">"3. <xliff:g id="LABEL">%1$s</xliff:g> do práce"</string>
<string name="clone_profile_label_badge" msgid="1871997694718793964">"Klon <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+ <string name="private_profile_label_badge" msgid="1712086003787839183">"Soukromá aplikace <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"Před uvolněním požádat o PIN"</string>
<string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"Před uvolněním požádat o bezpečnostní gesto"</string>
<string name="lock_to_app_unlock_password" msgid="9126722403506560473">"Před odepnutím požádat o heslo"</string>
@@ -2033,8 +2034,7 @@
<string name="autofill_update_title" msgid="3630695947047069136">"Aktualizovat ve službě "<b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>"?"</string>
<string name="autofill_update_title_with_type" msgid="5264152633488495704">"Aktualizovat údaj <xliff:g id="TYPE">%1$s</xliff:g> ve službě "<b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>"?"</string>
<string name="autofill_update_title_with_2types" msgid="1797514386321086273">"Aktualizovat údaje <xliff:g id="TYPE_0">%1$s</xliff:g> a <xliff:g id="TYPE_1">%2$s</xliff:g> ve službě "<b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>"?"</string>
- <!-- no translation found for autofill_update_title_with_3types (8285767070604652626) -->
- <skip />
+ <string name="autofill_update_title_with_3types" msgid="8285767070604652626">"Aktualizovat tyto položky ve službě "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>": <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> a <xliff:g id="TYPE_2">%3$s</xliff:g>?"</string>
<string name="autofill_save_yes" msgid="8035743017382012850">"Uložit"</string>
<string name="autofill_save_no" msgid="9212826374207023544">"Ne, děkuji"</string>
<string name="autofill_save_notnow" msgid="2853932672029024195">"Teď ne"</string>
diff --git a/core/res/res/values-da/strings.xml b/core/res/res/values-da/strings.xml
index 697800b8e951..ca2206c9be1d 100644
--- a/core/res/res/values-da/strings.xml
+++ b/core/res/res/values-da/strings.xml
@@ -671,12 +671,12 @@
<string name="fingerprint_icon_content_description" msgid="4741068463175388817">"Ikon for fingeraftryk"</string>
<string name="device_unlock_notification_name" msgid="2632928999862915709">"Enhedsoplåsning"</string>
<string name="alternative_unlock_setup_notification_title" msgid="6241508547901933544">"Prøv en anden metode til oplåsning"</string>
- <string name="alternative_face_setup_notification_content" msgid="3384959224091897331">"Brug ansigtslås, hvis dit fingeraftryk ikke genkendes, f.eks. når du har våde fingre"</string>
+ <string name="alternative_face_setup_notification_content" msgid="3384959224091897331">"Brug ansigtsoplåsning, hvis dit fingeraftryk ikke genkendes, f.eks. når du har våde fingre"</string>
<string name="alternative_fp_setup_notification_content" msgid="7454096947415721639">"Brug oplåsning med fingeraftryk, hvis dit ansigt ikke genkendes, f.eks. når der ikke er nok lys"</string>
- <string name="face_recalibrate_notification_name" msgid="7311163114750748686">"Ansigtslås"</string>
- <string name="face_recalibrate_notification_title" msgid="2524791952735579082">"Der er et problem med Ansigtslås"</string>
+ <string name="face_recalibrate_notification_name" msgid="7311163114750748686">"Ansigtsoplåsning"</string>
+ <string name="face_recalibrate_notification_title" msgid="2524791952735579082">"Der er et problem med Ansigtsoplåsning"</string>
<string name="face_recalibrate_notification_content" msgid="3064513770251355594">"Tryk for at slette din ansigtsmodel, og tilføj derefter dit ansigt igen"</string>
- <string name="face_sensor_privacy_enabled" msgid="7407126963510598508">"Hvis du vil bruge ansigtslåsen, skal du aktivere "<b>"Kameraadgang"</b>" under Indstillinger &gt; Privatliv"</string>
+ <string name="face_sensor_privacy_enabled" msgid="7407126963510598508">"Hvis du vil bruge ansigtsoplåsning, skal du aktivere "<b>"Kameraadgang"</b>" under Indstillinger &gt; Privatliv"</string>
<string name="fingerprint_recalibrate_notification_name" msgid="1414578431898579354">"Oplåsning med fingeraftryk"</string>
<string name="fingerprint_recalibrate_notification_title" msgid="2406561052064558497">"Fingeraftrykssensoren kan ikke bruges"</string>
<string name="fingerprint_recalibrate_notification_content" msgid="8519935717822194943">"Få den repareret."</string>
@@ -710,19 +710,19 @@
<string-array name="face_acquired_vendor">
</string-array>
<string name="face_error_hw_not_available" msgid="5085202213036026288">"Ansigt ikke verificeret. Hardware ikke tilgængelig."</string>
- <string name="face_error_timeout" msgid="2598544068593889762">"Prøv ansigtslås igen"</string>
+ <string name="face_error_timeout" msgid="2598544068593889762">"Prøv ansigtsoplåsning igen"</string>
<string name="face_error_no_space" msgid="5649264057026021723">"Der kan ikke gemmes nye ansigtsdata. Slet et gammelt først."</string>
<string name="face_error_canceled" msgid="2164434737103802131">"Ansigtshandlingen blev annulleret."</string>
- <string name="face_error_user_canceled" msgid="5766472033202928373">"Ansigtslås blev annulleret af brugeren"</string>
+ <string name="face_error_user_canceled" msgid="5766472033202928373">"Ansigtsoplåsning blev annulleret af brugeren"</string>
<string name="face_error_lockout" msgid="7864408714994529437">"Du har prøvet for mange gange. Prøv igen senere."</string>
- <string name="face_error_lockout_permanent" msgid="8533257333130473422">"Du har brugt for mange forsøg. Ansigtslås er utilgængelig."</string>
+ <string name="face_error_lockout_permanent" msgid="8533257333130473422">"Du har brugt for mange forsøg. Ansigtsoplåsning er utilgængelig."</string>
<string name="face_error_lockout_screen_lock" msgid="5062609811636860928">"Du har brugt for mange forsøg. Angiv skærmlåsen i stedet."</string>
<string name="face_error_unable_to_process" msgid="5723292697366130070">"Ansigtet kan ikke genkendes. Prøv igen."</string>
- <string name="face_error_not_enrolled" msgid="1134739108536328412">"Du har ikke konfigureret ansigtslås."</string>
- <string name="face_error_hw_not_present" msgid="7940978724978763011">"Ansigtslås understøttes ikke på denne enhed"</string>
+ <string name="face_error_not_enrolled" msgid="1134739108536328412">"Du har ikke konfigureret ansigtsoplåsning."</string>
+ <string name="face_error_hw_not_present" msgid="7940978724978763011">"Ansigtsoplåsning understøttes ikke på denne enhed"</string>
<string name="face_error_security_update_required" msgid="5076017208528750161">"Sensoren er midlertidigt deaktiveret."</string>
<string name="face_name_template" msgid="3877037340223318119">"Ansigt <xliff:g id="FACEID">%d</xliff:g>"</string>
- <string name="face_app_setting_name" msgid="5854024256907828015">"Brug ansigtslås"</string>
+ <string name="face_app_setting_name" msgid="5854024256907828015">"Brug ansigtsoplåsning"</string>
<string name="face_or_screen_lock_app_setting_name" msgid="1603149075605709106">"Brug ansigts- eller skærmlås"</string>
<string name="face_dialog_default_subtitle" msgid="6620492813371195429">"Brug dit ansigt for at fortsætte"</string>
<string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"Brug din ansigts- eller skærmlås for at fortsætte"</string>
@@ -975,7 +975,7 @@
<string name="lockscreen_pattern_wrong" msgid="2940138714468358458">"Prøv igen"</string>
<string name="lockscreen_password_wrong" msgid="8605355913868947490">"Prøv igen"</string>
<string name="lockscreen_storage_locked" msgid="634993789186443380">"Lås op for at se alle funktioner og data"</string>
- <string name="faceunlock_multiple_failures" msgid="681991538434031708">"Det maksimale antal forsøg på at bruge ansigtslås er overskredet"</string>
+ <string name="faceunlock_multiple_failures" msgid="681991538434031708">"Det maksimale antal forsøg på at bruge ansigtsoplåsning er overskredet"</string>
<string name="lockscreen_missing_sim_message_short" msgid="1229301273156907613">"Intet SIM-kort"</string>
<string name="lockscreen_missing_sim_message" product="tablet" msgid="3986843848305639161">"Intet SIM-kort i tabletten."</string>
<string name="lockscreen_missing_sim_message" product="tv" msgid="3903140876952198273">"Intet SIM-kort i din Android TV-enhed."</string>
@@ -1045,7 +1045,7 @@
<string name="keyguard_accessibility_expand_lock_area" msgid="4215280881346033434">"Udvid oplåsningsområdet."</string>
<string name="keyguard_accessibility_slide_unlock" msgid="2968195219692413046">"Lås op ved at stryge."</string>
<string name="keyguard_accessibility_pattern_unlock" msgid="8669128146589233293">"Lås op med mønster."</string>
- <string name="keyguard_accessibility_face_unlock" msgid="4533832120787386728">"Ansigtslås."</string>
+ <string name="keyguard_accessibility_face_unlock" msgid="4533832120787386728">"Ansigtsoplåsning."</string>
<string name="keyguard_accessibility_pin_unlock" msgid="4020864007967340068">"Lås op med pinkode."</string>
<string name="keyguard_accessibility_sim_pin_unlock" msgid="4895939120871890557">"Lås op ved hjælp af pinkoden til SIM-kortet."</string>
<string name="keyguard_accessibility_sim_puk_unlock" msgid="3459003464041899101">"Lås op ved hjælp af PUK-koden til SIM-kortet."</string>
@@ -1867,6 +1867,8 @@
<string name="managed_profile_label_badge_2" msgid="5673187309555352550">"2. <xliff:g id="LABEL">%1$s</xliff:g> til arbejde"</string>
<string name="managed_profile_label_badge_3" msgid="6882151970556391957">"3. <xliff:g id="LABEL">%1$s</xliff:g> til arbejde"</string>
<string name="clone_profile_label_badge" msgid="1871997694718793964">"Klon af <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+ <!-- no translation found for private_profile_label_badge (1712086003787839183) -->
+ <skip />
<string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"Bed om pinkode inden frigørelse"</string>
<string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"Bed om oplåsningsmønster ved deaktivering"</string>
<string name="lock_to_app_unlock_password" msgid="9126722403506560473">"Bed om adgangskode inden frigørelse"</string>
@@ -2031,8 +2033,7 @@
<string name="autofill_update_title" msgid="3630695947047069136">"Vil du opdatere i "<b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>"?"</string>
<string name="autofill_update_title_with_type" msgid="5264152633488495704">"Vil du opdatere <xliff:g id="TYPE">%1$s</xliff:g> i "<b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>"?"</string>
<string name="autofill_update_title_with_2types" msgid="1797514386321086273">"Vil du opdatere <xliff:g id="TYPE_0">%1$s</xliff:g> og <xliff:g id="TYPE_1">%2$s</xliff:g> i "<b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>"?"</string>
- <!-- no translation found for autofill_update_title_with_3types (8285767070604652626) -->
- <skip />
+ <string name="autofill_update_title_with_3types" msgid="8285767070604652626">"Vil du opdatere disse elementer i "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>": <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> og <xliff:g id="TYPE_2">%3$s</xliff:g>?"</string>
<string name="autofill_save_yes" msgid="8035743017382012850">"Gem"</string>
<string name="autofill_save_no" msgid="9212826374207023544">"Nej tak"</string>
<string name="autofill_save_notnow" msgid="2853932672029024195">"Ikke nu"</string>
diff --git a/core/res/res/values-de/strings.xml b/core/res/res/values-de/strings.xml
index b5e38b9f6340..be511e8a7c32 100644
--- a/core/res/res/values-de/strings.xml
+++ b/core/res/res/values-de/strings.xml
@@ -669,14 +669,10 @@
</string-array>
<string name="fingerprint_error_vendor_unknown" msgid="4170002184907291065">"Ein Problem ist aufgetreten. Versuch es noch einmal."</string>
<string name="fingerprint_icon_content_description" msgid="4741068463175388817">"Fingerabdruck-Symbol"</string>
- <!-- no translation found for device_unlock_notification_name (2632928999862915709) -->
- <skip />
- <!-- no translation found for alternative_unlock_setup_notification_title (6241508547901933544) -->
- <skip />
- <!-- no translation found for alternative_face_setup_notification_content (3384959224091897331) -->
- <skip />
- <!-- no translation found for alternative_fp_setup_notification_content (7454096947415721639) -->
- <skip />
+ <string name="device_unlock_notification_name" msgid="2632928999862915709">"Geräteentsperrung"</string>
+ <string name="alternative_unlock_setup_notification_title" msgid="6241508547901933544">"Andere Entsperrungsart verwenden"</string>
+ <string name="alternative_face_setup_notification_content" msgid="3384959224091897331">"Verwende die Entsperrung per Gesichtserkennung, wenn dein Fingerabdruck nicht erkannt wird, beispielsweise wenn deine Finger nass sind"</string>
+ <string name="alternative_fp_setup_notification_content" msgid="7454096947415721639">"Verwende die Entsperrung per Fingerabdruck, wenn dein Gesicht nicht erkannt wird, beispielsweise wenn es zu dunkel ist"</string>
<string name="face_recalibrate_notification_name" msgid="7311163114750748686">"Entsperrung per Gesichtserkennung"</string>
<string name="face_recalibrate_notification_title" msgid="2524791952735579082">"Problem bei der Entsperrung per Gesichtserkennung"</string>
<string name="face_recalibrate_notification_content" msgid="3064513770251355594">"Tippe, um dein Gesichtsmodell zu löschen, und füge es dann noch einmal hinzu"</string>
@@ -1871,6 +1867,8 @@
<string name="managed_profile_label_badge_2" msgid="5673187309555352550">"2. <xliff:g id="LABEL">%1$s</xliff:g> (geschäftlich)"</string>
<string name="managed_profile_label_badge_3" msgid="6882151970556391957">"3. <xliff:g id="LABEL">%1$s</xliff:g> (geschäftlich)"</string>
<string name="clone_profile_label_badge" msgid="1871997694718793964">"Klon <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+ <!-- no translation found for private_profile_label_badge (1712086003787839183) -->
+ <skip />
<string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"Vor dem Beenden nach PIN fragen"</string>
<string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"Vor dem Beenden nach Entsperrungsmuster fragen"</string>
<string name="lock_to_app_unlock_password" msgid="9126722403506560473">"Vor dem Beenden nach Passwort fragen"</string>
@@ -2035,8 +2033,7 @@
<string name="autofill_update_title" msgid="3630695947047069136">"In "<b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>" aktualisieren?"</string>
<string name="autofill_update_title_with_type" msgid="5264152633488495704">"<xliff:g id="TYPE">%1$s</xliff:g> in "<b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>" aktualisieren?"</string>
<string name="autofill_update_title_with_2types" msgid="1797514386321086273">"<xliff:g id="TYPE_0">%1$s</xliff:g> und <xliff:g id="TYPE_1">%2$s</xliff:g> in "<b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>" aktualisieren?"</string>
- <!-- no translation found for autofill_update_title_with_3types (8285767070604652626) -->
- <skip />
+ <string name="autofill_update_title_with_3types" msgid="8285767070604652626">"<xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> und <xliff:g id="TYPE_2">%3$s</xliff:g> in "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>" aktualisieren?"</string>
<string name="autofill_save_yes" msgid="8035743017382012850">"Speichern"</string>
<string name="autofill_save_no" msgid="9212826374207023544">"Nein danke"</string>
<string name="autofill_save_notnow" msgid="2853932672029024195">"Nicht jetzt"</string>
diff --git a/core/res/res/values-el/strings.xml b/core/res/res/values-el/strings.xml
index a0a44746251e..1d3471c0db95 100644
--- a/core/res/res/values-el/strings.xml
+++ b/core/res/res/values-el/strings.xml
@@ -1867,6 +1867,7 @@
<string name="managed_profile_label_badge_2" msgid="5673187309555352550">"<xliff:g id="LABEL">%1$s</xliff:g> εργασίας 2"</string>
<string name="managed_profile_label_badge_3" msgid="6882151970556391957">"<xliff:g id="LABEL">%1$s</xliff:g> εργασίας 3"</string>
<string name="clone_profile_label_badge" msgid="1871997694718793964">"Κλώνος <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+ <string name="private_profile_label_badge" msgid="1712086003787839183">"Ιδιωτικό <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"Να γίνεται ερώτηση για το PIN, πριν από το ξεκαρφίτσωμα"</string>
<string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"Να γίνεται ερώτηση για το μοτίβο ξεκλειδώματος, πριν από το ξεκαρφίτσωμα"</string>
<string name="lock_to_app_unlock_password" msgid="9126722403506560473">"Να γίνεται ερώτηση για τον κωδικό πρόσβασης, πριν από το ξεκαρφίτσωμα"</string>
@@ -2031,8 +2032,7 @@
<string name="autofill_update_title" msgid="3630695947047069136">"Ενημέρωση σε "<b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>";"</string>
<string name="autofill_update_title_with_type" msgid="5264152633488495704">"Ενημέρωση <xliff:g id="TYPE">%1$s</xliff:g> σε "<b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>";"</string>
<string name="autofill_update_title_with_2types" msgid="1797514386321086273">"Ενημέρωση <xliff:g id="TYPE_0">%1$s</xliff:g> και <xliff:g id="TYPE_1">%2$s</xliff:g> σε "<b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>";"</string>
- <!-- no translation found for autofill_update_title_with_3types (8285767070604652626) -->
- <skip />
+ <string name="autofill_update_title_with_3types" msgid="8285767070604652626">"Ενημέρωση αυτών των στοιχείων στο "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>": <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> και <xliff:g id="TYPE_2">%3$s</xliff:g>;"</string>
<string name="autofill_save_yes" msgid="8035743017382012850">"Αποθήκευση"</string>
<string name="autofill_save_no" msgid="9212826374207023544">"Όχι, ευχαριστώ"</string>
<string name="autofill_save_notnow" msgid="2853932672029024195">"Όχι τώρα"</string>
diff --git a/core/res/res/values-en-rAU/strings.xml b/core/res/res/values-en-rAU/strings.xml
index a931c58fec17..8c33f168f17d 100644
--- a/core/res/res/values-en-rAU/strings.xml
+++ b/core/res/res/values-en-rAU/strings.xml
@@ -1867,6 +1867,7 @@
<string name="managed_profile_label_badge_2" msgid="5673187309555352550">"2nd Work <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="managed_profile_label_badge_3" msgid="6882151970556391957">"3rd Work <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="clone_profile_label_badge" msgid="1871997694718793964">"Clone <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+ <string name="private_profile_label_badge" msgid="1712086003787839183">"Private <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"Ask for PIN before unpinning"</string>
<string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"Ask for unlock pattern before unpinning"</string>
<string name="lock_to_app_unlock_password" msgid="9126722403506560473">"Ask for password before unpinning"</string>
@@ -2031,8 +2032,7 @@
<string name="autofill_update_title" msgid="3630695947047069136">"Update in "<b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>"?"</string>
<string name="autofill_update_title_with_type" msgid="5264152633488495704">"Update <xliff:g id="TYPE">%1$s</xliff:g> in "<b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>"?"</string>
<string name="autofill_update_title_with_2types" msgid="1797514386321086273">"Update <xliff:g id="TYPE_0">%1$s</xliff:g> and <xliff:g id="TYPE_1">%2$s</xliff:g> in "<b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>"?"</string>
- <!-- no translation found for autofill_update_title_with_3types (8285767070604652626) -->
- <skip />
+ <string name="autofill_update_title_with_3types" msgid="8285767070604652626">"Update these items in "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>": <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g>, and <xliff:g id="TYPE_2">%3$s</xliff:g>?"</string>
<string name="autofill_save_yes" msgid="8035743017382012850">"Save"</string>
<string name="autofill_save_no" msgid="9212826374207023544">"No, thanks"</string>
<string name="autofill_save_notnow" msgid="2853932672029024195">"Not now"</string>
diff --git a/core/res/res/values-en-rCA/strings.xml b/core/res/res/values-en-rCA/strings.xml
index 1d657c7c202e..6dc9ce4ce735 100644
--- a/core/res/res/values-en-rCA/strings.xml
+++ b/core/res/res/values-en-rCA/strings.xml
@@ -1867,6 +1867,7 @@
<string name="managed_profile_label_badge_2" msgid="5673187309555352550">"2nd Work <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="managed_profile_label_badge_3" msgid="6882151970556391957">"3rd Work <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="clone_profile_label_badge" msgid="1871997694718793964">"Clone <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+ <string name="private_profile_label_badge" msgid="1712086003787839183">"Private <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"Ask for PIN before unpinning"</string>
<string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"Ask for unlock pattern before unpinning"</string>
<string name="lock_to_app_unlock_password" msgid="9126722403506560473">"Ask for password before unpinning"</string>
@@ -2031,8 +2032,7 @@
<string name="autofill_update_title" msgid="3630695947047069136">"Update in "<b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>"?"</string>
<string name="autofill_update_title_with_type" msgid="5264152633488495704">"Update <xliff:g id="TYPE">%1$s</xliff:g> in "<b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>"?"</string>
<string name="autofill_update_title_with_2types" msgid="1797514386321086273">"Update <xliff:g id="TYPE_0">%1$s</xliff:g> and <xliff:g id="TYPE_1">%2$s</xliff:g> in "<b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>"?"</string>
- <!-- no translation found for autofill_update_title_with_3types (8285767070604652626) -->
- <skip />
+ <string name="autofill_update_title_with_3types" msgid="8285767070604652626">"Update these items in "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>": <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g>, and <xliff:g id="TYPE_2">%3$s</xliff:g>?"</string>
<string name="autofill_save_yes" msgid="8035743017382012850">"Save"</string>
<string name="autofill_save_no" msgid="9212826374207023544">"No thanks"</string>
<string name="autofill_save_notnow" msgid="2853932672029024195">"Not now"</string>
diff --git a/core/res/res/values-en-rGB/strings.xml b/core/res/res/values-en-rGB/strings.xml
index 275b1bcc717b..3daab6cc1cfa 100644
--- a/core/res/res/values-en-rGB/strings.xml
+++ b/core/res/res/values-en-rGB/strings.xml
@@ -1867,6 +1867,7 @@
<string name="managed_profile_label_badge_2" msgid="5673187309555352550">"2nd Work <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="managed_profile_label_badge_3" msgid="6882151970556391957">"3rd Work <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="clone_profile_label_badge" msgid="1871997694718793964">"Clone <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+ <string name="private_profile_label_badge" msgid="1712086003787839183">"Private <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"Ask for PIN before unpinning"</string>
<string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"Ask for unlock pattern before unpinning"</string>
<string name="lock_to_app_unlock_password" msgid="9126722403506560473">"Ask for password before unpinning"</string>
@@ -2031,8 +2032,7 @@
<string name="autofill_update_title" msgid="3630695947047069136">"Update in "<b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>"?"</string>
<string name="autofill_update_title_with_type" msgid="5264152633488495704">"Update <xliff:g id="TYPE">%1$s</xliff:g> in "<b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>"?"</string>
<string name="autofill_update_title_with_2types" msgid="1797514386321086273">"Update <xliff:g id="TYPE_0">%1$s</xliff:g> and <xliff:g id="TYPE_1">%2$s</xliff:g> in "<b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>"?"</string>
- <!-- no translation found for autofill_update_title_with_3types (8285767070604652626) -->
- <skip />
+ <string name="autofill_update_title_with_3types" msgid="8285767070604652626">"Update these items in "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>": <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g>, and <xliff:g id="TYPE_2">%3$s</xliff:g>?"</string>
<string name="autofill_save_yes" msgid="8035743017382012850">"Save"</string>
<string name="autofill_save_no" msgid="9212826374207023544">"No, thanks"</string>
<string name="autofill_save_notnow" msgid="2853932672029024195">"Not now"</string>
diff --git a/core/res/res/values-en-rIN/strings.xml b/core/res/res/values-en-rIN/strings.xml
index 3504a53d6c11..67ebab14d297 100644
--- a/core/res/res/values-en-rIN/strings.xml
+++ b/core/res/res/values-en-rIN/strings.xml
@@ -1867,6 +1867,7 @@
<string name="managed_profile_label_badge_2" msgid="5673187309555352550">"2nd Work <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="managed_profile_label_badge_3" msgid="6882151970556391957">"3rd Work <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="clone_profile_label_badge" msgid="1871997694718793964">"Clone <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+ <string name="private_profile_label_badge" msgid="1712086003787839183">"Private <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"Ask for PIN before unpinning"</string>
<string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"Ask for unlock pattern before unpinning"</string>
<string name="lock_to_app_unlock_password" msgid="9126722403506560473">"Ask for password before unpinning"</string>
@@ -2031,8 +2032,7 @@
<string name="autofill_update_title" msgid="3630695947047069136">"Update in "<b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>"?"</string>
<string name="autofill_update_title_with_type" msgid="5264152633488495704">"Update <xliff:g id="TYPE">%1$s</xliff:g> in "<b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>"?"</string>
<string name="autofill_update_title_with_2types" msgid="1797514386321086273">"Update <xliff:g id="TYPE_0">%1$s</xliff:g> and <xliff:g id="TYPE_1">%2$s</xliff:g> in "<b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>"?"</string>
- <!-- no translation found for autofill_update_title_with_3types (8285767070604652626) -->
- <skip />
+ <string name="autofill_update_title_with_3types" msgid="8285767070604652626">"Update these items in "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>": <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g>, and <xliff:g id="TYPE_2">%3$s</xliff:g>?"</string>
<string name="autofill_save_yes" msgid="8035743017382012850">"Save"</string>
<string name="autofill_save_no" msgid="9212826374207023544">"No, thanks"</string>
<string name="autofill_save_notnow" msgid="2853932672029024195">"Not now"</string>
diff --git a/core/res/res/values-en-rXC/strings.xml b/core/res/res/values-en-rXC/strings.xml
index 9a727491bc14..d8b5016449b1 100644
--- a/core/res/res/values-en-rXC/strings.xml
+++ b/core/res/res/values-en-rXC/strings.xml
@@ -1867,6 +1867,7 @@
<string name="managed_profile_label_badge_2" msgid="5673187309555352550">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‏‏‎‏‎‏‏‏‎‏‏‎‎‏‏‎‏‎‏‏‏‎‎‏‏‎‎‏‏‎‏‏‎‏‎‎‏‎‎‏‏‎‏‎‎‎‎‎‎‏‏‏‏‏‎‎‏‏‎‎2nd Work ‎‏‎‎‏‏‎<xliff:g id="LABEL">%1$s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
<string name="managed_profile_label_badge_3" msgid="6882151970556391957">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‏‏‏‏‏‎‎‎‎‎‏‎‎‏‎‏‎‎‎‎‏‏‎‎‎‎‎‏‎‎‎‎‎‏‏‏‎‏‎‎‎‏‎‎‏‎‏‏‎‎‏‎‎‎‎‏‎‏‎‏‎3rd Work ‎‏‎‎‏‏‎<xliff:g id="LABEL">%1$s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
<string name="clone_profile_label_badge" msgid="1871997694718793964">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‎‎‏‏‏‏‏‏‎‏‎‏‎‏‎‏‎‏‏‏‏‏‏‏‏‎‎‎‎‏‎‏‏‏‎‎‎‎‏‎‎‎‎‎‏‎‏‏‎‎‎‏‏‏‎‏‏‎‎‎Clone ‎‏‎‎‏‏‎<xliff:g id="LABEL">%1$s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
+ <string name="private_profile_label_badge" msgid="1712086003787839183">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‎‏‏‏‏‏‎‎‎‎‏‎‏‎‎‎‏‏‎‏‎‎‏‎‎‏‏‎‎‏‎‎‎‎‎‎‏‎‏‏‎‎‎‏‎‎‏‏‎‏‏‎‏‏‎‎‏‏‏‏‎Private ‎‏‎‎‏‏‎<xliff:g id="LABEL">%1$s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
<string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‏‎‏‏‏‏‏‏‏‏‏‎‏‏‎‎‏‏‎‎‎‎‎‏‏‎‏‏‎‏‎‎‏‎‏‎‏‎‏‏‏‎‎‎‎‏‏‏‎‏‎‎‏‎‏‏‏‏‎‎Ask for PIN before unpinning‎‏‎‎‏‎"</string>
<string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‎‏‎‏‎‏‏‎‎‎‏‏‏‎‏‏‏‏‎‎‎‏‎‏‎‎‏‏‏‏‎‏‏‏‏‎‏‎‎‎‏‎‏‏‏‏‏‏‏‏‎‏‏‏‏‏‎‏‏‏‎Ask for unlock pattern before unpinning‎‏‎‎‏‎"</string>
<string name="lock_to_app_unlock_password" msgid="9126722403506560473">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‏‏‏‎‏‎‏‎‏‎‎‎‏‎‏‎‎‎‎‏‏‎‏‎‏‎‏‏‏‎‏‎‏‎‎‎‏‎‎‏‏‎‏‏‏‎‎‏‏‏‎‏‏‏‎‏‏‎‎‏‎Ask for password before unpinning‎‏‎‎‏‎"</string>
@@ -2031,8 +2032,7 @@
<string name="autofill_update_title" msgid="3630695947047069136">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‎‏‎‎‏‏‎‎‎‏‎‏‏‎‏‎‎‏‎‏‎‏‏‏‎‏‎‎‏‎‎‎‎‏‏‎‎‏‏‎‎‎‎‏‏‏‎‎‏‎‏‏‏‎‏‎‎‎‎‎Update in ‎‏‎‎‏‏‎"<b>"‎‏‎‎‏‏‏‎‎‏‎‎‏‏‎<xliff:g id="LABEL">%1$s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‏‎"</b>"‎‏‎‎‏‏‏‎?‎‏‎‎‏‎"</string>
<string name="autofill_update_title_with_type" msgid="5264152633488495704">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‎‎‏‎‎‎‎‏‏‏‎‎‎‎‎‎‏‏‎‏‏‏‎‏‏‎‏‏‏‏‏‎‎‏‎‏‎‎‎‎‏‎‎‏‏‎‏‎‏‎‎‎‏‎‏‏‎‎‎‎Update ‎‏‎‎‏‏‎<xliff:g id="TYPE">%1$s</xliff:g>‎‏‎‎‏‏‏‎ in ‎‏‎‎‏‏‎"<b>"‎‏‎‎‏‏‏‎‎‏‎‎‏‏‎<xliff:g id="LABEL">%2$s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‏‎"</b>"‎‏‎‎‏‏‏‎?‎‏‎‎‏‎"</string>
<string name="autofill_update_title_with_2types" msgid="1797514386321086273">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‎‎‎‏‏‏‏‎‎‏‎‎‎‎‎‏‏‎‏‏‏‎‎‏‏‏‏‏‎‎‎‏‎‏‏‎‏‎‏‎‎‏‎‏‎‎‏‎‏‏‏‎‏‎‎‎‎‎‏‎Update ‎‏‎‎‏‏‎<xliff:g id="TYPE_0">%1$s</xliff:g>‎‏‎‎‏‏‏‎ and ‎‏‎‎‏‏‎<xliff:g id="TYPE_1">%2$s</xliff:g>‎‏‎‎‏‏‏‎ in ‎‏‎‎‏‏‎"<b>"‎‏‎‎‏‏‏‎‎‏‎‎‏‏‎<xliff:g id="LABEL">%3$s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‏‎"</b>"‎‏‎‎‏‏‏‎?‎‏‎‎‏‎"</string>
- <!-- no translation found for autofill_update_title_with_3types (8285767070604652626) -->
- <skip />
+ <string name="autofill_update_title_with_3types" msgid="8285767070604652626">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‎‏‎‏‏‏‏‏‏‎‎‏‏‏‏‎‏‎‏‎‏‎‎‎‎‎‎‎‎‏‏‎‏‏‏‎‎‎‎‎‏‎‎‏‏‏‏‎‎‎‎‎‏‎‏‎‎‏‎‎Update these items in ‎‏‎‎‏‏‎"<b>"‎‏‎‎‏‏‏‎‎‏‎‎‏‏‎<xliff:g id="LABEL">%4$s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‏‎"</b>"‎‏‎‎‏‏‏‎: ‎‏‎‎‏‏‎<xliff:g id="TYPE_0">%1$s</xliff:g>‎‏‎‎‏‏‏‎, ‎‏‎‎‏‏‎<xliff:g id="TYPE_1">%2$s</xliff:g>‎‏‎‎‏‏‏‎, and ‎‏‎‎‏‏‎<xliff:g id="TYPE_2">%3$s</xliff:g>‎‏‎‎‏‏‏‎?‎‏‎‎‏‎"</string>
<string name="autofill_save_yes" msgid="8035743017382012850">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‏‏‏‏‎‎‎‎‏‎‎‏‎‏‏‎‎‎‏‏‎‏‏‎‎‏‎‏‏‏‏‏‎‎‏‎‏‏‎‎‎‎‏‎‏‏‎‎‏‏‏‏‎‏‏‎‎‏‎‎Save‎‏‎‎‏‎"</string>
<string name="autofill_save_no" msgid="9212826374207023544">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‏‏‏‏‏‏‎‏‏‎‏‎‏‎‎‎‏‎‎‎‏‏‎‎‎‏‏‎‏‎‎‏‎‎‏‏‏‏‏‏‎‏‎‏‏‎‏‎‏‎‎‏‏‎‏‏‏‎‎‎‎No thanks‎‏‎‎‏‎"</string>
<string name="autofill_save_notnow" msgid="2853932672029024195">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‎‏‏‏‏‎‎‏‏‎‏‏‎‎‏‏‎‏‎‎‏‎‏‎‎‏‎‎‏‏‏‏‏‎‎‏‎‎‏‎‏‎‏‏‏‏‎‏‏‏‏‏‏‏‎‎‎‎‏‏‎Not now‎‏‎‎‏‎"</string>
diff --git a/core/res/res/values-es-rUS/strings.xml b/core/res/res/values-es-rUS/strings.xml
index 8b651d138b67..e0aeb31e721d 100644
--- a/core/res/res/values-es-rUS/strings.xml
+++ b/core/res/res/values-es-rUS/strings.xml
@@ -1868,6 +1868,7 @@
<string name="managed_profile_label_badge_2" msgid="5673187309555352550">"<xliff:g id="LABEL">%1$s</xliff:g> de trabajo 2"</string>
<string name="managed_profile_label_badge_3" msgid="6882151970556391957">"<xliff:g id="LABEL">%1$s</xliff:g> de trabajo 3"</string>
<string name="clone_profile_label_badge" msgid="1871997694718793964">"Clon de <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+ <string name="private_profile_label_badge" msgid="1712086003787839183">"<xliff:g id="LABEL">%1$s</xliff:g> privado"</string>
<string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"Solicitar PIN para quitar fijación"</string>
<string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"Solicitar desbloqueo para quitar fijación"</string>
<string name="lock_to_app_unlock_password" msgid="9126722403506560473">"Solicitar contraseña para quitar fijación"</string>
@@ -2032,8 +2033,7 @@
<string name="autofill_update_title" msgid="3630695947047069136">"¿Quieres actualizar en "<b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>"?"</string>
<string name="autofill_update_title_with_type" msgid="5264152633488495704">"¿Quieres actualizar <xliff:g id="TYPE">%1$s</xliff:g> en "<b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>"?"</string>
<string name="autofill_update_title_with_2types" msgid="1797514386321086273">"¿Quieres actualizar <xliff:g id="TYPE_0">%1$s</xliff:g> y <xliff:g id="TYPE_1">%2$s</xliff:g> en "<b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>"?"</string>
- <!-- no translation found for autofill_update_title_with_3types (8285767070604652626) -->
- <skip />
+ <string name="autofill_update_title_with_3types" msgid="8285767070604652626">"¿Quieres actualizar estos elementos en "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>": <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> y <xliff:g id="TYPE_2">%3$s</xliff:g>?"</string>
<string name="autofill_save_yes" msgid="8035743017382012850">"Guardar"</string>
<string name="autofill_save_no" msgid="9212826374207023544">"No, gracias"</string>
<string name="autofill_save_notnow" msgid="2853932672029024195">"Ahora no"</string>
diff --git a/core/res/res/values-es/strings.xml b/core/res/res/values-es/strings.xml
index 9c678c578172..3bcc0f432a88 100644
--- a/core/res/res/values-es/strings.xml
+++ b/core/res/res/values-es/strings.xml
@@ -1868,6 +1868,8 @@
<string name="managed_profile_label_badge_2" msgid="5673187309555352550">"<xliff:g id="LABEL">%1$s</xliff:g> de trabajo 2"</string>
<string name="managed_profile_label_badge_3" msgid="6882151970556391957">"<xliff:g id="LABEL">%1$s</xliff:g> de trabajo 3"</string>
<string name="clone_profile_label_badge" msgid="1871997694718793964">"Clon de <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+ <!-- no translation found for private_profile_label_badge (1712086003787839183) -->
+ <skip />
<string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"Solicitar PIN para desactivar"</string>
<string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"Pedir patrón de desbloqueo para dejar de fijar"</string>
<string name="lock_to_app_unlock_password" msgid="9126722403506560473">"Solicitar contraseña para desactivar"</string>
@@ -2032,8 +2034,7 @@
<string name="autofill_update_title" msgid="3630695947047069136">"¿Actualizar en "<b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>"?"</string>
<string name="autofill_update_title_with_type" msgid="5264152633488495704">"¿Actualizar <xliff:g id="TYPE">%1$s</xliff:g> en "<b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>"?"</string>
<string name="autofill_update_title_with_2types" msgid="1797514386321086273">"¿Actualizar <xliff:g id="TYPE_0">%1$s</xliff:g> y <xliff:g id="TYPE_1">%2$s</xliff:g> en "<b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>"?"</string>
- <!-- no translation found for autofill_update_title_with_3types (8285767070604652626) -->
- <skip />
+ <string name="autofill_update_title_with_3types" msgid="8285767070604652626">"¿Actualizar estos elementos en "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>" (<xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> y <xliff:g id="TYPE_2">%3$s</xliff:g>)?"</string>
<string name="autofill_save_yes" msgid="8035743017382012850">"Guardar"</string>
<string name="autofill_save_no" msgid="9212826374207023544">"No, gracias"</string>
<string name="autofill_save_notnow" msgid="2853932672029024195">"Ahora no"</string>
diff --git a/core/res/res/values-et/strings.xml b/core/res/res/values-et/strings.xml
index c17a17995733..d212946da95e 100644
--- a/core/res/res/values-et/strings.xml
+++ b/core/res/res/values-et/strings.xml
@@ -1867,6 +1867,7 @@
<string name="managed_profile_label_badge_2" msgid="5673187309555352550">"2. töö <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="managed_profile_label_badge_3" msgid="6882151970556391957">"3. töö <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="clone_profile_label_badge" msgid="1871997694718793964">"Rakenduse <xliff:g id="LABEL">%1$s</xliff:g> kloon"</string>
+ <string name="private_profile_label_badge" msgid="1712086003787839183">"Privaatne <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"Enne vabastamist küsi PIN-koodi"</string>
<string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"Enne vabastamist küsi avamismustrit"</string>
<string name="lock_to_app_unlock_password" msgid="9126722403506560473">"Enne vabastamist küsi parooli"</string>
@@ -2031,8 +2032,7 @@
<string name="autofill_update_title" msgid="3630695947047069136">"Kas värskendada üksust teenuses "<b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>"?"</string>
<string name="autofill_update_title_with_type" msgid="5264152633488495704">"Kas värskendada üksust <xliff:g id="TYPE">%1$s</xliff:g> teenuses "<b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>"?"</string>
<string name="autofill_update_title_with_2types" msgid="1797514386321086273">"Kas värskendada üksusi <xliff:g id="TYPE_0">%1$s</xliff:g> ja <xliff:g id="TYPE_1">%2$s</xliff:g> teenuses "<b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>"?"</string>
- <!-- no translation found for autofill_update_title_with_3types (8285767070604652626) -->
- <skip />
+ <string name="autofill_update_title_with_3types" msgid="8285767070604652626">"Kas värskendada teenuses "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>" neid üksusi: <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> ja <xliff:g id="TYPE_2">%3$s</xliff:g>?"</string>
<string name="autofill_save_yes" msgid="8035743017382012850">"Salvesta"</string>
<string name="autofill_save_no" msgid="9212826374207023544">"Tänan, ei"</string>
<string name="autofill_save_notnow" msgid="2853932672029024195">"Hiljem"</string>
diff --git a/core/res/res/values-eu/strings.xml b/core/res/res/values-eu/strings.xml
index 7a6fa1d5699e..302acb04d085 100644
--- a/core/res/res/values-eu/strings.xml
+++ b/core/res/res/values-eu/strings.xml
@@ -669,14 +669,10 @@
</string-array>
<string name="fingerprint_error_vendor_unknown" msgid="4170002184907291065">"Arazo bat izan da. Saiatu berriro."</string>
<string name="fingerprint_icon_content_description" msgid="4741068463175388817">"Hatz-markaren ikonoa"</string>
- <!-- no translation found for device_unlock_notification_name (2632928999862915709) -->
- <skip />
- <!-- no translation found for alternative_unlock_setup_notification_title (6241508547901933544) -->
- <skip />
- <!-- no translation found for alternative_face_setup_notification_content (3384959224091897331) -->
- <skip />
- <!-- no translation found for alternative_fp_setup_notification_content (7454096947415721639) -->
- <skip />
+ <string name="device_unlock_notification_name" msgid="2632928999862915709">"Gailua desblokeatzea"</string>
+ <string name="alternative_unlock_setup_notification_title" msgid="6241508547901933544">"Probatu gailua desblokeatzeko beste modu bat"</string>
+ <string name="alternative_face_setup_notification_content" msgid="3384959224091897331">"Erabili Aurpegi bidez desblokeatzea hatz-marka ezagutzen ez denean (adibidez, hatzak bustita dauzkazunean)"</string>
+ <string name="alternative_fp_setup_notification_content" msgid="7454096947415721639">"Erabili Hatz-marka bidez desblokeatzea aurpegia ezagutzen ez denean (adibidez, argi nahikorik ez dagoenean)"</string>
<string name="face_recalibrate_notification_name" msgid="7311163114750748686">"Aurpegi bidez desblokeatzea"</string>
<string name="face_recalibrate_notification_title" msgid="2524791952735579082">"Arazoak ditugu aurpegi bidez desblokeatzeko eginbidearekin"</string>
<string name="face_recalibrate_notification_content" msgid="3064513770251355594">"Sakatu hau aurpegi-eredua ezabatzeko eta, gero, gehitu aurpegia berriro"</string>
@@ -1871,6 +1867,8 @@
<string name="managed_profile_label_badge_2" msgid="5673187309555352550">"Laneko 2. <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="managed_profile_label_badge_3" msgid="6882151970556391957">"Laneko 3. <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="clone_profile_label_badge" msgid="1871997694718793964">"<xliff:g id="LABEL">%1$s</xliff:g> aplikazioaren klona"</string>
+ <!-- no translation found for private_profile_label_badge (1712086003787839183) -->
+ <skip />
<string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"Eskatu PINa aingura kendu aurretik"</string>
<string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"Eskatu desblokeatzeko eredua aingura kendu aurretik"</string>
<string name="lock_to_app_unlock_password" msgid="9126722403506560473">"Eskatu pasahitza aingura kendu aurretik"</string>
@@ -2035,8 +2033,7 @@
<string name="autofill_update_title" msgid="3630695947047069136"><b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>" zerbitzuan eguneratu nahi duzu?"</string>
<string name="autofill_update_title_with_type" msgid="5264152633488495704"><b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>" zerbitzuan eguneratu nahi duzu <xliff:g id="TYPE">%1$s</xliff:g>?"</string>
<string name="autofill_update_title_with_2types" msgid="1797514386321086273"><b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>" zerbitzuan eguneratu nahi dituzu <xliff:g id="TYPE_0">%1$s</xliff:g> eta <xliff:g id="TYPE_1">%2$s</xliff:g>?"</string>
- <!-- no translation found for autofill_update_title_with_3types (8285767070604652626) -->
- <skip />
+ <string name="autofill_update_title_with_3types" msgid="8285767070604652626"><b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>" zerbitzuan eguneratu nahi dituzu <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> eta <xliff:g id="TYPE_2">%3$s</xliff:g>?"</string>
<string name="autofill_save_yes" msgid="8035743017382012850">"Gorde"</string>
<string name="autofill_save_no" msgid="9212826374207023544">"Ez, eskerrik asko"</string>
<string name="autofill_save_notnow" msgid="2853932672029024195">"Orain ez"</string>
diff --git a/core/res/res/values-fa/strings.xml b/core/res/res/values-fa/strings.xml
index c733bea6cfb5..7947b6ea6e8b 100644
--- a/core/res/res/values-fa/strings.xml
+++ b/core/res/res/values-fa/strings.xml
@@ -1133,9 +1133,9 @@
<string name="duration_hours_relative_future" msgid="6670440478481140565">"{count,plural, =1{# ساعت}one{# ساعت}other{# ساعت}}"</string>
<string name="duration_days_relative_future" msgid="8870658635774250746">"{count,plural, =1{# روز}one{# روز}other{# روز}}"</string>
<string name="duration_years_relative_future" msgid="8855853883925918380">"{count,plural, =1{# سال}one{# سال}other{# سال}}"</string>
- <string name="VideoView_error_title" msgid="5750686717225068016">"مشکل در ویدئو"</string>
- <string name="VideoView_error_text_invalid_progressive_playback" msgid="3782449246085134720">"متأسفیم، این ویدئو برای پخش جریانی با این دستگاه معتبر نیست."</string>
- <string name="VideoView_error_text_unknown" msgid="7658683339707607138">"پخش این ویدئو ممکن نیست."</string>
+ <string name="VideoView_error_title" msgid="5750686717225068016">"مشکل در ویدیو"</string>
+ <string name="VideoView_error_text_invalid_progressive_playback" msgid="3782449246085134720">"متأسفیم، این ویدیو برای پخش جریانی با این دستگاه معتبر نیست."</string>
+ <string name="VideoView_error_text_unknown" msgid="7658683339707607138">"پخش این ویدیو ممکن نیست."</string>
<string name="VideoView_error_button" msgid="5138809446603764272">"تأیید"</string>
<string name="relative_time" msgid="8572030016028033243">"<xliff:g id="DATE">%1$s</xliff:g>، <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="noon" msgid="8365974533050605886">"ظهر"</string>
@@ -1867,6 +1867,8 @@
<string name="managed_profile_label_badge_2" msgid="5673187309555352550">"کار دوم <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="managed_profile_label_badge_3" msgid="6882151970556391957">"کار سوم <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="clone_profile_label_badge" msgid="1871997694718793964">"همسانه <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+ <!-- no translation found for private_profile_label_badge (1712086003787839183) -->
+ <skip />
<string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"درخواست کد پین قبل از برداشتن پین"</string>
<string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"درخواست الگوی بازگشایی قفل قبل‌از برداشتن سنجاق"</string>
<string name="lock_to_app_unlock_password" msgid="9126722403506560473">"درخواست گذرواژه قبل از برداشتن سنجاق"</string>
@@ -2031,8 +2033,7 @@
<string name="autofill_update_title" msgid="3630695947047069136">"در "<b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>" به‌روزرسانی شود؟"</string>
<string name="autofill_update_title_with_type" msgid="5264152633488495704">"<xliff:g id="TYPE">%1$s</xliff:g> در "<b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>" به‌روزرسانی شود؟"</string>
<string name="autofill_update_title_with_2types" msgid="1797514386321086273">"<xliff:g id="TYPE_0">%1$s</xliff:g> و <xliff:g id="TYPE_1">%2$s</xliff:g> در "<b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>" به‌روزرسانی شود؟"</string>
- <!-- no translation found for autofill_update_title_with_3types (8285767070604652626) -->
- <skip />
+ <string name="autofill_update_title_with_3types" msgid="8285767070604652626">"این موارد در "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>": <xliff:g id="TYPE_0">%1$s</xliff:g>، <xliff:g id="TYPE_1">%2$s</xliff:g>، و <xliff:g id="TYPE_2">%3$s</xliff:g> به‌روزرسانی شود؟"</string>
<string name="autofill_save_yes" msgid="8035743017382012850">"ذخیره"</string>
<string name="autofill_save_no" msgid="9212826374207023544">"نه سپاسگزارم"</string>
<string name="autofill_save_notnow" msgid="2853932672029024195">"حالا نه"</string>
diff --git a/core/res/res/values-fi/strings.xml b/core/res/res/values-fi/strings.xml
index 5cf1c99db7e4..3b5c86e9f37d 100644
--- a/core/res/res/values-fi/strings.xml
+++ b/core/res/res/values-fi/strings.xml
@@ -1867,6 +1867,8 @@
<string name="managed_profile_label_badge_2" msgid="5673187309555352550">"Toinen <xliff:g id="LABEL">%1$s</xliff:g>, työ"</string>
<string name="managed_profile_label_badge_3" msgid="6882151970556391957">"Kolmas <xliff:g id="LABEL">%1$s</xliff:g>, työ"</string>
<string name="clone_profile_label_badge" msgid="1871997694718793964">"Kloonaa <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+ <!-- no translation found for private_profile_label_badge (1712086003787839183) -->
+ <skip />
<string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"Pyydä PIN ennen irrotusta"</string>
<string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"Pyydä lukituksenpoistokuvio ennen irrotusta"</string>
<string name="lock_to_app_unlock_password" msgid="9126722403506560473">"Pyydä salasana ennen irrotusta"</string>
@@ -2031,8 +2033,7 @@
<string name="autofill_update_title" msgid="3630695947047069136">"Päivitetäänkö "<b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>"?"</string>
<string name="autofill_update_title_with_type" msgid="5264152633488495704">"Päivitetäänkö <xliff:g id="TYPE">%1$s</xliff:g> ("<b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>")?"</string>
<string name="autofill_update_title_with_2types" msgid="1797514386321086273">"Päivitetäänkö <xliff:g id="TYPE_0">%1$s</xliff:g> ja <xliff:g id="TYPE_1">%2$s</xliff:g> ("<b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>")?"</string>
- <!-- no translation found for autofill_update_title_with_3types (8285767070604652626) -->
- <skip />
+ <string name="autofill_update_title_with_3types" msgid="8285767070604652626">"Päivitetäänkö nämä ("<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>"): <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> ja <xliff:g id="TYPE_2">%3$s</xliff:g>?"</string>
<string name="autofill_save_yes" msgid="8035743017382012850">"Tallenna"</string>
<string name="autofill_save_no" msgid="9212826374207023544">"Ei kiitos"</string>
<string name="autofill_save_notnow" msgid="2853932672029024195">"Ei nyt"</string>
diff --git a/core/res/res/values-fr-rCA/strings.xml b/core/res/res/values-fr-rCA/strings.xml
index fda118332241..782ccd0e45ce 100644
--- a/core/res/res/values-fr-rCA/strings.xml
+++ b/core/res/res/values-fr-rCA/strings.xml
@@ -1868,6 +1868,7 @@
<string name="managed_profile_label_badge_2" msgid="5673187309555352550">"2e <xliff:g id="LABEL">%1$s</xliff:g> professionnel(le)"</string>
<string name="managed_profile_label_badge_3" msgid="6882151970556391957">"3e <xliff:g id="LABEL">%1$s</xliff:g> professionnel(le)"</string>
<string name="clone_profile_label_badge" msgid="1871997694718793964">"Clone de <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+ <string name="private_profile_label_badge" msgid="1712086003787839183">"<xliff:g id="LABEL">%1$s</xliff:g> privé"</string>
<string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"Demander le NIP avant d\'annuler l\'épinglage"</string>
<string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"Demander le schéma de déverrouillage avant d\'annuler l\'épinglage"</string>
<string name="lock_to_app_unlock_password" msgid="9126722403506560473">"Demander le mot de passe avant d\'annuler l\'épinglage"</string>
@@ -2032,8 +2033,7 @@
<string name="autofill_update_title" msgid="3630695947047069136">"Mettre à jour sous "<b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>"?"</string>
<string name="autofill_update_title_with_type" msgid="5264152633488495704">"Mettre à jour <xliff:g id="TYPE">%1$s</xliff:g> sous "<b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>"?"</string>
<string name="autofill_update_title_with_2types" msgid="1797514386321086273">"Mettre à jour <xliff:g id="TYPE_0">%1$s</xliff:g> et <xliff:g id="TYPE_1">%2$s</xliff:g> sous "<b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>"?"</string>
- <!-- no translation found for autofill_update_title_with_3types (8285767070604652626) -->
- <skip />
+ <string name="autofill_update_title_with_3types" msgid="8285767070604652626">"Mettre à jour ces éléments sous "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>" : <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> et <xliff:g id="TYPE_2">%3$s</xliff:g>?"</string>
<string name="autofill_save_yes" msgid="8035743017382012850">"Enregistrer"</string>
<string name="autofill_save_no" msgid="9212826374207023544">"Non, merci"</string>
<string name="autofill_save_notnow" msgid="2853932672029024195">"Pas maintenant"</string>
diff --git a/core/res/res/values-fr/strings.xml b/core/res/res/values-fr/strings.xml
index 654a3f256ce6..b5ea2e2d8681 100644
--- a/core/res/res/values-fr/strings.xml
+++ b/core/res/res/values-fr/strings.xml
@@ -1868,6 +1868,8 @@
<string name="managed_profile_label_badge_2" msgid="5673187309555352550">"2e <xliff:g id="LABEL">%1$s</xliff:g> professionnelle"</string>
<string name="managed_profile_label_badge_3" msgid="6882151970556391957">"3e <xliff:g id="LABEL">%1$s</xliff:g> professionnelle"</string>
<string name="clone_profile_label_badge" msgid="1871997694718793964">"Cloner <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+ <!-- no translation found for private_profile_label_badge (1712086003787839183) -->
+ <skip />
<string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"Demander le code avant de retirer l\'épingle"</string>
<string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"Demander le schéma de déverrouillage avant de retirer l\'épingle"</string>
<string name="lock_to_app_unlock_password" msgid="9126722403506560473">"Demander le mot de passe avant de retirer l\'épingle"</string>
@@ -2032,8 +2034,7 @@
<string name="autofill_update_title" msgid="3630695947047069136">"Mettre à jour cet élément dans "<b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>" ?"</string>
<string name="autofill_update_title_with_type" msgid="5264152633488495704">"Mettre à jour <xliff:g id="TYPE">%1$s</xliff:g> dans "<b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>" ?"</string>
<string name="autofill_update_title_with_2types" msgid="1797514386321086273">"Mettre à jour <xliff:g id="TYPE_0">%1$s</xliff:g> et <xliff:g id="TYPE_1">%2$s</xliff:g> dans "<b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>" ?"</string>
- <!-- no translation found for autofill_update_title_with_3types (8285767070604652626) -->
- <skip />
+ <string name="autofill_update_title_with_3types" msgid="8285767070604652626">"Mettre à jour ces éléments dans "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>" : <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> et <xliff:g id="TYPE_2">%3$s</xliff:g> ?"</string>
<string name="autofill_save_yes" msgid="8035743017382012850">"Enregistrer"</string>
<string name="autofill_save_no" msgid="9212826374207023544">"Non, merci"</string>
<string name="autofill_save_notnow" msgid="2853932672029024195">"Pas maintenant"</string>
diff --git a/core/res/res/values-gl/strings.xml b/core/res/res/values-gl/strings.xml
index 51006b9d67f8..ea3f104d0d12 100644
--- a/core/res/res/values-gl/strings.xml
+++ b/core/res/res/values-gl/strings.xml
@@ -1867,6 +1867,8 @@
<string name="managed_profile_label_badge_2" msgid="5673187309555352550">"2.º <xliff:g id="LABEL">%1$s</xliff:g> do traballo"</string>
<string name="managed_profile_label_badge_3" msgid="6882151970556391957">"3.º <xliff:g id="LABEL">%1$s</xliff:g> do traballo"</string>
<string name="clone_profile_label_badge" msgid="1871997694718793964">"Clonar <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+ <!-- no translation found for private_profile_label_badge (1712086003787839183) -->
+ <skip />
<string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"Pedir PIN antes de soltar a fixación"</string>
<string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"Pedir padrón de desbloqueo antes de soltar a fixación"</string>
<string name="lock_to_app_unlock_password" msgid="9126722403506560473">"Pedir contrasinal antes de soltar a fixación"</string>
@@ -2031,8 +2033,7 @@
<string name="autofill_update_title" msgid="3630695947047069136">"Queres actualizar o contido en "<b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>"?"</string>
<string name="autofill_update_title_with_type" msgid="5264152633488495704">"Queres actualizar <xliff:g id="TYPE">%1$s</xliff:g> en "<b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>"?"</string>
<string name="autofill_update_title_with_2types" msgid="1797514386321086273">"Queres actualizar <xliff:g id="TYPE_0">%1$s</xliff:g> e <xliff:g id="TYPE_1">%2$s</xliff:g> en "<b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>"?"</string>
- <!-- no translation found for autofill_update_title_with_3types (8285767070604652626) -->
- <skip />
+ <string name="autofill_update_title_with_3types" msgid="8285767070604652626">"Queres actualizar estes datos (<xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> e <xliff:g id="TYPE_2">%3$s</xliff:g>) en "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>"?"</string>
<string name="autofill_save_yes" msgid="8035743017382012850">"Gardar"</string>
<string name="autofill_save_no" msgid="9212826374207023544">"Non, grazas"</string>
<string name="autofill_save_notnow" msgid="2853932672029024195">"Agora non"</string>
diff --git a/core/res/res/values-gu/strings.xml b/core/res/res/values-gu/strings.xml
index aa2a887cb2af..0a42b241e255 100644
--- a/core/res/res/values-gu/strings.xml
+++ b/core/res/res/values-gu/strings.xml
@@ -1867,6 +1867,8 @@
<string name="managed_profile_label_badge_2" msgid="5673187309555352550">"2જું કાર્ય <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="managed_profile_label_badge_3" msgid="6882151970556391957">"3જું કાર્ય <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="clone_profile_label_badge" msgid="1871997694718793964">"<xliff:g id="LABEL">%1$s</xliff:g>ની ક્લોન"</string>
+ <!-- no translation found for private_profile_label_badge (1712086003787839183) -->
+ <skip />
<string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"અનપિન કરતા પહેલાં પિન માટે પૂછો"</string>
<string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"અનપિન કરતા પહેલાં અનલૉક પૅટર્ન માટે પૂછો"</string>
<string name="lock_to_app_unlock_password" msgid="9126722403506560473">"અનપિન કરતાં પહેલાં પાસવર્ડ માટે પૂછો"</string>
@@ -2031,8 +2033,7 @@
<string name="autofill_update_title" msgid="3630695947047069136"><b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>"માં અપડેટ કરીએ?"</string>
<string name="autofill_update_title_with_type" msgid="5264152633488495704">"<xliff:g id="TYPE">%1$s</xliff:g>ને "<b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>"માં અપડેટ કરીએ?"</string>
<string name="autofill_update_title_with_2types" msgid="1797514386321086273">"<xliff:g id="TYPE_0">%1$s</xliff:g> અને <xliff:g id="TYPE_1">%2$s</xliff:g>ને "<b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>"માં અપડેટ કરીએ?"</string>
- <!-- no translation found for autofill_update_title_with_3types (8285767070604652626) -->
- <skip />
+ <string name="autofill_update_title_with_3types" msgid="8285767070604652626">"શું "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>"માંની: આ <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> અને <xliff:g id="TYPE_2">%3$s</xliff:g> આઇટમને અપડેટ કરીએ?"</string>
<string name="autofill_save_yes" msgid="8035743017382012850">"સાચવો"</string>
<string name="autofill_save_no" msgid="9212826374207023544">"ના, આભાર"</string>
<string name="autofill_save_notnow" msgid="2853932672029024195">"હમણાં નહીં"</string>
diff --git a/core/res/res/values-hi/strings.xml b/core/res/res/values-hi/strings.xml
index a81ada661d28..8a383a1bd5e2 100644
--- a/core/res/res/values-hi/strings.xml
+++ b/core/res/res/values-hi/strings.xml
@@ -1867,6 +1867,8 @@
<string name="managed_profile_label_badge_2" msgid="5673187309555352550">"दूसरा काम <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="managed_profile_label_badge_3" msgid="6882151970556391957">"तीसरा काम <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="clone_profile_label_badge" msgid="1871997694718793964">"<xliff:g id="LABEL">%1$s</xliff:g> का क्लोन"</string>
+ <!-- no translation found for private_profile_label_badge (1712086003787839183) -->
+ <skip />
<string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"अनपिन करने से पहले पिन के लिए पूछें"</string>
<string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"अनपिन करने से पहले लॉक खोलने के पैटर्न के लिए पूछें"</string>
<string name="lock_to_app_unlock_password" msgid="9126722403506560473">"अनपिन करने से पहले पासवर्ड के लिए पूछें"</string>
@@ -2031,8 +2033,7 @@
<string name="autofill_update_title" msgid="3630695947047069136">"क्या आप "<b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>" में अपडेट करना चाहते हैं?"</string>
<string name="autofill_update_title_with_type" msgid="5264152633488495704">"क्या आप "<b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>" में <xliff:g id="TYPE">%1$s</xliff:g> अपडेट करना चाहते हैं?"</string>
<string name="autofill_update_title_with_2types" msgid="1797514386321086273">"क्या आप "<b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>" में <xliff:g id="TYPE_0">%1$s</xliff:g> और <xliff:g id="TYPE_1">%2$s</xliff:g> अपडेट करना चाहते हैं?"</string>
- <!-- no translation found for autofill_update_title_with_3types (8285767070604652626) -->
- <skip />
+ <string name="autofill_update_title_with_3types" msgid="8285767070604652626">"क्या आपको "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>" में इन आइटम को अपडेट करना है: <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g>, और <xliff:g id="TYPE_2">%3$s</xliff:g>?"</string>
<string name="autofill_save_yes" msgid="8035743017382012850">"सेव करें"</string>
<string name="autofill_save_no" msgid="9212826374207023544">"नहीं, धन्यवाद"</string>
<string name="autofill_save_notnow" msgid="2853932672029024195">"अभी नहीं"</string>
diff --git a/core/res/res/values-hr/strings.xml b/core/res/res/values-hr/strings.xml
index fefddbce9abe..d7f5b4ac1b00 100644
--- a/core/res/res/values-hr/strings.xml
+++ b/core/res/res/values-hr/strings.xml
@@ -1868,6 +1868,7 @@
<string name="managed_profile_label_badge_2" msgid="5673187309555352550">"2. <xliff:g id="LABEL">%1$s</xliff:g> za posao"</string>
<string name="managed_profile_label_badge_3" msgid="6882151970556391957">"3. <xliff:g id="LABEL">%1$s</xliff:g> za posao"</string>
<string name="clone_profile_label_badge" msgid="1871997694718793964">"Kloniraj <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+ <string name="private_profile_label_badge" msgid="1712086003787839183">"Privatno <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"Traži PIN radi otkvačivanja"</string>
<string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"Traži uzorak za otključavanje radi otkvačivanja"</string>
<string name="lock_to_app_unlock_password" msgid="9126722403506560473">"Traži zaporku radi otkvačivanja"</string>
@@ -2032,8 +2033,7 @@
<string name="autofill_update_title" msgid="3630695947047069136">"Želite li ažurirati u oznaku "<b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>"?"</string>
<string name="autofill_update_title_with_type" msgid="5264152633488495704">"Želite li ažurirati podatke <xliff:g id="TYPE">%1$s</xliff:g> u oznaci "<b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>"?"</string>
<string name="autofill_update_title_with_2types" msgid="1797514386321086273">"Želite li ažurirati podatke <xliff:g id="TYPE_0">%1$s</xliff:g> i <xliff:g id="TYPE_1">%2$s</xliff:g> u oznaci "<b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>"?"</string>
- <!-- no translation found for autofill_update_title_with_3types (8285767070604652626) -->
- <skip />
+ <string name="autofill_update_title_with_3types" msgid="8285767070604652626">"Želite li ažurirati ove stavke u oznaci "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>": <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> i <xliff:g id="TYPE_2">%3$s</xliff:g>?"</string>
<string name="autofill_save_yes" msgid="8035743017382012850">"Spremi"</string>
<string name="autofill_save_no" msgid="9212826374207023544">"Ne, hvala"</string>
<string name="autofill_save_notnow" msgid="2853932672029024195">"Ne sad"</string>
diff --git a/core/res/res/values-hu/strings.xml b/core/res/res/values-hu/strings.xml
index 8c8b38fd76c4..57b81a0b4ac6 100644
--- a/core/res/res/values-hu/strings.xml
+++ b/core/res/res/values-hu/strings.xml
@@ -1867,6 +1867,7 @@
<string name="managed_profile_label_badge_2" msgid="5673187309555352550">"2. munkahelyi <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="managed_profile_label_badge_3" msgid="6882151970556391957">"3. munkahelyi <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="clone_profile_label_badge" msgid="1871997694718793964">"<xliff:g id="LABEL">%1$s</xliff:g> klónozása"</string>
+ <string name="private_profile_label_badge" msgid="1712086003787839183">"Privát <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"PIN-kód kérése a kitűzés feloldásához"</string>
<string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"Feloldási minta kérése a rögzítés feloldásához"</string>
<string name="lock_to_app_unlock_password" msgid="9126722403506560473">"Jelszó kérése a rögzítés feloldásához"</string>
@@ -2031,8 +2032,7 @@
<string name="autofill_update_title" msgid="3630695947047069136">"Frissíti a(z) "<b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>" szolgáltatásban?"</string>
<string name="autofill_update_title_with_type" msgid="5264152633488495704">"Frissíti a(z) "<b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>" szolgáltatásban a következőt: <xliff:g id="TYPE">%1$s</xliff:g>?"</string>
<string name="autofill_update_title_with_2types" msgid="1797514386321086273">"Frissíti a(z) "<b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>" szolgáltatásban a következőket: <xliff:g id="TYPE_0">%1$s</xliff:g> és <xliff:g id="TYPE_1">%2$s</xliff:g>?"</string>
- <!-- no translation found for autofill_update_title_with_3types (8285767070604652626) -->
- <skip />
+ <string name="autofill_update_title_with_3types" msgid="8285767070604652626">"Frissíti a(z) "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>" szolgáltatásban a következőket: <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> és <xliff:g id="TYPE_2">%3$s</xliff:g>?"</string>
<string name="autofill_save_yes" msgid="8035743017382012850">"Mentés"</string>
<string name="autofill_save_no" msgid="9212826374207023544">"Nem, köszönöm"</string>
<string name="autofill_save_notnow" msgid="2853932672029024195">"Ne most"</string>
diff --git a/core/res/res/values-hy/strings.xml b/core/res/res/values-hy/strings.xml
index e240c31446c8..59827cb558b8 100644
--- a/core/res/res/values-hy/strings.xml
+++ b/core/res/res/values-hy/strings.xml
@@ -1867,6 +1867,8 @@
<string name="managed_profile_label_badge_2" msgid="5673187309555352550">"2-րդ աշխատանք <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="managed_profile_label_badge_3" msgid="6882151970556391957">"3-րդ աշխատանք <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="clone_profile_label_badge" msgid="1871997694718793964">"<xliff:g id="LABEL">%1$s</xliff:g>-ի կլոն"</string>
+ <!-- no translation found for private_profile_label_badge (1712086003787839183) -->
+ <skip />
<string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"Հարցնել PIN կոդը"</string>
<string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"Հարցնել ապակողպող նախշը"</string>
<string name="lock_to_app_unlock_password" msgid="9126722403506560473">"Հարցնել գաղտնաբառը"</string>
@@ -2031,8 +2033,7 @@
<string name="autofill_update_title" msgid="3630695947047069136">"Թարմացնե՞լ "<b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>" ծառայությունում"</string>
<string name="autofill_update_title_with_type" msgid="5264152633488495704">"Թարմացնե՞լ տվյալները (<xliff:g id="TYPE">%1$s</xliff:g>) "<b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>" ծառայությունում"</string>
<string name="autofill_update_title_with_2types" msgid="1797514386321086273">"Թարմացնե՞լ տվյալները (<xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g>) "<b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>" ծառայությունում"</string>
- <!-- no translation found for autofill_update_title_with_3types (8285767070604652626) -->
- <skip />
+ <string name="autofill_update_title_with_3types" msgid="8285767070604652626">"Թարմացնե՞լ տվյալները (<xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g>, <xliff:g id="TYPE_2">%3$s</xliff:g>) "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>" ծառայությունում"</string>
<string name="autofill_save_yes" msgid="8035743017382012850">"Պահել"</string>
<string name="autofill_save_no" msgid="9212826374207023544">"Ոչ"</string>
<string name="autofill_save_notnow" msgid="2853932672029024195">"Ոչ հիմա"</string>
diff --git a/core/res/res/values-in/strings.xml b/core/res/res/values-in/strings.xml
index 5a9188d9cf5c..8603809903ae 100644
--- a/core/res/res/values-in/strings.xml
+++ b/core/res/res/values-in/strings.xml
@@ -1643,7 +1643,7 @@
<string name="media_route_status_in_use" msgid="6684112905244944724">"Sedang digunakan"</string>
<string name="display_manager_built_in_display_name" msgid="1015775198829722440">"Layar Built-In"</string>
<string name="display_manager_hdmi_display_name" msgid="1022758026251534975">"Layar HDMI"</string>
- <string name="display_manager_overlay_display_name" msgid="5306088205181005861">"Hamparan #<xliff:g id="ID">%1$d</xliff:g>"</string>
+ <string name="display_manager_overlay_display_name" msgid="5306088205181005861">"Overlay #<xliff:g id="ID">%1$d</xliff:g>"</string>
<string name="display_manager_overlay_display_title" msgid="1480158037150469170">"<xliff:g id="NAME">%1$s</xliff:g>: <xliff:g id="WIDTH">%2$d</xliff:g>x<xliff:g id="HEIGHT">%3$d</xliff:g>, <xliff:g id="DPI">%4$d</xliff:g> dpi"</string>
<string name="display_manager_overlay_display_secure_suffix" msgid="2810034719482834679">", aman"</string>
<string name="kg_forgot_pattern_button_text" msgid="406145459223122537">"Lupa Pola?"</string>
@@ -1867,6 +1867,7 @@
<string name="managed_profile_label_badge_2" msgid="5673187309555352550">"Upaya ke-2 <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="managed_profile_label_badge_3" msgid="6882151970556391957">"Upaya ke-3 <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="clone_profile_label_badge" msgid="1871997694718793964">"Clone <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+ <string name="private_profile_label_badge" msgid="1712086003787839183">"<xliff:g id="LABEL">%1$s</xliff:g> Pribadi"</string>
<string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"Meminta PIN sebelum melepas sematan"</string>
<string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"Meminta pola pembukaan kunci sebelum melepas sematan"</string>
<string name="lock_to_app_unlock_password" msgid="9126722403506560473">"Meminta sandi sebelum melepas sematan"</string>
@@ -2031,8 +2032,7 @@
<string name="autofill_update_title" msgid="3630695947047069136">"Perbarui di "<b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>"?"</string>
<string name="autofill_update_title_with_type" msgid="5264152633488495704">"Perbarui <xliff:g id="TYPE">%1$s</xliff:g> di "<b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>"?"</string>
<string name="autofill_update_title_with_2types" msgid="1797514386321086273">"Perbarui <xliff:g id="TYPE_0">%1$s</xliff:g> dan <xliff:g id="TYPE_1">%2$s</xliff:g> di "<b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>"?"</string>
- <!-- no translation found for autofill_update_title_with_3types (8285767070604652626) -->
- <skip />
+ <string name="autofill_update_title_with_3types" msgid="8285767070604652626">"Perbarui item-item berikut di "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>": <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g>, dan <xliff:g id="TYPE_2">%3$s</xliff:g>?"</string>
<string name="autofill_save_yes" msgid="8035743017382012850">"Simpan"</string>
<string name="autofill_save_no" msgid="9212826374207023544">"Lain kali"</string>
<string name="autofill_save_notnow" msgid="2853932672029024195">"Lain kali"</string>
diff --git a/core/res/res/values-is/strings.xml b/core/res/res/values-is/strings.xml
index 8ea6f6ad4228..7420a2511960 100644
--- a/core/res/res/values-is/strings.xml
+++ b/core/res/res/values-is/strings.xml
@@ -1867,6 +1867,8 @@
<string name="managed_profile_label_badge_2" msgid="5673187309555352550">"<xliff:g id="LABEL">%1$s</xliff:g> í vinnu (2)"</string>
<string name="managed_profile_label_badge_3" msgid="6882151970556391957">"<xliff:g id="LABEL">%1$s</xliff:g> í vinnu (3)"</string>
<string name="clone_profile_label_badge" msgid="1871997694718793964">"Afrit af <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+ <!-- no translation found for private_profile_label_badge (1712086003787839183) -->
+ <skip />
<string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"Biðja um PIN-númer til að losa"</string>
<string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"Biðja um opnunarmynstur til að losa"</string>
<string name="lock_to_app_unlock_password" msgid="9126722403506560473">"Biðja um aðgangsorð til að losa"</string>
@@ -2031,8 +2033,7 @@
<string name="autofill_update_title" msgid="3630695947047069136">"Uppfæra í "<b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>"?"</string>
<string name="autofill_update_title_with_type" msgid="5264152633488495704">"Uppfæra <xliff:g id="TYPE">%1$s</xliff:g> í "<b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>"?"</string>
<string name="autofill_update_title_with_2types" msgid="1797514386321086273">"Uppfæra <xliff:g id="TYPE_0">%1$s</xliff:g> og <xliff:g id="TYPE_1">%2$s</xliff:g> í "<b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>"?"</string>
- <!-- no translation found for autofill_update_title_with_3types (8285767070604652626) -->
- <skip />
+ <string name="autofill_update_title_with_3types" msgid="8285767070604652626">"Uppfæra þessi atriði í "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>": <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> og <xliff:g id="TYPE_2">%3$s</xliff:g>?"</string>
<string name="autofill_save_yes" msgid="8035743017382012850">"Vista"</string>
<string name="autofill_save_no" msgid="9212826374207023544">"Nei, takk"</string>
<string name="autofill_save_notnow" msgid="2853932672029024195">"Ekki núna"</string>
diff --git a/core/res/res/values-it/strings.xml b/core/res/res/values-it/strings.xml
index eb0b5698baed..168a1613fde6 100644
--- a/core/res/res/values-it/strings.xml
+++ b/core/res/res/values-it/strings.xml
@@ -1868,6 +1868,7 @@
<string name="managed_profile_label_badge_2" msgid="5673187309555352550">"<xliff:g id="LABEL">%1$s</xliff:g> di lavoro (2°)"</string>
<string name="managed_profile_label_badge_3" msgid="6882151970556391957">"<xliff:g id="LABEL">%1$s</xliff:g> di lavoro (3°)"</string>
<string name="clone_profile_label_badge" msgid="1871997694718793964">"<xliff:g id="LABEL">%1$s</xliff:g> (clone)"</string>
+ <string name="private_profile_label_badge" msgid="1712086003787839183">"<xliff:g id="LABEL">%1$s</xliff:g> privato"</string>
<string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"Richiedi il PIN per lo sblocco"</string>
<string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"Richiedi sequenza di sblocco prima di sbloccare"</string>
<string name="lock_to_app_unlock_password" msgid="9126722403506560473">"Richiedi password prima di sbloccare"</string>
@@ -2032,8 +2033,7 @@
<string name="autofill_update_title" msgid="3630695947047069136">"Vuoi aggiornare su "<b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>"?"</string>
<string name="autofill_update_title_with_type" msgid="5264152633488495704">"Vuoi aggiornare <xliff:g id="TYPE">%1$s</xliff:g> su "<b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>"?"</string>
<string name="autofill_update_title_with_2types" msgid="1797514386321086273">"Vuoi aggiornare <xliff:g id="TYPE_0">%1$s</xliff:g> e <xliff:g id="TYPE_1">%2$s</xliff:g> su "<b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>"?"</string>
- <!-- no translation found for autofill_update_title_with_3types (8285767070604652626) -->
- <skip />
+ <string name="autofill_update_title_with_3types" msgid="8285767070604652626">"Vuoi aggiornare i seguenti dati in "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>": <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> e <xliff:g id="TYPE_2">%3$s</xliff:g>?"</string>
<string name="autofill_save_yes" msgid="8035743017382012850">"Salva"</string>
<string name="autofill_save_no" msgid="9212826374207023544">"No, grazie"</string>
<string name="autofill_save_notnow" msgid="2853932672029024195">"Non ora"</string>
diff --git a/core/res/res/values-iw/strings.xml b/core/res/res/values-iw/strings.xml
index a3ffd39f7eae..1f909945c79a 100644
--- a/core/res/res/values-iw/strings.xml
+++ b/core/res/res/values-iw/strings.xml
@@ -1868,6 +1868,8 @@
<string name="managed_profile_label_badge_2" msgid="5673187309555352550">"<xliff:g id="LABEL">%1$s</xliff:g> שני בעבודה"</string>
<string name="managed_profile_label_badge_3" msgid="6882151970556391957">"<xliff:g id="LABEL">%1$s</xliff:g> שלישי בעבודה"</string>
<string name="clone_profile_label_badge" msgid="1871997694718793964">"שכפול של <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+ <!-- no translation found for private_profile_label_badge (1712086003787839183) -->
+ <skip />
<string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"יש לבקש קוד אימות לפני ביטול הצמדה"</string>
<string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"צריך לבקש קו ביטול נעילה לפני ביטול הצמדה"</string>
<string name="lock_to_app_unlock_password" msgid="9126722403506560473">"יש לבקש סיסמה לפני ביטול הצמדה"</string>
@@ -1956,7 +1958,7 @@
<string name="app_suspended_more_details" msgid="211260942831587014">"מידע נוסף"</string>
<string name="app_suspended_unsuspend_message" msgid="1665438589450555459">"ביטול ההשהיה של האפליקציה"</string>
<string name="work_mode_off_title" msgid="6367463960165135829">"להפעיל את האפליקציות לעבודה?"</string>
- <string name="work_mode_turn_on" msgid="5316648862401307800">"הפעלה"</string>
+ <string name="work_mode_turn_on" msgid="5316648862401307800">"ביטול ההשהיה"</string>
<string name="work_mode_emergency_call_button" msgid="6818855962881612322">"שיחת חירום"</string>
<string name="app_blocked_title" msgid="7353262160455028160">"האפליקציה לא זמינה"</string>
<string name="app_blocked_message" msgid="542972921087873023">"האפליקציה <xliff:g id="APP_NAME">%1$s</xliff:g> לא זמינה בשלב זה."</string>
@@ -2032,8 +2034,7 @@
<string name="autofill_update_title" msgid="3630695947047069136">"לעדכן בשירות "<b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>"?"</string>
<string name="autofill_update_title_with_type" msgid="5264152633488495704">"לעדכן <xliff:g id="TYPE">%1$s</xliff:g> בשירות "<b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>"?"</string>
<string name="autofill_update_title_with_2types" msgid="1797514386321086273">"האם לעדכן את <xliff:g id="TYPE_0">%1$s</xliff:g> ואת <xliff:g id="TYPE_1">%2$s</xliff:g> ב-"<b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>"?"</string>
- <!-- no translation found for autofill_update_title_with_3types (8285767070604652626) -->
- <skip />
+ <string name="autofill_update_title_with_3types" msgid="8285767070604652626">"לעדכן את הפריטים אלה ב-"<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>":‏ <xliff:g id="TYPE_0">%1$s</xliff:g>,‏ <xliff:g id="TYPE_1">%2$s</xliff:g> ו-<xliff:g id="TYPE_2">%3$s</xliff:g>?"</string>
<string name="autofill_save_yes" msgid="8035743017382012850">"שמירה"</string>
<string name="autofill_save_no" msgid="9212826374207023544">"לא, תודה"</string>
<string name="autofill_save_notnow" msgid="2853932672029024195">"לא עכשיו"</string>
diff --git a/core/res/res/values-ja/strings.xml b/core/res/res/values-ja/strings.xml
index aa4ac4e67d70..d7618754f200 100644
--- a/core/res/res/values-ja/strings.xml
+++ b/core/res/res/values-ja/strings.xml
@@ -321,7 +321,7 @@
<string name="permgrouplab_camera" msgid="9090413408963547706">"カメラ"</string>
<string name="permgroupdesc_camera" msgid="7585150538459320326">"写真と動画の撮影"</string>
<string name="permgrouplab_nearby_devices" msgid="5529147543651181991">"付近のデバイス"</string>
- <string name="permgroupdesc_nearby_devices" msgid="3213561597116913508">"付近のデバイスの検出と接続"</string>
+ <string name="permgroupdesc_nearby_devices" msgid="3213561597116913508">"付近のデバイスの\\n検出と接続"</string>
<string name="permgrouplab_calllog" msgid="7926834372073550288">"通話履歴"</string>
<string name="permgroupdesc_calllog" msgid="2026996642917801803">"通話履歴の読み取りと書き込み"</string>
<string name="permgrouplab_phone" msgid="570318944091926620">"電話"</string>
@@ -1867,6 +1867,7 @@
<string name="managed_profile_label_badge_2" msgid="5673187309555352550">"2 番目の仕事用<xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="managed_profile_label_badge_3" msgid="6882151970556391957">"3 番目の仕事用<xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="clone_profile_label_badge" msgid="1871997694718793964">"<xliff:g id="LABEL">%1$s</xliff:g> のクローン"</string>
+ <string name="private_profile_label_badge" msgid="1712086003787839183">"個人用<xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"オフライン再生を解除する前にPINの入力を求める"</string>
<string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"画面固定を解除する前にロック解除パターンの入力を求める"</string>
<string name="lock_to_app_unlock_password" msgid="9126722403506560473">"オフライン再生を解除する前にパスワードの入力を求める"</string>
@@ -2031,8 +2032,7 @@
<string name="autofill_update_title" msgid="3630695947047069136"><b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>" で更新しますか?"</string>
<string name="autofill_update_title_with_type" msgid="5264152633488495704">"<xliff:g id="TYPE">%1$s</xliff:g>を "<b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>" で更新しますか?"</string>
<string name="autofill_update_title_with_2types" msgid="1797514386321086273">"<xliff:g id="TYPE_0">%1$s</xliff:g>、<xliff:g id="TYPE_1">%2$s</xliff:g>を "<b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>" で更新しますか?"</string>
- <!-- no translation found for autofill_update_title_with_3types (8285767070604652626) -->
- <skip />
+ <string name="autofill_update_title_with_3types" msgid="8285767070604652626">"<xliff:g id="TYPE_0">%1$s</xliff:g>、<xliff:g id="TYPE_1">%2$s</xliff:g>、<xliff:g id="TYPE_2">%3$s</xliff:g>を "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>" で更新しますか?"</string>
<string name="autofill_save_yes" msgid="8035743017382012850">"はい"</string>
<string name="autofill_save_no" msgid="9212826374207023544">"いいえ"</string>
<string name="autofill_save_notnow" msgid="2853932672029024195">"後で"</string>
diff --git a/core/res/res/values-ka/strings.xml b/core/res/res/values-ka/strings.xml
index 9e730df86610..513b392abee0 100644
--- a/core/res/res/values-ka/strings.xml
+++ b/core/res/res/values-ka/strings.xml
@@ -1867,6 +1867,7 @@
<string name="managed_profile_label_badge_2" msgid="5673187309555352550">"მე-2 სამსახური <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="managed_profile_label_badge_3" msgid="6882151970556391957">"მე-3 სამსახური <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="clone_profile_label_badge" msgid="1871997694718793964">"<xliff:g id="LABEL">%1$s</xliff:g> კლონის შექმნა"</string>
+ <string name="private_profile_label_badge" msgid="1712086003787839183">"პირადი <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"ფიქსაციის მოხსნამდე PIN-ის მოთხოვნა"</string>
<string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"ფიქსაციის მოხსნამდე განბლოკვის ნიმუშის მოთხოვნა"</string>
<string name="lock_to_app_unlock_password" msgid="9126722403506560473">"ფიქსაციის მოხსნამდე პაროლის მოთხოვნა"</string>
@@ -2031,8 +2032,7 @@
<string name="autofill_update_title" msgid="3630695947047069136">"გსურთ "<b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>"-ში განახლება?"</string>
<string name="autofill_update_title_with_type" msgid="5264152633488495704">"გსურთ, "<b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>"-ში განაახლოთ <xliff:g id="TYPE">%1$s</xliff:g>?"</string>
<string name="autofill_update_title_with_2types" msgid="1797514386321086273">"გსურთ, "<b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>"-ში განაახლოთ <xliff:g id="TYPE_0">%1$s</xliff:g> და <xliff:g id="TYPE_1">%2$s</xliff:g>?"</string>
- <!-- no translation found for autofill_update_title_with_3types (8285767070604652626) -->
- <skip />
+ <string name="autofill_update_title_with_3types" msgid="8285767070604652626">"განახლდეს ეს ერთეულები "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>"-ში: <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> და <xliff:g id="TYPE_2">%3$s</xliff:g>?"</string>
<string name="autofill_save_yes" msgid="8035743017382012850">"შენახვა"</string>
<string name="autofill_save_no" msgid="9212826374207023544">"არა, გმადლობთ"</string>
<string name="autofill_save_notnow" msgid="2853932672029024195">"ახლა არა"</string>
diff --git a/core/res/res/values-kk/strings.xml b/core/res/res/values-kk/strings.xml
index 15610456753e..1d93a71f14c5 100644
--- a/core/res/res/values-kk/strings.xml
+++ b/core/res/res/values-kk/strings.xml
@@ -1867,6 +1867,8 @@
<string name="managed_profile_label_badge_2" msgid="5673187309555352550">"2-ші жұмыс профилі (<xliff:g id="LABEL">%1$s</xliff:g>)"</string>
<string name="managed_profile_label_badge_3" msgid="6882151970556391957">"3-ші жұмыс профилі (<xliff:g id="LABEL">%1$s</xliff:g>)"</string>
<string name="clone_profile_label_badge" msgid="1871997694718793964">"<xliff:g id="LABEL">%1$s</xliff:g> клондау"</string>
+ <!-- no translation found for private_profile_label_badge (1712086003787839183) -->
+ <skip />
<string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"Босату алдында PIN кодын сұрау"</string>
<string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"Босату алдында бекітпесін ашу өрнегін сұрау"</string>
<string name="lock_to_app_unlock_password" msgid="9126722403506560473">"Босату алдында құпия сөзді сұрау"</string>
@@ -2031,8 +2033,7 @@
<string name="autofill_update_title" msgid="3630695947047069136"><b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>" қызметінде жаңартылсын ба?"</string>
<string name="autofill_update_title_with_type" msgid="5264152633488495704">"<xliff:g id="TYPE">%1$s</xliff:g> деректері "<b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>" қызметінде жаңартылсын ба?"</string>
<string name="autofill_update_title_with_2types" msgid="1797514386321086273">"<xliff:g id="TYPE_0">%1$s</xliff:g> және <xliff:g id="TYPE_1">%2$s</xliff:g> деректері "<b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>" қызметінде жаңартылсын ба?"</string>
- <!-- no translation found for autofill_update_title_with_3types (8285767070604652626) -->
- <skip />
+ <string name="autofill_update_title_with_3types" msgid="8285767070604652626"><b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>" қызметіндегі <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> және <xliff:g id="TYPE_2">%3$s</xliff:g> деректері жаңартылсын ба?"</string>
<string name="autofill_save_yes" msgid="8035743017382012850">"Сақтау"</string>
<string name="autofill_save_no" msgid="9212826374207023544">"Жоқ, рақмет"</string>
<string name="autofill_save_notnow" msgid="2853932672029024195">"Қазір емес"</string>
diff --git a/core/res/res/values-km/strings.xml b/core/res/res/values-km/strings.xml
index cea9af4ae439..9047666092a5 100644
--- a/core/res/res/values-km/strings.xml
+++ b/core/res/res/values-km/strings.xml
@@ -1867,6 +1867,7 @@
<string name="managed_profile_label_badge_2" msgid="5673187309555352550">"<xliff:g id="LABEL">%1$s</xliff:g> ការងារទី 2"</string>
<string name="managed_profile_label_badge_3" msgid="6882151970556391957">"<xliff:g id="LABEL">%1$s</xliff:g> ការងារទី 3"</string>
<string name="clone_profile_label_badge" msgid="1871997694718793964">"ក្លូន <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+ <string name="private_profile_label_badge" msgid="1712086003787839183">"<xliff:g id="LABEL">%1$s</xliff:g> ឯកជន"</string>
<string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"សួរ​រក​កូដ PIN មុន​ពេលដកខ្ទាស់"</string>
<string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"សួរ​រក​លំនាំ​ដោះ​សោ​មុន​ពេលដោះខ្ទាស់"</string>
<string name="lock_to_app_unlock_password" msgid="9126722403506560473">"សួរ​រក​ពាក្យ​សម្ងាត់​មុន​ពេល​ផ្ដាច់"</string>
@@ -2031,8 +2032,7 @@
<string name="autofill_update_title" msgid="3630695947047069136">"ធ្វើ​បច្ចុប្បន្នភាព​នៅក្នុង "<b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>"?"</string>
<string name="autofill_update_title_with_type" msgid="5264152633488495704">"ធ្វើ​បច្ចុប្បន្នភាព <xliff:g id="TYPE">%1$s</xliff:g> នៅក្នុង "<b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>"?"</string>
<string name="autofill_update_title_with_2types" msgid="1797514386321086273">"ធ្វើ​បច្ចុប្បន្នភាព​ <xliff:g id="TYPE_0">%1$s</xliff:g> និង <xliff:g id="TYPE_1">%2$s</xliff:g> នៅក្នុង "<b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>"?"</string>
- <!-- no translation found for autofill_update_title_with_3types (8285767070604652626) -->
- <skip />
+ <string name="autofill_update_title_with_3types" msgid="8285767070604652626">"ធ្វើ​បច្ចុប្បន្នភាព​ធាតុ​ទាំងនេះ​នៅក្នុង "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>"៖ <xliff:g id="TYPE_0">%1$s</xliff:g> <xliff:g id="TYPE_1">%2$s</xliff:g> និង<xliff:g id="TYPE_2">%3$s</xliff:g>ឬ?"</string>
<string name="autofill_save_yes" msgid="8035743017382012850">"រក្សាទុក"</string>
<string name="autofill_save_no" msgid="9212826374207023544">"ទេ អរគុណ"</string>
<string name="autofill_save_notnow" msgid="2853932672029024195">"កុំ​ទាន់"</string>
diff --git a/core/res/res/values-kn/strings.xml b/core/res/res/values-kn/strings.xml
index 4cdb755669f8..19c6f5d20491 100644
--- a/core/res/res/values-kn/strings.xml
+++ b/core/res/res/values-kn/strings.xml
@@ -1867,6 +1867,7 @@
<string name="managed_profile_label_badge_2" msgid="5673187309555352550">"2 ನೇ ಕೆಲಸದ <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="managed_profile_label_badge_3" msgid="6882151970556391957">"3 ನೇ ಕೆಲಸದ <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="clone_profile_label_badge" msgid="1871997694718793964">"<xliff:g id="LABEL">%1$s</xliff:g> ಕ್ಲೋನ್"</string>
+ <string name="private_profile_label_badge" msgid="1712086003787839183">"ಖಾಸಗಿ <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"ಅನ್‌ಪಿನ್ ಮಾಡಲು ಪಿನ್‌ ಕೇಳು"</string>
<string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"ಅನ್‌ಪಿನ್ ಮಾಡಲು ಅನ್‌ಲಾಕ್ ಪ್ಯಾಟರ್ನ್ ಕೇಳಿ"</string>
<string name="lock_to_app_unlock_password" msgid="9126722403506560473">"ಅನ್‌ಪಿನ್ ಮಾಡಲು ಪಾಸ್‌ವರ್ಡ್ ಕೇಳು"</string>
@@ -2031,8 +2032,7 @@
<string name="autofill_update_title" msgid="3630695947047069136"><b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>" ನಲ್ಲಿ ಅಪ್‌ಡೇಟ್ ಮಾಡಬೇಕೆ?"</string>
<string name="autofill_update_title_with_type" msgid="5264152633488495704">"<xliff:g id="TYPE">%1$s</xliff:g> ಅನ್ನು "<b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>" ನಲ್ಲಿ ಅಪ್‌ಡೇಟ್ ಮಾಡಬೇಕೆ?"</string>
<string name="autofill_update_title_with_2types" msgid="1797514386321086273">"<xliff:g id="TYPE_0">%1$s</xliff:g> ಮತ್ತು <xliff:g id="TYPE_1">%2$s</xliff:g> ಅನ್ನು "<b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>" ನಲ್ಲಿ ಅಪ್‌ಡೇಟ್ ಮಾಡಬೇಕೆ?"</string>
- <!-- no translation found for autofill_update_title_with_3types (8285767070604652626) -->
- <skip />
+ <string name="autofill_update_title_with_3types" msgid="8285767070604652626">"ಈ ಮುಂದಿನ ಐಟಂಗಳನ್ನು "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>" ನಲ್ಲಿ ಅಪ್‌ಡೇಟ್ ಮಾಡಬೇಕೆ: <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> ಮತ್ತು <xliff:g id="TYPE_2">%3$s</xliff:g>?"</string>
<string name="autofill_save_yes" msgid="8035743017382012850">"ಉಳಿಸಿ"</string>
<string name="autofill_save_no" msgid="9212826374207023544">"ಬೇಡ"</string>
<string name="autofill_save_notnow" msgid="2853932672029024195">"ಸದ್ಯಕ್ಕೆ ಬೇಡ"</string>
diff --git a/core/res/res/values-ko/strings.xml b/core/res/res/values-ko/strings.xml
index ae92aa951dee..335a9572a866 100644
--- a/core/res/res/values-ko/strings.xml
+++ b/core/res/res/values-ko/strings.xml
@@ -1867,6 +1867,8 @@
<string name="managed_profile_label_badge_2" msgid="5673187309555352550">"두 번째 업무용 <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="managed_profile_label_badge_3" msgid="6882151970556391957">"세 번째 업무용<xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="clone_profile_label_badge" msgid="1871997694718793964">"<xliff:g id="LABEL">%1$s</xliff:g> 복사"</string>
+ <!-- no translation found for private_profile_label_badge (1712086003787839183) -->
+ <skip />
<string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"고정 해제 이전에 PIN 요청"</string>
<string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"고정 해제 시 잠금 해제 패턴 요청"</string>
<string name="lock_to_app_unlock_password" msgid="9126722403506560473">"고정 해제 이전에 비밀번호 요청"</string>
@@ -2031,8 +2033,7 @@
<string name="autofill_update_title" msgid="3630695947047069136"><b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>"에서 업데이트하시겠습니까?"</string>
<string name="autofill_update_title_with_type" msgid="5264152633488495704"><b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>"에서 <xliff:g id="TYPE">%1$s</xliff:g>을(를) 업데이트하시겠습니까?"</string>
<string name="autofill_update_title_with_2types" msgid="1797514386321086273"><b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>"에서 <xliff:g id="TYPE_0">%1$s</xliff:g> 및 <xliff:g id="TYPE_1">%2$s</xliff:g>을(를) 업데이트하시겠습니까?"</string>
- <!-- no translation found for autofill_update_title_with_3types (8285767070604652626) -->
- <skip />
+ <string name="autofill_update_title_with_3types" msgid="8285767070604652626"><b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>"에서 <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g>, <xliff:g id="TYPE_2">%3$s</xliff:g> 항목을 업데이트하시겠습니까?"</string>
<string name="autofill_save_yes" msgid="8035743017382012850">"저장"</string>
<string name="autofill_save_no" msgid="9212826374207023544">"사용 안함"</string>
<string name="autofill_save_notnow" msgid="2853932672029024195">"나중에"</string>
diff --git a/core/res/res/values-ky/strings.xml b/core/res/res/values-ky/strings.xml
index c585841dfd7d..df4929fac5b8 100644
--- a/core/res/res/values-ky/strings.xml
+++ b/core/res/res/values-ky/strings.xml
@@ -1867,6 +1867,8 @@
<string name="managed_profile_label_badge_2" msgid="5673187309555352550">"2-жумуш <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="managed_profile_label_badge_3" msgid="6882151970556391957">"3-жумуш <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="clone_profile_label_badge" msgid="1871997694718793964">"<xliff:g id="LABEL">%1$s</xliff:g> клону"</string>
+ <!-- no translation found for private_profile_label_badge (1712086003787839183) -->
+ <skip />
<string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"Бошотуудан мурун PIN суралсын"</string>
<string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"Бошотуудан мурун графикалык ачкыч суралсын"</string>
<string name="lock_to_app_unlock_password" msgid="9126722403506560473">"Бошотуудан мурун сырсөз суралсын"</string>
@@ -2031,8 +2033,7 @@
<string name="autofill_update_title" msgid="3630695947047069136"><b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>" кызматында жаңыртылсынбы?"</string>
<string name="autofill_update_title_with_type" msgid="5264152633488495704"><b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>" кызматындагы <xliff:g id="TYPE">%1$s</xliff:g> жаңыртылсын?"</string>
<string name="autofill_update_title_with_2types" msgid="1797514386321086273"><b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>" кызматындагы <xliff:g id="TYPE_0">%1$s</xliff:g> жана <xliff:g id="TYPE_1">%2$s</xliff:g> жаңыртылсынбы?"</string>
- <!-- no translation found for autofill_update_title_with_3types (8285767070604652626) -->
- <skip />
+ <string name="autofill_update_title_with_3types" msgid="8285767070604652626"><b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>" кызматындагы төмөнкүлөр жаңыртылсынбы: <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> жана <xliff:g id="TYPE_2">%3$s</xliff:g>?"</string>
<string name="autofill_save_yes" msgid="8035743017382012850">"Сактоо"</string>
<string name="autofill_save_no" msgid="9212826374207023544">"Жок, рахмат"</string>
<string name="autofill_save_notnow" msgid="2853932672029024195">"Азыр эмес"</string>
diff --git a/core/res/res/values-lo/strings.xml b/core/res/res/values-lo/strings.xml
index 8057449d27fb..cddabaf3afa6 100644
--- a/core/res/res/values-lo/strings.xml
+++ b/core/res/res/values-lo/strings.xml
@@ -1867,6 +1867,8 @@
<string name="managed_profile_label_badge_2" msgid="5673187309555352550">"ບ່ອນເຮັດວຽກທີ 2 <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="managed_profile_label_badge_3" msgid="6882151970556391957">"ບ່ອນເຮັດວຽກທີ 3 <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="clone_profile_label_badge" msgid="1871997694718793964">"ໂຄລນ <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+ <!-- no translation found for private_profile_label_badge (1712086003787839183) -->
+ <skip />
<string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"​ຖາມ​ຫາ PIN ກ່ອນ​ຍົກ​ເລີກ​ການປັກ​ໝຸດ"</string>
<string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"​ຖາມ​ຫາ​ຮູບ​ແບບ​ປົດ​ລັອກ​ກ່ອນ​ຍົກ​ເລີກ​ການ​ປັກ​ໝຸດ"</string>
<string name="lock_to_app_unlock_password" msgid="9126722403506560473">"​ຖາມ​ຫາ​ລະ​ຫັດ​ຜ່ານ​ກ່ອນ​ຍົກ​ເລີກ​ການ​ປັກ​ໝຸດ"</string>
@@ -2031,8 +2033,7 @@
<string name="autofill_update_title" msgid="3630695947047069136">"ອັບເດດໃນ "<b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>" ບໍ?"</string>
<string name="autofill_update_title_with_type" msgid="5264152633488495704">"ອັບເດດ <xliff:g id="TYPE">%1$s</xliff:g> ໃນ "<b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>" ບໍ?"</string>
<string name="autofill_update_title_with_2types" msgid="1797514386321086273">"ອັບເດດ <xliff:g id="TYPE_0">%1$s</xliff:g> ແລະ <xliff:g id="TYPE_1">%2$s</xliff:g> ໃນ "<b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>" ບໍ?"</string>
- <!-- no translation found for autofill_update_title_with_3types (8285767070604652626) -->
- <skip />
+ <string name="autofill_update_title_with_3types" msgid="8285767070604652626">"ອັບເດດລາຍການເຫຼົ່ານີ້ໃນ "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>": <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> ແລະ <xliff:g id="TYPE_2">%3$s</xliff:g> ບໍ?"</string>
<string name="autofill_save_yes" msgid="8035743017382012850">"ບັນທຶກ"</string>
<string name="autofill_save_no" msgid="9212826374207023544">"ບໍ່, ຂອບໃຈ"</string>
<string name="autofill_save_notnow" msgid="2853932672029024195">"ບໍ່ຟ້າວເທື່ອ"</string>
diff --git a/core/res/res/values-lt/strings.xml b/core/res/res/values-lt/strings.xml
index c6d36d1d1828..33168458ffb9 100644
--- a/core/res/res/values-lt/strings.xml
+++ b/core/res/res/values-lt/strings.xml
@@ -1869,6 +1869,7 @@
<string name="managed_profile_label_badge_2" msgid="5673187309555352550">"2-asis darbo <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="managed_profile_label_badge_3" msgid="6882151970556391957">"3-iasis darbo <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="clone_profile_label_badge" msgid="1871997694718793964">"„<xliff:g id="LABEL">%1$s</xliff:g>“ kopija"</string>
+ <string name="private_profile_label_badge" msgid="1712086003787839183">"Privat. „<xliff:g id="LABEL">%1$s</xliff:g>“"</string>
<string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"Prašyti PIN kodo prieš atsegant"</string>
<string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"Prašyti atrakinimo piešinio prieš atsegant"</string>
<string name="lock_to_app_unlock_password" msgid="9126722403506560473">"Prašyti slaptažodžio prieš atsegant"</string>
@@ -2033,8 +2034,7 @@
<string name="autofill_update_title" msgid="3630695947047069136">"Atnaujinti paslaugoje "<b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>"?"</string>
<string name="autofill_update_title_with_type" msgid="5264152633488495704">"Atnaujinti <xliff:g id="TYPE">%1$s</xliff:g> paslaugoje "<b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>"?"</string>
<string name="autofill_update_title_with_2types" msgid="1797514386321086273">"Atnaujinti <xliff:g id="TYPE_0">%1$s</xliff:g> ir <xliff:g id="TYPE_1">%2$s</xliff:g> paslaugoje "<b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>"?"</string>
- <!-- no translation found for autofill_update_title_with_3types (8285767070604652626) -->
- <skip />
+ <string name="autofill_update_title_with_3types" msgid="8285767070604652626">"Atnaujinti šiuos elementus paslaugoje "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>": <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> ir <xliff:g id="TYPE_2">%3$s</xliff:g>?"</string>
<string name="autofill_save_yes" msgid="8035743017382012850">"Išsaugoti"</string>
<string name="autofill_save_no" msgid="9212826374207023544">"Ne, ačiū"</string>
<string name="autofill_save_notnow" msgid="2853932672029024195">"Ne dabar"</string>
diff --git a/core/res/res/values-lv/strings.xml b/core/res/res/values-lv/strings.xml
index 45b9586dfd1f..fb1b7b9d5aef 100644
--- a/core/res/res/values-lv/strings.xml
+++ b/core/res/res/values-lv/strings.xml
@@ -1868,6 +1868,8 @@
<string name="managed_profile_label_badge_2" msgid="5673187309555352550">"2. darba profils: <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="managed_profile_label_badge_3" msgid="6882151970556391957">"3. darba profils: <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="clone_profile_label_badge" msgid="1871997694718793964">"<xliff:g id="LABEL">%1$s</xliff:g> (klons)"</string>
+ <!-- no translation found for private_profile_label_badge (1712086003787839183) -->
+ <skip />
<string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"Prasīt PIN kodu pirms atspraušanas"</string>
<string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"Pirms atspraušanas pieprasīt atbloķēšanas kombināciju"</string>
<string name="lock_to_app_unlock_password" msgid="9126722403506560473">"Pirms atspraušanas pieprasīt paroli"</string>
@@ -2032,8 +2034,7 @@
<string name="autofill_update_title" msgid="3630695947047069136">"Vai atjaunināt informāciju pakalpojumā "<b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>"?"</string>
<string name="autofill_update_title_with_type" msgid="5264152633488495704">"Vai atjaunināt informāciju <xliff:g id="TYPE">%1$s</xliff:g> pakalpojumā "<b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>"?"</string>
<string name="autofill_update_title_with_2types" msgid="1797514386321086273">"Vai atjaunināt informāciju <xliff:g id="TYPE_0">%1$s</xliff:g> un <xliff:g id="TYPE_1">%2$s</xliff:g> pakalpojumā "<b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>"?"</string>
- <!-- no translation found for autofill_update_title_with_3types (8285767070604652626) -->
- <skip />
+ <string name="autofill_update_title_with_3types" msgid="8285767070604652626">"Vai atjaunināt šos vienumus pakalpojumā "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>": <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> un <xliff:g id="TYPE_2">%3$s</xliff:g>?"</string>
<string name="autofill_save_yes" msgid="8035743017382012850">"Saglabāt"</string>
<string name="autofill_save_no" msgid="9212826374207023544">"Nē, paldies"</string>
<string name="autofill_save_notnow" msgid="2853932672029024195">"Vēlāk"</string>
diff --git a/core/res/res/values-mk/strings.xml b/core/res/res/values-mk/strings.xml
index 33e9a55e5bec..ae0a0350a34b 100644
--- a/core/res/res/values-mk/strings.xml
+++ b/core/res/res/values-mk/strings.xml
@@ -1867,6 +1867,7 @@
<string name="managed_profile_label_badge_2" msgid="5673187309555352550">"Втора деловна <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="managed_profile_label_badge_3" msgid="6882151970556391957">"Трета деловна <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="clone_profile_label_badge" msgid="1871997694718793964">"Клонирајте го <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+ <string name="private_profile_label_badge" msgid="1712086003787839183">"Приватен <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"Побарај PIN пред откачување"</string>
<string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"Побарај шема за откл. пред откачување"</string>
<string name="lock_to_app_unlock_password" msgid="9126722403506560473">"Побарај лозинка пред откачување"</string>
@@ -2031,8 +2032,7 @@
<string name="autofill_update_title" msgid="3630695947047069136">"Да се ажурира во "<b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>"?"</string>
<string name="autofill_update_title_with_type" msgid="5264152633488495704">"Да се ажурира <xliff:g id="TYPE">%1$s</xliff:g> во "<b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>"?"</string>
<string name="autofill_update_title_with_2types" msgid="1797514386321086273">"Да се ажурираат <xliff:g id="TYPE_0">%1$s</xliff:g> и <xliff:g id="TYPE_1">%2$s</xliff:g> во "<b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>"?"</string>
- <!-- no translation found for autofill_update_title_with_3types (8285767070604652626) -->
- <skip />
+ <string name="autofill_update_title_with_3types" msgid="8285767070604652626">"Да се ажурираат овие ставки во "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>": <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> и <xliff:g id="TYPE_2">%3$s</xliff:g>?"</string>
<string name="autofill_save_yes" msgid="8035743017382012850">"Зачувај"</string>
<string name="autofill_save_no" msgid="9212826374207023544">"Не, фала"</string>
<string name="autofill_save_notnow" msgid="2853932672029024195">"Не сега"</string>
diff --git a/core/res/res/values-ml/strings.xml b/core/res/res/values-ml/strings.xml
index 8a4ddf10c5ad..80e80618185e 100644
--- a/core/res/res/values-ml/strings.xml
+++ b/core/res/res/values-ml/strings.xml
@@ -1867,6 +1867,7 @@
<string name="managed_profile_label_badge_2" msgid="5673187309555352550">"രണ്ടാമത്തെ ഔദ്യോഗിക <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="managed_profile_label_badge_3" msgid="6882151970556391957">"മൂന്നാമത്തെ ഔദ്യോഗിക <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="clone_profile_label_badge" msgid="1871997694718793964">"ക്ലോൺ <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+ <string name="private_profile_label_badge" msgid="1712086003787839183">"സ്വകാര്യം <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"ചെയ്യുംമുമ്പ് പിൻ ചോദിക്കൂ"</string>
<string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"അൺപിന്നിനുമുമ്പ് അൺലോക്ക് പാറ്റേൺ ആവശ്യപ്പെടൂ"</string>
<string name="lock_to_app_unlock_password" msgid="9126722403506560473">"അൺപിന്നിനുമുമ്പ് പാസ്‌വേഡ് ആവശ്യപ്പെടൂ"</string>
@@ -2031,8 +2032,7 @@
<string name="autofill_update_title" msgid="3630695947047069136"><b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>" എന്നതിൽ അപ്‌ഡേറ്റ് ചെയ്യണോ?"</string>
<string name="autofill_update_title_with_type" msgid="5264152633488495704">"<xliff:g id="TYPE">%1$s</xliff:g>, "<b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>" എന്നതിൽ അപ്‌ഡേറ്റ് ചെയ്യണോ?"</string>
<string name="autofill_update_title_with_2types" msgid="1797514386321086273">"<xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> എന്നിവ "<b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>" എന്നതിൽ അപ്‌ഡേറ്റ് ചെയ്യണോ?"</string>
- <!-- no translation found for autofill_update_title_with_3types (8285767070604652626) -->
- <skip />
+ <string name="autofill_update_title_with_3types" msgid="8285767070604652626">"ഇനിപ്പറയുന്ന ഇനങ്ങൾ "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>" എന്നതിൽ അപ്‌ഡേറ്റ് ചെയ്യണോ: <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g>, <xliff:g id="TYPE_2">%3$s</xliff:g> ?"</string>
<string name="autofill_save_yes" msgid="8035743017382012850">"സംരക്ഷിക്കുക"</string>
<string name="autofill_save_no" msgid="9212826374207023544">"വേണ്ട, നന്ദി"</string>
<string name="autofill_save_notnow" msgid="2853932672029024195">"ഇപ്പോൾ വേണ്ട"</string>
diff --git a/core/res/res/values-mn/strings.xml b/core/res/res/values-mn/strings.xml
index 8332bb12e99c..d2bdb4d431af 100644
--- a/core/res/res/values-mn/strings.xml
+++ b/core/res/res/values-mn/strings.xml
@@ -971,7 +971,7 @@
<string name="lockscreen_pattern_instructions" msgid="3169991838169244941">"Тайлах хээгээ зурна уу"</string>
<string name="lockscreen_emergency_call" msgid="7500692654885445299">"Яаралтай тусламж"</string>
<string name="lockscreen_return_to_call" msgid="3156883574692006382">"Дуудлагаруу буцах"</string>
- <string name="lockscreen_pattern_correct" msgid="8050630103651508582">"Зөв!"</string>
+ <string name="lockscreen_pattern_correct" msgid="8050630103651508582">"Зөв"</string>
<string name="lockscreen_pattern_wrong" msgid="2940138714468358458">"Дахин оролдох"</string>
<string name="lockscreen_password_wrong" msgid="8605355913868947490">"Дахин оролдох"</string>
<string name="lockscreen_storage_locked" msgid="634993789186443380">"Бүх онцлог, өгөгдлийн түгжээг тайлах"</string>
@@ -1867,6 +1867,7 @@
<string name="managed_profile_label_badge_2" msgid="5673187309555352550">"2 дахь ажил <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="managed_profile_label_badge_3" msgid="6882151970556391957">"3 дахь ажил <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="clone_profile_label_badge" msgid="1871997694718793964">"Клон <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+ <string name="private_profile_label_badge" msgid="1712086003787839183">"Хувийн <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"Бэхэлснийг болиулахаасаа өмнө ПИН асуух"</string>
<string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"Бэхэлснийг болиулахаас өмнө түгжээ тайлах хээ асуух"</string>
<string name="lock_to_app_unlock_password" msgid="9126722403506560473">"Тогтоосныг суллахаас өмнө нууц үг асуух"</string>
@@ -2031,8 +2032,7 @@
<string name="autofill_update_title" msgid="3630695947047069136"><b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>"-д шинэчлэх үү?"</string>
<string name="autofill_update_title_with_type" msgid="5264152633488495704">"<xliff:g id="TYPE">%1$s</xliff:g>-г "<b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>"-д шинэчлэх үү?"</string>
<string name="autofill_update_title_with_2types" msgid="1797514386321086273">"<xliff:g id="TYPE_0">%1$s</xliff:g> болон <xliff:g id="TYPE_1">%2$s</xliff:g>-г "<b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>"-д шинэчлэх үү?"</string>
- <!-- no translation found for autofill_update_title_with_3types (8285767070604652626) -->
- <skip />
+ <string name="autofill_update_title_with_3types" msgid="8285767070604652626"><b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>"-н эдгээр зүйлийг шинэчлэх: <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> болон <xliff:g id="TYPE_2">%3$s</xliff:g>?"</string>
<string name="autofill_save_yes" msgid="8035743017382012850">"Хадгалах"</string>
<string name="autofill_save_no" msgid="9212826374207023544">"Үгүй, баярлалаа"</string>
<string name="autofill_save_notnow" msgid="2853932672029024195">"Одоо биш"</string>
diff --git a/core/res/res/values-mr/strings.xml b/core/res/res/values-mr/strings.xml
index effddd6745e0..5f7a5c14e984 100644
--- a/core/res/res/values-mr/strings.xml
+++ b/core/res/res/values-mr/strings.xml
@@ -1867,6 +1867,8 @@
<string name="managed_profile_label_badge_2" msgid="5673187309555352550">"2 रे कार्य <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="managed_profile_label_badge_3" msgid="6882151970556391957">"3 रे कार्य <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="clone_profile_label_badge" msgid="1871997694718793964">"<xliff:g id="LABEL">%1$s</xliff:g> क्लोन केलेले"</string>
+ <!-- no translation found for private_profile_label_badge (1712086003787839183) -->
+ <skip />
<string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"अनपिन करण्‍यापूर्वी पिन विचारा"</string>
<string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"अनपिन करण्‍यापूर्वी अनलॉक नमुन्यासाठी विचारा"</string>
<string name="lock_to_app_unlock_password" msgid="9126722403506560473">"अनपिन करण्‍यापूर्वी संकेतशब्दासाठी विचारा"</string>
@@ -2031,8 +2033,7 @@
<string name="autofill_update_title" msgid="3630695947047069136"><b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>" मध्ये अपडेट करायचे का?"</string>
<string name="autofill_update_title_with_type" msgid="5264152633488495704">"<xliff:g id="TYPE">%1$s</xliff:g>, "<b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>" मध्ये अपडेट करायचे का?"</string>
<string name="autofill_update_title_with_2types" msgid="1797514386321086273">"<xliff:g id="TYPE_0">%1$s</xliff:g> आणि <xliff:g id="TYPE_1">%2$s</xliff:g>, "<b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>" मध्ये अपडेट करायचे का?"</string>
- <!-- no translation found for autofill_update_title_with_3types (8285767070604652626) -->
- <skip />
+ <string name="autofill_update_title_with_3types" msgid="8285767070604652626">"हे आयटम "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>": <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> आणि <xliff:g id="TYPE_2">%3$s</xliff:g> मध्ये अपडेट करायचे आहेत का?"</string>
<string name="autofill_save_yes" msgid="8035743017382012850">"सेव्ह करा"</string>
<string name="autofill_save_no" msgid="9212826374207023544">"नाही, नको"</string>
<string name="autofill_save_notnow" msgid="2853932672029024195">"आता नको"</string>
diff --git a/core/res/res/values-ms/strings.xml b/core/res/res/values-ms/strings.xml
index bcaa06dbff08..74e904dab535 100644
--- a/core/res/res/values-ms/strings.xml
+++ b/core/res/res/values-ms/strings.xml
@@ -1867,6 +1867,7 @@
<string name="managed_profile_label_badge_2" msgid="5673187309555352550">"<xliff:g id="LABEL">%1$s</xliff:g> kerja ke-2"</string>
<string name="managed_profile_label_badge_3" msgid="6882151970556391957">"<xliff:g id="LABEL">%1$s</xliff:g> kerja ke-3"</string>
<string name="clone_profile_label_badge" msgid="1871997694718793964">"<xliff:g id="LABEL">%1$s</xliff:g> Klon"</string>
+ <string name="private_profile_label_badge" msgid="1712086003787839183">"<xliff:g id="LABEL">%1$s</xliff:g> Peribadi"</string>
<string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"Minta PIN sebelum menyahsemat"</string>
<string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"Minta corak buka kunci sebelum menyahsemat"</string>
<string name="lock_to_app_unlock_password" msgid="9126722403506560473">"Minta kata laluan sebelum menyahsemat"</string>
@@ -2031,8 +2032,7 @@
<string name="autofill_update_title" msgid="3630695947047069136">"Kemas kini dalam "<b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>"?"</string>
<string name="autofill_update_title_with_type" msgid="5264152633488495704">"Kemas kini <xliff:g id="TYPE">%1$s</xliff:g> dalam "<b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>"?"</string>
<string name="autofill_update_title_with_2types" msgid="1797514386321086273">"Kemas kini <xliff:g id="TYPE_0">%1$s</xliff:g> dan <xliff:g id="TYPE_1">%2$s</xliff:g> dalam "<b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>"?"</string>
- <!-- no translation found for autofill_update_title_with_3types (8285767070604652626) -->
- <skip />
+ <string name="autofill_update_title_with_3types" msgid="8285767070604652626">"Kemas kinikan item ini dalam "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>": <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> dan <xliff:g id="TYPE_2">%3$s</xliff:g> ?"</string>
<string name="autofill_save_yes" msgid="8035743017382012850">"Simpan"</string>
<string name="autofill_save_no" msgid="9212826374207023544">"Tidak perlu"</string>
<string name="autofill_save_notnow" msgid="2853932672029024195">"Bukan sekarang"</string>
diff --git a/core/res/res/values-my/strings.xml b/core/res/res/values-my/strings.xml
index 924bfe044bff..394a74e64752 100644
--- a/core/res/res/values-my/strings.xml
+++ b/core/res/res/values-my/strings.xml
@@ -1867,6 +1867,7 @@
<string name="managed_profile_label_badge_2" msgid="5673187309555352550">"ဒုတိယအလုပ် <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="managed_profile_label_badge_3" msgid="6882151970556391957">"တတိယအလုပ် <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="clone_profile_label_badge" msgid="1871997694718793964">"<xliff:g id="LABEL">%1$s</xliff:g> ပုံတူပွား"</string>
+ <string name="private_profile_label_badge" msgid="1712086003787839183">"သီးသန့် <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"ပင်မဖြုတ်မီမှာ PIN ကို မေးကြည့်ရန်"</string>
<string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"ပင်မဖြုတ်မီမှာ သော့ဖွင့် ရေးဆွဲမှုပုံစံကို မေးကြည့်ရန်"</string>
<string name="lock_to_app_unlock_password" msgid="9126722403506560473">"ပင်မဖြုတ်မီမှာ စကားဝှက်ကို မေးကြည့်ရန်"</string>
@@ -2031,8 +2032,7 @@
<string name="autofill_update_title" msgid="3630695947047069136"><b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>"တွင် အပ်ဒိတ်လုပ်လိုပါသလား။"</string>
<string name="autofill_update_title_with_type" msgid="5264152633488495704">"<xliff:g id="TYPE">%1$s</xliff:g> ကို "<b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>" တွင် အပ်ဒိတ်လုပ်လိုပါသလား။"</string>
<string name="autofill_update_title_with_2types" msgid="1797514386321086273">"<xliff:g id="TYPE_0">%1$s</xliff:g> နှင့် <xliff:g id="TYPE_1">%2$s</xliff:g> ကို "<b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>"တွင် အပ်ဒိတ်လုပ်လိုပါသလား။"</string>
- <!-- no translation found for autofill_update_title_with_3types (8285767070604652626) -->
- <skip />
+ <string name="autofill_update_title_with_3types" msgid="8285767070604652626">"ဤအရာများကို "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>" တွင် အပ်ဒိတ်လုပ်မလား- <xliff:g id="TYPE_0">%1$s</xliff:g>၊ <xliff:g id="TYPE_1">%2$s</xliff:g> နှင့် <xliff:g id="TYPE_2">%3$s</xliff:g>။"</string>
<string name="autofill_save_yes" msgid="8035743017382012850">"သိမ်းရန်"</string>
<string name="autofill_save_no" msgid="9212826374207023544">"မလိုပါ"</string>
<string name="autofill_save_notnow" msgid="2853932672029024195">"ယခုမလုပ်ပါ"</string>
diff --git a/core/res/res/values-nb/strings.xml b/core/res/res/values-nb/strings.xml
index 7ae201cfd859..ffc8bea2894b 100644
--- a/core/res/res/values-nb/strings.xml
+++ b/core/res/res/values-nb/strings.xml
@@ -1867,6 +1867,8 @@
<string name="managed_profile_label_badge_2" msgid="5673187309555352550">"Andre <xliff:g id="LABEL">%1$s</xliff:g> for jobben"</string>
<string name="managed_profile_label_badge_3" msgid="6882151970556391957">"Tredje <xliff:g id="LABEL">%1$s</xliff:g> for jobben"</string>
<string name="clone_profile_label_badge" msgid="1871997694718793964">"Klon <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+ <!-- no translation found for private_profile_label_badge (1712086003787839183) -->
+ <skip />
<string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"Krev PIN-kode for å løsne app"</string>
<string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"Krev opplåsingsmønster for å løsne apper"</string>
<string name="lock_to_app_unlock_password" msgid="9126722403506560473">"Krev passord for å løsne apper"</string>
@@ -2031,8 +2033,7 @@
<string name="autofill_update_title" msgid="3630695947047069136">"Vil du oppdatere i "<b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>"?"</string>
<string name="autofill_update_title_with_type" msgid="5264152633488495704">"Vil du oppdatere <xliff:g id="TYPE">%1$s</xliff:g> i "<b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>"?"</string>
<string name="autofill_update_title_with_2types" msgid="1797514386321086273">"Vil du oppdatere <xliff:g id="TYPE_0">%1$s</xliff:g> og <xliff:g id="TYPE_1">%2$s</xliff:g> i "<b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>"?"</string>
- <!-- no translation found for autofill_update_title_with_3types (8285767070604652626) -->
- <skip />
+ <string name="autofill_update_title_with_3types" msgid="8285767070604652626">"Vil du oppdatere disse elementene i "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>": <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> og <xliff:g id="TYPE_2">%3$s</xliff:g>?"</string>
<string name="autofill_save_yes" msgid="8035743017382012850">"Lagre"</string>
<string name="autofill_save_no" msgid="9212826374207023544">"Nei takk"</string>
<string name="autofill_save_notnow" msgid="2853932672029024195">"Ikke nå"</string>
diff --git a/core/res/res/values-ne/strings.xml b/core/res/res/values-ne/strings.xml
index 7d6d09fc5855..672cfbc8a633 100644
--- a/core/res/res/values-ne/strings.xml
+++ b/core/res/res/values-ne/strings.xml
@@ -1867,6 +1867,8 @@
<string name="managed_profile_label_badge_2" msgid="5673187309555352550">"कार्यालयको दोस्रो <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="managed_profile_label_badge_3" msgid="6882151970556391957">"कार्यालयको तेस्रो <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="clone_profile_label_badge" msgid="1871997694718793964">"<xliff:g id="LABEL">%1$s</xliff:g> क्लोन गर्नुहोस्"</string>
+ <!-- no translation found for private_profile_label_badge (1712086003787839183) -->
+ <skip />
<string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"अनपिन गर्नुअघि PIN मागियोस्"</string>
<string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"अनपिन गर्नअघि अनलक प्याटर्न माग्नुहोस्"</string>
<string name="lock_to_app_unlock_password" msgid="9126722403506560473">"पिन निकाल्नुअघि पासवर्ड सोध्नुहोस्"</string>
@@ -2031,8 +2033,7 @@
<string name="autofill_update_title" msgid="3630695947047069136"><b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>" मा अद्यावधिक गर्ने हो?"</string>
<string name="autofill_update_title_with_type" msgid="5264152633488495704">"<xliff:g id="TYPE">%1$s</xliff:g> लाई "<b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>" मा अद्यावधिक गर्ने हो?"</string>
<string name="autofill_update_title_with_2types" msgid="1797514386321086273">"<xliff:g id="TYPE_0">%1$s</xliff:g> र <xliff:g id="TYPE_1">%2$s</xliff:g> लाई "<b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>" मा अद्यावधिक गर्ने हो?"</string>
- <!-- no translation found for autofill_update_title_with_3types (8285767070604652626) -->
- <skip />
+ <string name="autofill_update_title_with_3types" msgid="8285767070604652626">"तपाईं "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>" मा भएका निम्न वस्तुहरू अपडेट गर्न चाहनुहुन्छ: <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> र <xliff:g id="TYPE_2">%3$s</xliff:g>?"</string>
<string name="autofill_save_yes" msgid="8035743017382012850">"सेभ गर्नुहोस्"</string>
<string name="autofill_save_no" msgid="9212826374207023544">"पर्दैन, धन्यवाद"</string>
<string name="autofill_save_notnow" msgid="2853932672029024195">"अहिले होइन"</string>
diff --git a/core/res/res/values-nl/strings.xml b/core/res/res/values-nl/strings.xml
index f92b3941670a..2846b6a115b0 100644
--- a/core/res/res/values-nl/strings.xml
+++ b/core/res/res/values-nl/strings.xml
@@ -1867,6 +1867,7 @@
<string name="managed_profile_label_badge_2" msgid="5673187309555352550">"2e <xliff:g id="LABEL">%1$s</xliff:g>, werk"</string>
<string name="managed_profile_label_badge_3" msgid="6882151970556391957">"3e <xliff:g id="LABEL">%1$s</xliff:g>, werk"</string>
<string name="clone_profile_label_badge" msgid="1871997694718793964">"Kloon van <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+ <string name="private_profile_label_badge" msgid="1712086003787839183">"Privé <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"Vraag pin voor losmaken"</string>
<string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"Vraag om ontgrendelingspatroon voor losmaken"</string>
<string name="lock_to_app_unlock_password" msgid="9126722403506560473">"Vraag wachtwoord voor losmaken"</string>
@@ -2031,8 +2032,7 @@
<string name="autofill_update_title" msgid="3630695947047069136">"Updaten in "<b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>"?"</string>
<string name="autofill_update_title_with_type" msgid="5264152633488495704">"<xliff:g id="TYPE">%1$s</xliff:g> updaten in "<b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>"?"</string>
<string name="autofill_update_title_with_2types" msgid="1797514386321086273">"<xliff:g id="TYPE_0">%1$s</xliff:g> en <xliff:g id="TYPE_1">%2$s</xliff:g> updaten in "<b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>"?"</string>
- <!-- no translation found for autofill_update_title_with_3types (8285767070604652626) -->
- <skip />
+ <string name="autofill_update_title_with_3types" msgid="8285767070604652626">"Deze items updaten in "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>": <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> en <xliff:g id="TYPE_2">%3$s</xliff:g>?"</string>
<string name="autofill_save_yes" msgid="8035743017382012850">"Opslaan"</string>
<string name="autofill_save_no" msgid="9212826374207023544">"Nee, bedankt"</string>
<string name="autofill_save_notnow" msgid="2853932672029024195">"Niet nu"</string>
diff --git a/core/res/res/values-or/strings.xml b/core/res/res/values-or/strings.xml
index b94ab7560199..41d8b509b1fa 100644
--- a/core/res/res/values-or/strings.xml
+++ b/core/res/res/values-or/strings.xml
@@ -1867,6 +1867,8 @@
<string name="managed_profile_label_badge_2" msgid="5673187309555352550">"2ୟ କାର୍ଯ୍ୟ <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="managed_profile_label_badge_3" msgid="6882151970556391957">"3ୟ କାର୍ଯ୍ୟ <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="clone_profile_label_badge" msgid="1871997694718793964">"<xliff:g id="LABEL">%1$s</xliff:g> କ୍ଲୋନ"</string>
+ <!-- no translation found for private_profile_label_badge (1712086003787839183) -->
+ <skip />
<string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"ଅନପିନ୍‌ କରିବା ପୂର୍ବରୁ PIN ପଚାରନ୍ତୁ"</string>
<string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"ଅନପିନ୍‌ କରିବା ପୂର୍ବରୁ ଲକ୍‌ ଖୋଲିବା ପାଟର୍ନ ପଚାରନ୍ତୁ"</string>
<string name="lock_to_app_unlock_password" msgid="9126722403506560473">"ଅନପିନ୍‌ କରିବା ପୂର୍ବରୁ ପାସ୍‌ୱର୍ଡ ପଚାରନ୍ତୁ"</string>
@@ -2031,8 +2033,7 @@
<string name="autofill_update_title" msgid="3630695947047069136"><b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>"ରେ ଅପ୍‌ଡେଟ୍ କରିବେ?"</string>
<string name="autofill_update_title_with_type" msgid="5264152633488495704"><b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>"ରେ <xliff:g id="TYPE">%1$s</xliff:g>କୁ ଅପ୍‌ଡେଟ୍ କରିବେ।"</string>
<string name="autofill_update_title_with_2types" msgid="1797514386321086273"><b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>"ରେ <xliff:g id="TYPE_0">%1$s</xliff:g> ଏବଂ <xliff:g id="TYPE_1">%2$s</xliff:g> ଅପ୍‌ଡେଟ୍ କରିବେ?"</string>
- <!-- no translation found for autofill_update_title_with_3types (8285767070604652626) -->
- <skip />
+ <string name="autofill_update_title_with_3types" msgid="8285767070604652626"><b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>"ରେ ଏହି ଆଇଟମଗୁଡ଼ିକୁ ଅପଡେଟ କରିବେ: <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> ଏବଂ <xliff:g id="TYPE_2">%3$s</xliff:g>?"</string>
<string name="autofill_save_yes" msgid="8035743017382012850">"ସେଭ୍‌ କରନ୍ତୁ"</string>
<string name="autofill_save_no" msgid="9212826374207023544">"ନାଁ, ପଚାରିଥିବାରୁ ଧନ୍ୟବାଦ"</string>
<string name="autofill_save_notnow" msgid="2853932672029024195">"ଏବେ ନୁହେଁ"</string>
diff --git a/core/res/res/values-pa/strings.xml b/core/res/res/values-pa/strings.xml
index c17b17b23648..8b9934fe860b 100644
--- a/core/res/res/values-pa/strings.xml
+++ b/core/res/res/values-pa/strings.xml
@@ -1867,6 +1867,8 @@
<string name="managed_profile_label_badge_2" msgid="5673187309555352550">"ਦੂਸਰੀ ਕਾਰਜ-ਸਥਾਨ <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="managed_profile_label_badge_3" msgid="6882151970556391957">"ਤੀਸਰੀ ਕਾਰਜ-ਸਥਾਨ <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="clone_profile_label_badge" msgid="1871997694718793964">"<xliff:g id="LABEL">%1$s</xliff:g> ਦਾ ਕਲੋਨ"</string>
+ <!-- no translation found for private_profile_label_badge (1712086003787839183) -->
+ <skip />
<string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"ਅਨਪਿੰਨ ਕਰਨ ਤੋਂ ਪਹਿਲਾਂ ਪਿੰਨ ਮੰਗੋ"</string>
<string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"ਅਨਪਿੰਨ ਕਰਨ ਤੋਂ ਪਹਿਲਾਂ ਅਣਲਾਕ ਪੈਟਰਨ ਵਾਸਤੇ ਪੁੱਛੋ"</string>
<string name="lock_to_app_unlock_password" msgid="9126722403506560473">"ਅਣਪਿੰਨ ਕਰਨ ਤੋਂ ਪਹਿਲਾਂ ਪਾਸਵਰਡ ਮੰਗੋ"</string>
@@ -2031,8 +2033,7 @@
<string name="autofill_update_title" msgid="3630695947047069136">"ਕੀ ਤੁਸੀਂ "<b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>" ਵਿੱਚ ਅੱਪਡੇਟ ਕਰਨਾ ਚਾਹੁੰਦੇ ਹੋ?"</string>
<string name="autofill_update_title_with_type" msgid="5264152633488495704">"ਕੀ ਤੁਸੀਂ "<b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>" ਵਿੱਚ <xliff:g id="TYPE">%1$s</xliff:g> ਨੂੰ ਅੱਪਡੇਟ ਕਰਨਾ ਚਾਹੁੰਦੇ ਹੋ?"</string>
<string name="autofill_update_title_with_2types" msgid="1797514386321086273">"ਕੀ ਤੁਸੀਂ "<b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>" ਵਿੱਚ <xliff:g id="TYPE_0">%1$s</xliff:g> ਅਤੇ <xliff:g id="TYPE_1">%2$s</xliff:g> ਨੂੰ ਅੱਪਡੇਟ ਕਰਨਾ ਚਾਹੁੰਦੇ ਹੋ?"</string>
- <!-- no translation found for autofill_update_title_with_3types (8285767070604652626) -->
- <skip />
+ <string name="autofill_update_title_with_3types" msgid="8285767070604652626">"ਕੀ ਤੁਸੀਂ "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>" ਵਿੱਚ ਇਨ੍ਹਾਂ ਆਈਟਮਾਂ ਨੂੰ ਅੱਪਡੇਟ ਕਰਨਾ ਚਾਹੁੰਦੇ ਹੋ: <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g>, ਅਤੇ<xliff:g id="TYPE_2">%3$s</xliff:g>?"</string>
<string name="autofill_save_yes" msgid="8035743017382012850">"ਰੱਖਿਅਤ ਕਰੋ"</string>
<string name="autofill_save_no" msgid="9212826374207023544">"ਨਹੀਂ ਧੰਨਵਾਦ"</string>
<string name="autofill_save_notnow" msgid="2853932672029024195">"ਹੁਣੇ ਨਹੀਂ"</string>
diff --git a/core/res/res/values-pl/strings.xml b/core/res/res/values-pl/strings.xml
index 45353b180c49..880892f9e786 100644
--- a/core/res/res/values-pl/strings.xml
+++ b/core/res/res/values-pl/strings.xml
@@ -1869,6 +1869,8 @@
<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="clone_profile_label_badge" msgid="1871997694718793964">"Klon aplikacji <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+ <!-- no translation found for private_profile_label_badge (1712086003787839183) -->
+ <skip />
<string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"Podaj PIN, aby odpiąć"</string>
<string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"Aby odpiąć, poproś o wzór odblokowania"</string>
<string name="lock_to_app_unlock_password" msgid="9126722403506560473">"Aby odpiąć, poproś o hasło"</string>
@@ -2033,8 +2035,7 @@
<string name="autofill_update_title" msgid="3630695947047069136">"Zaktualizować w: "<b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>"?"</string>
<string name="autofill_update_title_with_type" msgid="5264152633488495704">"Zaktualizować: <xliff:g id="TYPE">%1$s</xliff:g> w: "<b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>"?"</string>
<string name="autofill_update_title_with_2types" msgid="1797514386321086273">"Zaktualizować: <xliff:g id="TYPE_0">%1$s</xliff:g> i <xliff:g id="TYPE_1">%2$s</xliff:g> w: "<b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>"?"</string>
- <!-- no translation found for autofill_update_title_with_3types (8285767070604652626) -->
- <skip />
+ <string name="autofill_update_title_with_3types" msgid="8285767070604652626">"Zaktualizować w "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>" te elementy: <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> i <xliff:g id="TYPE_2">%3$s</xliff:g>?"</string>
<string name="autofill_save_yes" msgid="8035743017382012850">"Zapisz"</string>
<string name="autofill_save_no" msgid="9212826374207023544">"Nie, dziękuję"</string>
<string name="autofill_save_notnow" msgid="2853932672029024195">"Nie teraz"</string>
diff --git a/core/res/res/values-pt-rBR/strings.xml b/core/res/res/values-pt-rBR/strings.xml
index d4f35295c7c1..70f80a81750b 100644
--- a/core/res/res/values-pt-rBR/strings.xml
+++ b/core/res/res/values-pt-rBR/strings.xml
@@ -1868,6 +1868,7 @@
<string name="managed_profile_label_badge_2" msgid="5673187309555352550">"Segundo <xliff:g id="LABEL">%1$s</xliff:g> de trabalho"</string>
<string name="managed_profile_label_badge_3" msgid="6882151970556391957">"Terceiro <xliff:g id="LABEL">%1$s</xliff:g> de trabalho"</string>
<string name="clone_profile_label_badge" msgid="1871997694718793964">"<xliff:g id="LABEL">%1$s</xliff:g> (clone)"</string>
+ <string name="private_profile_label_badge" msgid="1712086003787839183">"<xliff:g id="LABEL">%1$s</xliff:g> particular"</string>
<string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"Pedir PIN antes de liberar"</string>
<string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"Pedir padrão de desbloqueio antes de liberar"</string>
<string name="lock_to_app_unlock_password" msgid="9126722403506560473">"Pedir senha antes de liberar"</string>
@@ -2032,8 +2033,7 @@
<string name="autofill_update_title" msgid="3630695947047069136">"Atualizar em "<b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>"?"</string>
<string name="autofill_update_title_with_type" msgid="5264152633488495704">"Atualizar <xliff:g id="TYPE">%1$s</xliff:g> em "<b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>"?"</string>
<string name="autofill_update_title_with_2types" msgid="1797514386321086273">"Atualizar <xliff:g id="TYPE_0">%1$s</xliff:g> e <xliff:g id="TYPE_1">%2$s</xliff:g> em "<b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>"?"</string>
- <!-- no translation found for autofill_update_title_with_3types (8285767070604652626) -->
- <skip />
+ <string name="autofill_update_title_with_3types" msgid="8285767070604652626">"Atualizar estes itens em "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>": <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> e <xliff:g id="TYPE_2">%3$s</xliff:g>?"</string>
<string name="autofill_save_yes" msgid="8035743017382012850">"Salvar"</string>
<string name="autofill_save_no" msgid="9212826374207023544">"Agora não"</string>
<string name="autofill_save_notnow" msgid="2853932672029024195">"Agora não"</string>
diff --git a/core/res/res/values-pt-rPT/strings.xml b/core/res/res/values-pt-rPT/strings.xml
index 53fbfd3a32f0..7341500d8b46 100644
--- a/core/res/res/values-pt-rPT/strings.xml
+++ b/core/res/res/values-pt-rPT/strings.xml
@@ -1868,6 +1868,7 @@
<string name="managed_profile_label_badge_2" msgid="5673187309555352550">"2.º <xliff:g id="LABEL">%1$s</xliff:g> de trabalho"</string>
<string name="managed_profile_label_badge_3" msgid="6882151970556391957">"3.º <xliff:g id="LABEL">%1$s</xliff:g> de trabalho"</string>
<string name="clone_profile_label_badge" msgid="1871997694718793964">"Clonar <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+ <string name="private_profile_label_badge" msgid="1712086003787839183">"<xliff:g id="LABEL">%1$s</xliff:g> privado"</string>
<string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"Pedir PIN antes de soltar"</string>
<string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"Pedir padrão de desbloqueio antes de soltar"</string>
<string name="lock_to_app_unlock_password" msgid="9126722403506560473">"Pedir palavra-passe antes de soltar"</string>
@@ -2032,8 +2033,7 @@
<string name="autofill_update_title" msgid="3630695947047069136">"Quer atualizar em "<b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>"?"</string>
<string name="autofill_update_title_with_type" msgid="5264152633488495704">"Quer atualizar <xliff:g id="TYPE">%1$s</xliff:g> em "<b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>"?"</string>
<string name="autofill_update_title_with_2types" msgid="1797514386321086273">"Quer atualizar <xliff:g id="TYPE_0">%1$s</xliff:g> e <xliff:g id="TYPE_1">%2$s</xliff:g> em "<b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>"?"</string>
- <!-- no translation found for autofill_update_title_with_3types (8285767070604652626) -->
- <skip />
+ <string name="autofill_update_title_with_3types" msgid="8285767070604652626">"Atualizar estes itens no serviço "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>": <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> e <xliff:g id="TYPE_2">%3$s</xliff:g>?"</string>
<string name="autofill_save_yes" msgid="8035743017382012850">"Guardar"</string>
<string name="autofill_save_no" msgid="9212826374207023544">"Não, obrigado"</string>
<string name="autofill_save_notnow" msgid="2853932672029024195">"Agora não"</string>
diff --git a/core/res/res/values-pt/strings.xml b/core/res/res/values-pt/strings.xml
index d4f35295c7c1..70f80a81750b 100644
--- a/core/res/res/values-pt/strings.xml
+++ b/core/res/res/values-pt/strings.xml
@@ -1868,6 +1868,7 @@
<string name="managed_profile_label_badge_2" msgid="5673187309555352550">"Segundo <xliff:g id="LABEL">%1$s</xliff:g> de trabalho"</string>
<string name="managed_profile_label_badge_3" msgid="6882151970556391957">"Terceiro <xliff:g id="LABEL">%1$s</xliff:g> de trabalho"</string>
<string name="clone_profile_label_badge" msgid="1871997694718793964">"<xliff:g id="LABEL">%1$s</xliff:g> (clone)"</string>
+ <string name="private_profile_label_badge" msgid="1712086003787839183">"<xliff:g id="LABEL">%1$s</xliff:g> particular"</string>
<string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"Pedir PIN antes de liberar"</string>
<string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"Pedir padrão de desbloqueio antes de liberar"</string>
<string name="lock_to_app_unlock_password" msgid="9126722403506560473">"Pedir senha antes de liberar"</string>
@@ -2032,8 +2033,7 @@
<string name="autofill_update_title" msgid="3630695947047069136">"Atualizar em "<b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>"?"</string>
<string name="autofill_update_title_with_type" msgid="5264152633488495704">"Atualizar <xliff:g id="TYPE">%1$s</xliff:g> em "<b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>"?"</string>
<string name="autofill_update_title_with_2types" msgid="1797514386321086273">"Atualizar <xliff:g id="TYPE_0">%1$s</xliff:g> e <xliff:g id="TYPE_1">%2$s</xliff:g> em "<b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>"?"</string>
- <!-- no translation found for autofill_update_title_with_3types (8285767070604652626) -->
- <skip />
+ <string name="autofill_update_title_with_3types" msgid="8285767070604652626">"Atualizar estes itens em "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>": <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> e <xliff:g id="TYPE_2">%3$s</xliff:g>?"</string>
<string name="autofill_save_yes" msgid="8035743017382012850">"Salvar"</string>
<string name="autofill_save_no" msgid="9212826374207023544">"Agora não"</string>
<string name="autofill_save_notnow" msgid="2853932672029024195">"Agora não"</string>
diff --git a/core/res/res/values-ro/strings.xml b/core/res/res/values-ro/strings.xml
index ce0eb91f23e1..5dc54639d14c 100644
--- a/core/res/res/values-ro/strings.xml
+++ b/core/res/res/values-ro/strings.xml
@@ -670,14 +670,10 @@
</string-array>
<string name="fingerprint_error_vendor_unknown" msgid="4170002184907291065">"A apărut o eroare. Încearcă din nou."</string>
<string name="fingerprint_icon_content_description" msgid="4741068463175388817">"Pictograma amprentă"</string>
- <!-- no translation found for device_unlock_notification_name (2632928999862915709) -->
- <skip />
- <!-- no translation found for alternative_unlock_setup_notification_title (6241508547901933544) -->
- <skip />
- <!-- no translation found for alternative_face_setup_notification_content (3384959224091897331) -->
- <skip />
- <!-- no translation found for alternative_fp_setup_notification_content (7454096947415721639) -->
- <skip />
+ <string name="device_unlock_notification_name" msgid="2632928999862915709">"Deblocarea dispozitivului"</string>
+ <string name="alternative_unlock_setup_notification_title" msgid="6241508547901933544">"Încearcă o altă modalitate de deblocare"</string>
+ <string name="alternative_face_setup_notification_content" msgid="3384959224091897331">"Folosește Deblocarea facială atunci când amprenta ta nu este recunoscută, de exemplu, când ai degetele ude"</string>
+ <string name="alternative_fp_setup_notification_content" msgid="7454096947415721639">"Folosește Deblocarea cu amprenta atunci când chipul tău nu este recunoscut, de exemplu, când nu există suficientă lumină"</string>
<string name="face_recalibrate_notification_name" msgid="7311163114750748686">"Deblocare facială"</string>
<string name="face_recalibrate_notification_title" msgid="2524791952735579082">"Problemă cu Deblocarea facială"</string>
<string name="face_recalibrate_notification_content" msgid="3064513770251355594">"Atinge pentru a șterge modelul facial, apoi adaugă din nou chipul"</string>
@@ -1872,6 +1868,8 @@
<string name="managed_profile_label_badge_2" msgid="5673187309555352550">"<xliff:g id="LABEL">%1$s</xliff:g> pentru serviciu (2)"</string>
<string name="managed_profile_label_badge_3" msgid="6882151970556391957">"<xliff:g id="LABEL">%1$s</xliff:g> pentru serviciu (3)"</string>
<string name="clone_profile_label_badge" msgid="1871997694718793964">"Clonă pentru <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+ <!-- no translation found for private_profile_label_badge (1712086003787839183) -->
+ <skip />
<string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"Solicită codul PIN înainte de a anula fixarea"</string>
<string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"Solicită mai întâi modelul pentru deblocare"</string>
<string name="lock_to_app_unlock_password" msgid="9126722403506560473">"Solicită parola înainte de a anula fixarea"</string>
@@ -2036,8 +2034,7 @@
<string name="autofill_update_title" msgid="3630695947047069136">"Actualizezi în "<b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>"?"</string>
<string name="autofill_update_title_with_type" msgid="5264152633488495704">"Actualizezi <xliff:g id="TYPE">%1$s</xliff:g> în "<b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>"?"</string>
<string name="autofill_update_title_with_2types" msgid="1797514386321086273">"Actualizezi <xliff:g id="TYPE_0">%1$s</xliff:g> și <xliff:g id="TYPE_1">%2$s</xliff:g> în "<b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>"?"</string>
- <!-- no translation found for autofill_update_title_with_3types (8285767070604652626) -->
- <skip />
+ <string name="autofill_update_title_with_3types" msgid="8285767070604652626">"Actualizezi aceste articole în "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>": <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> și <xliff:g id="TYPE_2">%3$s</xliff:g>?"</string>
<string name="autofill_save_yes" msgid="8035743017382012850">"Salvează"</string>
<string name="autofill_save_no" msgid="9212826374207023544">"Nu, mulțumesc"</string>
<string name="autofill_save_notnow" msgid="2853932672029024195">"Nu acum"</string>
diff --git a/core/res/res/values-ru/strings.xml b/core/res/res/values-ru/strings.xml
index 155f654faf98..e09593ee95c3 100644
--- a/core/res/res/values-ru/strings.xml
+++ b/core/res/res/values-ru/strings.xml
@@ -1869,6 +1869,8 @@
<string name="managed_profile_label_badge_2" msgid="5673187309555352550">"Задача 2: <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="managed_profile_label_badge_3" msgid="6882151970556391957">"Задача 3: <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="clone_profile_label_badge" msgid="1871997694718793964">"Клонировать <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+ <!-- no translation found for private_profile_label_badge (1712086003787839183) -->
+ <skip />
<string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"Запрашивать PIN-код"</string>
<string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"Запрашивать графический ключ"</string>
<string name="lock_to_app_unlock_password" msgid="9126722403506560473">"Запрашивать пароль"</string>
@@ -2033,8 +2035,7 @@
<string name="autofill_update_title" msgid="3630695947047069136">"Обновить в сервисе "<b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>"?"</string>
<string name="autofill_update_title_with_type" msgid="5264152633488495704">"Обновить данные (<xliff:g id="TYPE">%1$s</xliff:g>) в сервисе "<b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>"?"</string>
<string name="autofill_update_title_with_2types" msgid="1797514386321086273">"Обновить данные (<xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g>) в сервисе "<b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>"?"</string>
- <!-- no translation found for autofill_update_title_with_3types (8285767070604652626) -->
- <skip />
+ <string name="autofill_update_title_with_3types" msgid="8285767070604652626">"Обновить данные (<xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g>, <xliff:g id="TYPE_2">%3$s</xliff:g>) в сервисе "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>"?"</string>
<string name="autofill_save_yes" msgid="8035743017382012850">"Сохранить"</string>
<string name="autofill_save_no" msgid="9212826374207023544">"Нет, спасибо"</string>
<string name="autofill_save_notnow" msgid="2853932672029024195">"Не сейчас"</string>
diff --git a/core/res/res/values-si/strings.xml b/core/res/res/values-si/strings.xml
index 748501262381..99d90bee006b 100644
--- a/core/res/res/values-si/strings.xml
+++ b/core/res/res/values-si/strings.xml
@@ -1867,6 +1867,8 @@
<string name="managed_profile_label_badge_2" msgid="5673187309555352550">"2වන වැඩ <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="managed_profile_label_badge_3" msgid="6882151970556391957">"3වන වැඩ <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="clone_profile_label_badge" msgid="1871997694718793964">"<xliff:g id="LABEL">%1$s</xliff:g> ක්ලෝන කරන්න"</string>
+ <!-- no translation found for private_profile_label_badge (1712086003787839183) -->
+ <skip />
<string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"ගැලවීමට පෙර PIN විමසන්න"</string>
<string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"ගැලවීමට පෙර අගුළු අරින රටාව සඳහා අසන්න"</string>
<string name="lock_to_app_unlock_password" msgid="9126722403506560473">"ගැලවීමට පෙර මුරපදය විමසන්න"</string>
@@ -2031,8 +2033,7 @@
<string name="autofill_update_title" msgid="3630695947047069136"><b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>" තුළ යාවත්කාලීන කරන්නද?"</string>
<string name="autofill_update_title_with_type" msgid="5264152633488495704"><b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>" තුළ <xliff:g id="TYPE">%1$s</xliff:g> යාවත්කාලීන කරන්නද?"</string>
<string name="autofill_update_title_with_2types" msgid="1797514386321086273"><b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>" තුළ <xliff:g id="TYPE_0">%1$s</xliff:g> සහ <xliff:g id="TYPE_1">%2$s</xliff:g> යාවත්කාලීන කරන්නද?"</string>
- <!-- no translation found for autofill_update_title_with_3types (8285767070604652626) -->
- <skip />
+ <string name="autofill_update_title_with_3types" msgid="8285767070604652626"><b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>": <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g>, සහ <xliff:g id="TYPE_2">%3$s</xliff:g> තුළ මෙම අයිතම යාවත්කාලීන කරන්න ද?"</string>
<string name="autofill_save_yes" msgid="8035743017382012850">"සුරකින්න"</string>
<string name="autofill_save_no" msgid="9212826374207023544">"එපා ස්තූතියි"</string>
<string name="autofill_save_notnow" msgid="2853932672029024195">"දැන් නොවේ"</string>
diff --git a/core/res/res/values-sk/strings.xml b/core/res/res/values-sk/strings.xml
index c06c7cc8b8f3..a3ca1a6562f3 100644
--- a/core/res/res/values-sk/strings.xml
+++ b/core/res/res/values-sk/strings.xml
@@ -1869,6 +1869,8 @@
<string name="managed_profile_label_badge_2" msgid="5673187309555352550">"2. <xliff:g id="LABEL">%1$s</xliff:g> do práce"</string>
<string name="managed_profile_label_badge_3" msgid="6882151970556391957">"3. <xliff:g id="LABEL">%1$s</xliff:g> do práce"</string>
<string name="clone_profile_label_badge" msgid="1871997694718793964">"Klonovať <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+ <!-- no translation found for private_profile_label_badge (1712086003787839183) -->
+ <skip />
<string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"Pred odopnutím požiadať o číslo PIN"</string>
<string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"Pred uvoľnením požiadať o bezpečnostný vzor"</string>
<string name="lock_to_app_unlock_password" msgid="9126722403506560473">"Pred odopnutím požiadať o heslo"</string>
@@ -2033,8 +2035,7 @@
<string name="autofill_update_title" msgid="3630695947047069136">"Aktualizovať v službe "<b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>"?"</string>
<string name="autofill_update_title_with_type" msgid="5264152633488495704">"Chcete údaje <xliff:g id="TYPE">%1$s</xliff:g> aktualizovať v službe "<b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>"?"</string>
<string name="autofill_update_title_with_2types" msgid="1797514386321086273">"Chcete položky <xliff:g id="TYPE_0">%1$s</xliff:g> a <xliff:g id="TYPE_1">%2$s</xliff:g> aktualizovať v službe "<b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>"?"</string>
- <!-- no translation found for autofill_update_title_with_3types (8285767070604652626) -->
- <skip />
+ <string name="autofill_update_title_with_3types" msgid="8285767070604652626">"Chcete tieto položky aktualizovať v službe "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>": <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> a <xliff:g id="TYPE_2">%3$s</xliff:g>?"</string>
<string name="autofill_save_yes" msgid="8035743017382012850">"Uložiť"</string>
<string name="autofill_save_no" msgid="9212826374207023544">"Nie, vďaka"</string>
<string name="autofill_save_notnow" msgid="2853932672029024195">"Teraz nie"</string>
diff --git a/core/res/res/values-sl/strings.xml b/core/res/res/values-sl/strings.xml
index c25e052bb632..5292fc328640 100644
--- a/core/res/res/values-sl/strings.xml
+++ b/core/res/res/values-sl/strings.xml
@@ -1869,6 +1869,7 @@
<string name="managed_profile_label_badge_2" msgid="5673187309555352550">"2. službeni <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="managed_profile_label_badge_3" msgid="6882151970556391957">"3. službeni <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="clone_profile_label_badge" msgid="1871997694718793964">"Klon aplikacije <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+ <string name="private_profile_label_badge" msgid="1712086003787839183">"Zasebni <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"Zahtevaj PIN pred odpenjanjem"</string>
<string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"Pred odpenjanjem vprašaj za vzorec za odklepanje"</string>
<string name="lock_to_app_unlock_password" msgid="9126722403506560473">"Pred odpenjanjem vprašaj za geslo"</string>
@@ -2033,8 +2034,7 @@
<string name="autofill_update_title" msgid="3630695947047069136">"Želite posodobiti v aplikaciji "<b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>"?"</string>
<string name="autofill_update_title_with_type" msgid="5264152633488495704">"Želite posodobiti element <xliff:g id="TYPE">%1$s</xliff:g> v aplikaciji "<b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>"?"</string>
<string name="autofill_update_title_with_2types" msgid="1797514386321086273">"Želite posodobiti elementa <xliff:g id="TYPE_0">%1$s</xliff:g> in <xliff:g id="TYPE_1">%2$s</xliff:g> v aplikaciji "<b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>"?"</string>
- <!-- no translation found for autofill_update_title_with_3types (8285767070604652626) -->
- <skip />
+ <string name="autofill_update_title_with_3types" msgid="8285767070604652626">"Želite posodobiti te elemente v "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>": <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> in <xliff:g id="TYPE_2">%3$s</xliff:g>?"</string>
<string name="autofill_save_yes" msgid="8035743017382012850">"Shrani"</string>
<string name="autofill_save_no" msgid="9212826374207023544">"Ne, hvala"</string>
<string name="autofill_save_notnow" msgid="2853932672029024195">"Ne zdaj"</string>
diff --git a/core/res/res/values-sq/strings.xml b/core/res/res/values-sq/strings.xml
index c93b69958052..fd7453426231 100644
--- a/core/res/res/values-sq/strings.xml
+++ b/core/res/res/values-sq/strings.xml
@@ -1867,6 +1867,8 @@
<string name="managed_profile_label_badge_2" msgid="5673187309555352550">"<xliff:g id="LABEL">%1$s</xliff:g> i dytë i punës"</string>
<string name="managed_profile_label_badge_3" msgid="6882151970556391957">"<xliff:g id="LABEL">%1$s</xliff:g> i tretë i punës"</string>
<string name="clone_profile_label_badge" msgid="1871997694718793964">"Klonim i <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+ <!-- no translation found for private_profile_label_badge (1712086003787839183) -->
+ <skip />
<string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"Zhgozhdimi kërkon PIN-in"</string>
<string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"Kërko motivin e shkyçjes para heqjes së gozhdimit"</string>
<string name="lock_to_app_unlock_password" msgid="9126722403506560473">"Kërko fjalëkalim para heqjes nga gozhdimi."</string>
@@ -2031,8 +2033,7 @@
<string name="autofill_update_title" msgid="3630695947047069136">"Të përditësohet në "<b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>"?"</string>
<string name="autofill_update_title_with_type" msgid="5264152633488495704">"Të përditësohet <xliff:g id="TYPE">%1$s</xliff:g> në "<b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>"?"</string>
<string name="autofill_update_title_with_2types" msgid="1797514386321086273">"Të përditësohet <xliff:g id="TYPE_0">%1$s</xliff:g> dhe <xliff:g id="TYPE_1">%2$s</xliff:g> në "<b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>"?"</string>
- <!-- no translation found for autofill_update_title_with_3types (8285767070604652626) -->
- <skip />
+ <string name="autofill_update_title_with_3types" msgid="8285767070604652626">"Të përditësohen këta artikuj në "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>": <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> dhe <xliff:g id="TYPE_2">%3$s</xliff:g>?"</string>
<string name="autofill_save_yes" msgid="8035743017382012850">"Ruaj"</string>
<string name="autofill_save_no" msgid="9212826374207023544">"Jo, faleminderit"</string>
<string name="autofill_save_notnow" msgid="2853932672029024195">"Jo tani"</string>
diff --git a/core/res/res/values-sr/strings.xml b/core/res/res/values-sr/strings.xml
index 14dfac53966d..81c19152f0fb 100644
--- a/core/res/res/values-sr/strings.xml
+++ b/core/res/res/values-sr/strings.xml
@@ -494,7 +494,7 @@
<string name="permdesc_sim_communication" msgid="4179799296415957960">"Омогућава апликацији да шаље команде SIM картици. То је веома опасно."</string>
<string name="permlab_activityRecognition" msgid="1782303296053990884">"препознавање физичких активности"</string>
<string name="permdesc_activityRecognition" msgid="8667484762991357519">"Ова апликација може да препозна физичке активности."</string>
- <string name="permlab_camera" msgid="6320282492904119413">"снимање фотографија и видео снимака"</string>
+ <string name="permlab_camera" msgid="6320282492904119413">"снимање фотографија и видеа"</string>
<string name="permdesc_camera" msgid="5240801376168647151">"Ова апликација може да снима слике и видео снимке помоћу камере док се апликација користи."</string>
<string name="permlab_backgroundCamera" msgid="7549917926079731681">"да снима слике и видео снимке у позадини"</string>
<string name="permdesc_backgroundCamera" msgid="1615291686191138250">"Ова апликација може да снима фотографије и видео снимке помоћу камере у било ком тренутку."</string>
@@ -745,8 +745,8 @@
<string name="permdesc_readMediaVideo" msgid="3846400073770403528">"Омогућава апликацији да чита видео фајлове из дељеног меморијског простора."</string>
<string name="permlab_readMediaImages" msgid="4057590631020986789">"читање фајлова слика из дељеног меморијског простора"</string>
<string name="permdesc_readMediaImages" msgid="5836219373138469259">"Омогућава апликацији да чита фајлове слика из дељеног меморијског простора."</string>
- <string name="permlab_readVisualUserSelect" msgid="5516204215354667586">"читање фајлова слика и видео снимака које корисник бира из дељеног меморијског простора"</string>
- <string name="permdesc_readVisualUserSelect" msgid="8027174717714968217">"Омогућава апликацији да чита фајлове слика и видео снимака које изаберете из дељеног меморијског простора."</string>
+ <string name="permlab_readVisualUserSelect" msgid="5516204215354667586">"читање фајлова слика и видеа које корисник бира из дељеног меморијског простора"</string>
+ <string name="permdesc_readVisualUserSelect" msgid="8027174717714968217">"Омогућава апликацији да чита фајлове слика и видеа које изаберете из дељеног меморијског простора."</string>
<string name="permlab_sdcardWrite" msgid="4863021819671416668">"мењање или брисање садржаја дељеног меморијског простора"</string>
<string name="permdesc_sdcardWrite" msgid="8376047679331387102">"Дозвољава апликацији да уписује садржај дељеног меморијског простора."</string>
<string name="permlab_use_sip" msgid="8250774565189337477">"упућивање/пријем SIP позива"</string>
@@ -1172,7 +1172,7 @@
<string name="app_running_notification_text" msgid="5120815883400228566">"Додирните за више информација или заустављање апликације."</string>
<string name="ok" msgid="2646370155170753815">"Потврди"</string>
<string name="cancel" msgid="6908697720451760115">"Откажи"</string>
- <string name="yes" msgid="9069828999585032361">"Потврди"</string>
+ <string name="yes" msgid="9069828999585032361">"У реду"</string>
<string name="no" msgid="5122037903299899715">"Откажи"</string>
<string name="dialog_alert_title" msgid="651856561974090712">"Пажња"</string>
<string name="loading" msgid="3138021523725055037">"Учитава се…"</string>
@@ -1417,7 +1417,7 @@
<string name="ext_media_new_notification_message" msgid="6095403121990786986">"Додирните да бисте подесили"</string>
<string name="ext_media_new_notification_message" product="tv" msgid="216863352100263668">"Изаберите да бисте подесили"</string>
<string name="ext_media_new_notification_message" product="automotive" msgid="5140127881613227162">"Можда морате да реформатирате уређај. Додирните да бисте избацили."</string>
- <string name="ext_media_ready_notification_message" msgid="7509496364380197369">"За чување слика, видео снимака, музике и другог садржаја"</string>
+ <string name="ext_media_ready_notification_message" msgid="7509496364380197369">"За чување слика, видеа, музике и другог садржаја"</string>
<string name="ext_media_ready_notification_message" product="tv" msgid="8847134811163165935">"Прегледајте медијске фајлове"</string>
<string name="ext_media_unmountable_notification_title" msgid="4895444667278979910">"Проблем са: <xliff:g id="NAME">%s</xliff:g>"</string>
<string name="ext_media_unmountable_notification_title" product="automotive" msgid="3142723758949023280">"<xliff:g id="NAME">%s</xliff:g> не ради"</string>
@@ -1868,6 +1868,7 @@
<string name="managed_profile_label_badge_2" msgid="5673187309555352550">"2. пословни <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="managed_profile_label_badge_3" msgid="6882151970556391957">"3. пословни имејл <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="clone_profile_label_badge" msgid="1871997694718793964">"Клонирај <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+ <string name="private_profile_label_badge" msgid="1712086003787839183">"Приватни <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"Тражи PIN пре откачињања"</string>
<string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"Тражи шаблон за откључавање пре откачињања"</string>
<string name="lock_to_app_unlock_password" msgid="9126722403506560473">"Тражи лозинку пре откачињања"</string>
@@ -2032,8 +2033,7 @@
<string name="autofill_update_title" msgid="3630695947047069136">"Желите ли да ажурирате у услузи "<b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>"?"</string>
<string name="autofill_update_title_with_type" msgid="5264152633488495704">"Желите ли да ажурирате ставку <xliff:g id="TYPE">%1$s</xliff:g> у услузи "<b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>"?"</string>
<string name="autofill_update_title_with_2types" msgid="1797514386321086273">"Желите ли да ажурирате ставке <xliff:g id="TYPE_0">%1$s</xliff:g> и <xliff:g id="TYPE_1">%2$s</xliff:g> у услузи "<b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>"?"</string>
- <!-- no translation found for autofill_update_title_with_3types (8285767070604652626) -->
- <skip />
+ <string name="autofill_update_title_with_3types" msgid="8285767070604652626">"Желите ли да ажурирате ове ставке у услузи "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>": <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> и <xliff:g id="TYPE_2">%3$s</xliff:g>?"</string>
<string name="autofill_save_yes" msgid="8035743017382012850">"Сачувај"</string>
<string name="autofill_save_no" msgid="9212826374207023544">"Не, хвала"</string>
<string name="autofill_save_notnow" msgid="2853932672029024195">"Не сада"</string>
diff --git a/core/res/res/values-sv/strings.xml b/core/res/res/values-sv/strings.xml
index 8d0a41f4f27b..1ca3e08abb53 100644
--- a/core/res/res/values-sv/strings.xml
+++ b/core/res/res/values-sv/strings.xml
@@ -1867,6 +1867,8 @@
<string name="managed_profile_label_badge_2" msgid="5673187309555352550">"Andra <xliff:g id="LABEL">%1$s</xliff:g> för jobbet"</string>
<string name="managed_profile_label_badge_3" msgid="6882151970556391957">"Tredje <xliff:g id="LABEL">%1$s</xliff:g> för jobbet"</string>
<string name="clone_profile_label_badge" msgid="1871997694718793964">"Klona <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+ <!-- no translation found for private_profile_label_badge (1712086003787839183) -->
+ <skip />
<string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"Be om pinkod innan skärmen slutar fästas"</string>
<string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"Be om upplåsningsmönster innan skärmen slutar fästas"</string>
<string name="lock_to_app_unlock_password" msgid="9126722403506560473">"Be om lösenord innan skärmen slutar fästas"</string>
@@ -2031,8 +2033,7 @@
<string name="autofill_update_title" msgid="3630695947047069136">"Vill du uppdatera detta i "<b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>"?"</string>
<string name="autofill_update_title_with_type" msgid="5264152633488495704">"Vill du uppdatera <xliff:g id="TYPE">%1$s</xliff:g> i "<b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>"?"</string>
<string name="autofill_update_title_with_2types" msgid="1797514386321086273">"Vill du uppdatera <xliff:g id="TYPE_0">%1$s</xliff:g> och <xliff:g id="TYPE_1">%2$s</xliff:g> i "<b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>"?"</string>
- <!-- no translation found for autofill_update_title_with_3types (8285767070604652626) -->
- <skip />
+ <string name="autofill_update_title_with_3types" msgid="8285767070604652626">"Vill du uppdatera dessa objekt i "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>": <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> och <xliff:g id="TYPE_2">%3$s</xliff:g>?"</string>
<string name="autofill_save_yes" msgid="8035743017382012850">"Spara"</string>
<string name="autofill_save_no" msgid="9212826374207023544">"Nej tack"</string>
<string name="autofill_save_notnow" msgid="2853932672029024195">"Inte nu"</string>
diff --git a/core/res/res/values-sw/strings.xml b/core/res/res/values-sw/strings.xml
index afc1fc3b78e1..1ec2eeff1575 100644
--- a/core/res/res/values-sw/strings.xml
+++ b/core/res/res/values-sw/strings.xml
@@ -1867,6 +1867,7 @@
<string name="managed_profile_label_badge_2" msgid="5673187309555352550">"<xliff:g id="LABEL">%1$s</xliff:g> ya 2 ya Kazini"</string>
<string name="managed_profile_label_badge_3" msgid="6882151970556391957">"<xliff:g id="LABEL">%1$s</xliff:g> ya 3 ya Kazini"</string>
<string name="clone_profile_label_badge" msgid="1871997694718793964">"Nakala ya <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+ <string name="private_profile_label_badge" msgid="1712086003787839183">"Faragha <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"Itisha PIN kabla hujabandua"</string>
<string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"Omba mchoro wa kufungua kabla hujabandua"</string>
<string name="lock_to_app_unlock_password" msgid="9126722403506560473">"Omba nenosiri kabla hujabandua"</string>
@@ -2031,8 +2032,7 @@
<string name="autofill_update_title" msgid="3630695947047069136">"Ungependa kusasisha katika "<b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>"?"</string>
<string name="autofill_update_title_with_type" msgid="5264152633488495704">"Ungependa kusasisha <xliff:g id="TYPE">%1$s</xliff:g> katika "<b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>"?"</string>
<string name="autofill_update_title_with_2types" msgid="1797514386321086273">"Ungependa kusasisha <xliff:g id="TYPE_0">%1$s</xliff:g> na <xliff:g id="TYPE_1">%2$s</xliff:g> katika "<b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>"?"</string>
- <!-- no translation found for autofill_update_title_with_3types (8285767070604652626) -->
- <skip />
+ <string name="autofill_update_title_with_3types" msgid="8285767070604652626">"Ungependa kusasisha vipengee hivi katika "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>": <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> na <xliff:g id="TYPE_2">%3$s</xliff:g>?"</string>
<string name="autofill_save_yes" msgid="8035743017382012850">"Hifadhi"</string>
<string name="autofill_save_no" msgid="9212826374207023544">"Hapana"</string>
<string name="autofill_save_notnow" msgid="2853932672029024195">"Si sasa"</string>
diff --git a/core/res/res/values-ta/strings.xml b/core/res/res/values-ta/strings.xml
index 6052b4f98b4e..5b2b2b2d522a 100644
--- a/core/res/res/values-ta/strings.xml
+++ b/core/res/res/values-ta/strings.xml
@@ -1867,6 +1867,8 @@
<string name="managed_profile_label_badge_2" msgid="5673187309555352550">"2வது பணி <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="managed_profile_label_badge_3" msgid="6882151970556391957">"3வது பணி <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="clone_profile_label_badge" msgid="1871997694718793964">"குளோன் <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+ <!-- no translation found for private_profile_label_badge (1712086003787839183) -->
+ <skip />
<string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"அகற்றும் முன் PINஐக் கேள்"</string>
<string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"அகற்றும் முன் அன்லாக் பேட்டர்னைக் கேள்"</string>
<string name="lock_to_app_unlock_password" msgid="9126722403506560473">"அகற்றும் முன் கடவுச்சொல்லைக் கேள்"</string>
@@ -2031,8 +2033,7 @@
<string name="autofill_update_title" msgid="3630695947047069136"><b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>" இல் மாற்றவா?"</string>
<string name="autofill_update_title_with_type" msgid="5264152633488495704"><b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>" இல் <xliff:g id="TYPE">%1$s</xliff:g>ஐ மாற்றவா?"</string>
<string name="autofill_update_title_with_2types" msgid="1797514386321086273"><b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>" இல் <xliff:g id="TYPE_0">%1$s</xliff:g> மற்றும் <xliff:g id="TYPE_1">%2$s</xliff:g>ஐ மாற்றவா?"</string>
- <!-- no translation found for autofill_update_title_with_3types (8285767070604652626) -->
- <skip />
+ <string name="autofill_update_title_with_3types" msgid="8285767070604652626"><b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>" இல் <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> மற்றும் <xliff:g id="TYPE_2">%3$s</xliff:g>ஐ மாற்றவா?"</string>
<string name="autofill_save_yes" msgid="8035743017382012850">"சேமி"</string>
<string name="autofill_save_no" msgid="9212826374207023544">"வேண்டாம்"</string>
<string name="autofill_save_notnow" msgid="2853932672029024195">"இப்போது வேண்டாம்"</string>
diff --git a/core/res/res/values-te/strings.xml b/core/res/res/values-te/strings.xml
index 9da39c334b7d..5b9e737b7d63 100644
--- a/core/res/res/values-te/strings.xml
+++ b/core/res/res/values-te/strings.xml
@@ -1867,6 +1867,7 @@
<string name="managed_profile_label_badge_2" msgid="5673187309555352550">"2వ కార్యాలయం <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="managed_profile_label_badge_3" msgid="6882151970556391957">"3వ కార్యాలయం <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="clone_profile_label_badge" msgid="1871997694718793964">"క్లోన్ <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+ <string name="private_profile_label_badge" msgid="1712086003787839183">"ప్రైవేట్ <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"అన్‌పిన్ చేయడానికి ముందు పిన్‌ కోసం అడుగు"</string>
<string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"అన్‌పిన్ చేయడానికి ముందు అన్‌లాక్ ఆకృతి కోసం అడుగు"</string>
<string name="lock_to_app_unlock_password" msgid="9126722403506560473">"అన్‌పిన్ చేయడానికి ముందు పాస్‌వర్డ్ కోసం అడుగు"</string>
@@ -2031,8 +2032,7 @@
<string name="autofill_update_title" msgid="3630695947047069136"><b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>"లో అప్‌డేట్ చేయాలా?"</string>
<string name="autofill_update_title_with_type" msgid="5264152633488495704">"<xliff:g id="TYPE">%1$s</xliff:g>ని "<b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>"లో అప్‌డేట్ చేయాలా?"</string>
<string name="autofill_update_title_with_2types" msgid="1797514386321086273">"<xliff:g id="TYPE_0">%1$s</xliff:g> మరియు <xliff:g id="TYPE_1">%2$s</xliff:g>ని "<b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>"లో అప్‌డేట్ చేయాలా?"</string>
- <!-- no translation found for autofill_update_title_with_3types (8285767070604652626) -->
- <skip />
+ <string name="autofill_update_title_with_3types" msgid="8285767070604652626">"ఈ ఐటెమ్‌లను "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>"లో అప్‌డేట్ చేయండి: <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> అలాగే <xliff:g id="TYPE_2">%3$s</xliff:g> అప్‌డేట్ చేయాలా?"</string>
<string name="autofill_save_yes" msgid="8035743017382012850">"సేవ్ చేయండి"</string>
<string name="autofill_save_no" msgid="9212826374207023544">"వద్దు, ధన్యవాదాలు"</string>
<string name="autofill_save_notnow" msgid="2853932672029024195">"ఇప్పుడు కాదు"</string>
diff --git a/core/res/res/values-th/strings.xml b/core/res/res/values-th/strings.xml
index fa6638074c89..804562a90f62 100644
--- a/core/res/res/values-th/strings.xml
+++ b/core/res/res/values-th/strings.xml
@@ -1867,6 +1867,7 @@
<string name="managed_profile_label_badge_2" msgid="5673187309555352550">"<xliff:g id="LABEL">%1$s</xliff:g> งานที่ 2"</string>
<string name="managed_profile_label_badge_3" msgid="6882151970556391957">"<xliff:g id="LABEL">%1$s</xliff:g> งานที่ 3"</string>
<string name="clone_profile_label_badge" msgid="1871997694718793964">"โคลน <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+ <string name="private_profile_label_badge" msgid="1712086003787839183">"<xliff:g id="LABEL">%1$s</xliff:g> ส่วนตัว"</string>
<string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"ขอ PIN ก่อนเลิกปักหมุด"</string>
<string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"ขอรูปแบบการปลดล็อกก่อนเลิกปักหมุด"</string>
<string name="lock_to_app_unlock_password" msgid="9126722403506560473">"ขอรหัสผ่านก่อนเลิกปักหมุด"</string>
@@ -2031,8 +2032,7 @@
<string name="autofill_update_title" msgid="3630695947047069136">"อัปเดตใน "<b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>" ไหม"</string>
<string name="autofill_update_title_with_type" msgid="5264152633488495704">"อัปเดต<xliff:g id="TYPE">%1$s</xliff:g>ใน "<b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>" ไหม"</string>
<string name="autofill_update_title_with_2types" msgid="1797514386321086273">"อัปเดต<xliff:g id="TYPE_0">%1$s</xliff:g>และ<xliff:g id="TYPE_1">%2$s</xliff:g>ใน "<b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>" ไหม"</string>
- <!-- no translation found for autofill_update_title_with_3types (8285767070604652626) -->
- <skip />
+ <string name="autofill_update_title_with_3types" msgid="8285767070604652626">"อัปเดตข้อมูล<xliff:g id="TYPE_0">%1$s</xliff:g> <xliff:g id="TYPE_1">%2$s</xliff:g> และ<xliff:g id="TYPE_2">%3$s</xliff:g>ใน "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>" ไหม"</string>
<string name="autofill_save_yes" msgid="8035743017382012850">"บันทึก"</string>
<string name="autofill_save_no" msgid="9212826374207023544">"ไม่เป็นไร"</string>
<string name="autofill_save_notnow" msgid="2853932672029024195">"ไว้ทีหลัง"</string>
diff --git a/core/res/res/values-tl/strings.xml b/core/res/res/values-tl/strings.xml
index 840810cf9ab2..51e7ec641e1b 100644
--- a/core/res/res/values-tl/strings.xml
+++ b/core/res/res/values-tl/strings.xml
@@ -1867,6 +1867,7 @@
<string name="managed_profile_label_badge_2" msgid="5673187309555352550">"Pangalawang <xliff:g id="LABEL">%1$s</xliff:g> sa Trabaho"</string>
<string name="managed_profile_label_badge_3" msgid="6882151970556391957">"Pangatlong <xliff:g id="LABEL">%1$s</xliff:g> sa Trabaho"</string>
<string name="clone_profile_label_badge" msgid="1871997694718793964">"I-clone ang <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+ <string name="private_profile_label_badge" msgid="1712086003787839183">"Pribadong <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"Humingi ng PIN bago mag-unpin"</string>
<string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"Humingi ng pattern sa pag-unlock bago mag-unpin"</string>
<string name="lock_to_app_unlock_password" msgid="9126722403506560473">"Humingi ng password bago mag-unpin"</string>
@@ -2031,8 +2032,7 @@
<string name="autofill_update_title" msgid="3630695947047069136">"I-update sa "<b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>"?"</string>
<string name="autofill_update_title_with_type" msgid="5264152633488495704">"I-update ang <xliff:g id="TYPE">%1$s</xliff:g> sa "<b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>"?"</string>
<string name="autofill_update_title_with_2types" msgid="1797514386321086273">"I-update ang <xliff:g id="TYPE_0">%1$s</xliff:g> at <xliff:g id="TYPE_1">%2$s</xliff:g> sa "<b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>"?"</string>
- <!-- no translation found for autofill_update_title_with_3types (8285767070604652626) -->
- <skip />
+ <string name="autofill_update_title_with_3types" msgid="8285767070604652626">"I-update ang mga item na ito sa "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>": <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g>, at <xliff:g id="TYPE_2">%3$s</xliff:g>?"</string>
<string name="autofill_save_yes" msgid="8035743017382012850">"I-save"</string>
<string name="autofill_save_no" msgid="9212826374207023544">"Hindi, salamat na lang"</string>
<string name="autofill_save_notnow" msgid="2853932672029024195">"Hindi ngayon"</string>
diff --git a/core/res/res/values-tr/strings.xml b/core/res/res/values-tr/strings.xml
index 90a57311840f..33b050aa2cef 100644
--- a/core/res/res/values-tr/strings.xml
+++ b/core/res/res/values-tr/strings.xml
@@ -1867,6 +1867,8 @@
<string name="managed_profile_label_badge_2" msgid="5673187309555352550">"İş için 2. <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="managed_profile_label_badge_3" msgid="6882151970556391957">"İş için 3. <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="clone_profile_label_badge" msgid="1871997694718793964">"<xliff:g id="LABEL">%1$s</xliff:g> klonu"</string>
+ <!-- no translation found for private_profile_label_badge (1712086003787839183) -->
+ <skip />
<string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"Sabitlemeyi kaldırmadan önce PIN\'i sor"</string>
<string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"Sabitlemeyi kaldırmadan önce kilit açma desenini sor"</string>
<string name="lock_to_app_unlock_password" msgid="9126722403506560473">"Sabitlemeyi kaldırmadan önce şifre sor"</string>
@@ -2031,8 +2033,7 @@
<string name="autofill_update_title" msgid="3630695947047069136"><b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>" hizmetinde güncellensin mi?"</string>
<string name="autofill_update_title_with_type" msgid="5264152633488495704">"<xliff:g id="TYPE">%1$s</xliff:g> "<b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>" hizmetinde güncellensin mi?"</string>
<string name="autofill_update_title_with_2types" msgid="1797514386321086273">"<xliff:g id="TYPE_0">%1$s</xliff:g> ve <xliff:g id="TYPE_1">%2$s</xliff:g> "<b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>" hizmetinde güncellensin mi?"</string>
- <!-- no translation found for autofill_update_title_with_3types (8285767070604652626) -->
- <skip />
+ <string name="autofill_update_title_with_3types" msgid="8285767070604652626">"Şu öğeler "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>" hizmetinde güncellensin mi: <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> ve <xliff:g id="TYPE_2">%3$s</xliff:g>?"</string>
<string name="autofill_save_yes" msgid="8035743017382012850">"Kaydet"</string>
<string name="autofill_save_no" msgid="9212826374207023544">"Hayır, teşekkürler"</string>
<string name="autofill_save_notnow" msgid="2853932672029024195">"Şimdi değil"</string>
diff --git a/core/res/res/values-uk/strings.xml b/core/res/res/values-uk/strings.xml
index f8a725daaaaf..f6d426d53b28 100644
--- a/core/res/res/values-uk/strings.xml
+++ b/core/res/res/values-uk/strings.xml
@@ -1869,6 +1869,8 @@
<string name="managed_profile_label_badge_2" msgid="5673187309555352550">"2-а робота: <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="managed_profile_label_badge_3" msgid="6882151970556391957">"3-я робота: <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="clone_profile_label_badge" msgid="1871997694718793964">"Копія додатка <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+ <!-- no translation found for private_profile_label_badge (1712086003787839183) -->
+ <skip />
<string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"PIN-код для відкріплення"</string>
<string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"Запитувати ключ розблокування перед відкріпленням"</string>
<string name="lock_to_app_unlock_password" msgid="9126722403506560473">"Запитувати пароль перед відкріпленням"</string>
@@ -2033,8 +2035,7 @@
<string name="autofill_update_title" msgid="3630695947047069136">"Оновити в сервісі "<b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>"?"</string>
<string name="autofill_update_title_with_type" msgid="5264152633488495704">"Оновити дані (<xliff:g id="TYPE">%1$s</xliff:g>) у сервісі "<b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>"?"</string>
<string name="autofill_update_title_with_2types" msgid="1797514386321086273">"Оновити дані (<xliff:g id="TYPE_0">%1$s</xliff:g> і <xliff:g id="TYPE_1">%2$s</xliff:g>) у сервісі "<b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>"?"</string>
- <!-- no translation found for autofill_update_title_with_3types (8285767070604652626) -->
- <skip />
+ <string name="autofill_update_title_with_3types" msgid="8285767070604652626">"Оновити в сервісі "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>" такі дані: <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> і <xliff:g id="TYPE_2">%3$s</xliff:g>?"</string>
<string name="autofill_save_yes" msgid="8035743017382012850">"Зберегти"</string>
<string name="autofill_save_no" msgid="9212826374207023544">"Ні, дякую"</string>
<string name="autofill_save_notnow" msgid="2853932672029024195">"Не зараз"</string>
diff --git a/core/res/res/values-ur/strings.xml b/core/res/res/values-ur/strings.xml
index 227f25d4bf87..c8cd1cb2b9d9 100644
--- a/core/res/res/values-ur/strings.xml
+++ b/core/res/res/values-ur/strings.xml
@@ -1867,6 +1867,8 @@
<string name="managed_profile_label_badge_2" msgid="5673187309555352550">"دوسرا کام <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="managed_profile_label_badge_3" msgid="6882151970556391957">"تیسرا کام <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="clone_profile_label_badge" msgid="1871997694718793964">"<xliff:g id="LABEL">%1$s</xliff:g> کلون"</string>
+ <!-- no translation found for private_profile_label_badge (1712086003787839183) -->
+ <skip />
<string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"‏پن ہٹانے سے پہلے PIN طلب کریں"</string>
<string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"پن ہٹانے سے پہلے غیر مقفل کرنے کا پیٹرن طلب کریں"</string>
<string name="lock_to_app_unlock_password" msgid="9126722403506560473">"پن ہٹانے سے پہلے پاس ورڈ طلب کریں"</string>
@@ -2031,8 +2033,7 @@
<string name="autofill_update_title" msgid="3630695947047069136"><b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>" میں اپ ڈیٹ کریں؟"</string>
<string name="autofill_update_title_with_type" msgid="5264152633488495704"><b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>" میں <xliff:g id="TYPE">%1$s</xliff:g> اپ ڈیٹ کریں؟"</string>
<string name="autofill_update_title_with_2types" msgid="1797514386321086273">"<xliff:g id="TYPE_0">%1$s</xliff:g> اور <xliff:g id="TYPE_1">%2$s</xliff:g> کو "<b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>" میں اپ ڈیٹ کریں؟"</string>
- <!-- no translation found for autofill_update_title_with_3types (8285767070604652626) -->
- <skip />
+ <string name="autofill_update_title_with_3types" msgid="8285767070604652626">"ان آئٹمز کو "<b>"<xliff:g id="LABEL">%4$s</xliff:g> "</b>" میں اپ ڈیٹ کریں: <xliff:g id="TYPE_0">%1$s</xliff:g>، <xliff:g id="TYPE_1">%2$s</xliff:g> اور <xliff:g id="TYPE_2">%3$s</xliff:g>؟"</string>
<string name="autofill_save_yes" msgid="8035743017382012850">"محفوظ کریں"</string>
<string name="autofill_save_no" msgid="9212826374207023544">"نہیں، شکریہ"</string>
<string name="autofill_save_notnow" msgid="2853932672029024195">"ابھی نہیں"</string>
diff --git a/core/res/res/values-uz/strings.xml b/core/res/res/values-uz/strings.xml
index a0b43c7bb15e..696edd384309 100644
--- a/core/res/res/values-uz/strings.xml
+++ b/core/res/res/values-uz/strings.xml
@@ -1867,6 +1867,7 @@
<string name="managed_profile_label_badge_2" msgid="5673187309555352550">"2-ishxona <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="managed_profile_label_badge_3" msgid="6882151970556391957">"3-ishxona <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="clone_profile_label_badge" msgid="1871997694718793964">"<xliff:g id="LABEL">%1$s</xliff:g> nusxasini yaratish"</string>
+ <string name="private_profile_label_badge" msgid="1712086003787839183">"Shaxsiy <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"Yechishda PIN kod talab qilinsin"</string>
<string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"Yechishdan oldin grafik kalit so‘ralsin"</string>
<string name="lock_to_app_unlock_password" msgid="9126722403506560473">"Bo‘shatishdan oldin parol so‘ralsin"</string>
@@ -2031,8 +2032,7 @@
<string name="autofill_update_title" msgid="3630695947047069136"><b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>" xizmatida yangilansinmi?"</string>
<string name="autofill_update_title_with_type" msgid="5264152633488495704">"<xliff:g id="TYPE">%1$s</xliff:g> "<b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>" xizmatida yangilansinmi?"</string>
<string name="autofill_update_title_with_2types" msgid="1797514386321086273">"<xliff:g id="TYPE_0">%1$s</xliff:g> va <xliff:g id="TYPE_1">%2$s</xliff:g> "<b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>" xizmatida yangilansinmi?"</string>
- <!-- no translation found for autofill_update_title_with_3types (8285767070604652626) -->
- <skip />
+ <string name="autofill_update_title_with_3types" msgid="8285767070604652626"><b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>" xizmatidagi <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> va <xliff:g id="TYPE_2">%3$s</xliff:g> yangilansinmi?"</string>
<string name="autofill_save_yes" msgid="8035743017382012850">"Saqlash"</string>
<string name="autofill_save_no" msgid="9212826374207023544">"Kerak emas"</string>
<string name="autofill_save_notnow" msgid="2853932672029024195">"Keyinroq"</string>
diff --git a/core/res/res/values-vi/strings.xml b/core/res/res/values-vi/strings.xml
index f6abefbb2959..5b92609c8b96 100644
--- a/core/res/res/values-vi/strings.xml
+++ b/core/res/res/values-vi/strings.xml
@@ -1867,6 +1867,8 @@
<string name="managed_profile_label_badge_2" msgid="5673187309555352550">"Công việc thứ 2 <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="managed_profile_label_badge_3" msgid="6882151970556391957">"Công việc thứ 2 <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="clone_profile_label_badge" msgid="1871997694718793964">"Sao chép <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+ <!-- no translation found for private_profile_label_badge (1712086003787839183) -->
+ <skip />
<string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"Hỏi mã PIN trước khi bỏ ghim"</string>
<string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"Hỏi hình mở khóa trước khi bỏ ghim"</string>
<string name="lock_to_app_unlock_password" msgid="9126722403506560473">"Hỏi mật khẩu trước khi bỏ ghim"</string>
@@ -2031,8 +2033,7 @@
<string name="autofill_update_title" msgid="3630695947047069136">"Cập nhật trong "<b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>"?"</string>
<string name="autofill_update_title_with_type" msgid="5264152633488495704">"Cập nhật <xliff:g id="TYPE">%1$s</xliff:g> trong "<b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>"?"</string>
<string name="autofill_update_title_with_2types" msgid="1797514386321086273">"Cập nhật <xliff:g id="TYPE_0">%1$s</xliff:g> và <xliff:g id="TYPE_1">%2$s</xliff:g> trong "<b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>"?"</string>
- <!-- no translation found for autofill_update_title_with_3types (8285767070604652626) -->
- <skip />
+ <string name="autofill_update_title_with_3types" msgid="8285767070604652626">"Cập nhật các mục <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> và <xliff:g id="TYPE_2">%3$s</xliff:g> trong "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>"?"</string>
<string name="autofill_save_yes" msgid="8035743017382012850">"Lưu"</string>
<string name="autofill_save_no" msgid="9212826374207023544">"Không, cảm ơn"</string>
<string name="autofill_save_notnow" msgid="2853932672029024195">"Để sau"</string>
diff --git a/core/res/res/values-zh-rCN/strings.xml b/core/res/res/values-zh-rCN/strings.xml
index 10d865b64d12..f900b59c8eba 100644
--- a/core/res/res/values-zh-rCN/strings.xml
+++ b/core/res/res/values-zh-rCN/strings.xml
@@ -1867,6 +1867,7 @@
<string name="managed_profile_label_badge_2" msgid="5673187309555352550">"第二个工作<xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="managed_profile_label_badge_3" msgid="6882151970556391957">"第三个工作<xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="clone_profile_label_badge" msgid="1871997694718793964">"<xliff:g id="LABEL">%1$s</xliff:g>克隆"</string>
+ <string name="private_profile_label_badge" msgid="1712086003787839183">"私人“<xliff:g id="LABEL">%1$s</xliff:g>”"</string>
<string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"取消时要求输入PIN码"</string>
<string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"取消时要求绘制解锁图案"</string>
<string name="lock_to_app_unlock_password" msgid="9126722403506560473">"取消时要求输入密码"</string>
@@ -2031,8 +2032,7 @@
<string name="autofill_update_title" msgid="3630695947047069136">"要在"<b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>"中更新吗?"</string>
<string name="autofill_update_title_with_type" msgid="5264152633488495704">"要在"<b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>"中更新<xliff:g id="TYPE">%1$s</xliff:g>吗?"</string>
<string name="autofill_update_title_with_2types" msgid="1797514386321086273">"要在"<b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>"中更新<xliff:g id="TYPE_0">%1$s</xliff:g>和<xliff:g id="TYPE_1">%2$s</xliff:g>吗?"</string>
- <!-- no translation found for autofill_update_title_with_3types (8285767070604652626) -->
- <skip />
+ <string name="autofill_update_title_with_3types" msgid="8285767070604652626">"要在"<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>"中更新<xliff:g id="TYPE_0">%1$s</xliff:g>、<xliff:g id="TYPE_1">%2$s</xliff:g>和<xliff:g id="TYPE_2">%3$s</xliff:g>吗?"</string>
<string name="autofill_save_yes" msgid="8035743017382012850">"保存"</string>
<string name="autofill_save_no" msgid="9212826374207023544">"不用了"</string>
<string name="autofill_save_notnow" msgid="2853932672029024195">"以后再说"</string>
diff --git a/core/res/res/values-zh-rHK/strings.xml b/core/res/res/values-zh-rHK/strings.xml
index 8de69311ad7e..7140539391e7 100644
--- a/core/res/res/values-zh-rHK/strings.xml
+++ b/core/res/res/values-zh-rHK/strings.xml
@@ -1867,6 +1867,7 @@
<string name="managed_profile_label_badge_2" msgid="5673187309555352550">"第二個工作<xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="managed_profile_label_badge_3" msgid="6882151970556391957">"第三個工作<xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="clone_profile_label_badge" msgid="1871997694718793964">"複製 <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+ <string name="private_profile_label_badge" msgid="1712086003787839183">"私人<xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"取消固定時必須輸入 PIN"</string>
<string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"取消固定時必須提供解鎖圖案"</string>
<string name="lock_to_app_unlock_password" msgid="9126722403506560473">"取消固定時必須輸入密碼"</string>
@@ -2031,8 +2032,7 @@
<string name="autofill_update_title" msgid="3630695947047069136">"要在 "<b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>" 中更新嗎?"</string>
<string name="autofill_update_title_with_type" msgid="5264152633488495704">"要在 "<b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>" 中更新<xliff:g id="TYPE">%1$s</xliff:g>嗎?"</string>
<string name="autofill_update_title_with_2types" msgid="1797514386321086273">"要在 "<b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>" 中更新<xliff:g id="TYPE_0">%1$s</xliff:g>和<xliff:g id="TYPE_1">%2$s</xliff:g>嗎?"</string>
- <!-- no translation found for autofill_update_title_with_3types (8285767070604652626) -->
- <skip />
+ <string name="autofill_update_title_with_3types" msgid="8285767070604652626">"要在 "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>" 中更新<xliff:g id="TYPE_0">%1$s</xliff:g>、<xliff:g id="TYPE_1">%2$s</xliff:g>和<xliff:g id="TYPE_2">%3$s</xliff:g>嗎?"</string>
<string name="autofill_save_yes" msgid="8035743017382012850">"儲存"</string>
<string name="autofill_save_no" msgid="9212826374207023544">"不用了,謝謝"</string>
<string name="autofill_save_notnow" msgid="2853932672029024195">"暫時不要"</string>
diff --git a/core/res/res/values-zh-rTW/strings.xml b/core/res/res/values-zh-rTW/strings.xml
index c0631e9a72a2..61fe93977e92 100644
--- a/core/res/res/values-zh-rTW/strings.xml
+++ b/core/res/res/values-zh-rTW/strings.xml
@@ -1867,6 +1867,7 @@
<string name="managed_profile_label_badge_2" msgid="5673187309555352550">"第 2 項工作:<xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="managed_profile_label_badge_3" msgid="6882151970556391957">"第 3 項工作:<xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="clone_profile_label_badge" msgid="1871997694718793964">"複製<xliff:g id="LABEL">%1$s</xliff:g>"</string>
+ <string name="private_profile_label_badge" msgid="1712086003787839183">"私人 <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"取消固定時必須輸入 PIN"</string>
<string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"取消固定時必須畫出解鎖圖案"</string>
<string name="lock_to_app_unlock_password" msgid="9126722403506560473">"取消固定時必須輸入密碼"</string>
@@ -2031,8 +2032,7 @@
<string name="autofill_update_title" msgid="3630695947047069136">"要更新 "<b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>" 中的內容嗎?"</string>
<string name="autofill_update_title_with_type" msgid="5264152633488495704">"要更新 "<b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>" 中的<xliff:g id="TYPE">%1$s</xliff:g>嗎?"</string>
<string name="autofill_update_title_with_2types" msgid="1797514386321086273">"要更新 "<b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>" 中的<xliff:g id="TYPE_0">%1$s</xliff:g>和<xliff:g id="TYPE_1">%2$s</xliff:g>嗎?"</string>
- <!-- no translation found for autofill_update_title_with_3types (8285767070604652626) -->
- <skip />
+ <string name="autofill_update_title_with_3types" msgid="8285767070604652626">"要更新 "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>" 中的<xliff:g id="TYPE_0">%1$s</xliff:g>、<xliff:g id="TYPE_1">%2$s</xliff:g>和<xliff:g id="TYPE_2">%3$s</xliff:g>嗎?"</string>
<string name="autofill_save_yes" msgid="8035743017382012850">"儲存"</string>
<string name="autofill_save_no" msgid="9212826374207023544">"不用了,謝謝"</string>
<string name="autofill_save_notnow" msgid="2853932672029024195">"暫時不要"</string>
diff --git a/core/res/res/values-zu/strings.xml b/core/res/res/values-zu/strings.xml
index e9b408048793..77a41fce44e3 100644
--- a/core/res/res/values-zu/strings.xml
+++ b/core/res/res/values-zu/strings.xml
@@ -1867,6 +1867,7 @@
<string name="managed_profile_label_badge_2" msgid="5673187309555352550">"Umsebenzi wesibili <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="managed_profile_label_badge_3" msgid="6882151970556391957">"Umsebenzi wesithathu <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="clone_profile_label_badge" msgid="1871997694718793964">"I-Clone <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+ <string name="private_profile_label_badge" msgid="1712086003787839183">"Okuyimfihlo <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"Cela iphinikhodi ngaphambi kokuphina"</string>
<string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"Cela iphethini yokuvula ngaphambi kokususa ukuphina"</string>
<string name="lock_to_app_unlock_password" msgid="9126722403506560473">"Cela iphasiwedi ngaphambi kokususa ukuphina"</string>
@@ -2031,8 +2032,7 @@
<string name="autofill_update_title" msgid="3630695947047069136">"Buyekeza ku-"<b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>"?"</string>
<string name="autofill_update_title_with_type" msgid="5264152633488495704">"Buyekeza i-<xliff:g id="TYPE">%1$s</xliff:g> ku-"<b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>"?"</string>
<string name="autofill_update_title_with_2types" msgid="1797514386321086273">"Buyekeza i-<xliff:g id="TYPE_0">%1$s</xliff:g> ne-<xliff:g id="TYPE_1">%2$s</xliff:g> ku-"<b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>"?"</string>
- <!-- no translation found for autofill_update_title_with_3types (8285767070604652626) -->
- <skip />
+ <string name="autofill_update_title_with_3types" msgid="8285767070604652626">"Buyekeza lezi zinto ku-"<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>": <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g>, ne-<xliff:g id="TYPE_2">%3$s</xliff:g>?"</string>
<string name="autofill_save_yes" msgid="8035743017382012850">"Londoloza"</string>
<string name="autofill_save_no" msgid="9212826374207023544">"Cha ngiyabonga"</string>
<string name="autofill_save_notnow" msgid="2853932672029024195">"Hhayi manje"</string>
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index a72f779bf70c..367a4f5f050d 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -935,6 +935,9 @@
without impacting power, performance, and app compatibility (e.g. protected content). -->
<bool name="config_reduceBrightColorsAvailable">@bool/config_setColorTransformAccelerated</bool>
+ <!-- Whether to show Fold lock behavior setting feature in Settings App -->
+ <bool name="config_fold_lock_behavior">false</bool>
+
<string-array name="config_reduceBrightColorsCoefficientsNonlinear">
<!-- a-coefficient --> <item>-0.4429953456</item>
<!-- b-coefficient --> <item>-0.2434077725</item>
@@ -1185,6 +1188,9 @@
-->
<integer name="config_shortPressOnSleepBehavior">0</integer>
+ <!-- Whether to silence telephony ringer on sleep key event -->
+ <bool name="config_silenceRingerOnSleepKey">false</bool>
+
<!-- Control the behavior when the user long presses the stem primary button.
Stem primary button is only used on watch form factor. If a device is not
a watch, setting this config is no-op.
@@ -5477,6 +5483,13 @@
of known compatibility issues. -->
<string-array name="config_highRefreshRateBlacklist"></string-array>
+ <!-- The list of packages to automatically opt in to refresh rate suppressing by small area
+ detection. Format of this array should be packageName:threshold and threshold value should
+ be between 0 to 1-->
+ <string-array name="config_smallAreaDetectionAllowlist" translatable="false">
+ <!-- Add packages:threshold here -->
+ </string-array>
+
<!-- The list of packages to force slowJpegMode for Apps using Camera API1 -->
<string-array name="config_forceSlowJpegModeList" translatable="false">
<!-- Add packages here -->
@@ -6182,6 +6195,8 @@
<!-- Default value for Settings.SEARCH_PRESS_HOLD_NAV_HANDLE_ENABLED -->
<bool name="config_searchPressHoldNavHandleEnabledDefault">true</bool>
+ <!-- Default value for Settings.ASSIST_LONG_PRESS_HOME_ENABLED for search overlay -->
+ <bool name="config_searchLongPressHomeEnabledDefault">true</bool>
<!-- The maximum byte size of the information contained in the bundle of
HotwordDetectedResult. -->
diff --git a/core/res/res/values/styles.xml b/core/res/res/values/styles.xml
index 164f713200ac..13d04e53b508 100644
--- a/core/res/res/values/styles.xml
+++ b/core/res/res/values/styles.xml
@@ -1500,12 +1500,8 @@ please see styles_device_defaults.xml.
<item name="fontFamily">google-sans-text-medium</item>
<item name="textStyle">normal</item>
<item name="textAllCaps">false</item>
- <item name="layout_marginTop">6dp</item>
- <item name="layout_marginBottom">6dp</item>
- <item name="paddingStart">16dp</item>
- <item name="paddingEnd">16dp</item>
- <item name="paddingTop">8dp</item>
- <item name="paddingBottom">8dp</item>
+ <item name="paddingStart">24dp</item>
+ <item name="paddingEnd">24dp</item>
</style>
<!-- @hide Tonal button for Autofill half screen dialog -->
<style name="AutofillHalfSheetTonalButton" parent="AutofillHalfSheetButton">
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index ee0563b5d7cd..1965172c8047 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -343,6 +343,7 @@
<java-symbol type="string" name="config_defaultHealthConnectApp" />
<java-symbol type="bool" name="config_sendAudioBecomingNoisy" />
<java-symbol type="bool" name="config_enableScreenshotChord" />
+ <java-symbol type="bool" name="config_fold_lock_behavior" />
<java-symbol type="bool" name="config_enableWifiDisplay" />
<java-symbol type="bool" name="config_allowAnimationsInLowPowerMode" />
<java-symbol type="bool" name="config_useDevInputEventForAudioJack" />
@@ -464,6 +465,7 @@
<java-symbol type="integer" name="config_toastDefaultGravity" />
<java-symbol type="integer" name="config_triplePressOnPowerBehavior" />
<java-symbol type="integer" name="config_shortPressOnSleepBehavior" />
+ <java-symbol type="bool" name="config_silenceRingerOnSleepKey" />
<java-symbol type="integer" name="config_longPressOnStemPrimaryBehavior" />
<java-symbol type="integer" name="config_shortPressOnStemPrimaryBehavior" />
<java-symbol type="string" name="config_primaryShortPressTargetActivity" />
@@ -4287,6 +4289,8 @@
<java-symbol type="array" name="config_highRefreshRateBlacklist" />
<java-symbol type="array" name="config_forceSlowJpegModeList" />
+ <java-symbol type="array" name="config_smallAreaDetectionAllowlist" />
+
<java-symbol type="layout" name="chooser_dialog" />
<java-symbol type="layout" name="chooser_dialog_item" />
<java-symbol type="drawable" name="chooser_dialog_background" />
@@ -4914,6 +4918,7 @@
<java-symbol type="bool" name="config_assistTouchGestureEnabledDefault" />
<java-symbol type="bool" name="config_searchPressHoldNavHandleEnabledDefault" />
+ <java-symbol type="bool" name="config_searchLongPressHomeEnabledDefault" />
<java-symbol type="integer" name="config_hotwordDetectedResultMaxBundleSize" />
diff --git a/core/tests/batterystatstests/BatteryUsageStatsProtoTests/src/com/android/internal/os/BatteryUsageStatsPulledTest.java b/core/tests/batterystatstests/BatteryUsageStatsProtoTests/src/com/android/internal/os/BatteryUsageStatsPulledTest.java
index 0676f899674d..aaaa3c7740c5 100644
--- a/core/tests/batterystatstests/BatteryUsageStatsProtoTests/src/com/android/internal/os/BatteryUsageStatsPulledTest.java
+++ b/core/tests/batterystatstests/BatteryUsageStatsProtoTests/src/com/android/internal/os/BatteryUsageStatsPulledTest.java
@@ -241,7 +241,8 @@ public class BatteryUsageStatsPulledTest {
final BatteryUsageStats.Builder builder =
new BatteryUsageStats.Builder(new String[]{"CustomConsumer1", "CustomConsumer2"},
/* includePowerModels */ true,
- /* includeProcessStats */true)
+ /* includeProcessStats */ true,
+ /* minConsumedPowerThreshold */ 0)
.setDischargePercentage(20)
.setDischargedPowerRange(1000, 2000)
.setDischargeDurationMs(1234)
@@ -325,7 +326,7 @@ public class BatteryUsageStatsPulledTest {
@Test
public void testLargeAtomTruncated() {
final BatteryUsageStats.Builder builder =
- new BatteryUsageStats.Builder(new String[0], true, false);
+ new BatteryUsageStats.Builder(new String[0], true, false, 0);
// If not truncated, this BatteryUsageStats object would generate a proto buffer
// significantly larger than 50 Kb
for (int i = 0; i < 3000; i++) {
diff --git a/core/tests/coretests/res/layout/viewgroup_test.xml b/core/tests/coretests/res/layout/viewgroup_test.xml
index 04f4f5228b06..9b5704756044 100644
--- a/core/tests/coretests/res/layout/viewgroup_test.xml
+++ b/core/tests/coretests/res/layout/viewgroup_test.xml
@@ -42,8 +42,8 @@
android:id="@+id/view_translate"
android:layout_width="20dp"
android:layout_height="10dp"
- android:translationX="10dp"
- android:translationY="20dp"
+ android:translationX="10px"
+ android:translationY="20px"
android:text="Hello World!"
android:background="#2F00FF00" />
<FrameLayout
diff --git a/core/tests/coretests/src/android/app/activity/ActivityThreadTest.java b/core/tests/coretests/src/android/app/activity/ActivityThreadTest.java
index a9234791247e..0778311e98bd 100644
--- a/core/tests/coretests/src/android/app/activity/ActivityThreadTest.java
+++ b/core/tests/coretests/src/android/app/activity/ActivityThreadTest.java
@@ -67,7 +67,6 @@ import android.view.View;
import android.window.WindowContextInfo;
import android.window.WindowTokenClientController;
-import androidx.test.filters.FlakyTest;
import androidx.test.filters.MediumTest;
import androidx.test.platform.app.InstrumentationRegistry;
import androidx.test.rule.ActivityTestRule;
@@ -254,15 +253,9 @@ public class ActivityThreadTest {
// Execute a local relaunch item with current scaled config (e.g. simulate recreate),
// the config should not be scaled again.
- final Configuration currentConfig = activity.getResources().getConfiguration();
- final ClientTransaction localTransaction =
- newTransaction(activityThread, activity.getActivityToken());
- localTransaction.addCallback(ActivityRelaunchItem.obtain(
- null /* pendingResults */, null /* pendingIntents */, 0 /* configChanges */,
- new MergedConfiguration(currentConfig, currentConfig),
- true /* preserveWindow */));
InstrumentationRegistry.getInstrumentation().runOnMainSync(
- () -> activityThread.executeTransaction(localTransaction));
+ () -> activityThread.executeTransaction(
+ newRelaunchResumeTransaction(activity)));
assertScreenScale(scale, activity, originalActivityConfig, originalActivityMetrics);
} finally {
@@ -630,7 +623,6 @@ public class ActivityThreadTest {
});
}
- @FlakyTest(bugId = 295234586)
@Test
public void testHandleConfigurationChanged_DoesntOverrideActivityConfig() {
final TestActivity activity = mActivityTestRule.launchActivity(new Intent());
@@ -836,8 +828,10 @@ public class ActivityThreadTest {
}
private static ClientTransaction newRelaunchResumeTransaction(Activity activity) {
+ final Configuration currentConfig = activity.getResources().getConfiguration();
final ClientTransactionItem callbackItem = ActivityRelaunchItem.obtain(null,
- null, 0, new MergedConfiguration(), false /* preserveWindow */);
+ null, 0, new MergedConfiguration(currentConfig, currentConfig),
+ false /* preserveWindow */);
final ResumeActivityItem resumeStateRequest =
ResumeActivityItem.obtain(true /* isForward */,
false /* shouldSendCompatFakeFocus*/);
diff --git a/core/tests/coretests/src/android/provider/DeviceConfigTest.java b/core/tests/coretests/src/android/provider/DeviceConfigTest.java
index 1ea20f162680..349fe7b36ef5 100644
--- a/core/tests/coretests/src/android/provider/DeviceConfigTest.java
+++ b/core/tests/coretests/src/android/provider/DeviceConfigTest.java
@@ -53,6 +53,7 @@ public class DeviceConfigTest {
private static final long WAIT_FOR_PROPERTY_CHANGE_TIMEOUT_MILLIS = 2000; // 2 sec
private static final String DEFAULT_VALUE = "test_default_value";
private static final String NAMESPACE = "namespace1";
+ private static final String NAMESPACE2 = "namespace2";
private static final String KEY = "key1";
private static final String KEY2 = "key2";
private static final String KEY3 = "key3";
@@ -67,6 +68,89 @@ public class DeviceConfigTest {
deleteViaContentProvider(NAMESPACE, KEY);
deleteViaContentProvider(NAMESPACE, KEY2);
deleteViaContentProvider(NAMESPACE, KEY3);
+ DeviceConfig.clearAllLocalOverrides();
+ }
+
+ /**
+ * Test that creating a sticky local override for a flag prevents further writes to that flag.
+ */
+ @Test
+ public void testAddStickyLocalOverridePreventsWrites() {
+ DeviceConfig.setLocalOverride(NAMESPACE, KEY, VALUE);
+
+ String key1Value = DeviceConfig.getProperty(NAMESPACE, KEY);
+ assertThat(key1Value).isEqualTo(VALUE);
+
+ DeviceConfig.setProperty(NAMESPACE, KEY, VALUE2, /* makeDefault= */ false);
+ key1Value = DeviceConfig.getProperty(NAMESPACE, KEY);
+ assertThat(key1Value).isEqualTo(VALUE);
+ }
+
+ /**
+ * Test that when we locally override a flag, we can still write other flags.
+ */
+ @Test
+ public void testAddStickyLocalOverrideDoesNotAffectOtherFlags() {
+ DeviceConfig.setLocalOverride(NAMESPACE, KEY, VALUE);
+ DeviceConfig.setProperty(NAMESPACE, KEY2, VALUE2, /* makeDefault= */ false);
+ String key2Value = DeviceConfig.getProperty(NAMESPACE, KEY2);
+ assertThat(key2Value).isEqualTo(VALUE2);
+ }
+
+ /**
+ * Test that when we apply some overrides, they show up in the override list.
+ */
+ @Test
+ public void testGetStickyLocalOverrides() {
+ DeviceConfig.setProperty(NAMESPACE, KEY, VALUE2, false);
+ DeviceConfig.setProperty(NAMESPACE, KEY2, VALUE, false);
+ DeviceConfig.setLocalOverride(NAMESPACE, KEY, VALUE);
+ DeviceConfig.setLocalOverride(NAMESPACE, KEY2, VALUE2);
+
+ Map<String, Map<String, String>> expectedOverrides = new HashMap<>();
+ Map<String, String> expectedInnerMap = new HashMap<>();
+ expectedInnerMap.put(KEY, VALUE2);
+ expectedInnerMap.put(KEY2, VALUE);
+ expectedOverrides.put(NAMESPACE, expectedInnerMap);
+
+ assertThat(DeviceConfig.getUnderlyingValuesForOverriddenFlags())
+ .isEqualTo(expectedOverrides);
+ }
+
+ /**
+ * Test that when we clear all overrides, the override list is empty.
+ */
+ @Test
+ public void testClearStickyLocalOverrides() {
+ DeviceConfig.setLocalOverride(NAMESPACE2, KEY, VALUE);
+ DeviceConfig.setLocalOverride(NAMESPACE2, KEY2, VALUE2);
+
+ DeviceConfig.clearAllLocalOverrides();
+
+ Map<String, Map<String, String>> overrides =
+ DeviceConfig.getUnderlyingValuesForOverriddenFlags();
+ assertThat(overrides).isEmpty();
+ }
+
+ /**
+ * Test that when we clear a single override, it doesn't appear in the list.
+ */
+ @Test
+ public void testClearStickyLocalOverride() {
+ DeviceConfig.setProperty(NAMESPACE, KEY, VALUE2, false);
+ DeviceConfig.setProperty(NAMESPACE2, KEY2, VALUE, false);
+ DeviceConfig.setLocalOverride(NAMESPACE, KEY, VALUE);
+ DeviceConfig.setLocalOverride(NAMESPACE2, KEY2, VALUE2);
+
+ DeviceConfig.clearLocalOverride(NAMESPACE, KEY);
+
+ Map<String, Map<String, String>> expectedOverrides = new HashMap<>();
+ Map<String, String> expectedInnerMap = new HashMap<>();
+ expectedInnerMap.put(KEY2, VALUE);
+ expectedOverrides.put(NAMESPACE2, expectedInnerMap);
+
+ assertThat(DeviceConfig.getUnderlyingValuesForOverriddenFlags())
+ .isEqualTo(expectedOverrides);
}
@Test
diff --git a/core/tests/coretests/src/android/view/ImeInsetsSourceConsumerTest.java b/core/tests/coretests/src/android/view/ImeInsetsSourceConsumerTest.java
index f45db23ace76..8c93fbbc6b47 100644
--- a/core/tests/coretests/src/android/view/ImeInsetsSourceConsumerTest.java
+++ b/core/tests/coretests/src/android/view/ImeInsetsSourceConsumerTest.java
@@ -16,7 +16,7 @@
package android.view;
-import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
+import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
import static android.view.InsetsSource.ID_IME;
import static android.view.WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
@@ -81,8 +81,7 @@ public class ImeInsetsSourceConsumerTest {
Insets.of(10, 10, 10, 10), rect, rect, rect, rect));
mController.calculateInsets(
false,
- false,
- TYPE_APPLICATION, WINDOWING_MODE_UNDEFINED,
+ TYPE_APPLICATION, ACTIVITY_TYPE_UNDEFINED,
SOFT_INPUT_ADJUST_RESIZE, 0, 0);
mImeConsumer = mController.getImeSourceConsumer();
});
diff --git a/core/tests/coretests/src/android/view/InsetsControllerTest.java b/core/tests/coretests/src/android/view/InsetsControllerTest.java
index b8f0d5c82eac..1568174e1955 100644
--- a/core/tests/coretests/src/android/view/InsetsControllerTest.java
+++ b/core/tests/coretests/src/android/view/InsetsControllerTest.java
@@ -16,7 +16,7 @@
package android.view;
-import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
+import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
import static android.view.InsetsController.ANIMATION_TYPE_HIDE;
import static android.view.InsetsController.ANIMATION_TYPE_NONE;
import static android.view.InsetsController.ANIMATION_TYPE_RESIZE;
@@ -171,8 +171,7 @@ public class InsetsControllerTest {
mController.onStateChanged(state);
mController.calculateInsets(
false,
- false,
- TYPE_APPLICATION, WINDOWING_MODE_UNDEFINED,
+ TYPE_APPLICATION, ACTIVITY_TYPE_UNDEFINED,
SOFT_INPUT_ADJUST_RESIZE, 0, 0);
mController.onFrameChanged(new Rect(0, 0, 100, 100));
});
diff --git a/core/tests/coretests/src/android/view/InsetsStateTest.java b/core/tests/coretests/src/android/view/InsetsStateTest.java
index b06cd39d9236..906d84ec96b6 100644
--- a/core/tests/coretests/src/android/view/InsetsStateTest.java
+++ b/core/tests/coretests/src/android/view/InsetsStateTest.java
@@ -16,8 +16,9 @@
package android.view;
-import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
-import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
+import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
+import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
+import static android.view.InsetsSource.FLAG_FORCE_CONSUMING;
import static android.view.InsetsSource.ID_IME;
import static android.view.InsetsState.ISIDE_BOTTOM;
import static android.view.InsetsState.ISIDE_TOP;
@@ -101,7 +102,7 @@ public class InsetsStateTest {
.setVisible(true);
SparseIntArray typeSideMap = new SparseIntArray();
WindowInsets insets = mState.calculateInsets(new Rect(0, 0, 100, 300), null, false,
- false, SOFT_INPUT_ADJUST_RESIZE, 0, 0, TYPE_APPLICATION, WINDOWING_MODE_UNDEFINED,
+ SOFT_INPUT_ADJUST_RESIZE, 0, 0, TYPE_APPLICATION, ACTIVITY_TYPE_UNDEFINED,
typeSideMap);
assertEquals(Insets.of(0, 100, 0, 100), insets.getSystemWindowInsets());
assertEquals(Insets.of(0, 100, 0, 100), insets.getInsets(Type.all()));
@@ -120,7 +121,7 @@ public class InsetsStateTest {
.setFrame(new Rect(0, 100, 100, 300))
.setVisible(true);
WindowInsets insets = mState.calculateInsets(new Rect(0, 0, 100, 300), null, false,
- false, SOFT_INPUT_ADJUST_RESIZE, 0, 0, TYPE_APPLICATION, WINDOWING_MODE_UNDEFINED,
+ SOFT_INPUT_ADJUST_RESIZE, 0, 0, TYPE_APPLICATION, ACTIVITY_TYPE_UNDEFINED,
null);
assertEquals(100, insets.getStableInsetBottom());
assertEquals(Insets.of(0, 0, 0, 100), insets.getInsetsIgnoringVisibility(systemBars()));
@@ -139,7 +140,7 @@ public class InsetsStateTest {
.setFrame(new Rect(80, 0, 100, 300))
.setVisible(true);
WindowInsets insets = mState.calculateInsets(new Rect(0, 0, 100, 300), null, false,
- false, 0, 0, 0, TYPE_APPLICATION, WINDOWING_MODE_UNDEFINED, null);
+ 0, 0, 0, TYPE_APPLICATION, ACTIVITY_TYPE_UNDEFINED, null);
assertEquals(Insets.of(0, 100, 20, 0), insets.getSystemWindowInsets());
assertEquals(Insets.of(0, 100, 0, 0), insets.getInsets(statusBars()));
assertEquals(Insets.of(0, 0, 20, 0), insets.getInsets(navigationBars()));
@@ -154,7 +155,7 @@ public class InsetsStateTest {
.setFrame(new Rect(80, 0, 100, 300))
.setVisible(true);
WindowInsets insets = mState.calculateInsets(new Rect(0, 0, 100, 300), null, false,
- false, 0, 0, 0, TYPE_APPLICATION, WINDOWING_MODE_UNDEFINED, null);
+ 0, 0, 0, TYPE_APPLICATION, ACTIVITY_TYPE_UNDEFINED, null);
assertEquals(Insets.of(0, 100, 20, 0), insets.getSystemWindowInsets());
assertEquals(Insets.of(0, 100, 0, 0), insets.getInsets(Type.statusBars()));
assertEquals(Insets.of(0, 0, 20, 0), insets.getInsets(Type.navigationBars()));
@@ -169,7 +170,7 @@ public class InsetsStateTest {
.setFrame(new Rect(0, 200, 100, 300))
.setVisible(true);
WindowInsets insets = mState.calculateInsets(new Rect(0, 0, 100, 300), null, false,
- false, SOFT_INPUT_ADJUST_NOTHING, 0, 0, TYPE_APPLICATION, WINDOWING_MODE_UNDEFINED,
+ SOFT_INPUT_ADJUST_NOTHING, 0, 0, TYPE_APPLICATION, ACTIVITY_TYPE_UNDEFINED,
null);
assertEquals(0, insets.getSystemWindowInsetBottom());
assertEquals(100, insets.getInsets(ime()).bottom);
@@ -185,12 +186,12 @@ public class InsetsStateTest {
.setFrame(new Rect(0, 200, 100, 300))
.setVisible(true);
WindowInsets insets = mState.calculateInsets(new Rect(0, 0, 100, 300), null, false,
- false, SOFT_INPUT_ADJUST_NOTHING, 0, SYSTEM_UI_FLAG_LAYOUT_STABLE, TYPE_APPLICATION,
- WINDOWING_MODE_UNDEFINED, null);
+ SOFT_INPUT_ADJUST_NOTHING, 0, SYSTEM_UI_FLAG_LAYOUT_STABLE, TYPE_APPLICATION,
+ ACTIVITY_TYPE_UNDEFINED, null);
assertEquals(100, insets.getSystemWindowInsetTop());
- insets = mState.calculateInsets(new Rect(0, 0, 100, 300), null, false, false,
+ insets = mState.calculateInsets(new Rect(0, 0, 100, 300), null, false,
SOFT_INPUT_ADJUST_NOTHING, 0, 0 /* legacySystemUiFlags */, TYPE_APPLICATION,
- WINDOWING_MODE_UNDEFINED, null);
+ ACTIVITY_TYPE_UNDEFINED, null);
assertEquals(0, insets.getSystemWindowInsetTop());
}
@@ -200,12 +201,12 @@ public class InsetsStateTest {
.setFrame(new Rect(0, 0, 100, 100))
.setVisible(false);
WindowInsets insets = mState.calculateInsets(new Rect(0, 0, 100, 300), null, false,
- false, SOFT_INPUT_ADJUST_NOTHING, FLAG_FULLSCREEN, SYSTEM_UI_FLAG_LAYOUT_STABLE,
- TYPE_APPLICATION, WINDOWING_MODE_UNDEFINED, null);
+ SOFT_INPUT_ADJUST_NOTHING, FLAG_FULLSCREEN, SYSTEM_UI_FLAG_LAYOUT_STABLE,
+ TYPE_APPLICATION, ACTIVITY_TYPE_UNDEFINED, null);
assertEquals(0, insets.getSystemWindowInsetTop());
- insets = mState.calculateInsets(new Rect(0, 0, 100, 300), null, false, false,
+ insets = mState.calculateInsets(new Rect(0, 0, 100, 300), null, false,
SOFT_INPUT_ADJUST_NOTHING, 0, 0 /* legacySystemUiFlags */, TYPE_APPLICATION,
- WINDOWING_MODE_UNDEFINED, null);
+ ACTIVITY_TYPE_UNDEFINED, null);
assertEquals(0, insets.getSystemWindowInsetTop());
}
@@ -213,22 +214,23 @@ public class InsetsStateTest {
public void testCalculateInsets_flagLayoutNoLimits() {
mState.getOrCreateSource(ID_STATUS_BAR, statusBars())
.setFrame(new Rect(0, 0, 100, 100))
- .setVisible(true);
+ .setVisible(true)
+ .setFlags(FLAG_FORCE_CONSUMING);
WindowInsets insets = mState.calculateInsets(new Rect(0, 0, 100, 300), null, false,
- false, SOFT_INPUT_ADJUST_NOTHING, FLAG_LAYOUT_NO_LIMITS,
- 0 /* legacySystemUiFlags */, TYPE_APPLICATION, WINDOWING_MODE_UNDEFINED, null);
+ SOFT_INPUT_ADJUST_NOTHING, FLAG_LAYOUT_NO_LIMITS,
+ 0 /* legacySystemUiFlags */, TYPE_APPLICATION, ACTIVITY_TYPE_UNDEFINED, null);
assertEquals(0, insets.getSystemWindowInsetTop());
insets = mState.calculateInsets(new Rect(0, 0, 100, 300), null, false,
- false, SOFT_INPUT_ADJUST_NOTHING, FLAG_LAYOUT_NO_LIMITS,
- 0 /* legacySystemUiFlags */, TYPE_SYSTEM_ERROR, WINDOWING_MODE_UNDEFINED, null);
+ SOFT_INPUT_ADJUST_NOTHING, FLAG_LAYOUT_NO_LIMITS,
+ 0 /* legacySystemUiFlags */, TYPE_SYSTEM_ERROR, ACTIVITY_TYPE_UNDEFINED, null);
assertEquals(100, insets.getSystemWindowInsetTop());
insets = mState.calculateInsets(new Rect(0, 0, 100, 300), null, false,
- false, SOFT_INPUT_ADJUST_NOTHING, FLAG_LAYOUT_NO_LIMITS,
- 0 /* legacySystemUiFlags */, TYPE_WALLPAPER, WINDOWING_MODE_UNDEFINED, null);
+ SOFT_INPUT_ADJUST_NOTHING, FLAG_LAYOUT_NO_LIMITS,
+ 0 /* legacySystemUiFlags */, TYPE_WALLPAPER, ACTIVITY_TYPE_UNDEFINED, null);
assertEquals(100, insets.getSystemWindowInsetTop());
insets = mState.calculateInsets(new Rect(0, 0, 100, 300), null, false,
- false, SOFT_INPUT_ADJUST_NOTHING, FLAG_LAYOUT_NO_LIMITS,
- 0 /* legacySystemUiFlags */, TYPE_APPLICATION, WINDOWING_MODE_FREEFORM, null);
+ SOFT_INPUT_ADJUST_NOTHING, FLAG_LAYOUT_NO_LIMITS,
+ 0 /* legacySystemUiFlags */, TYPE_APPLICATION, ACTIVITY_TYPE_STANDARD, null);
assertEquals(100, insets.getSystemWindowInsetTop());
}
@@ -243,7 +245,7 @@ public class InsetsStateTest {
.setVisible(true);
Insets visibleInsets = mState.calculateVisibleInsets(
- new Rect(0, 0, 100, 400), TYPE_APPLICATION, WINDOWING_MODE_UNDEFINED,
+ new Rect(0, 0, 100, 400), TYPE_APPLICATION, ACTIVITY_TYPE_UNDEFINED,
SOFT_INPUT_ADJUST_NOTHING, 0 /* windowFlags */);
assertEquals(Insets.of(0, 300, 0, 0), visibleInsets);
}
@@ -255,7 +257,7 @@ public class InsetsStateTest {
.setVisible(true);
Insets visibleInsets = mState.calculateVisibleInsets(
- new Rect(0, 0, 150, 400), TYPE_APPLICATION, WINDOWING_MODE_UNDEFINED,
+ new Rect(0, 0, 150, 400), TYPE_APPLICATION, ACTIVITY_TYPE_UNDEFINED,
SOFT_INPUT_ADJUST_NOTHING, 0 /* windowFlags */);
assertEquals(Insets.of(0, 300, 0, 0), visibleInsets);
}
@@ -269,7 +271,7 @@ public class InsetsStateTest {
.setFrame(new Rect(80, 0, 100, 300))
.setVisible(true);
WindowInsets insets = mState.calculateInsets(new Rect(0, 0, 100, 300), null, false,
- false, 0, 0, 0, TYPE_APPLICATION, WINDOWING_MODE_UNDEFINED, null);
+ 0, 0, 0, TYPE_APPLICATION, ACTIVITY_TYPE_UNDEFINED, null);
assertEquals(Insets.of(0, 100, 20, 0), insets.getSystemWindowInsets());
assertEquals(Insets.of(0, 100, 0, 0), insets.getInsets(statusBars()));
assertEquals(Insets.of(0, 0, 20, 0), insets.getInsets(navigationBars()));
@@ -284,7 +286,7 @@ public class InsetsStateTest {
.setFrame(new Rect(80, 0, 100, 300))
.setVisible(true);
WindowInsets insets = mState.calculateInsets(new Rect(0, 0, 100, 300), null, false,
- false, 0, 0, 0, TYPE_APPLICATION, WINDOWING_MODE_UNDEFINED, null);
+ 0, 0, 0, TYPE_APPLICATION, ACTIVITY_TYPE_UNDEFINED, null);
assertEquals(Insets.of(0, 100, 20, 0), insets.getSystemWindowInsets());
assertEquals(Insets.of(0, 100, 0, 0), insets.getInsets(statusBars()));
assertEquals(Insets.of(0, 0, 20, 0), insets.getInsets(navigationBars()));
@@ -292,11 +294,11 @@ public class InsetsStateTest {
@Test
public void testCalculateInsets_emptyIme() {
- WindowInsets insets1 = mState.calculateInsets(new Rect(), null, false, false,
- SOFT_INPUT_ADJUST_NOTHING, 0, 0, TYPE_APPLICATION, WINDOWING_MODE_UNDEFINED, null);
+ WindowInsets insets1 = mState.calculateInsets(new Rect(), null, false,
+ SOFT_INPUT_ADJUST_NOTHING, 0, 0, TYPE_APPLICATION, ACTIVITY_TYPE_UNDEFINED, null);
mState.getOrCreateSource(ID_IME, ime());
- WindowInsets insets2 = mState.calculateInsets(new Rect(), null, false, false,
- SOFT_INPUT_ADJUST_NOTHING, 0, 0, TYPE_APPLICATION, WINDOWING_MODE_UNDEFINED, null);
+ WindowInsets insets2 = mState.calculateInsets(new Rect(), null, false,
+ SOFT_INPUT_ADJUST_NOTHING, 0, 0, TYPE_APPLICATION, ACTIVITY_TYPE_UNDEFINED, null);
assertEquals(Insets.NONE, insets1.getInsets(ime()));
assertEquals(Insets.NONE, insets2.getInsets(ime()));
assertEquals(insets1, insets2);
@@ -311,8 +313,8 @@ public class InsetsStateTest {
.setFrame(new Rect(0, 200, 100, 300))
.setVisible(true);
mState.removeSource(ID_IME);
- WindowInsets insets = mState.calculateInsets(new Rect(0, 0, 100, 300), null, false, false,
- SOFT_INPUT_ADJUST_RESIZE, 0, 0, TYPE_APPLICATION, WINDOWING_MODE_UNDEFINED, null);
+ WindowInsets insets = mState.calculateInsets(new Rect(0, 0, 100, 300), null, false,
+ SOFT_INPUT_ADJUST_RESIZE, 0, 0, TYPE_APPLICATION, ACTIVITY_TYPE_UNDEFINED, null);
assertEquals(0, insets.getSystemWindowInsetBottom());
}
@@ -527,7 +529,7 @@ public class InsetsStateTest {
.setFrame(new Rect(0, 100, 100, 300))
.setVisible(true);
Insets visibleInsets = mState.calculateVisibleInsets(
- new Rect(0, 0, 100, 300), TYPE_APPLICATION, WINDOWING_MODE_UNDEFINED,
+ new Rect(0, 0, 100, 300), TYPE_APPLICATION, ACTIVITY_TYPE_UNDEFINED,
SOFT_INPUT_ADJUST_PAN, 0 /* windowFlags */);
assertEquals(Insets.of(0, 100, 0, 100), visibleInsets);
}
@@ -546,7 +548,7 @@ public class InsetsStateTest {
.setFrame(new Rect(0, 100, 100, 300))
.setVisible(true);
Insets visibleInsets = mState.calculateVisibleInsets(
- new Rect(0, 0, 100, 300), TYPE_APPLICATION, WINDOWING_MODE_UNDEFINED,
+ new Rect(0, 0, 100, 300), TYPE_APPLICATION, ACTIVITY_TYPE_UNDEFINED,
SOFT_INPUT_ADJUST_NOTHING, 0 /* windowFlags */);
assertEquals(Insets.of(0, 100, 0, 0), visibleInsets);
}
@@ -565,7 +567,7 @@ public class InsetsStateTest {
.setFrame(new Rect(0, 100, 100, 300))
.setVisible(true);
Insets visibleInsets = mState.calculateVisibleInsets(
- new Rect(0, 0, 100, 300), TYPE_APPLICATION, WINDOWING_MODE_UNDEFINED,
+ new Rect(0, 0, 100, 300), TYPE_APPLICATION, ACTIVITY_TYPE_UNDEFINED,
SOFT_INPUT_ADJUST_PAN, FLAG_LAYOUT_NO_LIMITS);
assertEquals(Insets.NONE, visibleInsets);
}
@@ -599,8 +601,8 @@ public class InsetsStateTest {
new Rect(0, 0, 1, 2),
new Rect(197, 296, 200, 300),
new Rect(197, 296, 200, 300)));
- DisplayCutout cutout = mState.calculateInsets(new Rect(1, 1, 199, 300), null, false, false,
- SOFT_INPUT_ADJUST_UNSPECIFIED, 0, 0, TYPE_APPLICATION, WINDOWING_MODE_UNDEFINED,
+ DisplayCutout cutout = mState.calculateInsets(new Rect(1, 1, 199, 300), null, false,
+ SOFT_INPUT_ADJUST_UNSPECIFIED, 0, 0, TYPE_APPLICATION, ACTIVITY_TYPE_UNDEFINED,
new SparseIntArray()).getDisplayCutout();
assertEquals(0, cutout.getSafeInsetLeft());
assertEquals(1, cutout.getSafeInsetTop());
@@ -625,8 +627,8 @@ public class InsetsStateTest {
new RoundedCorner(POSITION_BOTTOM_RIGHT, 20, 180, 380),
new RoundedCorner(POSITION_BOTTOM_LEFT, 20, 20, 380)));
WindowInsets windowInsets = mState.calculateInsets(new Rect(1, 2, 197, 396), null, false,
- false, SOFT_INPUT_ADJUST_UNSPECIFIED, 0, 0, TYPE_APPLICATION,
- WINDOWING_MODE_UNDEFINED, new SparseIntArray());
+ SOFT_INPUT_ADJUST_UNSPECIFIED, 0, 0, TYPE_APPLICATION,
+ ACTIVITY_TYPE_UNDEFINED, new SparseIntArray());
assertEquals(new RoundedCorner(POSITION_TOP_LEFT, 10, 9, 8),
windowInsets.getRoundedCorner(POSITION_TOP_LEFT));
assertEquals(new RoundedCorner(POSITION_TOP_RIGHT, 10, 189, 8),
@@ -642,8 +644,8 @@ public class InsetsStateTest {
mState.setDisplayFrame(new Rect(0, 0, 200, 400));
mState.setDisplayShape(DisplayShape.createDefaultDisplayShape(200, 400, false));
WindowInsets windowInsets = mState.calculateInsets(new Rect(10, 20, 200, 400), null, false,
- false, SOFT_INPUT_ADJUST_UNSPECIFIED, 0, 0, TYPE_APPLICATION,
- WINDOWING_MODE_UNDEFINED, new SparseIntArray());
+ SOFT_INPUT_ADJUST_UNSPECIFIED, 0, 0, TYPE_APPLICATION,
+ ACTIVITY_TYPE_UNDEFINED, new SparseIntArray());
final DisplayShape expect =
DisplayShape.createDefaultDisplayShape(200, 400, false).setOffset(-10, -20);
diff --git a/core/tests/vibrator/src/android/os/vibrator/persistence/ParsedVibrationTest.java b/core/tests/vibrator/src/android/os/vibrator/persistence/ParsedVibrationTest.java
index 274c25a17f58..94298dcd2c74 100644
--- a/core/tests/vibrator/src/android/os/vibrator/persistence/ParsedVibrationTest.java
+++ b/core/tests/vibrator/src/android/os/vibrator/persistence/ParsedVibrationTest.java
@@ -92,18 +92,18 @@ public class ParsedVibrationTest {
}
@Test
- public void testGetVibrationEffectListForTesting() {
+ public void testGetVibrationEffects() {
ParsedVibration parsedVibration =
new ParsedVibration(List.of(mEffect1, mEffect2, mEffect3));
- assertThat(parsedVibration.getVibrationEffectListForTesting())
+ assertThat(parsedVibration.getVibrationEffects())
.containsExactly(mEffect1, mEffect2, mEffect3)
.inOrder();
parsedVibration = new ParsedVibration(List.of(mEffect1));
- assertThat(parsedVibration.getVibrationEffectListForTesting()).containsExactly(mEffect1);
+ assertThat(parsedVibration.getVibrationEffects()).containsExactly(mEffect1);
parsedVibration = new ParsedVibration(List.of());
- assertThat(parsedVibration.getVibrationEffectListForTesting()).isEmpty();
+ assertThat(parsedVibration.getVibrationEffects()).isEmpty();
}
private Subject assertThatResolution(
diff --git a/core/tests/vibrator/src/android/os/vibrator/persistence/VibrationEffectXmlSerializationTest.java b/core/tests/vibrator/src/android/os/vibrator/persistence/VibrationEffectXmlSerializationTest.java
index d73b5cb5713b..2814a5f5366c 100644
--- a/core/tests/vibrator/src/android/os/vibrator/persistence/VibrationEffectXmlSerializationTest.java
+++ b/core/tests/vibrator/src/android/os/vibrator/persistence/VibrationEffectXmlSerializationTest.java
@@ -363,8 +363,7 @@ public class VibrationEffectXmlSerializationTest {
private void assertParseDocumentSucceeds(String xml, int flags, VibrationEffect... effects)
throws Exception {
- assertThat(parseDocument(xml, flags).getVibrationEffectListForTesting())
- .containsExactly(effects);
+ assertThat(parseDocument(xml, flags).getVibrationEffects()).containsExactly(effects);
}
/**
@@ -381,8 +380,7 @@ public class VibrationEffectXmlSerializationTest {
String tagName = parser.getName();
assertThat(Set.of("vibration", "vibration-select")).contains(tagName);
- assertThat(parseElement(parser, flags).getVibrationEffectListForTesting())
- .containsExactly(effects);
+ assertThat(parseElement(parser, flags).getVibrationEffects()).containsExactly(effects);
assertThat(parser.getEventType()).isEqualTo(XmlPullParser.END_TAG);
assertThat(parser.getName()).isEqualTo(tagName);
}
diff --git a/graphics/java/android/graphics/Typeface.java b/graphics/java/android/graphics/Typeface.java
index 9fb627fcc501..4c4e8fa9c088 100644
--- a/graphics/java/android/graphics/Typeface.java
+++ b/graphics/java/android/graphics/Typeface.java
@@ -1475,7 +1475,10 @@ public class Typeface {
String locale = SystemProperties.get("persist.sys.locale", "en-US");
String script = ULocale.addLikelySubtags(ULocale.forLanguageTag(locale)).getScript();
- FontConfig config = SystemFonts.getSystemPreinstalledFontConfig();
+ // The feature flag cannot be referred from Zygote. Use legacy fonts.xml for preloading font
+ // files.
+ // TODO(nona): Use new XML file once the feature is fully launched.
+ FontConfig config = SystemFonts.getSystemPreinstalledFontConfigFromLegacyXml();
for (int i = 0; i < config.getFontFamilies().size(); ++i) {
FontConfig.FontFamily family = config.getFontFamilies().get(i);
if (!family.getLocaleList().isEmpty()) {
diff --git a/graphics/java/android/graphics/fonts/SystemFonts.java b/graphics/java/android/graphics/fonts/SystemFonts.java
index 36bfb98e726b..9810022abfed 100644
--- a/graphics/java/android/graphics/fonts/SystemFonts.java
+++ b/graphics/java/android/graphics/fonts/SystemFonts.java
@@ -48,6 +48,8 @@ public final class SystemFonts {
private static final String TAG = "SystemFonts";
private static final String FONTS_XML = "/system/etc/font_fallback.xml";
+ private static final String LEGACY_FONTS_XML = "/system/etc/fonts.xml";
+
/** @hide */
public static final String SYSTEM_FONT_DIR = "/system/fonts/";
private static final String OEM_XML = "/product/etc/fonts_customization.xml";
@@ -230,7 +232,13 @@ public final class SystemFonts {
long lastModifiedDate,
int configVersion
) {
- return getSystemFontConfigInternal(FONTS_XML, SYSTEM_FONT_DIR, OEM_XML, OEM_FONT_DIR,
+ final String fontsXml;
+ if (com.android.text.flags.Flags.deprecateFontsXml()) {
+ fontsXml = FONTS_XML;
+ } else {
+ fontsXml = LEGACY_FONTS_XML;
+ }
+ return getSystemFontConfigInternal(fontsXml, SYSTEM_FONT_DIR, OEM_XML, OEM_FONT_DIR,
updatableFontMap, lastModifiedDate, configVersion);
}
@@ -255,10 +263,24 @@ public final class SystemFonts {
* @hide
*/
public static @NonNull FontConfig getSystemPreinstalledFontConfig() {
- return getSystemFontConfigInternal(FONTS_XML, SYSTEM_FONT_DIR, OEM_XML, OEM_FONT_DIR, null,
+ final String fontsXml;
+ if (com.android.text.flags.Flags.deprecateFontsXml()) {
+ fontsXml = FONTS_XML;
+ } else {
+ fontsXml = LEGACY_FONTS_XML;
+ }
+ return getSystemFontConfigInternal(fontsXml, SYSTEM_FONT_DIR, OEM_XML, OEM_FONT_DIR, null,
0, 0);
}
+ /**
+ * @hide
+ */
+ public static @NonNull FontConfig getSystemPreinstalledFontConfigFromLegacyXml() {
+ return getSystemFontConfigInternal(LEGACY_FONTS_XML, SYSTEM_FONT_DIR, OEM_XML, OEM_FONT_DIR,
+ null, 0, 0);
+ }
+
/* package */ static @NonNull FontConfig getSystemFontConfigInternal(
@NonNull String fontsXml,
@NonNull String systemFontDir,
diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/WindowExtensionsImpl.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/WindowExtensionsImpl.java
index 55eabb039c01..c3d8f9a99d79 100644
--- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/WindowExtensionsImpl.java
+++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/WindowExtensionsImpl.java
@@ -16,12 +16,14 @@
package androidx.window.extensions;
+import android.app.ActivityTaskManager;
import android.app.ActivityThread;
import android.app.Application;
import android.content.Context;
import android.window.TaskFragmentOrganizer;
import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
import androidx.window.common.DeviceStateManagerFoldingFeatureProducer;
import androidx.window.common.RawFoldingFeatureProducer;
import androidx.window.extensions.area.WindowAreaComponent;
@@ -111,9 +113,13 @@ public class WindowExtensionsImpl implements WindowExtensions {
* {@link WindowExtensions#getWindowLayoutComponent()}.
* @return {@link ActivityEmbeddingComponent} OEM implementation.
*/
- @NonNull
+ @Nullable
public ActivityEmbeddingComponent getActivityEmbeddingComponent() {
if (mSplitController == null) {
+ if (!ActivityTaskManager.supportsMultiWindow(getApplication())) {
+ // Disable AE for device that doesn't support multi window.
+ return null;
+ }
synchronized (mLock) {
if (mSplitController == null) {
mSplitController = new SplitController(
diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/layout/WindowLayoutComponentImpl.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/layout/WindowLayoutComponentImpl.java
index ccf95527efea..e03e1ecd6015 100644
--- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/layout/WindowLayoutComponentImpl.java
+++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/layout/WindowLayoutComponentImpl.java
@@ -319,13 +319,17 @@ public class WindowLayoutComponentImpl implements WindowLayoutComponent {
return features;
}
+ // We will transform the feature bounds to the Activity window, so using the rotation
+ // from the same source (WindowConfiguration) to make sure they are synchronized.
+ final int rotation = windowConfiguration.getDisplayRotation();
+
for (CommonFoldingFeature baseFeature : storedFeatures) {
Integer state = convertToExtensionState(baseFeature.getState());
if (state == null) {
continue;
}
Rect featureRect = baseFeature.getRect();
- rotateRectToDisplayRotation(displayId, featureRect);
+ rotateRectToDisplayRotation(displayId, rotation, featureRect);
transformToWindowSpaceRect(windowConfiguration, featureRect);
if (isZero(featureRect)) {
diff --git a/libs/WindowManager/Jetpack/src/androidx/window/sidecar/SampleSidecarImpl.java b/libs/WindowManager/Jetpack/src/androidx/window/sidecar/SampleSidecarImpl.java
index 5bfb0ebdcaa8..15a329bd9509 100644
--- a/libs/WindowManager/Jetpack/src/androidx/window/sidecar/SampleSidecarImpl.java
+++ b/libs/WindowManager/Jetpack/src/androidx/window/sidecar/SampleSidecarImpl.java
@@ -120,10 +120,12 @@ class SampleSidecarImpl extends StubSidecar {
}
List<SidecarDisplayFeature> features = new ArrayList<>();
+ final int rotation = activity.getResources().getConfiguration().windowConfiguration
+ .getDisplayRotation();
for (CommonFoldingFeature baseFeature : mStoredFeatures) {
SidecarDisplayFeature feature = new SidecarDisplayFeature();
Rect featureRect = baseFeature.getRect();
- rotateRectToDisplayRotation(displayId, featureRect);
+ rotateRectToDisplayRotation(displayId, rotation, featureRect);
transformToWindowSpaceRect(activity, featureRect);
feature.setRect(featureRect);
feature.setType(baseFeature.getType());
diff --git a/libs/WindowManager/Jetpack/src/androidx/window/util/ExtensionHelper.java b/libs/WindowManager/Jetpack/src/androidx/window/util/ExtensionHelper.java
index 9e2611f392a3..6b193fc53935 100644
--- a/libs/WindowManager/Jetpack/src/androidx/window/util/ExtensionHelper.java
+++ b/libs/WindowManager/Jetpack/src/androidx/window/util/ExtensionHelper.java
@@ -16,8 +16,6 @@
package androidx.window.util;
-import static android.view.Surface.ROTATION_0;
-import static android.view.Surface.ROTATION_180;
import static android.view.Surface.ROTATION_270;
import static android.view.Surface.ROTATION_90;
@@ -25,12 +23,14 @@ import android.app.WindowConfiguration;
import android.content.Context;
import android.graphics.Rect;
import android.hardware.display.DisplayManagerGlobal;
+import android.util.RotationUtils;
import android.view.DisplayInfo;
import android.view.Surface;
import android.view.WindowManager;
import androidx.annotation.NonNull;
import androidx.annotation.UiContext;
+import androidx.annotation.VisibleForTesting;
/**
* Util class for both Sidecar and Extensions.
@@ -44,47 +44,41 @@ public final class ExtensionHelper {
/**
* Rotates the input rectangle specified in default display orientation to the current display
* rotation.
+ *
+ * @param displayId the display id.
+ * @param rotation the target rotation relative to the default display orientation.
+ * @param inOutRect the input/output Rect as specified in the default display orientation.
*/
- public static void rotateRectToDisplayRotation(int displayId, Rect inOutRect) {
- DisplayManagerGlobal dmGlobal = DisplayManagerGlobal.getInstance();
- DisplayInfo displayInfo = dmGlobal.getDisplayInfo(displayId);
- int rotation = displayInfo.rotation;
+ public static void rotateRectToDisplayRotation(
+ int displayId, @Surface.Rotation int rotation, @NonNull Rect inOutRect) {
+ final DisplayManagerGlobal dmGlobal = DisplayManagerGlobal.getInstance();
+ final DisplayInfo displayInfo = dmGlobal.getDisplayInfo(displayId);
- boolean isSideRotation = rotation == ROTATION_90 || rotation == ROTATION_270;
- int displayWidth = isSideRotation ? displayInfo.logicalHeight : displayInfo.logicalWidth;
- int displayHeight = isSideRotation ? displayInfo.logicalWidth : displayInfo.logicalHeight;
-
- inOutRect.intersect(0, 0, displayWidth, displayHeight);
-
- rotateBounds(inOutRect, displayWidth, displayHeight, rotation);
+ rotateRectToDisplayRotation(displayInfo, rotation, inOutRect);
}
- /**
- * Rotates the input rectangle within parent bounds for a given delta.
- */
- private static void rotateBounds(Rect inOutRect, int parentWidth, int parentHeight,
- @Surface.Rotation int delta) {
- int origLeft = inOutRect.left;
- switch (delta) {
- case ROTATION_0:
- return;
- case ROTATION_90:
- inOutRect.left = inOutRect.top;
- inOutRect.top = parentWidth - inOutRect.right;
- inOutRect.right = inOutRect.bottom;
- inOutRect.bottom = parentWidth - origLeft;
- return;
- case ROTATION_180:
- inOutRect.left = parentWidth - inOutRect.right;
- inOutRect.right = parentWidth - origLeft;
- return;
- case ROTATION_270:
- inOutRect.left = parentHeight - inOutRect.bottom;
- inOutRect.bottom = inOutRect.right;
- inOutRect.right = parentHeight - inOutRect.top;
- inOutRect.top = origLeft;
- return;
+ @VisibleForTesting
+ static void rotateRectToDisplayRotation(@NonNull DisplayInfo displayInfo,
+ @Surface.Rotation int rotation, @NonNull Rect inOutRect) {
+ // The inOutRect is specified in the default display orientation, so here we need to get
+ // the display width and height in the default orientation to perform the intersection and
+ // rotation.
+ final boolean isSideRotation =
+ displayInfo.rotation == ROTATION_90 || displayInfo.rotation == ROTATION_270;
+ final int baseDisplayWidth =
+ isSideRotation ? displayInfo.logicalHeight : displayInfo.logicalWidth;
+ final int baseDisplayHeight =
+ isSideRotation ? displayInfo.logicalWidth : displayInfo.logicalHeight;
+
+ final boolean success = inOutRect.intersect(0, 0, baseDisplayWidth, baseDisplayHeight);
+ if (!success) {
+ throw new IllegalArgumentException("inOutRect must intersect with the display."
+ + " inOutRect: " + inOutRect
+ + ", baseDisplayWidth: " + baseDisplayWidth
+ + ", baseDisplayHeight: " + baseDisplayHeight);
}
+
+ RotationUtils.rotateBounds(inOutRect, baseDisplayWidth, baseDisplayHeight, rotation);
}
/** Transforms rectangle from absolute coordinate space to the window coordinate space. */
diff --git a/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/WindowExtensionsTest.java b/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/WindowExtensionsTest.java
index d189ae2cf72e..068269297193 100644
--- a/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/WindowExtensionsTest.java
+++ b/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/WindowExtensionsTest.java
@@ -16,8 +16,11 @@
package androidx.window.extensions;
+import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
+
import static com.google.common.truth.Truth.assertThat;
+import android.app.ActivityTaskManager;
import android.platform.test.annotations.Presubmit;
import androidx.test.ext.junit.runners.AndroidJUnit4;
@@ -29,7 +32,7 @@ import org.junit.Test;
import org.junit.runner.RunWith;
/**
- * Test class for {@link WindowExtensionsTest}.
+ * Test class for {@link WindowExtensions}.
*
* Build/Install/Run:
* atest WMJetpackUnitTests:WindowExtensionsTest
@@ -52,7 +55,11 @@ public class WindowExtensionsTest {
@Test
public void testGetActivityEmbeddingComponent() {
- assertThat(mExtensions.getActivityEmbeddingComponent()).isNotNull();
+ if (ActivityTaskManager.supportsMultiWindow(getInstrumentation().getContext())) {
+ assertThat(mExtensions.getActivityEmbeddingComponent()).isNotNull();
+ } else {
+ assertThat(mExtensions.getActivityEmbeddingComponent()).isNull();
+ }
}
@Test
diff --git a/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/util/ExtensionHelperTest.java b/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/util/ExtensionHelperTest.java
new file mode 100644
index 000000000000..ae783de228fb
--- /dev/null
+++ b/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/util/ExtensionHelperTest.java
@@ -0,0 +1,130 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.window.util;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertThrows;
+
+import android.graphics.Rect;
+import android.platform.test.annotations.Presubmit;
+import android.view.DisplayInfo;
+import android.view.Surface;
+
+import androidx.annotation.NonNull;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+import androidx.test.filters.SmallTest;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+/**
+ * Test class for {@link ExtensionHelper}.
+ *
+ * Build/Install/Run:
+ * atest WMJetpackUnitTests:ExtensionHelperTest
+ */
+@Presubmit
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class ExtensionHelperTest {
+
+ private static final int MOCK_DISPLAY_HEIGHT = 1000;
+ private static final int MOCK_DISPLAY_WIDTH = 2000;
+ private static final int MOCK_FEATURE_LEFT = 100;
+ private static final int MOCK_FEATURE_RIGHT = 200;
+
+ private static final int[] ROTATIONS = {
+ Surface.ROTATION_0,
+ Surface.ROTATION_90,
+ Surface.ROTATION_180,
+ Surface.ROTATION_270
+ };
+
+ private static final DisplayInfo[] MOCK_DISPLAY_INFOS = {
+ getMockDisplayInfo(Surface.ROTATION_0),
+ getMockDisplayInfo(Surface.ROTATION_90),
+ getMockDisplayInfo(Surface.ROTATION_180),
+ getMockDisplayInfo(Surface.ROTATION_270),
+ };
+
+ @Test
+ public void testRotateRectToDisplayRotation() {
+ for (int rotation : ROTATIONS) {
+ final Rect expectedResult = getExpectedFeatureRectAfterRotation(rotation);
+ // The method should return correctly rotated Rect even if the requested rotation value
+ // differs from the rotation in DisplayInfo. This is because the WindowConfiguration is
+ // not always synced with DisplayInfo.
+ for (DisplayInfo displayInfo : MOCK_DISPLAY_INFOS) {
+ final Rect rect = getMockFeatureRect();
+ ExtensionHelper.rotateRectToDisplayRotation(displayInfo, rotation, rect);
+ assertEquals(
+ "Result Rect should equal to expected for rotation: " + rotation
+ + "; displayInfo: " + displayInfo,
+ expectedResult, rect);
+ }
+ }
+ }
+
+ @Test
+ public void testRotateRectToDisplayRotation_invalidInputRect() {
+ final Rect invalidRect = new Rect(
+ MOCK_DISPLAY_WIDTH + 10, 0, MOCK_DISPLAY_WIDTH + 10, MOCK_DISPLAY_HEIGHT);
+ assertThrows(IllegalArgumentException.class,
+ () -> ExtensionHelper.rotateRectToDisplayRotation(
+ MOCK_DISPLAY_INFOS[0], ROTATIONS[0], invalidRect));
+ }
+
+
+ @NonNull
+ private static DisplayInfo getMockDisplayInfo(@Surface.Rotation int rotation) {
+ final DisplayInfo displayInfo = new DisplayInfo();
+ displayInfo.rotation = rotation;
+ if (rotation == Surface.ROTATION_0 || rotation == Surface.ROTATION_180) {
+ displayInfo.logicalWidth = MOCK_DISPLAY_WIDTH;
+ displayInfo.logicalHeight = MOCK_DISPLAY_HEIGHT;
+ } else {
+ displayInfo.logicalWidth = MOCK_DISPLAY_HEIGHT;
+ displayInfo.logicalHeight = MOCK_DISPLAY_WIDTH;
+ }
+ return displayInfo;
+ }
+
+ @NonNull
+ private static Rect getMockFeatureRect() {
+ return new Rect(MOCK_FEATURE_LEFT, 0, MOCK_FEATURE_RIGHT, MOCK_DISPLAY_HEIGHT);
+ }
+
+ @NonNull
+ private static Rect getExpectedFeatureRectAfterRotation(@Surface.Rotation int rotation) {
+ switch (rotation) {
+ case Surface.ROTATION_0:
+ return new Rect(
+ MOCK_FEATURE_LEFT, 0, MOCK_FEATURE_RIGHT, MOCK_DISPLAY_HEIGHT);
+ case Surface.ROTATION_90:
+ return new Rect(0, MOCK_DISPLAY_WIDTH - MOCK_FEATURE_RIGHT,
+ MOCK_DISPLAY_HEIGHT, MOCK_DISPLAY_WIDTH - MOCK_FEATURE_LEFT);
+ case Surface.ROTATION_180:
+ return new Rect(MOCK_DISPLAY_WIDTH - MOCK_FEATURE_RIGHT, 0,
+ MOCK_DISPLAY_WIDTH - MOCK_FEATURE_LEFT, MOCK_DISPLAY_HEIGHT);
+ case Surface.ROTATION_270:
+ return new Rect(0, MOCK_FEATURE_LEFT, MOCK_DISPLAY_HEIGHT,
+ MOCK_FEATURE_RIGHT);
+ default:
+ throw new IllegalArgumentException("Unknown rotation value: " + rotation);
+ }
+ }
+}
diff --git a/libs/WindowManager/Shell/res/values-af/strings.xml b/libs/WindowManager/Shell/res/values-af/strings.xml
index 1164d3778826..4f763425b601 100644
--- a/libs/WindowManager/Shell/res/values-af/strings.xml
+++ b/libs/WindowManager/Shell/res/values-af/strings.xml
@@ -76,10 +76,8 @@
<string name="bubbles_user_education_got_it" msgid="3382046149225428296">"Het dit"</string>
<string name="bubble_overflow_empty_title" msgid="2397251267073294968">"Geen onlangse borrels nie"</string>
<string name="bubble_overflow_empty_subtitle" msgid="2627417924958633713">"Onlangse borrels en borrels wat toegemaak is, sal hier verskyn"</string>
- <!-- no translation found for bubble_bar_education_manage_title (6148404487810835924) -->
- <skip />
- <!-- no translation found for bubble_bar_education_manage_text (3199732148641842038) -->
- <skip />
+ <string name="bubble_bar_education_manage_title" msgid="6148404487810835924">"Beheer borrels enige tyd"</string>
+ <string name="bubble_bar_education_manage_text" msgid="3199732148641842038">"Tik hier om te bestuur watter apps en gesprekke in borrels kan verskyn"</string>
<string name="notification_bubble_title" msgid="6082910224488253378">"Borrel"</string>
<string name="manage_bubbles_text" msgid="7730624269650594419">"Bestuur"</string>
<string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"Borrel is toegemaak."</string>
diff --git a/libs/WindowManager/Shell/res/values-am/strings.xml b/libs/WindowManager/Shell/res/values-am/strings.xml
index ffed367926e1..1e5f5f136315 100644
--- a/libs/WindowManager/Shell/res/values-am/strings.xml
+++ b/libs/WindowManager/Shell/res/values-am/strings.xml
@@ -76,10 +76,8 @@
<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>
- <!-- no translation found for bubble_bar_education_manage_title (6148404487810835924) -->
- <skip />
- <!-- no translation found for bubble_bar_education_manage_text (3199732148641842038) -->
- <skip />
+ <string name="bubble_bar_education_manage_title" msgid="6148404487810835924">"በማንኛውም ጊዜ ዓረፋዎችን ይቆጣጠሩ"</string>
+ <string name="bubble_bar_education_manage_text" msgid="3199732148641842038">"የትኛዎቹ መተግበሪያዎች እና ውይይቶች ዓረፋ መፍጠር እንደሚችሉ ለማስተዳደር እዚህ ጋር መታ ያድርጉ"</string>
<string name="notification_bubble_title" msgid="6082910224488253378">"አረፋ"</string>
<string name="manage_bubbles_text" msgid="7730624269650594419">"ያቀናብሩ"</string>
<string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"አረፋ ተሰናብቷል።"</string>
diff --git a/libs/WindowManager/Shell/res/values-ar/strings.xml b/libs/WindowManager/Shell/res/values-ar/strings.xml
index 4e9b76bc4948..9c52608a8d23 100644
--- a/libs/WindowManager/Shell/res/values-ar/strings.xml
+++ b/libs/WindowManager/Shell/res/values-ar/strings.xml
@@ -76,10 +76,8 @@
<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>
- <!-- no translation found for bubble_bar_education_manage_title (6148404487810835924) -->
- <skip />
- <!-- no translation found for bubble_bar_education_manage_text (3199732148641842038) -->
- <skip />
+ <string name="bubble_bar_education_manage_title" msgid="6148404487810835924">"التحكّم في إظهار الفقاعات في أي وقت"</string>
+ <string name="bubble_bar_education_manage_text" msgid="3199732148641842038">"انقر هنا للتحكّم في إظهار فقاعات التطبيقات والمحادثات التي تريدها."</string>
<string name="notification_bubble_title" msgid="6082910224488253378">"فقاعة"</string>
<string name="manage_bubbles_text" msgid="7730624269650594419">"إدارة"</string>
<string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"تم إغلاق الفقاعة."</string>
diff --git a/libs/WindowManager/Shell/res/values-as/strings.xml b/libs/WindowManager/Shell/res/values-as/strings.xml
index a583f349d1f1..e880b8744f40 100644
--- a/libs/WindowManager/Shell/res/values-as/strings.xml
+++ b/libs/WindowManager/Shell/res/values-as/strings.xml
@@ -76,10 +76,8 @@
<string name="bubbles_user_education_got_it" msgid="3382046149225428296">"বুজি পালোঁ"</string>
<string name="bubble_overflow_empty_title" msgid="2397251267073294968">"কোনো শেহতীয়া bubbles নাই"</string>
<string name="bubble_overflow_empty_subtitle" msgid="2627417924958633713">"শেহতীয়া bubbles আৰু অগ্ৰাহ্য কৰা bubbles ইয়াত প্ৰদর্শিত হ\'ব"</string>
- <!-- no translation found for bubble_bar_education_manage_title (6148404487810835924) -->
- <skip />
- <!-- no translation found for bubble_bar_education_manage_text (3199732148641842038) -->
- <skip />
+ <string name="bubble_bar_education_manage_title" msgid="6148404487810835924">"যিকোনো সময়তে বাবল নিয়ন্ত্ৰণ কৰক"</string>
+ <string name="bubble_bar_education_manage_text" msgid="3199732148641842038">"কোনবোৰ এপ্‌ আৰু বাৰ্তালাপ বাবল হ’ব পাৰে সেয়া পৰিচালনা কৰিবলৈ ইয়াত টিপক"</string>
<string name="notification_bubble_title" msgid="6082910224488253378">"বাবল"</string>
<string name="manage_bubbles_text" msgid="7730624269650594419">"পৰিচালনা কৰক"</string>
<string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"বাবল অগ্ৰাহ্য কৰা হৈছে"</string>
diff --git a/libs/WindowManager/Shell/res/values-az/strings.xml b/libs/WindowManager/Shell/res/values-az/strings.xml
index fb09258aef26..6e746fb761f0 100644
--- a/libs/WindowManager/Shell/res/values-az/strings.xml
+++ b/libs/WindowManager/Shell/res/values-az/strings.xml
@@ -76,10 +76,8 @@
<string name="bubbles_user_education_got_it" msgid="3382046149225428296">"Anladım"</string>
<string name="bubble_overflow_empty_title" msgid="2397251267073294968">"Yumrucuqlar yoxdur"</string>
<string name="bubble_overflow_empty_subtitle" msgid="2627417924958633713">"Son yumrucuqlar və buraxılmış yumrucuqlar burada görünəcək"</string>
- <!-- no translation found for bubble_bar_education_manage_title (6148404487810835924) -->
- <skip />
- <!-- no translation found for bubble_bar_education_manage_text (3199732148641842038) -->
- <skip />
+ <string name="bubble_bar_education_manage_title" msgid="6148404487810835924">"Yumrucuqları idarə edin"</string>
+ <string name="bubble_bar_education_manage_text" msgid="3199732148641842038">"Bura toxunaraq yumrucuq göstərəcək tətbiq və söhbətləri idarə edin"</string>
<string name="notification_bubble_title" msgid="6082910224488253378">"Qabarcıq"</string>
<string name="manage_bubbles_text" msgid="7730624269650594419">"İdarə edin"</string>
<string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"Qabarcıqdan imtina edilib."</string>
diff --git a/libs/WindowManager/Shell/res/values-b+sr+Latn/strings.xml b/libs/WindowManager/Shell/res/values-b+sr+Latn/strings.xml
index a9ba12e6508a..3be326907cd2 100644
--- a/libs/WindowManager/Shell/res/values-b+sr+Latn/strings.xml
+++ b/libs/WindowManager/Shell/res/values-b+sr+Latn/strings.xml
@@ -76,10 +76,8 @@
<string name="bubbles_user_education_got_it" msgid="3382046149225428296">"Važi"</string>
<string name="bubble_overflow_empty_title" msgid="2397251267073294968">"Nema nedavnih oblačića"</string>
<string name="bubble_overflow_empty_subtitle" msgid="2627417924958633713">"Ovde se prikazuju nedavni i odbačeni oblačići"</string>
- <!-- no translation found for bubble_bar_education_manage_title (6148404487810835924) -->
- <skip />
- <!-- no translation found for bubble_bar_education_manage_text (3199732148641842038) -->
- <skip />
+ <string name="bubble_bar_education_manage_title" msgid="6148404487810835924">"Kontrolišite oblačiće u svakom trenutku"</string>
+ <string name="bubble_bar_education_manage_text" msgid="3199732148641842038">"Dodirnite ovde i odredite koje aplikacije i konverzacije mogu da imaju oblačić"</string>
<string name="notification_bubble_title" msgid="6082910224488253378">"Oblačić"</string>
<string name="manage_bubbles_text" msgid="7730624269650594419">"Upravljajte"</string>
<string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"Oblačić je odbačen."</string>
diff --git a/libs/WindowManager/Shell/res/values-be/strings.xml b/libs/WindowManager/Shell/res/values-be/strings.xml
index eef363be387b..85ae1c10617c 100644
--- a/libs/WindowManager/Shell/res/values-be/strings.xml
+++ b/libs/WindowManager/Shell/res/values-be/strings.xml
@@ -76,10 +76,8 @@
<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>
- <!-- no translation found for bubble_bar_education_manage_title (6148404487810835924) -->
- <skip />
- <!-- no translation found for bubble_bar_education_manage_text (3199732148641842038) -->
- <skip />
+ <string name="bubble_bar_education_manage_title" msgid="6148404487810835924">"Кіруйце наладамі ўсплывальных апавяшчэнняў у любы час"</string>
+ <string name="bubble_bar_education_manage_text" msgid="3199732148641842038">"Каб кіраваць усплывальнымі апавяшчэннямі для праграм і размоў, націсніце тут"</string>
<string name="notification_bubble_title" msgid="6082910224488253378">"Усплывальнае апавяшчэнне"</string>
<string name="manage_bubbles_text" msgid="7730624269650594419">"Кіраваць"</string>
<string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"Усплывальнае апавяшчэнне адхілена."</string>
diff --git a/libs/WindowManager/Shell/res/values-bg/strings.xml b/libs/WindowManager/Shell/res/values-bg/strings.xml
index 281bd9d5f37d..640fb2e0ef92 100644
--- a/libs/WindowManager/Shell/res/values-bg/strings.xml
+++ b/libs/WindowManager/Shell/res/values-bg/strings.xml
@@ -76,10 +76,8 @@
<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>
- <!-- no translation found for bubble_bar_education_manage_title (6148404487810835924) -->
- <skip />
- <!-- no translation found for bubble_bar_education_manage_text (3199732148641842038) -->
- <skip />
+ <string name="bubble_bar_education_manage_title" msgid="6148404487810835924">"Управление на балончетата по всяко време"</string>
+ <string name="bubble_bar_education_manage_text" msgid="3199732148641842038">"Докоснете тук, за да управл. кои прил. и разговори могат да показват балончета"</string>
<string name="notification_bubble_title" msgid="6082910224488253378">"Балонче"</string>
<string name="manage_bubbles_text" msgid="7730624269650594419">"Управление"</string>
<string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"Балончето е отхвърлено."</string>
diff --git a/libs/WindowManager/Shell/res/values-bn/strings.xml b/libs/WindowManager/Shell/res/values-bn/strings.xml
index 3dae948f96ea..e7c8886a99be 100644
--- a/libs/WindowManager/Shell/res/values-bn/strings.xml
+++ b/libs/WindowManager/Shell/res/values-bn/strings.xml
@@ -76,10 +76,8 @@
<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>
- <!-- no translation found for bubble_bar_education_manage_title (6148404487810835924) -->
- <skip />
- <!-- no translation found for bubble_bar_education_manage_text (3199732148641842038) -->
- <skip />
+ <string name="bubble_bar_education_manage_title" msgid="6148404487810835924">"যেকোনও সময় বাবল নিয়ন্ত্রণ করুন"</string>
+ <string name="bubble_bar_education_manage_text" msgid="3199732148641842038">"কোন অ্যাপ ও কথোপকথনের জন্য বাবলের সুবিধা চান তা ম্যানেজ করতে এখানে ট্যাপ করুন"</string>
<string name="notification_bubble_title" msgid="6082910224488253378">"বাবল"</string>
<string name="manage_bubbles_text" msgid="7730624269650594419">"ম্যানেজ করুন"</string>
<string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"বাবল বাতিল করা হয়েছে।"</string>
diff --git a/libs/WindowManager/Shell/res/values-bs/strings.xml b/libs/WindowManager/Shell/res/values-bs/strings.xml
index 8b7eb6143fb3..1335f8d897be 100644
--- a/libs/WindowManager/Shell/res/values-bs/strings.xml
+++ b/libs/WindowManager/Shell/res/values-bs/strings.xml
@@ -76,10 +76,8 @@
<string name="bubbles_user_education_got_it" msgid="3382046149225428296">"Razumijem"</string>
<string name="bubble_overflow_empty_title" msgid="2397251267073294968">"Nema nedavnih oblačića"</string>
<string name="bubble_overflow_empty_subtitle" msgid="2627417924958633713">"Nedavni i odbačeni oblačići će se pojaviti ovdje"</string>
- <!-- no translation found for bubble_bar_education_manage_title (6148404487810835924) -->
- <skip />
- <!-- no translation found for bubble_bar_education_manage_text (3199732148641842038) -->
- <skip />
+ <string name="bubble_bar_education_manage_title" msgid="6148404487810835924">"Upravljajte oblačićima u svakom trenutku"</string>
+ <string name="bubble_bar_education_manage_text" msgid="3199732148641842038">"Dodirnite ovdje da upravljate time koje aplikacije i razgovori mogu imati oblačić"</string>
<string name="notification_bubble_title" msgid="6082910224488253378">"Oblačić"</string>
<string name="manage_bubbles_text" msgid="7730624269650594419">"Upravljaj"</string>
<string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"Oblačić je odbačen."</string>
diff --git a/libs/WindowManager/Shell/res/values-ca/strings.xml b/libs/WindowManager/Shell/res/values-ca/strings.xml
index 2250f9d7132a..22fc21c64e09 100644
--- a/libs/WindowManager/Shell/res/values-ca/strings.xml
+++ b/libs/WindowManager/Shell/res/values-ca/strings.xml
@@ -76,10 +76,8 @@
<string name="bubbles_user_education_got_it" msgid="3382046149225428296">"Entesos"</string>
<string name="bubble_overflow_empty_title" msgid="2397251267073294968">"No hi ha bombolles recents"</string>
<string name="bubble_overflow_empty_subtitle" msgid="2627417924958633713">"Les bombolles recents i les ignorades es mostraran aquí"</string>
- <!-- no translation found for bubble_bar_education_manage_title (6148404487810835924) -->
- <skip />
- <!-- no translation found for bubble_bar_education_manage_text (3199732148641842038) -->
- <skip />
+ <string name="bubble_bar_education_manage_title" msgid="6148404487810835924">"Controla les bombolles en qualsevol moment"</string>
+ <string name="bubble_bar_education_manage_text" msgid="3199732148641842038">"Toca aquí per gestionar quines aplicacions i converses poden fer servir bombolles"</string>
<string name="notification_bubble_title" msgid="6082910224488253378">"Bombolla"</string>
<string name="manage_bubbles_text" msgid="7730624269650594419">"Gestiona"</string>
<string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"La bombolla s\'ha ignorat."</string>
diff --git a/libs/WindowManager/Shell/res/values-cs/strings.xml b/libs/WindowManager/Shell/res/values-cs/strings.xml
index ebee2c181d58..a85fa7c9435d 100644
--- a/libs/WindowManager/Shell/res/values-cs/strings.xml
+++ b/libs/WindowManager/Shell/res/values-cs/strings.xml
@@ -76,10 +76,8 @@
<string name="bubbles_user_education_got_it" msgid="3382046149225428296">"OK"</string>
<string name="bubble_overflow_empty_title" msgid="2397251267073294968">"Žádné nedávné bubliny"</string>
<string name="bubble_overflow_empty_subtitle" msgid="2627417924958633713">"Zde se budou zobrazovat nedávné bubliny a zavřené bubliny"</string>
- <!-- no translation found for bubble_bar_education_manage_title (6148404487810835924) -->
- <skip />
- <!-- no translation found for bubble_bar_education_manage_text (3199732148641842038) -->
- <skip />
+ <string name="bubble_bar_education_manage_title" msgid="6148404487810835924">"Nastavení bublin můžete kdykoli upravit"</string>
+ <string name="bubble_bar_education_manage_text" msgid="3199732148641842038">"Klepnutím sem lze spravovat, které aplikace a konverzace mohou vytvářet bubliny"</string>
<string name="notification_bubble_title" msgid="6082910224488253378">"Bublina"</string>
<string name="manage_bubbles_text" msgid="7730624269650594419">"Spravovat"</string>
<string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"Bublina byla zavřena."</string>
diff --git a/libs/WindowManager/Shell/res/values-da/strings.xml b/libs/WindowManager/Shell/res/values-da/strings.xml
index 4e4624371ab9..cd621f802d91 100644
--- a/libs/WindowManager/Shell/res/values-da/strings.xml
+++ b/libs/WindowManager/Shell/res/values-da/strings.xml
@@ -76,10 +76,8 @@
<string name="bubbles_user_education_got_it" msgid="3382046149225428296">"OK"</string>
<string name="bubble_overflow_empty_title" msgid="2397251267073294968">"Ingen seneste bobler"</string>
<string name="bubble_overflow_empty_subtitle" msgid="2627417924958633713">"Nye bobler og afviste bobler vises her"</string>
- <!-- no translation found for bubble_bar_education_manage_title (6148404487810835924) -->
- <skip />
- <!-- no translation found for bubble_bar_education_manage_text (3199732148641842038) -->
- <skip />
+ <string name="bubble_bar_education_manage_title" msgid="6148404487810835924">"Administrer bobler når som helst"</string>
+ <string name="bubble_bar_education_manage_text" msgid="3199732148641842038">"Tryk her for at administrere, hvilke apps og samtaler der kan vises i bobler"</string>
<string name="notification_bubble_title" msgid="6082910224488253378">"Boble"</string>
<string name="manage_bubbles_text" msgid="7730624269650594419">"Administrer"</string>
<string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"Boblen blev lukket."</string>
diff --git a/libs/WindowManager/Shell/res/values-de/strings.xml b/libs/WindowManager/Shell/res/values-de/strings.xml
index 1d5182a14f97..366fdefc3013 100644
--- a/libs/WindowManager/Shell/res/values-de/strings.xml
+++ b/libs/WindowManager/Shell/res/values-de/strings.xml
@@ -76,10 +76,8 @@
<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>
- <!-- no translation found for bubble_bar_education_manage_title (6148404487810835924) -->
- <skip />
- <!-- no translation found for bubble_bar_education_manage_text (3199732148641842038) -->
- <skip />
+ <string name="bubble_bar_education_manage_title" msgid="6148404487810835924">"Bubble-Einstellungen festlegen"</string>
+ <string name="bubble_bar_education_manage_text" msgid="3199732148641842038">"Tippe hier, um zu verwalten, welche Apps und Unterhaltungen als Bubble angezeigt werden können"</string>
<string name="notification_bubble_title" msgid="6082910224488253378">"Bubble"</string>
<string name="manage_bubbles_text" msgid="7730624269650594419">"Verwalten"</string>
<string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"Bubble verworfen."</string>
diff --git a/libs/WindowManager/Shell/res/values-el/strings.xml b/libs/WindowManager/Shell/res/values-el/strings.xml
index 34a6a071286d..a449b9f3c665 100644
--- a/libs/WindowManager/Shell/res/values-el/strings.xml
+++ b/libs/WindowManager/Shell/res/values-el/strings.xml
@@ -76,10 +76,8 @@
<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>
- <!-- no translation found for bubble_bar_education_manage_title (6148404487810835924) -->
- <skip />
- <!-- no translation found for bubble_bar_education_manage_text (3199732148641842038) -->
- <skip />
+ <string name="bubble_bar_education_manage_title" msgid="6148404487810835924">"Ελέγξτε τα συννεφάκια ανά πάσα στιγμή."</string>
+ <string name="bubble_bar_education_manage_text" msgid="3199732148641842038">"Πατήστε εδώ για τη διαχείριση εφαρμογών και συζητήσεων που προβάλλουν συννεφάκια"</string>
<string name="notification_bubble_title" msgid="6082910224488253378">"Συννεφάκι"</string>
<string name="manage_bubbles_text" msgid="7730624269650594419">"Διαχείριση"</string>
<string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"Το συννεφάκι παραβλέφθηκε."</string>
diff --git a/libs/WindowManager/Shell/res/values-en-rAU/strings.xml b/libs/WindowManager/Shell/res/values-en-rAU/strings.xml
index c6e1c5f1a5a3..c7dd3882734b 100644
--- a/libs/WindowManager/Shell/res/values-en-rAU/strings.xml
+++ b/libs/WindowManager/Shell/res/values-en-rAU/strings.xml
@@ -76,10 +76,8 @@
<string name="bubbles_user_education_got_it" msgid="3382046149225428296">"OK"</string>
<string name="bubble_overflow_empty_title" msgid="2397251267073294968">"No recent bubbles"</string>
<string name="bubble_overflow_empty_subtitle" msgid="2627417924958633713">"Recent bubbles and dismissed bubbles will appear here"</string>
- <!-- no translation found for bubble_bar_education_manage_title (6148404487810835924) -->
- <skip />
- <!-- no translation found for bubble_bar_education_manage_text (3199732148641842038) -->
- <skip />
+ <string name="bubble_bar_education_manage_title" msgid="6148404487810835924">"Control bubbles at any time"</string>
+ <string name="bubble_bar_education_manage_text" msgid="3199732148641842038">"Tap here to manage which apps and conversations can bubble"</string>
<string name="notification_bubble_title" msgid="6082910224488253378">"Bubble"</string>
<string name="manage_bubbles_text" msgid="7730624269650594419">"Manage"</string>
<string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"Bubble dismissed."</string>
diff --git a/libs/WindowManager/Shell/res/values-en-rCA/strings.xml b/libs/WindowManager/Shell/res/values-en-rCA/strings.xml
index e536930ec925..99da073cb2c2 100644
--- a/libs/WindowManager/Shell/res/values-en-rCA/strings.xml
+++ b/libs/WindowManager/Shell/res/values-en-rCA/strings.xml
@@ -76,10 +76,8 @@
<string name="bubbles_user_education_got_it" msgid="3382046149225428296">"Got it"</string>
<string name="bubble_overflow_empty_title" msgid="2397251267073294968">"No recent bubbles"</string>
<string name="bubble_overflow_empty_subtitle" msgid="2627417924958633713">"Recent bubbles and dismissed bubbles will appear here"</string>
- <!-- no translation found for bubble_bar_education_manage_title (6148404487810835924) -->
- <skip />
- <!-- no translation found for bubble_bar_education_manage_text (3199732148641842038) -->
- <skip />
+ <string name="bubble_bar_education_manage_title" msgid="6148404487810835924">"Control bubbles anytime"</string>
+ <string name="bubble_bar_education_manage_text" msgid="3199732148641842038">"Tap here to manage which apps and conversations can bubble"</string>
<string name="notification_bubble_title" msgid="6082910224488253378">"Bubble"</string>
<string name="manage_bubbles_text" msgid="7730624269650594419">"Manage"</string>
<string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"Bubble dismissed."</string>
diff --git a/libs/WindowManager/Shell/res/values-en-rGB/strings.xml b/libs/WindowManager/Shell/res/values-en-rGB/strings.xml
index c6e1c5f1a5a3..c7dd3882734b 100644
--- a/libs/WindowManager/Shell/res/values-en-rGB/strings.xml
+++ b/libs/WindowManager/Shell/res/values-en-rGB/strings.xml
@@ -76,10 +76,8 @@
<string name="bubbles_user_education_got_it" msgid="3382046149225428296">"OK"</string>
<string name="bubble_overflow_empty_title" msgid="2397251267073294968">"No recent bubbles"</string>
<string name="bubble_overflow_empty_subtitle" msgid="2627417924958633713">"Recent bubbles and dismissed bubbles will appear here"</string>
- <!-- no translation found for bubble_bar_education_manage_title (6148404487810835924) -->
- <skip />
- <!-- no translation found for bubble_bar_education_manage_text (3199732148641842038) -->
- <skip />
+ <string name="bubble_bar_education_manage_title" msgid="6148404487810835924">"Control bubbles at any time"</string>
+ <string name="bubble_bar_education_manage_text" msgid="3199732148641842038">"Tap here to manage which apps and conversations can bubble"</string>
<string name="notification_bubble_title" msgid="6082910224488253378">"Bubble"</string>
<string name="manage_bubbles_text" msgid="7730624269650594419">"Manage"</string>
<string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"Bubble dismissed."</string>
diff --git a/libs/WindowManager/Shell/res/values-en-rIN/strings.xml b/libs/WindowManager/Shell/res/values-en-rIN/strings.xml
index c6e1c5f1a5a3..c7dd3882734b 100644
--- a/libs/WindowManager/Shell/res/values-en-rIN/strings.xml
+++ b/libs/WindowManager/Shell/res/values-en-rIN/strings.xml
@@ -76,10 +76,8 @@
<string name="bubbles_user_education_got_it" msgid="3382046149225428296">"OK"</string>
<string name="bubble_overflow_empty_title" msgid="2397251267073294968">"No recent bubbles"</string>
<string name="bubble_overflow_empty_subtitle" msgid="2627417924958633713">"Recent bubbles and dismissed bubbles will appear here"</string>
- <!-- no translation found for bubble_bar_education_manage_title (6148404487810835924) -->
- <skip />
- <!-- no translation found for bubble_bar_education_manage_text (3199732148641842038) -->
- <skip />
+ <string name="bubble_bar_education_manage_title" msgid="6148404487810835924">"Control bubbles at any time"</string>
+ <string name="bubble_bar_education_manage_text" msgid="3199732148641842038">"Tap here to manage which apps and conversations can bubble"</string>
<string name="notification_bubble_title" msgid="6082910224488253378">"Bubble"</string>
<string name="manage_bubbles_text" msgid="7730624269650594419">"Manage"</string>
<string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"Bubble dismissed."</string>
diff --git a/libs/WindowManager/Shell/res/values-en-rXC/strings.xml b/libs/WindowManager/Shell/res/values-en-rXC/strings.xml
index 83631eb3ff41..cc19579c1216 100644
--- a/libs/WindowManager/Shell/res/values-en-rXC/strings.xml
+++ b/libs/WindowManager/Shell/res/values-en-rXC/strings.xml
@@ -76,10 +76,8 @@
<string name="bubbles_user_education_got_it" msgid="3382046149225428296">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‏‏‏‎‏‏‏‎‏‏‏‏‎‏‏‏‎‎‎‏‎‎‎‎‏‏‎‏‏‏‎‎‏‎‏‎‏‎‎‎‏‏‏‏‎‎‏‏‎‏‎‏‎‏‎‎‏‎‎‎‎Got it‎‏‎‎‏‎"</string>
<string name="bubble_overflow_empty_title" msgid="2397251267073294968">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‎‎‎‏‎‏‎‎‎‏‎‎‏‎‏‏‏‏‏‏‎‏‎‏‎‎‏‏‏‎‎‎‎‎‏‏‎‏‎‎‎‎‏‎‎‏‎‎‎‎‏‎‎‏‏‏‏‎‎‎‎No recent bubbles‎‏‎‎‏‎"</string>
<string name="bubble_overflow_empty_subtitle" msgid="2627417924958633713">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‎‏‎‎‎‏‏‏‎‏‏‎‎‏‏‏‎‏‏‎‏‎‏‎‏‏‏‎‏‎‎‏‏‏‎‏‏‎‏‎‎‏‏‏‎‎‏‏‏‏‏‎‏‏‏‏‎‎‎‏‎Recent bubbles and dismissed bubbles will appear here‎‏‎‎‏‎"</string>
- <!-- no translation found for bubble_bar_education_manage_title (6148404487810835924) -->
- <skip />
- <!-- no translation found for bubble_bar_education_manage_text (3199732148641842038) -->
- <skip />
+ <string name="bubble_bar_education_manage_title" msgid="6148404487810835924">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‎‏‎‏‎‏‎‏‎‎‏‏‏‎‎‎‎‏‎‏‎‏‎‎‏‏‏‎‎‏‎‏‎‏‏‏‎‏‏‎‎‎‎‏‏‏‏‎‎‏‎‏‏‏‎‏‎‏‎‎‎Control bubbles anytime‎‏‎‎‏‎"</string>
+ <string name="bubble_bar_education_manage_text" msgid="3199732148641842038">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‏‏‎‎‎‏‏‎‎‏‏‏‏‎‏‏‏‎‏‏‎‏‏‎‏‏‏‏‏‎‏‏‎‎‎‎‎‎‏‏‎‎‎‏‏‏‎‎‎‎‏‏‎‏‏‏‎‏‏‎‎Tap here to manage which apps and conversations can bubble‎‏‎‎‏‎"</string>
<string name="notification_bubble_title" msgid="6082910224488253378">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‎‏‎‎‎‏‏‎‏‎‏‎‏‏‎‏‎‏‏‎‏‎‎‏‏‏‏‎‏‏‎‏‏‎‏‏‎‎‏‏‎‏‏‎‏‏‎‎‎‏‏‏‏‏‎‎‎‎‏‎‎Bubble‎‏‎‎‏‎"</string>
<string name="manage_bubbles_text" msgid="7730624269650594419">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‎‏‏‎‏‎‎‏‎‎‎‏‎‏‏‎‎‎‏‏‏‎‏‎‎‎‎‏‎‎‎‏‏‎‎‏‎‎‎‏‎‎‏‏‎‎‎‏‎‏‎‎‏‏‏‎‎‏‏‎Manage‎‏‎‎‏‎"</string>
<string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‏‎‎‎‎‎‏‏‏‏‏‎‎‏‏‏‎‏‏‎‏‏‏‎‎‎‏‎‏‎‎‏‎‎‏‎‎‎‏‎‏‏‎‏‏‎‏‎‏‎‏‎‏‏‏‏‏‎‏‎Bubble dismissed.‎‏‎‎‏‎"</string>
diff --git a/libs/WindowManager/Shell/res/values-es-rUS/strings.xml b/libs/WindowManager/Shell/res/values-es-rUS/strings.xml
index c0dfeefef0c0..80d10f26e4e9 100644
--- a/libs/WindowManager/Shell/res/values-es-rUS/strings.xml
+++ b/libs/WindowManager/Shell/res/values-es-rUS/strings.xml
@@ -76,10 +76,8 @@
<string name="bubbles_user_education_got_it" msgid="3382046149225428296">"Entendido"</string>
<string name="bubble_overflow_empty_title" msgid="2397251267073294968">"No hay burbujas recientes"</string>
<string name="bubble_overflow_empty_subtitle" msgid="2627417924958633713">"Las burbujas recientes y las que se descartaron aparecerán aquí"</string>
- <!-- no translation found for bubble_bar_education_manage_title (6148404487810835924) -->
- <skip />
- <!-- no translation found for bubble_bar_education_manage_text (3199732148641842038) -->
- <skip />
+ <string name="bubble_bar_education_manage_title" msgid="6148404487810835924">"Controla las burbujas"</string>
+ <string name="bubble_bar_education_manage_text" msgid="3199732148641842038">"Presiona para administrar las apps y conversaciones que pueden mostrar burbujas"</string>
<string name="notification_bubble_title" msgid="6082910224488253378">"Cuadro"</string>
<string name="manage_bubbles_text" msgid="7730624269650594419">"Administrar"</string>
<string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"Se descartó el cuadro."</string>
diff --git a/libs/WindowManager/Shell/res/values-es/strings.xml b/libs/WindowManager/Shell/res/values-es/strings.xml
index 0e66c9bbb819..13dfce03b775 100644
--- a/libs/WindowManager/Shell/res/values-es/strings.xml
+++ b/libs/WindowManager/Shell/res/values-es/strings.xml
@@ -76,10 +76,8 @@
<string name="bubbles_user_education_got_it" msgid="3382046149225428296">"Entendido"</string>
<string name="bubble_overflow_empty_title" msgid="2397251267073294968">"No hay burbujas recientes"</string>
<string name="bubble_overflow_empty_subtitle" msgid="2627417924958633713">"Las burbujas recientes y las cerradas aparecerán aquí"</string>
- <!-- no translation found for bubble_bar_education_manage_title (6148404487810835924) -->
- <skip />
- <!-- no translation found for bubble_bar_education_manage_text (3199732148641842038) -->
- <skip />
+ <string name="bubble_bar_education_manage_title" msgid="6148404487810835924">"Controla las burbujas cuando quieras"</string>
+ <string name="bubble_bar_education_manage_text" msgid="3199732148641842038">"Toca aquí para gestionar qué aplicaciones y conversaciones pueden usar burbujas"</string>
<string name="notification_bubble_title" msgid="6082910224488253378">"Burbuja"</string>
<string name="manage_bubbles_text" msgid="7730624269650594419">"Gestionar"</string>
<string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"Burbuja cerrada."</string>
diff --git a/libs/WindowManager/Shell/res/values-et/strings.xml b/libs/WindowManager/Shell/res/values-et/strings.xml
index 201f336b6a96..269968f48c77 100644
--- a/libs/WindowManager/Shell/res/values-et/strings.xml
+++ b/libs/WindowManager/Shell/res/values-et/strings.xml
@@ -76,10 +76,8 @@
<string name="bubbles_user_education_got_it" msgid="3382046149225428296">"Selge"</string>
<string name="bubble_overflow_empty_title" msgid="2397251267073294968">"Hiljutisi mulle pole"</string>
<string name="bubble_overflow_empty_subtitle" msgid="2627417924958633713">"Siin kuvatakse hiljutised ja suletud mullid."</string>
- <!-- no translation found for bubble_bar_education_manage_title (6148404487810835924) -->
- <skip />
- <!-- no translation found for bubble_bar_education_manage_text (3199732148641842038) -->
- <skip />
+ <string name="bubble_bar_education_manage_title" msgid="6148404487810835924">"Juhtige mulle igal ajal"</string>
+ <string name="bubble_bar_education_manage_text" msgid="3199732148641842038">"Puudutage siin, et hallata, milliseid rakendusi ja vestlusi saab mullina kuvada"</string>
<string name="notification_bubble_title" msgid="6082910224488253378">"Mull"</string>
<string name="manage_bubbles_text" msgid="7730624269650594419">"Halda"</string>
<string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"Mullist loobuti."</string>
diff --git a/libs/WindowManager/Shell/res/values-eu/strings.xml b/libs/WindowManager/Shell/res/values-eu/strings.xml
index 84439546f72e..b4a8d57abc94 100644
--- a/libs/WindowManager/Shell/res/values-eu/strings.xml
+++ b/libs/WindowManager/Shell/res/values-eu/strings.xml
@@ -76,10 +76,8 @@
<string name="bubbles_user_education_got_it" msgid="3382046149225428296">"Ados"</string>
<string name="bubble_overflow_empty_title" msgid="2397251267073294968">"Ez dago azkenaldiko burbuilarik"</string>
<string name="bubble_overflow_empty_subtitle" msgid="2627417924958633713">"Azken burbuilak eta baztertutakoak agertuko dira hemen"</string>
- <!-- no translation found for bubble_bar_education_manage_title (6148404487810835924) -->
- <skip />
- <!-- no translation found for bubble_bar_education_manage_text (3199732148641842038) -->
- <skip />
+ <string name="bubble_bar_education_manage_title" msgid="6148404487810835924">"Kontrolatu burbuilak edonoiz"</string>
+ <string name="bubble_bar_education_manage_text" msgid="3199732148641842038">"Sakatu hau burbuiletan zein aplikazio eta elkarrizketa ager daitezkeen kudeatzeko"</string>
<string name="notification_bubble_title" msgid="6082910224488253378">"Burbuila"</string>
<string name="manage_bubbles_text" msgid="7730624269650594419">"Kudeatu"</string>
<string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"Baztertu da globoa."</string>
diff --git a/libs/WindowManager/Shell/res/values-fa/strings.xml b/libs/WindowManager/Shell/res/values-fa/strings.xml
index 4f546e7a2c1b..434bfe11db4e 100644
--- a/libs/WindowManager/Shell/res/values-fa/strings.xml
+++ b/libs/WindowManager/Shell/res/values-fa/strings.xml
@@ -76,10 +76,8 @@
<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>
- <!-- no translation found for bubble_bar_education_manage_title (6148404487810835924) -->
- <skip />
- <!-- no translation found for bubble_bar_education_manage_text (3199732148641842038) -->
- <skip />
+ <string name="bubble_bar_education_manage_title" msgid="6148404487810835924">"کنترل حبابک‌ها در هرزمانی"</string>
+ <string name="bubble_bar_education_manage_text" msgid="3199732148641842038">"برای مدیریت اینکه کدام برنامه‌ها و مکالمه‌ها حباب داشته باشند، ضربه بزنید"</string>
<string name="notification_bubble_title" msgid="6082910224488253378">"حباب"</string>
<string name="manage_bubbles_text" msgid="7730624269650594419">"مدیریت"</string>
<string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"حبابک رد شد."</string>
diff --git a/libs/WindowManager/Shell/res/values-fi/strings.xml b/libs/WindowManager/Shell/res/values-fi/strings.xml
index d8a18a033616..a04ef1252aa8 100644
--- a/libs/WindowManager/Shell/res/values-fi/strings.xml
+++ b/libs/WindowManager/Shell/res/values-fi/strings.xml
@@ -76,10 +76,8 @@
<string name="bubbles_user_education_got_it" msgid="3382046149225428296">"Okei"</string>
<string name="bubble_overflow_empty_title" msgid="2397251267073294968">"Ei viimeaikaisia kuplia"</string>
<string name="bubble_overflow_empty_subtitle" msgid="2627417924958633713">"Viimeaikaiset ja äskettäin ohitetut kuplat näkyvät täällä"</string>
- <!-- no translation found for bubble_bar_education_manage_title (6148404487810835924) -->
- <skip />
- <!-- no translation found for bubble_bar_education_manage_text (3199732148641842038) -->
- <skip />
+ <string name="bubble_bar_education_manage_title" msgid="6148404487810835924">"Muuta kuplien asetuksia milloin tahansa"</string>
+ <string name="bubble_bar_education_manage_text" msgid="3199732148641842038">"Valitse napauttamalla tästä, mitkä sovellukset ja keskustelut voivat kuplia"</string>
<string name="notification_bubble_title" msgid="6082910224488253378">"Kupla"</string>
<string name="manage_bubbles_text" msgid="7730624269650594419">"Ylläpidä"</string>
<string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"Kupla ohitettu."</string>
diff --git a/libs/WindowManager/Shell/res/values-fr-rCA/strings.xml b/libs/WindowManager/Shell/res/values-fr-rCA/strings.xml
index b2077f9b05d9..fbc619144f71 100644
--- a/libs/WindowManager/Shell/res/values-fr-rCA/strings.xml
+++ b/libs/WindowManager/Shell/res/values-fr-rCA/strings.xml
@@ -76,10 +76,8 @@
<string name="bubbles_user_education_got_it" msgid="3382046149225428296">"OK"</string>
<string name="bubble_overflow_empty_title" msgid="2397251267073294968">"Aucune bulle récente"</string>
<string name="bubble_overflow_empty_subtitle" msgid="2627417924958633713">"Les bulles récentes et les bulles ignorées s\'afficheront ici"</string>
- <!-- no translation found for bubble_bar_education_manage_title (6148404487810835924) -->
- <skip />
- <!-- no translation found for bubble_bar_education_manage_text (3199732148641842038) -->
- <skip />
+ <string name="bubble_bar_education_manage_title" msgid="6148404487810835924">"Gérez les bulles en tout temps"</string>
+ <string name="bubble_bar_education_manage_text" msgid="3199732148641842038">"Touchez ici pour gérer les applis et les conversations à inclure aux bulles"</string>
<string name="notification_bubble_title" msgid="6082910224488253378">"Bulle"</string>
<string name="manage_bubbles_text" msgid="7730624269650594419">"Gérer"</string>
<string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"Bulle ignorée."</string>
diff --git a/libs/WindowManager/Shell/res/values-fr/strings.xml b/libs/WindowManager/Shell/res/values-fr/strings.xml
index b1b83133584d..e1fe2917a729 100644
--- a/libs/WindowManager/Shell/res/values-fr/strings.xml
+++ b/libs/WindowManager/Shell/res/values-fr/strings.xml
@@ -76,10 +76,8 @@
<string name="bubbles_user_education_got_it" msgid="3382046149225428296">"OK"</string>
<string name="bubble_overflow_empty_title" msgid="2397251267073294968">"Aucune bulle récente"</string>
<string name="bubble_overflow_empty_subtitle" msgid="2627417924958633713">"Les bulles récentes et ignorées s\'afficheront ici"</string>
- <!-- no translation found for bubble_bar_education_manage_title (6148404487810835924) -->
- <skip />
- <!-- no translation found for bubble_bar_education_manage_text (3199732148641842038) -->
- <skip />
+ <string name="bubble_bar_education_manage_title" msgid="6148404487810835924">"Contrôlez les bulles à tout moment"</string>
+ <string name="bubble_bar_education_manage_text" msgid="3199732148641842038">"Appuyez ici pour gérer les applis et conversations s\'affichant dans des bulles"</string>
<string name="notification_bubble_title" msgid="6082910224488253378">"Bulle"</string>
<string name="manage_bubbles_text" msgid="7730624269650594419">"Gérer"</string>
<string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"Bulle fermée."</string>
diff --git a/libs/WindowManager/Shell/res/values-gl/strings.xml b/libs/WindowManager/Shell/res/values-gl/strings.xml
index fd90e31dc6c4..485a89502c86 100644
--- a/libs/WindowManager/Shell/res/values-gl/strings.xml
+++ b/libs/WindowManager/Shell/res/values-gl/strings.xml
@@ -76,10 +76,8 @@
<string name="bubbles_user_education_got_it" msgid="3382046149225428296">"Entendido"</string>
<string name="bubble_overflow_empty_title" msgid="2397251267073294968">"Non hai burbullas recentes"</string>
<string name="bubble_overflow_empty_subtitle" msgid="2627417924958633713">"As burbullas recentes e ignoradas aparecerán aquí."</string>
- <!-- no translation found for bubble_bar_education_manage_title (6148404487810835924) -->
- <skip />
- <!-- no translation found for bubble_bar_education_manage_text (3199732148641842038) -->
- <skip />
+ <string name="bubble_bar_education_manage_title" msgid="6148404487810835924">"Controlar as burbullas"</string>
+ <string name="bubble_bar_education_manage_text" msgid="3199732148641842038">"Toca para xestionar as aplicacións e conversas que poden aparecer en burbullas"</string>
<string name="notification_bubble_title" msgid="6082910224488253378">"Burbulla"</string>
<string name="manage_bubbles_text" msgid="7730624269650594419">"Xestionar"</string>
<string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"Ignorouse a burbulla."</string>
diff --git a/libs/WindowManager/Shell/res/values-gu/strings.xml b/libs/WindowManager/Shell/res/values-gu/strings.xml
index d7e34fb2888b..365faef85ff6 100644
--- a/libs/WindowManager/Shell/res/values-gu/strings.xml
+++ b/libs/WindowManager/Shell/res/values-gu/strings.xml
@@ -76,10 +76,8 @@
<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>
- <!-- no translation found for bubble_bar_education_manage_title (6148404487810835924) -->
- <skip />
- <!-- no translation found for bubble_bar_education_manage_text (3199732148641842038) -->
- <skip />
+ <string name="bubble_bar_education_manage_title" msgid="6148404487810835924">"બબલને કોઈપણ સમયે નિયંત્રિત કરે છે"</string>
+ <string name="bubble_bar_education_manage_text" msgid="3199732148641842038">"કઈ ઍપ અને વાતચીતોને બબલ કરવા માગો છો તે મેનેજ કરવા માટે, અહીં ટૅપ કરો"</string>
<string name="notification_bubble_title" msgid="6082910224488253378">"બબલ"</string>
<string name="manage_bubbles_text" msgid="7730624269650594419">"મેનેજ કરો"</string>
<string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"બબલ છોડી દેવાયો."</string>
diff --git a/libs/WindowManager/Shell/res/values-hi/strings.xml b/libs/WindowManager/Shell/res/values-hi/strings.xml
index 679ea65bb882..76579d10b695 100644
--- a/libs/WindowManager/Shell/res/values-hi/strings.xml
+++ b/libs/WindowManager/Shell/res/values-hi/strings.xml
@@ -76,19 +76,14 @@
<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>
- <!-- no translation found for bubble_bar_education_manage_title (6148404487810835924) -->
- <skip />
- <!-- no translation found for bubble_bar_education_manage_text (3199732148641842038) -->
- <skip />
+ <string name="bubble_bar_education_manage_title" msgid="6148404487810835924">"जब चाहें, बबल्स की सुविधा को कंट्रोल करें"</string>
+ <string name="bubble_bar_education_manage_text" msgid="3199732148641842038">"किसी ऐप्लिकेशन और बातचीत के लिए बबल की सुविधा को मैनेज करने के लिए यहां टैप करें"</string>
<string name="notification_bubble_title" msgid="6082910224488253378">"बबल"</string>
<string name="manage_bubbles_text" msgid="7730624269650594419">"मैनेज करें"</string>
<string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"बबल खारिज किया गया."</string>
- <!-- no translation found for restart_button_description (4564728020654658478) -->
- <skip />
- <!-- no translation found for user_aspect_ratio_settings_button_hint (734835849600713016) -->
- <skip />
- <!-- no translation found for user_aspect_ratio_settings_button_description (4315566801697411684) -->
- <skip />
+ <string name="restart_button_description" msgid="4564728020654658478">"बेहतर व्यू पाने के लिए, टैप करके ऐप्लिकेशन को रीस्टार्ट करें"</string>
+ <string name="user_aspect_ratio_settings_button_hint" msgid="734835849600713016">"सेटिंग में जाकर इस ऐप्लिकेशन का आसपेक्ट रेशियो (लंबाई-चौड़ाई का अनुपात) बदलें"</string>
+ <string name="user_aspect_ratio_settings_button_description" msgid="4315566801697411684">"आसपेक्ट रेशियो (लंबाई-चौड़ाई का अनुपात) बदलें"</string>
<string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"क्या कैमरे से जुड़ी कोई समस्या है?\nफिर से फ़िट करने के लिए टैप करें"</string>
<string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"क्या समस्या ठीक नहीं हुई?\nपहले जैसा करने के लिए टैप करें"</string>
<string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"क्या कैमरे से जुड़ी कोई समस्या नहीं है? खारिज करने के लिए टैप करें."</string>
diff --git a/libs/WindowManager/Shell/res/values-hr/strings.xml b/libs/WindowManager/Shell/res/values-hr/strings.xml
index 88aa1b2b645d..de071f1b959d 100644
--- a/libs/WindowManager/Shell/res/values-hr/strings.xml
+++ b/libs/WindowManager/Shell/res/values-hr/strings.xml
@@ -76,10 +76,8 @@
<string name="bubbles_user_education_got_it" msgid="3382046149225428296">"Shvaćam"</string>
<string name="bubble_overflow_empty_title" msgid="2397251267073294968">"Nema nedavnih oblačića"</string>
<string name="bubble_overflow_empty_subtitle" msgid="2627417924958633713">"Ovdje će se prikazivati nedavni i odbačeni oblačići"</string>
- <!-- no translation found for bubble_bar_education_manage_title (6148404487810835924) -->
- <skip />
- <!-- no translation found for bubble_bar_education_manage_text (3199732148641842038) -->
- <skip />
+ <string name="bubble_bar_education_manage_title" msgid="6148404487810835924">"Upravljanje oblačićima u svakom trenutku"</string>
+ <string name="bubble_bar_education_manage_text" msgid="3199732148641842038">"Dodirnite ovdje da biste odredili koje aplikacije i razgovori mogu imati oblačić"</string>
<string name="notification_bubble_title" msgid="6082910224488253378">"Oblačić"</string>
<string name="manage_bubbles_text" msgid="7730624269650594419">"Upravljanje"</string>
<string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"Oblačić odbačen."</string>
diff --git a/libs/WindowManager/Shell/res/values-hu/strings.xml b/libs/WindowManager/Shell/res/values-hu/strings.xml
index 5a88bc4753a9..b5631bbf0152 100644
--- a/libs/WindowManager/Shell/res/values-hu/strings.xml
+++ b/libs/WindowManager/Shell/res/values-hu/strings.xml
@@ -76,10 +76,8 @@
<string name="bubbles_user_education_got_it" msgid="3382046149225428296">"Értem"</string>
<string name="bubble_overflow_empty_title" msgid="2397251267073294968">"Nincsenek buborékok a közelmúltból"</string>
<string name="bubble_overflow_empty_subtitle" msgid="2627417924958633713">"A legutóbbi és az elvetett buborékok itt jelennek majd meg"</string>
- <!-- no translation found for bubble_bar_education_manage_title (6148404487810835924) -->
- <skip />
- <!-- no translation found for bubble_bar_education_manage_text (3199732148641842038) -->
- <skip />
+ <string name="bubble_bar_education_manage_title" msgid="6148404487810835924">"Buborékok vezérlése bármikor"</string>
+ <string name="bubble_bar_education_manage_text" msgid="3199732148641842038">"Ide koppintva jeleníthetők meg az alkalmazások és a beszélgetések buborékként"</string>
<string name="notification_bubble_title" msgid="6082910224488253378">"Buborék"</string>
<string name="manage_bubbles_text" msgid="7730624269650594419">"Kezelés"</string>
<string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"Buborék elvetve."</string>
diff --git a/libs/WindowManager/Shell/res/values-hy/strings.xml b/libs/WindowManager/Shell/res/values-hy/strings.xml
index 54b1213ad216..2d5d371df41e 100644
--- a/libs/WindowManager/Shell/res/values-hy/strings.xml
+++ b/libs/WindowManager/Shell/res/values-hy/strings.xml
@@ -76,10 +76,8 @@
<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>
- <!-- no translation found for bubble_bar_education_manage_title (6148404487810835924) -->
- <skip />
- <!-- no translation found for bubble_bar_education_manage_text (3199732148641842038) -->
- <skip />
+ <string name="bubble_bar_education_manage_title" msgid="6148404487810835924">"Ամպիկների կարգավորումներ"</string>
+ <string name="bubble_bar_education_manage_text" msgid="3199732148641842038">"Հպեք այստեղ՝ ընտրելու, թե որ հավելվածների և զրույցների համար ամպիկներ ցուցադրել"</string>
<string name="notification_bubble_title" msgid="6082910224488253378">"Պղպջակ"</string>
<string name="manage_bubbles_text" msgid="7730624269650594419">"Կառավարել"</string>
<string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"Ամպիկը փակվեց։"</string>
diff --git a/libs/WindowManager/Shell/res/values-in/strings.xml b/libs/WindowManager/Shell/res/values-in/strings.xml
index 32167b30946b..90b1f152d035 100644
--- a/libs/WindowManager/Shell/res/values-in/strings.xml
+++ b/libs/WindowManager/Shell/res/values-in/strings.xml
@@ -76,10 +76,8 @@
<string name="bubbles_user_education_got_it" msgid="3382046149225428296">"Oke"</string>
<string name="bubble_overflow_empty_title" msgid="2397251267073294968">"Tidak ada balon baru-baru ini"</string>
<string name="bubble_overflow_empty_subtitle" msgid="2627417924958633713">"Balon yang baru dipakai dan balon yang telah ditutup akan muncul di sini"</string>
- <!-- no translation found for bubble_bar_education_manage_title (6148404487810835924) -->
- <skip />
- <!-- no translation found for bubble_bar_education_manage_text (3199732148641842038) -->
- <skip />
+ <string name="bubble_bar_education_manage_title" msgid="6148404487810835924">"Kontrol balon kapan saja"</string>
+ <string name="bubble_bar_education_manage_text" msgid="3199732148641842038">"Ketuk di sini untuk mengelola balon aplikasi dan percakapan"</string>
<string name="notification_bubble_title" msgid="6082910224488253378">"Balon"</string>
<string name="manage_bubbles_text" msgid="7730624269650594419">"Kelola"</string>
<string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"Balon ditutup."</string>
diff --git a/libs/WindowManager/Shell/res/values-is/strings.xml b/libs/WindowManager/Shell/res/values-is/strings.xml
index 1304ae149425..813f9e6f4021 100644
--- a/libs/WindowManager/Shell/res/values-is/strings.xml
+++ b/libs/WindowManager/Shell/res/values-is/strings.xml
@@ -76,10 +76,8 @@
<string name="bubbles_user_education_got_it" msgid="3382046149225428296">"Ég skil"</string>
<string name="bubble_overflow_empty_title" msgid="2397251267073294968">"Engar nýlegar blöðrur"</string>
<string name="bubble_overflow_empty_subtitle" msgid="2627417924958633713">"Nýlegar blöðrur og blöðrur sem þú hefur lokað birtast hér"</string>
- <!-- no translation found for bubble_bar_education_manage_title (6148404487810835924) -->
- <skip />
- <!-- no translation found for bubble_bar_education_manage_text (3199732148641842038) -->
- <skip />
+ <string name="bubble_bar_education_manage_title" msgid="6148404487810835924">"Hægt er að stjórna blöðrum hvenær sem er"</string>
+ <string name="bubble_bar_education_manage_text" msgid="3199732148641842038">"Ýttu hér til að stjórna því hvaða forrit og samtöl mega nota blöðrur."</string>
<string name="notification_bubble_title" msgid="6082910224488253378">"Blaðra"</string>
<string name="manage_bubbles_text" msgid="7730624269650594419">"Stjórna"</string>
<string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"Blöðru lokað."</string>
diff --git a/libs/WindowManager/Shell/res/values-it/strings.xml b/libs/WindowManager/Shell/res/values-it/strings.xml
index dceac5c2722a..8918821a8f27 100644
--- a/libs/WindowManager/Shell/res/values-it/strings.xml
+++ b/libs/WindowManager/Shell/res/values-it/strings.xml
@@ -76,10 +76,8 @@
<string name="bubbles_user_education_got_it" msgid="3382046149225428296">"OK"</string>
<string name="bubble_overflow_empty_title" msgid="2397251267073294968">"Nessuna bolla recente"</string>
<string name="bubble_overflow_empty_subtitle" msgid="2627417924958633713">"Le bolle recenti e ignorate appariranno qui"</string>
- <!-- no translation found for bubble_bar_education_manage_title (6148404487810835924) -->
- <skip />
- <!-- no translation found for bubble_bar_education_manage_text (3199732148641842038) -->
- <skip />
+ <string name="bubble_bar_education_manage_title" msgid="6148404487810835924">"Gestisci le bolle in qualsiasi momento"</string>
+ <string name="bubble_bar_education_manage_text" msgid="3199732148641842038">"Tocca qui per gestire le app e le conversazioni per cui mostrare le bolle"</string>
<string name="notification_bubble_title" msgid="6082910224488253378">"Fumetto"</string>
<string name="manage_bubbles_text" msgid="7730624269650594419">"Gestisci"</string>
<string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"Fumetto ignorato."</string>
diff --git a/libs/WindowManager/Shell/res/values-iw/strings.xml b/libs/WindowManager/Shell/res/values-iw/strings.xml
index 7cde568b9123..4d7a0936a3e0 100644
--- a/libs/WindowManager/Shell/res/values-iw/strings.xml
+++ b/libs/WindowManager/Shell/res/values-iw/strings.xml
@@ -76,10 +76,8 @@
<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>
- <!-- no translation found for bubble_bar_education_manage_title (6148404487810835924) -->
- <skip />
- <!-- no translation found for bubble_bar_education_manage_text (3199732148641842038) -->
- <skip />
+ <string name="bubble_bar_education_manage_title" msgid="6148404487810835924">"שליטה בבועות בכל זמן"</string>
+ <string name="bubble_bar_education_manage_text" msgid="3199732148641842038">"אפשר להקיש כאן כדי לקבוע אילו אפליקציות ושיחות יוכלו להופיע בבועות"</string>
<string name="notification_bubble_title" msgid="6082910224488253378">"בועה"</string>
<string name="manage_bubbles_text" msgid="7730624269650594419">"ניהול"</string>
<string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"הבועה נסגרה."</string>
diff --git a/libs/WindowManager/Shell/res/values-ja/strings.xml b/libs/WindowManager/Shell/res/values-ja/strings.xml
index 3b3c4e493e4c..96683590d097 100644
--- a/libs/WindowManager/Shell/res/values-ja/strings.xml
+++ b/libs/WindowManager/Shell/res/values-ja/strings.xml
@@ -76,10 +76,8 @@
<string name="bubbles_user_education_got_it" msgid="3382046149225428296">"OK"</string>
<string name="bubble_overflow_empty_title" msgid="2397251267073294968">"最近閉じたバブルはありません"</string>
<string name="bubble_overflow_empty_subtitle" msgid="2627417924958633713">"最近表示されたバブルや閉じたバブルが、ここに表示されます"</string>
- <!-- no translation found for bubble_bar_education_manage_title (6148404487810835924) -->
- <skip />
- <!-- no translation found for bubble_bar_education_manage_text (3199732148641842038) -->
- <skip />
+ <string name="bubble_bar_education_manage_title" msgid="6148404487810835924">"バブルはいつでも管理可能"</string>
+ <string name="bubble_bar_education_manage_text" msgid="3199732148641842038">"バブルで表示するアプリや会話を管理するには、ここをタップします"</string>
<string name="notification_bubble_title" msgid="6082910224488253378">"バブル"</string>
<string name="manage_bubbles_text" msgid="7730624269650594419">"管理"</string>
<string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"ふきだしが非表示になっています。"</string>
diff --git a/libs/WindowManager/Shell/res/values-ka/strings.xml b/libs/WindowManager/Shell/res/values-ka/strings.xml
index 3c32e0e6fe8d..a949a18fd449 100644
--- a/libs/WindowManager/Shell/res/values-ka/strings.xml
+++ b/libs/WindowManager/Shell/res/values-ka/strings.xml
@@ -76,10 +76,8 @@
<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>
- <!-- no translation found for bubble_bar_education_manage_title (6148404487810835924) -->
- <skip />
- <!-- no translation found for bubble_bar_education_manage_text (3199732148641842038) -->
- <skip />
+ <string name="bubble_bar_education_manage_title" msgid="6148404487810835924">"ამოხტომის გაკონტროლება ნებისმიერ დროს"</string>
+ <string name="bubble_bar_education_manage_text" msgid="3199732148641842038">"აქ შეეხეთ იმის სამართავად, თუ რომელი აპები და საუბრები ამოხტეს"</string>
<string name="notification_bubble_title" msgid="6082910224488253378">"ბუშტი"</string>
<string name="manage_bubbles_text" msgid="7730624269650594419">"მართვა"</string>
<string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"ბუშტი დაიხურა."</string>
diff --git a/libs/WindowManager/Shell/res/values-kk/strings.xml b/libs/WindowManager/Shell/res/values-kk/strings.xml
index ac5f4bf60309..cbc924907cac 100644
--- a/libs/WindowManager/Shell/res/values-kk/strings.xml
+++ b/libs/WindowManager/Shell/res/values-kk/strings.xml
@@ -76,10 +76,8 @@
<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>
- <!-- no translation found for bubble_bar_education_manage_title (6148404487810835924) -->
- <skip />
- <!-- no translation found for bubble_bar_education_manage_text (3199732148641842038) -->
- <skip />
+ <string name="bubble_bar_education_manage_title" msgid="6148404487810835924">"Қалқыма хабарларды кез келген уақытта басқарыңыз"</string>
+ <string name="bubble_bar_education_manage_text" msgid="3199732148641842038">"Қалқыма хабарда көрсетілетін қолданбалар мен әңгімелерді реттеу үшін осы жерді түртіңіз."</string>
<string name="notification_bubble_title" msgid="6082910224488253378">"Көпіршік"</string>
<string name="manage_bubbles_text" msgid="7730624269650594419">"Басқару"</string>
<string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"Қалқыма хабар жабылды."</string>
diff --git a/libs/WindowManager/Shell/res/values-km/strings.xml b/libs/WindowManager/Shell/res/values-km/strings.xml
index adb229ab8039..3e36113995d9 100644
--- a/libs/WindowManager/Shell/res/values-km/strings.xml
+++ b/libs/WindowManager/Shell/res/values-km/strings.xml
@@ -76,10 +76,8 @@
<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>
- <!-- no translation found for bubble_bar_education_manage_title (6148404487810835924) -->
- <skip />
- <!-- no translation found for bubble_bar_education_manage_text (3199732148641842038) -->
- <skip />
+ <string name="bubble_bar_education_manage_title" msgid="6148404487810835924">"គ្រប់គ្រង​ផ្ទាំងអណ្ដែតនៅពេលណាក៏បាន"</string>
+ <string name="bubble_bar_education_manage_text" msgid="3199732148641842038">"ចុចត្រង់នេះ ដើម្បីគ្រប់គ្រងកម្មវិធី និងការសន្ទនាដែលអាចបង្ហាញជាផ្ទាំងអណ្ដែត"</string>
<string name="notification_bubble_title" msgid="6082910224488253378">"ពពុះ"</string>
<string name="manage_bubbles_text" msgid="7730624269650594419">"គ្រប់គ្រង"</string>
<string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"បានច្រានចោល​សារលេចឡើង។"</string>
diff --git a/libs/WindowManager/Shell/res/values-kn/strings.xml b/libs/WindowManager/Shell/res/values-kn/strings.xml
index 33c50e7530a7..5e0dad8255b4 100644
--- a/libs/WindowManager/Shell/res/values-kn/strings.xml
+++ b/libs/WindowManager/Shell/res/values-kn/strings.xml
@@ -76,10 +76,8 @@
<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>
- <!-- no translation found for bubble_bar_education_manage_title (6148404487810835924) -->
- <skip />
- <!-- no translation found for bubble_bar_education_manage_text (3199732148641842038) -->
- <skip />
+ <string name="bubble_bar_education_manage_title" msgid="6148404487810835924">"ಯಾವುದೇ ಸಮಯದಲ್ಲಿ ಬಬಲ್ಸ್ ಅನ್ನು ನಿಯಂತ್ರಿಸಿ"</string>
+ <string name="bubble_bar_education_manage_text" msgid="3199732148641842038">"ಯಾವ ಆ್ಯಪ್‌ಗಳು ಮತ್ತು ಸಂಭಾಷಣೆಗಳನ್ನು ಬಬಲ್ ಮಾಡಬಹುದು ಎಂಬುದನ್ನು ನಿರ್ವಹಿಸಲು ಟ್ಯಾಪ್ ಮಾಡಿ"</string>
<string name="notification_bubble_title" msgid="6082910224488253378">"ಬಬಲ್"</string>
<string name="manage_bubbles_text" msgid="7730624269650594419">"ನಿರ್ವಹಿಸಿ"</string>
<string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"ಬಬಲ್ ವಜಾಗೊಳಿಸಲಾಗಿದೆ."</string>
diff --git a/libs/WindowManager/Shell/res/values-ko/strings.xml b/libs/WindowManager/Shell/res/values-ko/strings.xml
index dc76769618aa..f1b34556954e 100644
--- a/libs/WindowManager/Shell/res/values-ko/strings.xml
+++ b/libs/WindowManager/Shell/res/values-ko/strings.xml
@@ -76,10 +76,8 @@
<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>
- <!-- no translation found for bubble_bar_education_manage_title (6148404487810835924) -->
- <skip />
- <!-- no translation found for bubble_bar_education_manage_text (3199732148641842038) -->
- <skip />
+ <string name="bubble_bar_education_manage_title" msgid="6148404487810835924">"언제든지 대화창을 제어하세요"</string>
+ <string name="bubble_bar_education_manage_text" msgid="3199732148641842038">"대화창을 만들 수 있는 앱과 대화를 관리하려면 여기를 탭하세요."</string>
<string name="notification_bubble_title" msgid="6082910224488253378">"버블"</string>
<string name="manage_bubbles_text" msgid="7730624269650594419">"관리"</string>
<string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"대화창을 닫았습니다."</string>
diff --git a/libs/WindowManager/Shell/res/values-ky/strings.xml b/libs/WindowManager/Shell/res/values-ky/strings.xml
index b1c0a6712093..200359aded72 100644
--- a/libs/WindowManager/Shell/res/values-ky/strings.xml
+++ b/libs/WindowManager/Shell/res/values-ky/strings.xml
@@ -76,10 +76,8 @@
<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>
- <!-- no translation found for bubble_bar_education_manage_title (6148404487810835924) -->
- <skip />
- <!-- no translation found for bubble_bar_education_manage_text (3199732148641842038) -->
- <skip />
+ <string name="bubble_bar_education_manage_title" msgid="6148404487810835924">"Калкып чыкма билдирмелерди каалаган убакта көзөмөлдөңүз"</string>
+ <string name="bubble_bar_education_manage_text" msgid="3199732148641842038">"Калкып чыкма билдирме түрүндө көрүнө турган колдонмолор менен маектерди тандоо үчүн бул жерди таптаңыз"</string>
<string name="notification_bubble_title" msgid="6082910224488253378">"Көбүк"</string>
<string name="manage_bubbles_text" msgid="7730624269650594419">"Башкаруу"</string>
<string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"Калкып чыкма билдирме жабылды."</string>
diff --git a/libs/WindowManager/Shell/res/values-lo/strings.xml b/libs/WindowManager/Shell/res/values-lo/strings.xml
index 0b5da776df17..43835d5afa67 100644
--- a/libs/WindowManager/Shell/res/values-lo/strings.xml
+++ b/libs/WindowManager/Shell/res/values-lo/strings.xml
@@ -76,10 +76,8 @@
<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>
- <!-- no translation found for bubble_bar_education_manage_title (6148404487810835924) -->
- <skip />
- <!-- no translation found for bubble_bar_education_manage_text (3199732148641842038) -->
- <skip />
+ <string name="bubble_bar_education_manage_title" msgid="6148404487810835924">"ຄວບຄຸມຟອງໄດ້ທຸກເວລາ"</string>
+ <string name="bubble_bar_education_manage_text" msgid="3199732148641842038">"ແຕະບ່ອນນີ້ເພື່ອຈັດການແອັບ ແລະ ການສົນທະນາທີ່ສາມາດສະແດງເປັນແບບຟອງໄດ້"</string>
<string name="notification_bubble_title" msgid="6082910224488253378">"ຟອງ"</string>
<string name="manage_bubbles_text" msgid="7730624269650594419">"ຈັດການ"</string>
<string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"ປິດ Bubble ໄສ້ແລ້ວ."</string>
diff --git a/libs/WindowManager/Shell/res/values-lt/strings.xml b/libs/WindowManager/Shell/res/values-lt/strings.xml
index ecec41a10d36..0c6cc58aa1ec 100644
--- a/libs/WindowManager/Shell/res/values-lt/strings.xml
+++ b/libs/WindowManager/Shell/res/values-lt/strings.xml
@@ -76,10 +76,8 @@
<string name="bubbles_user_education_got_it" msgid="3382046149225428296">"Supratau"</string>
<string name="bubble_overflow_empty_title" msgid="2397251267073294968">"Nėra naujausių burbulų"</string>
<string name="bubble_overflow_empty_subtitle" msgid="2627417924958633713">"Naujausi ir atsisakyti burbulai bus rodomi čia"</string>
- <!-- no translation found for bubble_bar_education_manage_title (6148404487810835924) -->
- <skip />
- <!-- no translation found for bubble_bar_education_manage_text (3199732148641842038) -->
- <skip />
+ <string name="bubble_bar_education_manage_title" msgid="6148404487810835924">"Bet kada valdyti burbulus"</string>
+ <string name="bubble_bar_education_manage_text" msgid="3199732148641842038">"Palietę čia valdykite, kurie pokalbiai ir programos gali būti rodomi burbuluose"</string>
<string name="notification_bubble_title" msgid="6082910224488253378">"Debesėlis"</string>
<string name="manage_bubbles_text" msgid="7730624269650594419">"Tvarkyti"</string>
<string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"Debesėlio atsisakyta."</string>
diff --git a/libs/WindowManager/Shell/res/values-lv/strings.xml b/libs/WindowManager/Shell/res/values-lv/strings.xml
index d3a15bda9fd2..f86e937edd33 100644
--- a/libs/WindowManager/Shell/res/values-lv/strings.xml
+++ b/libs/WindowManager/Shell/res/values-lv/strings.xml
@@ -76,10 +76,8 @@
<string name="bubbles_user_education_got_it" msgid="3382046149225428296">"Labi"</string>
<string name="bubble_overflow_empty_title" msgid="2397251267073294968">"Nav nesen aizvērtu burbuļu"</string>
<string name="bubble_overflow_empty_subtitle" msgid="2627417924958633713">"Šeit būs redzami nesen rādītie burbuļi un aizvērtie burbuļi"</string>
- <!-- no translation found for bubble_bar_education_manage_title (6148404487810835924) -->
- <skip />
- <!-- no translation found for bubble_bar_education_manage_text (3199732148641842038) -->
- <skip />
+ <string name="bubble_bar_education_manage_title" msgid="6148404487810835924">"Pārvaldīt burbuļus jebkurā laikā"</string>
+ <string name="bubble_bar_education_manage_text" msgid="3199732148641842038">"Pieskarieties šeit, lai pārvaldītu, kuras lietotnes un sarunas var rādīt burbulī"</string>
<string name="notification_bubble_title" msgid="6082910224488253378">"Burbulis"</string>
<string name="manage_bubbles_text" msgid="7730624269650594419">"Pārvaldīt"</string>
<string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"Burbulis ir noraidīts."</string>
diff --git a/libs/WindowManager/Shell/res/values-mk/strings.xml b/libs/WindowManager/Shell/res/values-mk/strings.xml
index 008cff29ee9e..49e850fac1c0 100644
--- a/libs/WindowManager/Shell/res/values-mk/strings.xml
+++ b/libs/WindowManager/Shell/res/values-mk/strings.xml
@@ -76,10 +76,8 @@
<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>
- <!-- no translation found for bubble_bar_education_manage_title (6148404487810835924) -->
- <skip />
- <!-- no translation found for bubble_bar_education_manage_text (3199732148641842038) -->
- <skip />
+ <string name="bubble_bar_education_manage_title" msgid="6148404487810835924">"Контролирајте ги балончињата во секое време"</string>
+ <string name="bubble_bar_education_manage_text" msgid="3199732148641842038">"Допрете тука за да одредите на кои апл. и разговори може да се појават балончиња"</string>
<string name="notification_bubble_title" msgid="6082910224488253378">"Балонче"</string>
<string name="manage_bubbles_text" msgid="7730624269650594419">"Управувајте"</string>
<string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"Балончето е отфрлено."</string>
diff --git a/libs/WindowManager/Shell/res/values-ml/strings.xml b/libs/WindowManager/Shell/res/values-ml/strings.xml
index 4e2f339b3989..fbb5514e4648 100644
--- a/libs/WindowManager/Shell/res/values-ml/strings.xml
+++ b/libs/WindowManager/Shell/res/values-ml/strings.xml
@@ -76,10 +76,8 @@
<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>
- <!-- no translation found for bubble_bar_education_manage_title (6148404487810835924) -->
- <skip />
- <!-- no translation found for bubble_bar_education_manage_text (3199732148641842038) -->
- <skip />
+ <string name="bubble_bar_education_manage_title" msgid="6148404487810835924">"ബബിളുകൾ ഏതുസമയത്തും നിയന്ത്രിക്കുക"</string>
+ <string name="bubble_bar_education_manage_text" msgid="3199732148641842038">"ഏതൊക്കെ ആപ്പുകളും സംഭാഷണങ്ങളും ബബിൾ ചെയ്യാനാകുമെന്നത് മാനേജ് ചെയ്യാൻ ഇവിടെ ടാപ്പ് ചെയ്യുക"</string>
<string name="notification_bubble_title" msgid="6082910224488253378">"ബബിൾ"</string>
<string name="manage_bubbles_text" msgid="7730624269650594419">"മാനേജ് ചെയ്യുക"</string>
<string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"ബബിൾ ഡിസ്മിസ് ചെയ്തു."</string>
diff --git a/libs/WindowManager/Shell/res/values-mn/strings.xml b/libs/WindowManager/Shell/res/values-mn/strings.xml
index c2081cfb69d7..8274f4456c57 100644
--- a/libs/WindowManager/Shell/res/values-mn/strings.xml
+++ b/libs/WindowManager/Shell/res/values-mn/strings.xml
@@ -76,10 +76,8 @@
<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>
- <!-- no translation found for bubble_bar_education_manage_title (6148404487810835924) -->
- <skip />
- <!-- no translation found for bubble_bar_education_manage_text (3199732148641842038) -->
- <skip />
+ <string name="bubble_bar_education_manage_title" msgid="6148404487810835924">"Бөмбөлгүүдийг хүссэн үедээ хянах"</string>
+ <string name="bubble_bar_education_manage_text" msgid="3199732148641842038">"Ямар апп болон харилцан ярианууд бөмбөлгөөр харагдахыг энд удирдана уу"</string>
<string name="notification_bubble_title" msgid="6082910224488253378">"Бөмбөлөг"</string>
<string name="manage_bubbles_text" msgid="7730624269650594419">"Удирдах"</string>
<string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"Бөмбөлгийг үл хэрэгссэн."</string>
diff --git a/libs/WindowManager/Shell/res/values-mr/strings.xml b/libs/WindowManager/Shell/res/values-mr/strings.xml
index f563ec63c8ce..c1f3e123ac41 100644
--- a/libs/WindowManager/Shell/res/values-mr/strings.xml
+++ b/libs/WindowManager/Shell/res/values-mr/strings.xml
@@ -76,10 +76,8 @@
<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>
- <!-- no translation found for bubble_bar_education_manage_title (6148404487810835924) -->
- <skip />
- <!-- no translation found for bubble_bar_education_manage_text (3199732148641842038) -->
- <skip />
+ <string name="bubble_bar_education_manage_title" msgid="6148404487810835924">"बबल कधीही नियंत्रित करा"</string>
+ <string name="bubble_bar_education_manage_text" msgid="3199732148641842038">"कोणती ॲप्स आणि संभाषणे बबल होऊ शकतात हे व्यवस्थापित करण्यासाठी येथे टॅप करा"</string>
<string name="notification_bubble_title" msgid="6082910224488253378">"बबल"</string>
<string name="manage_bubbles_text" msgid="7730624269650594419">"व्यवस्थापित करा"</string>
<string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"बबल डिसमिस केला."</string>
diff --git a/libs/WindowManager/Shell/res/values-ms/strings.xml b/libs/WindowManager/Shell/res/values-ms/strings.xml
index 054d2968e5a2..82d84e8da6d9 100644
--- a/libs/WindowManager/Shell/res/values-ms/strings.xml
+++ b/libs/WindowManager/Shell/res/values-ms/strings.xml
@@ -76,10 +76,8 @@
<string name="bubbles_user_education_got_it" msgid="3382046149225428296">"OK"</string>
<string name="bubble_overflow_empty_title" msgid="2397251267073294968">"Tiada gelembung terbaharu"</string>
<string name="bubble_overflow_empty_subtitle" msgid="2627417924958633713">"Gelembung baharu dan gelembung yang diketepikan akan dipaparkan di sini"</string>
- <!-- no translation found for bubble_bar_education_manage_title (6148404487810835924) -->
- <skip />
- <!-- no translation found for bubble_bar_education_manage_text (3199732148641842038) -->
- <skip />
+ <string name="bubble_bar_education_manage_title" msgid="6148404487810835924">"Kawal gelembung pada bila-bila masa"</string>
+ <string name="bubble_bar_education_manage_text" msgid="3199732148641842038">"Ketik di sini untuk mengurus apl dan perbualan yang boleh menggunakan gelembung"</string>
<string name="notification_bubble_title" msgid="6082910224488253378">"Gelembung"</string>
<string name="manage_bubbles_text" msgid="7730624269650594419">"Urus"</string>
<string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"Gelembung diketepikan."</string>
diff --git a/libs/WindowManager/Shell/res/values-my/strings.xml b/libs/WindowManager/Shell/res/values-my/strings.xml
index 8af8bf48a0d8..2e88ab341984 100644
--- a/libs/WindowManager/Shell/res/values-my/strings.xml
+++ b/libs/WindowManager/Shell/res/values-my/strings.xml
@@ -76,10 +76,8 @@
<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>
- <!-- no translation found for bubble_bar_education_manage_title (6148404487810835924) -->
- <skip />
- <!-- no translation found for bubble_bar_education_manage_text (3199732148641842038) -->
- <skip />
+ <string name="bubble_bar_education_manage_title" msgid="6148404487810835924">"ပူဖောင်းကွက်ကို အချိန်မရွေး ထိန်းချုပ်ရန်"</string>
+ <string name="bubble_bar_education_manage_text" msgid="3199732148641842038">"ပူဖောင်းကွက်သုံးနိုင်သည့် အက်ပ်နှင့် စကားဝိုင်းများ စီမံရန် ဤနေရာကို တို့ပါ"</string>
<string name="notification_bubble_title" msgid="6082910224488253378">"ပူဖောင်းဖောက်သံ"</string>
<string name="manage_bubbles_text" msgid="7730624269650594419">"စီမံရန်"</string>
<string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"ပူဖောင်းကွက် ဖယ်လိုက်သည်။"</string>
diff --git a/libs/WindowManager/Shell/res/values-nb/strings.xml b/libs/WindowManager/Shell/res/values-nb/strings.xml
index 8ac35371ee8a..f7ea9ce78dd8 100644
--- a/libs/WindowManager/Shell/res/values-nb/strings.xml
+++ b/libs/WindowManager/Shell/res/values-nb/strings.xml
@@ -76,10 +76,8 @@
<string name="bubbles_user_education_got_it" msgid="3382046149225428296">"Greit"</string>
<string name="bubble_overflow_empty_title" msgid="2397251267073294968">"Ingen nylige bobler"</string>
<string name="bubble_overflow_empty_subtitle" msgid="2627417924958633713">"Nylige bobler og avviste bobler vises her"</string>
- <!-- no translation found for bubble_bar_education_manage_title (6148404487810835924) -->
- <skip />
- <!-- no translation found for bubble_bar_education_manage_text (3199732148641842038) -->
- <skip />
+ <string name="bubble_bar_education_manage_title" msgid="6148404487810835924">"Kontroller bobler når som helst"</string>
+ <string name="bubble_bar_education_manage_text" msgid="3199732148641842038">"Trykk her for å administrere hvilke apper og samtaler som kan vises i bobler"</string>
<string name="notification_bubble_title" msgid="6082910224488253378">"Boble"</string>
<string name="manage_bubbles_text" msgid="7730624269650594419">"Administrer"</string>
<string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"Boblen er avvist."</string>
diff --git a/libs/WindowManager/Shell/res/values-ne/strings.xml b/libs/WindowManager/Shell/res/values-ne/strings.xml
index a46e356acce1..3f6dc046c10b 100644
--- a/libs/WindowManager/Shell/res/values-ne/strings.xml
+++ b/libs/WindowManager/Shell/res/values-ne/strings.xml
@@ -76,10 +76,8 @@
<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>
- <!-- no translation found for bubble_bar_education_manage_title (6148404487810835924) -->
- <skip />
- <!-- no translation found for bubble_bar_education_manage_text (3199732148641842038) -->
- <skip />
+ <string name="bubble_bar_education_manage_title" msgid="6148404487810835924">"जुनसुकै बेला बबलसम्बन्धी सुविधा नियन्त्रण गर्नुहोस्"</string>
+ <string name="bubble_bar_education_manage_text" msgid="3199732148641842038">"कुन एप र कुराकानी बबल प्रयोग गर्न सक्छन् भन्ने कुराको व्यवस्थापन गर्न यहाँ ट्याप गर्नुहोस्"</string>
<string name="notification_bubble_title" msgid="6082910224488253378">"बबल"</string>
<string name="manage_bubbles_text" msgid="7730624269650594419">"व्यवस्थापन गर्नुहोस्"</string>
<string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"बबल हटाइयो।"</string>
diff --git a/libs/WindowManager/Shell/res/values-nl/strings.xml b/libs/WindowManager/Shell/res/values-nl/strings.xml
index ed013153c80a..978ed3ccad3c 100644
--- a/libs/WindowManager/Shell/res/values-nl/strings.xml
+++ b/libs/WindowManager/Shell/res/values-nl/strings.xml
@@ -76,10 +76,8 @@
<string name="bubbles_user_education_got_it" msgid="3382046149225428296">"OK"</string>
<string name="bubble_overflow_empty_title" msgid="2397251267073294968">"Geen recente bubbels"</string>
<string name="bubble_overflow_empty_subtitle" msgid="2627417924958633713">"Recente bubbels en gesloten bubbels zie je hier"</string>
- <!-- no translation found for bubble_bar_education_manage_title (6148404487810835924) -->
- <skip />
- <!-- no translation found for bubble_bar_education_manage_text (3199732148641842038) -->
- <skip />
+ <string name="bubble_bar_education_manage_title" msgid="6148404487810835924">"Bubbels beheren wanneer je wilt"</string>
+ <string name="bubble_bar_education_manage_text" msgid="3199732148641842038">"Tik hier om te beheren welke apps en gesprekken als bubbel kunnen worden getoond"</string>
<string name="notification_bubble_title" msgid="6082910224488253378">"Bubbel"</string>
<string name="manage_bubbles_text" msgid="7730624269650594419">"Beheren"</string>
<string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"Bubbel gesloten."</string>
diff --git a/libs/WindowManager/Shell/res/values-or/strings.xml b/libs/WindowManager/Shell/res/values-or/strings.xml
index 8465907f3836..b66448b6308f 100644
--- a/libs/WindowManager/Shell/res/values-or/strings.xml
+++ b/libs/WindowManager/Shell/res/values-or/strings.xml
@@ -76,10 +76,8 @@
<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>
- <!-- no translation found for bubble_bar_education_manage_title (6148404487810835924) -->
- <skip />
- <!-- no translation found for bubble_bar_education_manage_text (3199732148641842038) -->
- <skip />
+ <string name="bubble_bar_education_manage_title" msgid="6148404487810835924">"ଯେ କୌଣସି ସମୟରେ ବବଲଗୁଡ଼ିକ ନିୟନ୍ତ୍ରଣ କରନ୍ତୁ"</string>
+ <string name="bubble_bar_education_manage_text" msgid="3199732148641842038">"କେଉଁ ଆପ୍ସ ଓ ବାର୍ତ୍ତାଳାପଗୁଡ଼ିକ ବବଲ ହୋଇପାରିବ ତାହା ପରିଚାଳନା କରିବାକୁ ଏଠାରେ ଟାପ କରନ୍ତୁ"</string>
<string name="notification_bubble_title" msgid="6082910224488253378">"ବବଲ୍"</string>
<string name="manage_bubbles_text" msgid="7730624269650594419">"ପରିଚାଳନା କରନ୍ତୁ"</string>
<string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"ବବଲ୍ ଖାରଜ କରାଯାଇଛି।"</string>
diff --git a/libs/WindowManager/Shell/res/values-pa/strings.xml b/libs/WindowManager/Shell/res/values-pa/strings.xml
index 243fec3b4417..72cb92053e56 100644
--- a/libs/WindowManager/Shell/res/values-pa/strings.xml
+++ b/libs/WindowManager/Shell/res/values-pa/strings.xml
@@ -76,10 +76,8 @@
<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>
- <!-- no translation found for bubble_bar_education_manage_title (6148404487810835924) -->
- <skip />
- <!-- no translation found for bubble_bar_education_manage_text (3199732148641842038) -->
- <skip />
+ <string name="bubble_bar_education_manage_title" msgid="6148404487810835924">"ਬਬਲ ਦੀ ਸੁਵਿਧਾ ਨੂੰ ਕਿਸੇ ਵੀ ਵੇਲੇ ਕੰਟਰੋਲ ਕਰੋ"</string>
+ <string name="bubble_bar_education_manage_text" msgid="3199732148641842038">"ਇਹ ਪ੍ਰਬੰਧਨ ਕਰਨ ਲਈ ਇੱਥੇ ਟੈਪ ਕਰੋ ਕਿ ਕਿਹੜੀਆਂ ਐਪਾਂ ਅਤੇ ਗੱਲਾਂਬਾਤਾਂ ਬਬਲ ਹੋ ਸਕਦੀਆਂ ਹਨ"</string>
<string name="notification_bubble_title" msgid="6082910224488253378">"ਬੁਲਬੁਲਾ"</string>
<string name="manage_bubbles_text" msgid="7730624269650594419">"ਪ੍ਰਬੰਧਨ ਕਰੋ"</string>
<string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"ਬਬਲ ਨੂੰ ਖਾਰਜ ਕੀਤਾ ਗਿਆ।"</string>
diff --git a/libs/WindowManager/Shell/res/values-pl/strings.xml b/libs/WindowManager/Shell/res/values-pl/strings.xml
index 34bc1a08207f..24c1f1410fde 100644
--- a/libs/WindowManager/Shell/res/values-pl/strings.xml
+++ b/libs/WindowManager/Shell/res/values-pl/strings.xml
@@ -76,10 +76,8 @@
<string name="bubbles_user_education_got_it" msgid="3382046149225428296">"OK"</string>
<string name="bubble_overflow_empty_title" msgid="2397251267073294968">"Brak ostatnich dymków"</string>
<string name="bubble_overflow_empty_subtitle" msgid="2627417924958633713">"Tutaj będą pojawiać się ostatnie i odrzucone dymki"</string>
- <!-- no translation found for bubble_bar_education_manage_title (6148404487810835924) -->
- <skip />
- <!-- no translation found for bubble_bar_education_manage_text (3199732148641842038) -->
- <skip />
+ <string name="bubble_bar_education_manage_title" msgid="6148404487810835924">"Zarządzaj dymkami, kiedy chcesz"</string>
+ <string name="bubble_bar_education_manage_text" msgid="3199732148641842038">"Kliknij tutaj, aby zarządzać wyświetlaniem aplikacji i rozmów jako dymków"</string>
<string name="notification_bubble_title" msgid="6082910224488253378">"Dymek"</string>
<string name="manage_bubbles_text" msgid="7730624269650594419">"Zarządzaj"</string>
<string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"Zamknięto dymek"</string>
diff --git a/libs/WindowManager/Shell/res/values-pt-rBR/strings.xml b/libs/WindowManager/Shell/res/values-pt-rBR/strings.xml
index 85f2fa48b81f..69002026f2e5 100644
--- a/libs/WindowManager/Shell/res/values-pt-rBR/strings.xml
+++ b/libs/WindowManager/Shell/res/values-pt-rBR/strings.xml
@@ -76,10 +76,8 @@
<string name="bubbles_user_education_got_it" msgid="3382046149225428296">"Ok"</string>
<string name="bubble_overflow_empty_title" msgid="2397251267073294968">"Nenhum balão recente"</string>
<string name="bubble_overflow_empty_subtitle" msgid="2627417924958633713">"Os balões recentes e dispensados aparecerão aqui"</string>
- <!-- no translation found for bubble_bar_education_manage_title (6148404487810835924) -->
- <skip />
- <!-- no translation found for bubble_bar_education_manage_text (3199732148641842038) -->
- <skip />
+ <string name="bubble_bar_education_manage_title" msgid="6148404487810835924">"Controle os balões a qualquer momento"</string>
+ <string name="bubble_bar_education_manage_text" msgid="3199732148641842038">"Toque aqui para gerenciar quais apps e conversas podem aparecer em balões"</string>
<string name="notification_bubble_title" msgid="6082910224488253378">"Bolha"</string>
<string name="manage_bubbles_text" msgid="7730624269650594419">"Gerenciar"</string>
<string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"Balão dispensado."</string>
diff --git a/libs/WindowManager/Shell/res/values-pt-rPT/strings.xml b/libs/WindowManager/Shell/res/values-pt-rPT/strings.xml
index 083e2e7143dc..853c682b5089 100644
--- a/libs/WindowManager/Shell/res/values-pt-rPT/strings.xml
+++ b/libs/WindowManager/Shell/res/values-pt-rPT/strings.xml
@@ -76,10 +76,8 @@
<string name="bubbles_user_education_got_it" msgid="3382046149225428296">"OK"</string>
<string name="bubble_overflow_empty_title" msgid="2397251267073294968">"Nenhum balão recente"</string>
<string name="bubble_overflow_empty_subtitle" msgid="2627417924958633713">"Os balões recentes e ignorados vão aparecer aqui."</string>
- <!-- no translation found for bubble_bar_education_manage_title (6148404487810835924) -->
- <skip />
- <!-- no translation found for bubble_bar_education_manage_text (3199732148641842038) -->
- <skip />
+ <string name="bubble_bar_education_manage_title" msgid="6148404487810835924">"Controle os balões em qualquer altura"</string>
+ <string name="bubble_bar_education_manage_text" msgid="3199732148641842038">"Toque aqui para gerir que apps e conversas podem aparecer em balões"</string>
<string name="notification_bubble_title" msgid="6082910224488253378">"Balão"</string>
<string name="manage_bubbles_text" msgid="7730624269650594419">"Gerir"</string>
<string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"Balão ignorado."</string>
diff --git a/libs/WindowManager/Shell/res/values-pt/strings.xml b/libs/WindowManager/Shell/res/values-pt/strings.xml
index 85f2fa48b81f..69002026f2e5 100644
--- a/libs/WindowManager/Shell/res/values-pt/strings.xml
+++ b/libs/WindowManager/Shell/res/values-pt/strings.xml
@@ -76,10 +76,8 @@
<string name="bubbles_user_education_got_it" msgid="3382046149225428296">"Ok"</string>
<string name="bubble_overflow_empty_title" msgid="2397251267073294968">"Nenhum balão recente"</string>
<string name="bubble_overflow_empty_subtitle" msgid="2627417924958633713">"Os balões recentes e dispensados aparecerão aqui"</string>
- <!-- no translation found for bubble_bar_education_manage_title (6148404487810835924) -->
- <skip />
- <!-- no translation found for bubble_bar_education_manage_text (3199732148641842038) -->
- <skip />
+ <string name="bubble_bar_education_manage_title" msgid="6148404487810835924">"Controle os balões a qualquer momento"</string>
+ <string name="bubble_bar_education_manage_text" msgid="3199732148641842038">"Toque aqui para gerenciar quais apps e conversas podem aparecer em balões"</string>
<string name="notification_bubble_title" msgid="6082910224488253378">"Bolha"</string>
<string name="manage_bubbles_text" msgid="7730624269650594419">"Gerenciar"</string>
<string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"Balão dispensado."</string>
diff --git a/libs/WindowManager/Shell/res/values-ro/strings.xml b/libs/WindowManager/Shell/res/values-ro/strings.xml
index 6e8d1160d08c..7356f7cf08d2 100644
--- a/libs/WindowManager/Shell/res/values-ro/strings.xml
+++ b/libs/WindowManager/Shell/res/values-ro/strings.xml
@@ -76,10 +76,8 @@
<string name="bubbles_user_education_got_it" msgid="3382046149225428296">"OK"</string>
<string name="bubble_overflow_empty_title" msgid="2397251267073294968">"Nu există baloane recente"</string>
<string name="bubble_overflow_empty_subtitle" msgid="2627417924958633713">"Baloanele recente și baloanele respinse vor apărea aici"</string>
- <!-- no translation found for bubble_bar_education_manage_title (6148404487810835924) -->
- <skip />
- <!-- no translation found for bubble_bar_education_manage_text (3199732148641842038) -->
- <skip />
+ <string name="bubble_bar_education_manage_title" msgid="6148404487810835924">"Controlează baloanele oricând"</string>
+ <string name="bubble_bar_education_manage_text" msgid="3199732148641842038">"Atinge aici pentru a gestiona aplicațiile și conversațiile care pot apărea în balon"</string>
<string name="notification_bubble_title" msgid="6082910224488253378">"Balon"</string>
<string name="manage_bubbles_text" msgid="7730624269650594419">"Gestionează"</string>
<string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"Balonul a fost respins."</string>
diff --git a/libs/WindowManager/Shell/res/values-ru/strings.xml b/libs/WindowManager/Shell/res/values-ru/strings.xml
index c3cd9594552a..61e3ec9b7da2 100644
--- a/libs/WindowManager/Shell/res/values-ru/strings.xml
+++ b/libs/WindowManager/Shell/res/values-ru/strings.xml
@@ -76,10 +76,8 @@
<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>
- <!-- no translation found for bubble_bar_education_manage_title (6148404487810835924) -->
- <skip />
- <!-- no translation found for bubble_bar_education_manage_text (3199732148641842038) -->
- <skip />
+ <string name="bubble_bar_education_manage_title" msgid="6148404487810835924">"Всплывающие чаты"</string>
+ <string name="bubble_bar_education_manage_text" msgid="3199732148641842038">"Укажите приложения и разговоры, для которых разрешены всплывающие чаты."</string>
<string name="notification_bubble_title" msgid="6082910224488253378">"Всплывающая подсказка"</string>
<string name="manage_bubbles_text" msgid="7730624269650594419">"Настроить"</string>
<string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"Всплывающий чат закрыт."</string>
diff --git a/libs/WindowManager/Shell/res/values-si/strings.xml b/libs/WindowManager/Shell/res/values-si/strings.xml
index a1e246a95bf2..ac78385b9644 100644
--- a/libs/WindowManager/Shell/res/values-si/strings.xml
+++ b/libs/WindowManager/Shell/res/values-si/strings.xml
@@ -76,10 +76,8 @@
<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>
- <!-- no translation found for bubble_bar_education_manage_title (6148404487810835924) -->
- <skip />
- <!-- no translation found for bubble_bar_education_manage_text (3199732148641842038) -->
- <skip />
+ <string name="bubble_bar_education_manage_title" msgid="6148404487810835924">"ඕනෑම වේලාවක බුබුලු පාලනය කරන්න"</string>
+ <string name="bubble_bar_education_manage_text" msgid="3199732148641842038">"බුබුලු කළ හැකි යෙදුම් සහ සංවාද කළමනාකරණය කිරීමට මෙහි තට්ටු කරන්න"</string>
<string name="notification_bubble_title" msgid="6082910224488253378">"බුබුළු"</string>
<string name="manage_bubbles_text" msgid="7730624269650594419">"කළමනා කරන්න"</string>
<string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"බුබුල ඉවත දමා ඇත."</string>
diff --git a/libs/WindowManager/Shell/res/values-sk/strings.xml b/libs/WindowManager/Shell/res/values-sk/strings.xml
index c27425d6948a..d659d51afc5f 100644
--- a/libs/WindowManager/Shell/res/values-sk/strings.xml
+++ b/libs/WindowManager/Shell/res/values-sk/strings.xml
@@ -76,10 +76,8 @@
<string name="bubbles_user_education_got_it" msgid="3382046149225428296">"Dobre"</string>
<string name="bubble_overflow_empty_title" msgid="2397251267073294968">"Žiadne nedávne bubliny"</string>
<string name="bubble_overflow_empty_subtitle" msgid="2627417924958633713">"Tu sa budú zobrazovať nedávne a zavreté bubliny"</string>
- <!-- no translation found for bubble_bar_education_manage_title (6148404487810835924) -->
- <skip />
- <!-- no translation found for bubble_bar_education_manage_text (3199732148641842038) -->
- <skip />
+ <string name="bubble_bar_education_manage_title" msgid="6148404487810835924">"Ovládajte bubliny kedykoľvek"</string>
+ <string name="bubble_bar_education_manage_text" msgid="3199732148641842038">"Klepnite tu a spravujte, ktoré aplikácie a konverzácie môžu ovládať bubliny"</string>
<string name="notification_bubble_title" msgid="6082910224488253378">"Bublina"</string>
<string name="manage_bubbles_text" msgid="7730624269650594419">"Spravovať"</string>
<string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"Bublina bola zavretá."</string>
diff --git a/libs/WindowManager/Shell/res/values-sl/strings.xml b/libs/WindowManager/Shell/res/values-sl/strings.xml
index e3dcca899bf2..91871fbf94ec 100644
--- a/libs/WindowManager/Shell/res/values-sl/strings.xml
+++ b/libs/WindowManager/Shell/res/values-sl/strings.xml
@@ -76,10 +76,8 @@
<string name="bubbles_user_education_got_it" msgid="3382046149225428296">"V redu"</string>
<string name="bubble_overflow_empty_title" msgid="2397251267073294968">"Ni nedavnih oblačkov"</string>
<string name="bubble_overflow_empty_subtitle" msgid="2627417924958633713">"Tukaj bodo prikazani tako nedavni kot tudi opuščeni oblački"</string>
- <!-- no translation found for bubble_bar_education_manage_title (6148404487810835924) -->
- <skip />
- <!-- no translation found for bubble_bar_education_manage_text (3199732148641842038) -->
- <skip />
+ <string name="bubble_bar_education_manage_title" msgid="6148404487810835924">"Upravljanje oblačkov"</string>
+ <string name="bubble_bar_education_manage_text" msgid="3199732148641842038">"Dotaknite se tukaj za upravljanje aplikacij in pogovorov, ki so lahko prikazani v oblačkih"</string>
<string name="notification_bubble_title" msgid="6082910224488253378">"Mehurček"</string>
<string name="manage_bubbles_text" msgid="7730624269650594419">"Upravljanje"</string>
<string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"Oblaček je bil opuščen."</string>
diff --git a/libs/WindowManager/Shell/res/values-sq/strings.xml b/libs/WindowManager/Shell/res/values-sq/strings.xml
index b5b2d1891cab..45eb04a45271 100644
--- a/libs/WindowManager/Shell/res/values-sq/strings.xml
+++ b/libs/WindowManager/Shell/res/values-sq/strings.xml
@@ -76,10 +76,8 @@
<string name="bubbles_user_education_got_it" msgid="3382046149225428296">"E kuptova"</string>
<string name="bubble_overflow_empty_title" msgid="2397251267073294968">"Nuk ka flluska të fundit"</string>
<string name="bubble_overflow_empty_subtitle" msgid="2627417924958633713">"Flluskat e fundit dhe flluskat e hequra do të shfaqen këtu"</string>
- <!-- no translation found for bubble_bar_education_manage_title (6148404487810835924) -->
- <skip />
- <!-- no translation found for bubble_bar_education_manage_text (3199732148641842038) -->
- <skip />
+ <string name="bubble_bar_education_manage_title" msgid="6148404487810835924">"Kontrollo flluskat në çdo moment"</string>
+ <string name="bubble_bar_education_manage_text" msgid="3199732148641842038">"Trokit këtu për të menaxhuar aplikacionet e bisedat që do të shfaqen në flluska"</string>
<string name="notification_bubble_title" msgid="6082910224488253378">"Flluskë"</string>
<string name="manage_bubbles_text" msgid="7730624269650594419">"Menaxho"</string>
<string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"Flluska u hoq."</string>
diff --git a/libs/WindowManager/Shell/res/values-sr/strings.xml b/libs/WindowManager/Shell/res/values-sr/strings.xml
index 3404bca2bb9d..368df542796f 100644
--- a/libs/WindowManager/Shell/res/values-sr/strings.xml
+++ b/libs/WindowManager/Shell/res/values-sr/strings.xml
@@ -76,10 +76,8 @@
<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>
- <!-- no translation found for bubble_bar_education_manage_title (6148404487810835924) -->
- <skip />
- <!-- no translation found for bubble_bar_education_manage_text (3199732148641842038) -->
- <skip />
+ <string name="bubble_bar_education_manage_title" msgid="6148404487810835924">"Контролишите облачиће у сваком тренутку"</string>
+ <string name="bubble_bar_education_manage_text" msgid="3199732148641842038">"Додирните овде и одредите које апликације и конверзације могу да имају облачић"</string>
<string name="notification_bubble_title" msgid="6082910224488253378">"Облачић"</string>
<string name="manage_bubbles_text" msgid="7730624269650594419">"Управљајте"</string>
<string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"Облачић је одбачен."</string>
diff --git a/libs/WindowManager/Shell/res/values-sv/strings.xml b/libs/WindowManager/Shell/res/values-sv/strings.xml
index 1f81e0fa5f64..35d5b7af2b62 100644
--- a/libs/WindowManager/Shell/res/values-sv/strings.xml
+++ b/libs/WindowManager/Shell/res/values-sv/strings.xml
@@ -76,10 +76,8 @@
<string name="bubbles_user_education_got_it" msgid="3382046149225428296">"OK"</string>
<string name="bubble_overflow_empty_title" msgid="2397251267073294968">"Inga nya bubblor"</string>
<string name="bubble_overflow_empty_subtitle" msgid="2627417924958633713">"De senaste bubblorna och ignorerade bubblor visas här"</string>
- <!-- no translation found for bubble_bar_education_manage_title (6148404487810835924) -->
- <skip />
- <!-- no translation found for bubble_bar_education_manage_text (3199732148641842038) -->
- <skip />
+ <string name="bubble_bar_education_manage_title" msgid="6148404487810835924">"Styr bubblor när som helst"</string>
+ <string name="bubble_bar_education_manage_text" msgid="3199732148641842038">"Tryck här för att hantera vilka appar och konversationer som får visas i bubblor"</string>
<string name="notification_bubble_title" msgid="6082910224488253378">"Bubbla"</string>
<string name="manage_bubbles_text" msgid="7730624269650594419">"Hantera"</string>
<string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"Bubblan ignorerades."</string>
diff --git a/libs/WindowManager/Shell/res/values-sw/strings.xml b/libs/WindowManager/Shell/res/values-sw/strings.xml
index 8ec4e3415a51..52e0a6960948 100644
--- a/libs/WindowManager/Shell/res/values-sw/strings.xml
+++ b/libs/WindowManager/Shell/res/values-sw/strings.xml
@@ -76,10 +76,8 @@
<string name="bubbles_user_education_got_it" msgid="3382046149225428296">"Nimeelewa"</string>
<string name="bubble_overflow_empty_title" msgid="2397251267073294968">"Hakuna viputo vya hivi majuzi"</string>
<string name="bubble_overflow_empty_subtitle" msgid="2627417924958633713">"Viputo vya hivi karibuni na vile vilivyoondolewa vitaonekana hapa"</string>
- <!-- no translation found for bubble_bar_education_manage_title (6148404487810835924) -->
- <skip />
- <!-- no translation found for bubble_bar_education_manage_text (3199732148641842038) -->
- <skip />
+ <string name="bubble_bar_education_manage_title" msgid="6148404487810835924">"Dhibiti viputo wakati wowote"</string>
+ <string name="bubble_bar_education_manage_text" msgid="3199732148641842038">"Gusa hapa ili udhibiti programu na mazungumzo yanayoweza kutumia viputo"</string>
<string name="notification_bubble_title" msgid="6082910224488253378">"Kiputo"</string>
<string name="manage_bubbles_text" msgid="7730624269650594419">"Dhibiti"</string>
<string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"Umeondoa kiputo."</string>
diff --git a/libs/WindowManager/Shell/res/values-ta/strings.xml b/libs/WindowManager/Shell/res/values-ta/strings.xml
index 6a8559dc262c..98a7d679014c 100644
--- a/libs/WindowManager/Shell/res/values-ta/strings.xml
+++ b/libs/WindowManager/Shell/res/values-ta/strings.xml
@@ -76,10 +76,8 @@
<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>
- <!-- no translation found for bubble_bar_education_manage_title (6148404487810835924) -->
- <skip />
- <!-- no translation found for bubble_bar_education_manage_text (3199732148641842038) -->
- <skip />
+ <string name="bubble_bar_education_manage_title" msgid="6148404487810835924">"எப்போது வேண்டுமானாலும் குமிழ்களைக் கட்டுப்படுத்துங்கள்"</string>
+ <string name="bubble_bar_education_manage_text" msgid="3199732148641842038">"எந்தெந்த ஆப்ஸும் உரையாடல்களும் குமிழியாகலாம் என்பதை நிர்வகிக்க இங்கே தட்டுங்கள்"</string>
<string name="notification_bubble_title" msgid="6082910224488253378">"பபிள்"</string>
<string name="manage_bubbles_text" msgid="7730624269650594419">"நிர்வகி"</string>
<string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"குமிழ் நிராகரிக்கப்பட்டது."</string>
diff --git a/libs/WindowManager/Shell/res/values-te/strings.xml b/libs/WindowManager/Shell/res/values-te/strings.xml
index 1c1e3cbd5697..70f810e21fcc 100644
--- a/libs/WindowManager/Shell/res/values-te/strings.xml
+++ b/libs/WindowManager/Shell/res/values-te/strings.xml
@@ -76,10 +76,8 @@
<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>
- <!-- no translation found for bubble_bar_education_manage_title (6148404487810835924) -->
- <skip />
- <!-- no translation found for bubble_bar_education_manage_text (3199732148641842038) -->
- <skip />
+ <string name="bubble_bar_education_manage_title" msgid="6148404487810835924">"బబుల్స్‌ను ఎప్పుడైనా కంట్రోల్ చేయండి"</string>
+ <string name="bubble_bar_education_manage_text" msgid="3199732148641842038">"ఏ యాప్‌లు, సంభాషణలను బబుల్ చేయాలో మేనేజ్ చేయడానికి ఇక్కడ ట్యాప్ చేయండి"</string>
<string name="notification_bubble_title" msgid="6082910224488253378">"బబుల్"</string>
<string name="manage_bubbles_text" msgid="7730624269650594419">"మేనేజ్ చేయండి"</string>
<string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"బబుల్ విస్మరించబడింది."</string>
diff --git a/libs/WindowManager/Shell/res/values-th/strings.xml b/libs/WindowManager/Shell/res/values-th/strings.xml
index a0f0e275ba17..0efaab2d2f15 100644
--- a/libs/WindowManager/Shell/res/values-th/strings.xml
+++ b/libs/WindowManager/Shell/res/values-th/strings.xml
@@ -76,10 +76,8 @@
<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>
- <!-- no translation found for bubble_bar_education_manage_title (6148404487810835924) -->
- <skip />
- <!-- no translation found for bubble_bar_education_manage_text (3199732148641842038) -->
- <skip />
+ <string name="bubble_bar_education_manage_title" msgid="6148404487810835924">"ควบคุมบับเบิลได้ทุกเมื่อ"</string>
+ <string name="bubble_bar_education_manage_text" msgid="3199732148641842038">"แตะที่นี่เพื่อจัดการแอปและการสนทนาที่แสดงเป็นบับเบิลได้"</string>
<string name="notification_bubble_title" msgid="6082910224488253378">"บับเบิล"</string>
<string name="manage_bubbles_text" msgid="7730624269650594419">"จัดการ"</string>
<string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"ปิดบับเบิลแล้ว"</string>
diff --git a/libs/WindowManager/Shell/res/values-tl/strings.xml b/libs/WindowManager/Shell/res/values-tl/strings.xml
index 9bc17f091a30..e5d535015c52 100644
--- a/libs/WindowManager/Shell/res/values-tl/strings.xml
+++ b/libs/WindowManager/Shell/res/values-tl/strings.xml
@@ -76,10 +76,8 @@
<string name="bubbles_user_education_got_it" msgid="3382046149225428296">"OK"</string>
<string name="bubble_overflow_empty_title" msgid="2397251267073294968">"Walang kamakailang bubble"</string>
<string name="bubble_overflow_empty_subtitle" msgid="2627417924958633713">"Lalabas dito ang mga kamakailang bubble at na-dismiss na bubble"</string>
- <!-- no translation found for bubble_bar_education_manage_title (6148404487810835924) -->
- <skip />
- <!-- no translation found for bubble_bar_education_manage_text (3199732148641842038) -->
- <skip />
+ <string name="bubble_bar_education_manage_title" msgid="6148404487810835924">"Kontrolin ang mga bubble anumang oras"</string>
+ <string name="bubble_bar_education_manage_text" msgid="3199732148641842038">"Mag-tap dito para pamahalaan ang mga app at conversion na puwedeng mag-bubble"</string>
<string name="notification_bubble_title" msgid="6082910224488253378">"Bubble"</string>
<string name="manage_bubbles_text" msgid="7730624269650594419">"Pamahalaan"</string>
<string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"Na-dismiss na ang bubble."</string>
diff --git a/libs/WindowManager/Shell/res/values-tr/strings.xml b/libs/WindowManager/Shell/res/values-tr/strings.xml
index 059ec7340d69..8e7f1620354b 100644
--- a/libs/WindowManager/Shell/res/values-tr/strings.xml
+++ b/libs/WindowManager/Shell/res/values-tr/strings.xml
@@ -76,10 +76,8 @@
<string name="bubbles_user_education_got_it" msgid="3382046149225428296">"Anladım"</string>
<string name="bubble_overflow_empty_title" msgid="2397251267073294968">"Son kapatılan baloncuk yok"</string>
<string name="bubble_overflow_empty_subtitle" msgid="2627417924958633713">"Son baloncuklar ve kapattığınız baloncuklar burada görünür"</string>
- <!-- no translation found for bubble_bar_education_manage_title (6148404487810835924) -->
- <skip />
- <!-- no translation found for bubble_bar_education_manage_text (3199732148641842038) -->
- <skip />
+ <string name="bubble_bar_education_manage_title" msgid="6148404487810835924">"Baloncukları istediğiniz zaman kontrol edin"</string>
+ <string name="bubble_bar_education_manage_text" msgid="3199732148641842038">"Buraya dokunarak baloncuk olarak gösterilecek uygulama ve görüşmeleri yönetin"</string>
<string name="notification_bubble_title" msgid="6082910224488253378">"Baloncuk"</string>
<string name="manage_bubbles_text" msgid="7730624269650594419">"Yönet"</string>
<string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"Balon kapatıldı."</string>
diff --git a/libs/WindowManager/Shell/res/values-uk/strings.xml b/libs/WindowManager/Shell/res/values-uk/strings.xml
index a4a4a78a8755..5c7c6c4dae30 100644
--- a/libs/WindowManager/Shell/res/values-uk/strings.xml
+++ b/libs/WindowManager/Shell/res/values-uk/strings.xml
@@ -76,10 +76,8 @@
<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>
- <!-- no translation found for bubble_bar_education_manage_title (6148404487810835924) -->
- <skip />
- <!-- no translation found for bubble_bar_education_manage_text (3199732148641842038) -->
- <skip />
+ <string name="bubble_bar_education_manage_title" msgid="6148404487810835924">"Контроль спливаючих чатів"</string>
+ <string name="bubble_bar_education_manage_text" msgid="3199732148641842038">"Натисніть тут, щоб вибрати, для яких додатків і розмов дозволити спливаючі чати"</string>
<string name="notification_bubble_title" msgid="6082910224488253378">"Спливаюче сповіщення"</string>
<string name="manage_bubbles_text" msgid="7730624269650594419">"Налаштувати"</string>
<string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"Спливаюче сповіщення закрито."</string>
diff --git a/libs/WindowManager/Shell/res/values-ur/strings.xml b/libs/WindowManager/Shell/res/values-ur/strings.xml
index b25f13eed644..451d048ca825 100644
--- a/libs/WindowManager/Shell/res/values-ur/strings.xml
+++ b/libs/WindowManager/Shell/res/values-ur/strings.xml
@@ -76,10 +76,8 @@
<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>
- <!-- no translation found for bubble_bar_education_manage_title (6148404487810835924) -->
- <skip />
- <!-- no translation found for bubble_bar_education_manage_text (3199732148641842038) -->
- <skip />
+ <string name="bubble_bar_education_manage_title" msgid="6148404487810835924">"کسی بھی وقت بلبلے کو کنٹرول کریں"</string>
+ <string name="bubble_bar_education_manage_text" msgid="3199732148641842038">"یہ نظم کرنے کے لیے یہاں تھپتھپائیں کہ کون سی ایپس اور گفتگوئیں بلبلہ سکتی ہیں"</string>
<string name="notification_bubble_title" msgid="6082910224488253378">"بلبلہ"</string>
<string name="manage_bubbles_text" msgid="7730624269650594419">"نظم کریں"</string>
<string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"بلبلہ برخاست کر دیا گیا۔"</string>
diff --git a/libs/WindowManager/Shell/res/values-uz/strings.xml b/libs/WindowManager/Shell/res/values-uz/strings.xml
index 5acf7293a060..4211ea7a5e7d 100644
--- a/libs/WindowManager/Shell/res/values-uz/strings.xml
+++ b/libs/WindowManager/Shell/res/values-uz/strings.xml
@@ -76,10 +76,8 @@
<string name="bubbles_user_education_got_it" msgid="3382046149225428296">"OK"</string>
<string name="bubble_overflow_empty_title" msgid="2397251267073294968">"Hech qanday bulutcha topilmadi"</string>
<string name="bubble_overflow_empty_subtitle" msgid="2627417924958633713">"Eng oxirgi va yopilgan bulutchali chatlar shu yerda chiqadi"</string>
- <!-- no translation found for bubble_bar_education_manage_title (6148404487810835924) -->
- <skip />
- <!-- no translation found for bubble_bar_education_manage_text (3199732148641842038) -->
- <skip />
+ <string name="bubble_bar_education_manage_title" msgid="6148404487810835924">"Bulutchalardagi bildirishnomalar"</string>
+ <string name="bubble_bar_education_manage_text" msgid="3199732148641842038">"Bulutchalarda bildirishnomalar chiqishiga ruxsat beruvchi ilova va suhbatlarni tanlang."</string>
<string name="notification_bubble_title" msgid="6082910224488253378">"Pufaklar"</string>
<string name="manage_bubbles_text" msgid="7730624269650594419">"Boshqarish"</string>
<string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"Bulutcha yopildi."</string>
diff --git a/libs/WindowManager/Shell/res/values-vi/strings.xml b/libs/WindowManager/Shell/res/values-vi/strings.xml
index 0777abc087fa..0a0205d8f591 100644
--- a/libs/WindowManager/Shell/res/values-vi/strings.xml
+++ b/libs/WindowManager/Shell/res/values-vi/strings.xml
@@ -76,10 +76,8 @@
<string name="bubbles_user_education_got_it" msgid="3382046149225428296">"Đã hiểu"</string>
<string name="bubble_overflow_empty_title" msgid="2397251267073294968">"Không có bong bóng trò chuyện nào gần đây"</string>
<string name="bubble_overflow_empty_subtitle" msgid="2627417924958633713">"Bong bóng trò chuyện đã đóng và bong bóng trò chuyện gần đây sẽ xuất hiện ở đây"</string>
- <!-- no translation found for bubble_bar_education_manage_title (6148404487810835924) -->
- <skip />
- <!-- no translation found for bubble_bar_education_manage_text (3199732148641842038) -->
- <skip />
+ <string name="bubble_bar_education_manage_title" msgid="6148404487810835924">"Kiểm soát bong bóng bất cứ lúc nào"</string>
+ <string name="bubble_bar_education_manage_text" msgid="3199732148641842038">"Nhấn vào đây để quản lý việc dùng bong bóng cho các ứng dụng và cuộc trò chuyện"</string>
<string name="notification_bubble_title" msgid="6082910224488253378">"Bong bóng"</string>
<string name="manage_bubbles_text" msgid="7730624269650594419">"Quản lý"</string>
<string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"Đã đóng bong bóng."</string>
diff --git a/libs/WindowManager/Shell/res/values-zh-rCN/strings.xml b/libs/WindowManager/Shell/res/values-zh-rCN/strings.xml
index cde5fe3045da..29dc077469e6 100644
--- a/libs/WindowManager/Shell/res/values-zh-rCN/strings.xml
+++ b/libs/WindowManager/Shell/res/values-zh-rCN/strings.xml
@@ -76,10 +76,8 @@
<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>
- <!-- no translation found for bubble_bar_education_manage_title (6148404487810835924) -->
- <skip />
- <!-- no translation found for bubble_bar_education_manage_text (3199732148641842038) -->
- <skip />
+ <string name="bubble_bar_education_manage_title" msgid="6148404487810835924">"随时控制对话泡"</string>
+ <string name="bubble_bar_education_manage_text" msgid="3199732148641842038">"点按此处即可管理哪些应用和对话可以显示对话泡"</string>
<string name="notification_bubble_title" msgid="6082910224488253378">"气泡"</string>
<string name="manage_bubbles_text" msgid="7730624269650594419">"管理"</string>
<string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"已关闭对话泡。"</string>
diff --git a/libs/WindowManager/Shell/res/values-zh-rHK/strings.xml b/libs/WindowManager/Shell/res/values-zh-rHK/strings.xml
index fcb0c91f41d5..0755d61e6a6d 100644
--- a/libs/WindowManager/Shell/res/values-zh-rHK/strings.xml
+++ b/libs/WindowManager/Shell/res/values-zh-rHK/strings.xml
@@ -76,10 +76,8 @@
<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>
- <!-- no translation found for bubble_bar_education_manage_title (6148404487810835924) -->
- <skip />
- <!-- no translation found for bubble_bar_education_manage_text (3199732148641842038) -->
- <skip />
+ <string name="bubble_bar_education_manage_title" msgid="6148404487810835924">"隨時控制對話氣泡"</string>
+ <string name="bubble_bar_education_manage_text" msgid="3199732148641842038">"輕按這裡即可管理哪些應用程式和對話可以使用對話氣泡"</string>
<string name="notification_bubble_title" msgid="6082910224488253378">"氣泡"</string>
<string name="manage_bubbles_text" msgid="7730624269650594419">"管理"</string>
<string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"對話氣泡已關閉。"</string>
diff --git a/libs/WindowManager/Shell/res/values-zh-rTW/strings.xml b/libs/WindowManager/Shell/res/values-zh-rTW/strings.xml
index f272e91fe7a8..f93188343fdf 100644
--- a/libs/WindowManager/Shell/res/values-zh-rTW/strings.xml
+++ b/libs/WindowManager/Shell/res/values-zh-rTW/strings.xml
@@ -76,10 +76,8 @@
<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>
- <!-- no translation found for bubble_bar_education_manage_title (6148404487810835924) -->
- <skip />
- <!-- no translation found for bubble_bar_education_manage_text (3199732148641842038) -->
- <skip />
+ <string name="bubble_bar_education_manage_title" msgid="6148404487810835924">"你隨時可以控管對話框的各項設定"</string>
+ <string name="bubble_bar_education_manage_text" msgid="3199732148641842038">"輕觸這裡即可管理哪些應用程式和對話可顯示對話框"</string>
<string name="notification_bubble_title" msgid="6082910224488253378">"泡泡"</string>
<string name="manage_bubbles_text" msgid="7730624269650594419">"管理"</string>
<string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"已關閉泡泡。"</string>
diff --git a/libs/WindowManager/Shell/res/values-zu/strings.xml b/libs/WindowManager/Shell/res/values-zu/strings.xml
index c1ba6ee01cef..3ba0abee2a95 100644
--- a/libs/WindowManager/Shell/res/values-zu/strings.xml
+++ b/libs/WindowManager/Shell/res/values-zu/strings.xml
@@ -76,10 +76,8 @@
<string name="bubbles_user_education_got_it" msgid="3382046149225428296">"Ngiyezwa"</string>
<string name="bubble_overflow_empty_title" msgid="2397251267073294968">"Awekho amabhamuza akamuva"</string>
<string name="bubble_overflow_empty_subtitle" msgid="2627417924958633713">"Amabhamuza akamuva namabhamuza asusiwe azobonakala lapha."</string>
- <!-- no translation found for bubble_bar_education_manage_title (6148404487810835924) -->
- <skip />
- <!-- no translation found for bubble_bar_education_manage_text (3199732148641842038) -->
- <skip />
+ <string name="bubble_bar_education_manage_title" msgid="6148404487810835924">"Lawula amabhamuza noma nini"</string>
+ <string name="bubble_bar_education_manage_text" msgid="3199732148641842038">"Thepha lapha ukuze ulawule ukuthi yimaphi ama-app kanye nezingxoxo ezingenza amabhamuza"</string>
<string name="notification_bubble_title" msgid="6082910224488253378">"Ibhamuza"</string>
<string name="manage_bubbles_text" msgid="7730624269650594419">"Phatha"</string>
<string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"Ibhamuza licashisiwe."</string>
diff --git a/libs/WindowManager/Shell/res/values/dimen.xml b/libs/WindowManager/Shell/res/values/dimen.xml
index 7edf2fc84f48..cba86c8b3dcf 100644
--- a/libs/WindowManager/Shell/res/values/dimen.xml
+++ b/libs/WindowManager/Shell/res/values/dimen.xml
@@ -428,9 +428,12 @@
<!-- The height of the handle menu's "Windowing" pill in desktop mode. -->
<dimen name="desktop_mode_handle_menu_windowing_pill_height">52dp</dimen>
- <!-- The height of the handle menu's "More Actions" pill in desktop mode. -->
+ <!-- The height of the handle menu's "More Actions" pill in desktop mode, but not freeform. -->
<dimen name="desktop_mode_handle_menu_more_actions_pill_height">156dp</dimen>
+ <!-- The height of the handle menu's "More Actions" pill in freeform desktop windowing mode. -->
+ <dimen name="desktop_mode_handle_menu_more_actions_pill_freeform_height">104dp</dimen>
+
<!-- The top margin of the handle menu in desktop mode. -->
<dimen name="desktop_mode_handle_menu_margin_top">4dp</dimen>
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/ShellTaskOrganizer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/ShellTaskOrganizer.java
index 9aac694e41bf..04795768aefc 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/ShellTaskOrganizer.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/ShellTaskOrganizer.java
@@ -103,7 +103,7 @@ public class ShellTaskOrganizer extends TaskOrganizer implements
default void onBackPressedOnTaskRoot(RunningTaskInfo taskInfo) {}
/** Whether this task listener supports compat UI. */
default boolean supportCompatUI() {
- // All TaskListeners should support compat UI except PIP.
+ // All TaskListeners should support compat UI except PIP and StageCoordinator.
return true;
}
/** Attaches a child window surface to the task surface. */
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/Bubble.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/Bubble.java
index 9a2b81243861..85ea8097a2c1 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/Bubble.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/Bubble.java
@@ -973,9 +973,9 @@ public class Bubble implements BubbleViewProvider {
pw.print(" suppressNotif: "); pw.println(shouldSuppressNotification());
pw.print(" autoExpand: "); pw.println(shouldAutoExpand());
pw.print(" isDismissable: "); pw.println(mIsDismissable);
- pw.println(" bubbleMetadataFlagListener null: " + (mBubbleMetadataFlagListener == null));
+ pw.println(" bubbleMetadataFlagListener null?: " + (mBubbleMetadataFlagListener == null));
if (mExpandedView != null) {
- mExpandedView.dump(pw);
+ mExpandedView.dump(pw, " ");
}
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleController.java
index 645a96153080..dfdc79ea7afa 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleController.java
@@ -1991,13 +1991,20 @@ public class BubbleController implements ConfigurationChangeListener,
* Description of current bubble state.
*/
private void dump(PrintWriter pw, String prefix) {
- pw.println("BubbleController state:");
+ pw.print(prefix); pw.println("BubbleController state:");
+ pw.print(prefix); pw.println(" currentUserId= " + mCurrentUserId);
+ pw.print(prefix); pw.println(" isStatusBarShade= " + mIsStatusBarShade);
+ pw.print(prefix); pw.println(" isShowingAsBubbleBar= " + isShowingAsBubbleBar());
+ pw.println();
+
mBubbleData.dump(pw);
pw.println();
+
if (mStackView != null) {
mStackView.dump(pw);
}
pw.println();
+
mImpl.mCachedState.dump(pw);
}
@@ -2246,8 +2253,7 @@ public class BubbleController implements ConfigurationChangeListener,
pw.println("mIsStackExpanded: " + mIsStackExpanded);
pw.println("mSelectedBubbleKey: " + mSelectedBubbleKey);
- pw.print("mSuppressedBubbleKeys: ");
- pw.println(mSuppressedBubbleKeys.size());
+ pw.println("mSuppressedBubbleKeys: " + mSuppressedBubbleKeys.size());
for (String key : mSuppressedBubbleKeys) {
pw.println(" suppressing: " + key);
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleData.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleData.java
index cc8f50e09fcb..c6f74af0284b 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleData.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleData.java
@@ -1231,29 +1231,30 @@ public class BubbleData {
* Description of current bubble data state.
*/
public void dump(PrintWriter pw) {
- pw.print("selected: ");
+ pw.println("BubbleData state:");
+ pw.print(" selected: ");
pw.println(mSelectedBubble != null
? mSelectedBubble.getKey()
: "null");
- pw.print("expanded: ");
+ pw.print(" expanded: ");
pw.println(mExpanded);
- pw.print("stack bubble count: ");
+ pw.print("Stack bubble count: ");
pw.println(mBubbles.size());
for (Bubble bubble : mBubbles) {
bubble.dump(pw);
}
- pw.print("overflow bubble count: ");
+ pw.print("Overflow bubble count: ");
pw.println(mOverflowBubbles.size());
for (Bubble bubble : mOverflowBubbles) {
bubble.dump(pw);
}
- pw.print("summaryKeys: ");
+ pw.print("SummaryKeys: ");
pw.println(mSuppressedGroupKeys.size());
for (String key : mSuppressedGroupKeys.keySet()) {
- pw.println(" suppressing: " + key);
+ pw.println(" suppressing: " + key);
}
}
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleDebugConfig.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleDebugConfig.java
index 76662c47238f..1c0e0522d359 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleDebugConfig.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleDebugConfig.java
@@ -77,20 +77,25 @@ public class BubbleDebugConfig {
static String formatBubblesString(List<Bubble> bubbles, BubbleViewProvider selected) {
StringBuilder sb = new StringBuilder();
- for (Bubble bubble : bubbles) {
+ for (int i = 0; i < bubbles.size(); i++) {
+ Bubble bubble = bubbles.get(i);
if (bubble == null) {
- sb.append(" <null> !!!!!\n");
+ sb.append(" <null> !!!!!");
} else {
boolean isSelected = (selected != null
- && selected.getKey() != BubbleOverflow.KEY
+ && !BubbleOverflow.KEY.equals(selected.getKey())
&& bubble == selected);
String arrow = isSelected ? "=>" : " ";
- sb.append(String.format("%s Bubble{act=%12d, showInShade=%d, key=%s}\n",
+
+ sb.append(String.format("%s Bubble{act=%12d, showInShade=%d, key=%s}",
arrow,
bubble.getLastActivity(),
(bubble.showInShade() ? 1 : 0),
bubble.getKey()));
}
+ if (i != bubbles.size() - 1) {
+ sb.append("\n");
+ }
}
return sb.toString();
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleExpandedView.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleExpandedView.java
index e6986012dd88..37bcf1ddeac5 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleExpandedView.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleExpandedView.java
@@ -1094,9 +1094,9 @@ public class BubbleExpandedView extends LinearLayout {
/**
* Description of current expanded view state.
*/
- public void dump(@NonNull PrintWriter pw) {
- pw.print("BubbleExpandedView");
- pw.print(" taskId: "); pw.println(mTaskId);
- pw.print(" stackView: "); pw.println(mStackView);
+ public void dump(@NonNull PrintWriter pw, @NonNull String prefix) {
+ pw.print(prefix); pw.println("BubbleExpandedView:");
+ pw.print(prefix); pw.print(" taskId: "); pw.println(mTaskId);
+ pw.print(prefix); pw.print(" stackView: "); pw.println(mStackView);
}
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleStackView.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleStackView.java
index 52c9bf8462ec..093ecb1e3ade 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleStackView.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleStackView.java
@@ -305,8 +305,7 @@ public class BubbleStackView extends FrameLayout
String bubblesOnScreen = BubbleDebugConfig.formatBubblesString(
getBubblesOnScreen(), getExpandedBubble());
- pw.print(" stack visibility : "); pw.println(getVisibility());
- pw.print(" bubbles on screen: "); pw.println(bubblesOnScreen);
+ pw.println(" bubbles on screen: "); pw.println(bubblesOnScreen);
pw.print(" gestureInProgress: "); pw.println(mIsGestureInProgress);
pw.print(" showingDismiss: "); pw.println(mDismissView.isShowing());
pw.print(" isExpansionAnimating: "); pw.println(mIsExpansionAnimating);
@@ -314,7 +313,8 @@ public class BubbleStackView extends FrameLayout
pw.print(" expandedContainerAlpha: "); pw.println(mExpandedViewContainer.getAlpha());
pw.print(" expandedContainerMatrix: ");
pw.println(mExpandedViewContainer.getAnimationMatrix());
-
+ pw.print(" stack visibility : "); pw.println(getVisibility());
+ pw.print(" temporarilyInvisible: "); pw.println(mTemporarilyInvisible);
mStackAnimationController.dump(pw);
mExpandedAnimationController.dump(pw);
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayChangeController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayChangeController.java
index 72702e7c2b88..b828aac39040 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayChangeController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayChangeController.java
@@ -18,6 +18,7 @@ package com.android.wm.shell.common;
import android.annotation.Nullable;
import android.os.RemoteException;
+import android.os.Trace;
import android.util.Slog;
import android.view.IDisplayChangeWindowCallback;
import android.view.IDisplayChangeWindowController;
@@ -40,6 +41,7 @@ import java.util.concurrent.CopyOnWriteArrayList;
*/
public class DisplayChangeController {
private static final String TAG = DisplayChangeController.class.getSimpleName();
+ private static final String HANDLE_DISPLAY_CHANGE_TRACE_TAG = "HandleRemoteDisplayChange";
private final ShellExecutor mMainExecutor;
private final IWindowManager mWmService;
@@ -81,9 +83,15 @@ public class DisplayChangeController {
/** Query all listeners for changes that should happen on display change. */
void dispatchOnDisplayChange(WindowContainerTransaction outWct, int displayId,
int fromRotation, int toRotation, DisplayAreaInfo newDisplayAreaInfo) {
+ if (Trace.isTagEnabled(Trace.TRACE_TAG_WINDOW_MANAGER)) {
+ Trace.beginSection("dispatchOnDisplayChange");
+ }
for (OnDisplayChangingListener c : mDisplayChangeListener) {
c.onDisplayChange(displayId, fromRotation, toRotation, newDisplayAreaInfo, outWct);
}
+ if (Trace.isTagEnabled(Trace.TRACE_TAG_WINDOW_MANAGER)) {
+ Trace.endSection();
+ }
}
private void onDisplayChange(int displayId, int fromRotation, int toRotation,
@@ -94,6 +102,10 @@ public class DisplayChangeController {
callback.continueDisplayChange(t);
} catch (RemoteException e) {
Slog.e(TAG, "Failed to continue handling display change", e);
+ } finally {
+ if (Trace.isTagEnabled(Trace.TRACE_TAG_WINDOW_MANAGER)) {
+ Trace.endAsyncSection(HANDLE_DISPLAY_CHANGE_TRACE_TAG, callback.hashCode());
+ }
}
}
@@ -103,6 +115,9 @@ public class DisplayChangeController {
@Override
public void onDisplayChange(int displayId, int fromRotation, int toRotation,
DisplayAreaInfo newDisplayAreaInfo, IDisplayChangeWindowCallback callback) {
+ if (Trace.isTagEnabled(Trace.TRACE_TAG_WINDOW_MANAGER)) {
+ Trace.beginAsyncSection(HANDLE_DISPLAY_CHANGE_TRACE_TAG, callback.hashCode());
+ }
mMainExecutor.execute(() -> DisplayChangeController.this
.onDisplayChange(displayId, fromRotation, toRotation,
newDisplayAreaInfo, callback));
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/UserAspectRatioSettingsWindowManager.java b/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/UserAspectRatioSettingsWindowManager.java
index cbff4640239e..77aefc8f7e4a 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/UserAspectRatioSettingsWindowManager.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/UserAspectRatioSettingsWindowManager.java
@@ -208,7 +208,7 @@ class UserAspectRatioSettingsWindowManager extends CompatUIWindowManagerAbstract
}
private boolean getHasUserAspectRatioSettingsButton(@NonNull TaskInfo taskInfo) {
- return taskInfo.topActivityEligibleForUserAspectRatioButton
+ return taskInfo.topActivityEligibleForUserAspectRatioButton
&& (taskInfo.topActivityBoundsLetterboxed
|| taskInfo.isUserFullscreenOverrideEnabled);
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellBaseModule.java b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellBaseModule.java
index 1c2cee52d68d..998cd5d08c72 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellBaseModule.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellBaseModule.java
@@ -72,7 +72,6 @@ import com.android.wm.shell.compatui.CompatUIConfiguration;
import com.android.wm.shell.compatui.CompatUIController;
import com.android.wm.shell.compatui.CompatUIShellCommandHandler;
import com.android.wm.shell.desktopmode.DesktopMode;
-import com.android.wm.shell.desktopmode.DesktopModeController;
import com.android.wm.shell.desktopmode.DesktopModeStatus;
import com.android.wm.shell.desktopmode.DesktopModeTaskRepository;
import com.android.wm.shell.desktopmode.DesktopTasksController;
@@ -109,13 +108,13 @@ import com.android.wm.shell.unfold.UnfoldAnimationController;
import com.android.wm.shell.unfold.UnfoldTransitionHandler;
import com.android.wm.shell.windowdecor.WindowDecorViewModel;
+import java.util.Optional;
+
import dagger.BindsOptionalOf;
import dagger.Lazy;
import dagger.Module;
import dagger.Provides;
-import java.util.Optional;
-
/**
* Provides basic dependencies from {@link com.android.wm.shell}, these dependencies are only
* accessible from components within the WM subcomponent (can be explicitly exposed to the
@@ -800,30 +799,10 @@ public abstract class WMShellBaseModule {
@WMSingleton
@Provides
static Optional<DesktopMode> provideDesktopMode(
- Optional<DesktopModeController> desktopModeController,
Optional<DesktopTasksController> desktopTasksController) {
- if (DesktopModeStatus.isProto2Enabled()) {
- return desktopTasksController.map(DesktopTasksController::asDesktopMode);
- }
- return desktopModeController.map(DesktopModeController::asDesktopMode);
+ return desktopTasksController.map(DesktopTasksController::asDesktopMode);
}
- @BindsOptionalOf
- @DynamicOverride
- abstract DesktopModeController optionalDesktopModeController();
-
- @WMSingleton
- @Provides
- static Optional<DesktopModeController> provideDesktopModeController(
- @DynamicOverride Optional<Lazy<DesktopModeController>> desktopModeController) {
- // Use optional-of-lazy for the dependency that this provider relies on.
- // Lazy ensures that this provider will not be the cause the dependency is created
- // when it will not be returned due to the condition below.
- if (DesktopModeStatus.isProto1Enabled()) {
- return desktopModeController.map(Lazy::get);
- }
- return Optional.empty();
- }
@BindsOptionalOf
@DynamicOverride
@@ -836,7 +815,7 @@ public abstract class WMShellBaseModule {
// Use optional-of-lazy for the dependency that this provider relies on.
// Lazy ensures that this provider will not be the cause the dependency is created
// when it will not be returned due to the condition below.
- if (DesktopModeStatus.isProto2Enabled()) {
+ if (DesktopModeStatus.isEnabled()) {
return desktopTasksController.map(Lazy::get);
}
return Optional.empty();
@@ -853,7 +832,7 @@ public abstract class WMShellBaseModule {
// Use optional-of-lazy for the dependency that this provider relies on.
// Lazy ensures that this provider will not be the cause the dependency is created
// when it will not be returned due to the condition below.
- if (DesktopModeStatus.isAnyEnabled()) {
+ if (DesktopModeStatus.isEnabled()) {
return desktopModeTaskRepository.map(Lazy::get);
}
return Optional.empty();
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java
index c641e87e2055..e9f3e1a2647c 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java
@@ -54,7 +54,6 @@ import com.android.wm.shell.common.annotations.ShellBackgroundThread;
import com.android.wm.shell.common.annotations.ShellMainThread;
import com.android.wm.shell.dagger.back.ShellBackAnimationModule;
import com.android.wm.shell.dagger.pip.PipModule;
-import com.android.wm.shell.desktopmode.DesktopModeController;
import com.android.wm.shell.desktopmode.DesktopModeStatus;
import com.android.wm.shell.desktopmode.DesktopModeTaskRepository;
import com.android.wm.shell.desktopmode.DesktopTasksController;
@@ -197,10 +196,9 @@ public abstract class WMShellModule {
ShellController shellController,
SyncTransactionQueue syncQueue,
Transitions transitions,
- Optional<DesktopModeController> desktopModeController,
Optional<DesktopTasksController> desktopTasksController,
RootTaskDisplayAreaOrganizer rootTaskDisplayAreaOrganizer) {
- if (DesktopModeStatus.isAnyEnabled()) {
+ if (DesktopModeStatus.isEnabled()) {
return new DesktopModeWindowDecorViewModel(
context,
mainHandler,
@@ -211,7 +209,6 @@ public abstract class WMShellModule {
shellController,
syncQueue,
transitions,
- desktopModeController,
desktopTasksController,
rootTaskDisplayAreaOrganizer);
}
@@ -353,13 +350,12 @@ public abstract class WMShellModule {
@Nullable PipTransitionController pipTransitionController,
Optional<RecentsTransitionHandler> recentsTransitionHandler,
KeyguardTransitionHandler keyguardTransitionHandler,
- Optional<DesktopModeController> desktopModeController,
Optional<DesktopTasksController> desktopTasksController,
Optional<UnfoldTransitionHandler> unfoldHandler,
Transitions transitions) {
return new DefaultMixedHandler(shellInit, transitions, splitScreenOptional,
pipTransitionController, recentsTransitionHandler,
- keyguardTransitionHandler, desktopModeController, desktopTasksController,
+ keyguardTransitionHandler, desktopTasksController,
unfoldHandler);
}
@@ -471,24 +467,6 @@ public abstract class WMShellModule {
@WMSingleton
@Provides
@DynamicOverride
- static DesktopModeController provideDesktopModeController(Context context,
- ShellInit shellInit,
- ShellController shellController,
- ShellTaskOrganizer shellTaskOrganizer,
- RootTaskDisplayAreaOrganizer rootTaskDisplayAreaOrganizer,
- Transitions transitions,
- @DynamicOverride DesktopModeTaskRepository desktopModeTaskRepository,
- @ShellMainThread Handler mainHandler,
- @ShellMainThread ShellExecutor mainExecutor
- ) {
- return new DesktopModeController(context, shellInit, shellController, shellTaskOrganizer,
- rootTaskDisplayAreaOrganizer, transitions, desktopModeTaskRepository, mainHandler,
- mainExecutor);
- }
-
- @WMSingleton
- @Provides
- @DynamicOverride
static DesktopTasksController provideDesktopTasksController(
Context context,
ShellInit shellInit,
@@ -553,8 +531,7 @@ public abstract class WMShellModule {
@ShellCreateTriggerOverride
@Provides
static Object provideIndependentShellComponentsToCreate(
- DefaultMixedHandler defaultMixedHandler,
- Optional<DesktopModeController> desktopModeController) {
+ DefaultMixedHandler defaultMixedHandler) {
return new Object();
}
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeController.java
deleted file mode 100644
index 5b24d7a60c4e..000000000000
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeController.java
+++ /dev/null
@@ -1,557 +0,0 @@
-/*
- * Copyright (C) 2022 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.wm.shell.desktopmode;
-
-import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
-import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
-import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
-import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
-import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
-import static android.view.WindowManager.TRANSIT_CHANGE;
-import static android.view.WindowManager.TRANSIT_NONE;
-import static android.view.WindowManager.TRANSIT_OPEN;
-import static android.view.WindowManager.TRANSIT_TO_FRONT;
-
-import static com.android.wm.shell.common.ExecutorUtils.executeRemoteCallWithTaskPermission;
-import static com.android.wm.shell.protolog.ShellProtoLogGroup.WM_SHELL_DESKTOP_MODE;
-import static com.android.wm.shell.sysui.ShellSharedConstants.KEY_EXTRA_SHELL_DESKTOP_MODE;
-
-import android.app.ActivityManager.RunningTaskInfo;
-import android.app.WindowConfiguration;
-import android.content.Context;
-import android.content.res.TypedArray;
-import android.database.ContentObserver;
-import android.graphics.Region;
-import android.net.Uri;
-import android.os.Handler;
-import android.os.IBinder;
-import android.os.RemoteException;
-import android.os.UserHandle;
-import android.provider.Settings;
-import android.util.ArraySet;
-import android.view.SurfaceControl;
-import android.view.WindowManager;
-import android.window.DisplayAreaInfo;
-import android.window.TransitionInfo;
-import android.window.TransitionRequestInfo;
-import android.window.WindowContainerTransaction;
-
-import androidx.annotation.BinderThread;
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-
-import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.protolog.common.ProtoLog;
-import com.android.wm.shell.RootTaskDisplayAreaOrganizer;
-import com.android.wm.shell.ShellTaskOrganizer;
-import com.android.wm.shell.common.ExternalInterfaceBinder;
-import com.android.wm.shell.common.RemoteCallable;
-import com.android.wm.shell.common.ShellExecutor;
-import com.android.wm.shell.common.annotations.ExternalThread;
-import com.android.wm.shell.common.annotations.ShellMainThread;
-import com.android.wm.shell.sysui.ShellController;
-import com.android.wm.shell.sysui.ShellInit;
-import com.android.wm.shell.transition.Transitions;
-
-import java.util.ArrayList;
-import java.util.Comparator;
-import java.util.List;
-import java.util.concurrent.Executor;
-import java.util.function.Consumer;
-
-/**
- * Handles windowing changes when desktop mode system setting changes
- */
-public class DesktopModeController implements RemoteCallable<DesktopModeController>,
- Transitions.TransitionHandler {
-
- private final Context mContext;
- private final ShellController mShellController;
- private final ShellTaskOrganizer mShellTaskOrganizer;
- private final RootTaskDisplayAreaOrganizer mRootTaskDisplayAreaOrganizer;
- private final Transitions mTransitions;
- private final DesktopModeTaskRepository mDesktopModeTaskRepository;
- private final ShellExecutor mMainExecutor;
- private final DesktopModeImpl mDesktopModeImpl = new DesktopModeImpl();
- private final SettingsObserver mSettingsObserver;
-
- public DesktopModeController(Context context,
- ShellInit shellInit,
- ShellController shellController,
- ShellTaskOrganizer shellTaskOrganizer,
- RootTaskDisplayAreaOrganizer rootTaskDisplayAreaOrganizer,
- Transitions transitions,
- DesktopModeTaskRepository desktopModeTaskRepository,
- @ShellMainThread Handler mainHandler,
- @ShellMainThread ShellExecutor mainExecutor) {
- mContext = context;
- mShellController = shellController;
- mShellTaskOrganizer = shellTaskOrganizer;
- mRootTaskDisplayAreaOrganizer = rootTaskDisplayAreaOrganizer;
- mTransitions = transitions;
- mDesktopModeTaskRepository = desktopModeTaskRepository;
- mMainExecutor = mainExecutor;
- mSettingsObserver = new SettingsObserver(mContext, mainHandler);
- if (DesktopModeStatus.isProto1Enabled()) {
- shellInit.addInitCallback(this::onInit, this);
- }
- }
-
- private void onInit() {
- ProtoLog.d(WM_SHELL_DESKTOP_MODE, "Initialize DesktopModeController");
- mShellController.addExternalInterface(KEY_EXTRA_SHELL_DESKTOP_MODE,
- this::createExternalInterface, this);
- mSettingsObserver.observe();
- if (DesktopModeStatus.isActive(mContext)) {
- updateDesktopModeActive(true);
- }
- mTransitions.addHandler(this);
- }
-
- @Override
- public Context getContext() {
- return mContext;
- }
-
- @Override
- public ShellExecutor getRemoteCallExecutor() {
- return mMainExecutor;
- }
-
- /**
- * Get connection interface between sysui and shell
- */
- public DesktopMode asDesktopMode() {
- return mDesktopModeImpl;
- }
-
- /**
- * Creates a new instance of the external interface to pass to another process.
- */
- private ExternalInterfaceBinder createExternalInterface() {
- return new IDesktopModeImpl(this);
- }
-
- /**
- * Adds a listener to find out about changes in the visibility of freeform tasks.
- *
- * @param listener the listener to add.
- * @param callbackExecutor the executor to call the listener on.
- */
- public void addVisibleTasksListener(DesktopModeTaskRepository.VisibleTasksListener listener,
- Executor callbackExecutor) {
- mDesktopModeTaskRepository.addVisibleTasksListener(listener, callbackExecutor);
- }
-
- /**
- * Adds a listener to track changes to corners of desktop mode tasks.
- * @param listener the listener to add.
- * @param callbackExecutor the executor to call the listener on.
- */
- public void addTaskCornerListener(Consumer<Region> listener,
- Executor callbackExecutor) {
- mDesktopModeTaskRepository.setTaskCornerListener(listener, callbackExecutor);
- }
-
- @VisibleForTesting
- void updateDesktopModeActive(boolean active) {
- ProtoLog.d(WM_SHELL_DESKTOP_MODE, "updateDesktopModeActive: active=%s", active);
-
- int displayId = mContext.getDisplayId();
-
- ArrayList<RunningTaskInfo> runningTasks = mShellTaskOrganizer.getRunningTasks(displayId);
-
- WindowContainerTransaction wct = new WindowContainerTransaction();
- // Reset freeform windowing mode that is set per task level so tasks inherit it
- clearFreeformForStandardTasks(runningTasks, wct);
- if (active) {
- moveHomeBehindVisibleTasks(runningTasks, wct);
- setDisplayAreaWindowingMode(displayId, WINDOWING_MODE_FREEFORM, wct);
- } else {
- clearBoundsForStandardTasks(runningTasks, wct);
- setDisplayAreaWindowingMode(displayId, WINDOWING_MODE_FULLSCREEN, wct);
- }
- if (Transitions.ENABLE_SHELL_TRANSITIONS) {
- mTransitions.startTransition(TRANSIT_CHANGE, wct, null);
- } else {
- mRootTaskDisplayAreaOrganizer.applyTransaction(wct);
- }
- }
-
- private WindowContainerTransaction clearBoundsForStandardTasks(
- ArrayList<RunningTaskInfo> runningTasks, WindowContainerTransaction wct) {
- ProtoLog.v(WM_SHELL_DESKTOP_MODE, "prepareClearBoundsForTasks");
- for (RunningTaskInfo taskInfo : runningTasks) {
- if (taskInfo.getActivityType() == ACTIVITY_TYPE_STANDARD) {
- ProtoLog.v(WM_SHELL_DESKTOP_MODE, "clearing bounds for token=%s taskInfo=%s",
- taskInfo.token, taskInfo);
- wct.setBounds(taskInfo.token, null);
- }
- }
- return wct;
- }
-
- private void clearFreeformForStandardTasks(ArrayList<RunningTaskInfo> runningTasks,
- WindowContainerTransaction wct) {
- ProtoLog.v(WM_SHELL_DESKTOP_MODE, "prepareClearFreeformForTasks");
- for (RunningTaskInfo taskInfo : runningTasks) {
- if (taskInfo.getWindowingMode() == WINDOWING_MODE_FREEFORM
- && taskInfo.getActivityType() == ACTIVITY_TYPE_STANDARD) {
- ProtoLog.v(WM_SHELL_DESKTOP_MODE,
- "clearing windowing mode for token=%s taskInfo=%s", taskInfo.token,
- taskInfo);
- wct.setWindowingMode(taskInfo.token, WINDOWING_MODE_UNDEFINED);
- }
- }
- }
-
- private void moveHomeBehindVisibleTasks(ArrayList<RunningTaskInfo> runningTasks,
- WindowContainerTransaction wct) {
- ProtoLog.v(WM_SHELL_DESKTOP_MODE, "moveHomeBehindVisibleTasks");
- RunningTaskInfo homeTask = null;
- ArrayList<RunningTaskInfo> visibleTasks = new ArrayList<>();
- for (RunningTaskInfo taskInfo : runningTasks) {
- if (taskInfo.getActivityType() == ACTIVITY_TYPE_HOME) {
- homeTask = taskInfo;
- } else if (taskInfo.getActivityType() == ACTIVITY_TYPE_STANDARD
- && taskInfo.isVisible()) {
- visibleTasks.add(taskInfo);
- }
- }
- if (homeTask == null) {
- ProtoLog.w(WM_SHELL_DESKTOP_MODE, "moveHomeBehindVisibleTasks: home task not found");
- } else {
- ProtoLog.v(WM_SHELL_DESKTOP_MODE, "moveHomeBehindVisibleTasks: visible tasks %d",
- visibleTasks.size());
- wct.reorder(homeTask.getToken(), true /* onTop */);
- for (RunningTaskInfo task : visibleTasks) {
- wct.reorder(task.getToken(), true /* onTop */);
- }
- }
- }
-
- private void setDisplayAreaWindowingMode(int displayId,
- @WindowConfiguration.WindowingMode int windowingMode, WindowContainerTransaction wct) {
- DisplayAreaInfo displayAreaInfo = mRootTaskDisplayAreaOrganizer.getDisplayAreaInfo(
- displayId);
- if (displayAreaInfo == null) {
- ProtoLog.e(WM_SHELL_DESKTOP_MODE,
- "unable to update windowing mode for display %d display not found", displayId);
- return;
- }
-
- ProtoLog.v(WM_SHELL_DESKTOP_MODE,
- "setWindowingMode: displayId=%d current wmMode=%d new wmMode=%d", displayId,
- displayAreaInfo.configuration.windowConfiguration.getWindowingMode(),
- windowingMode);
-
- wct.setWindowingMode(displayAreaInfo.token, windowingMode);
- }
-
- /**
- * Show apps on desktop
- */
- void showDesktopApps(int displayId) {
- // Bring apps to front, ignoring their visibility status to always ensure they are on top.
- WindowContainerTransaction wct = new WindowContainerTransaction();
- bringDesktopAppsToFront(displayId, wct);
-
- if (!wct.isEmpty()) {
- if (Transitions.ENABLE_SHELL_TRANSITIONS) {
- // TODO(b/268662477): add animation for the transition
- mTransitions.startTransition(TRANSIT_NONE, wct, null /* handler */);
- } else {
- mShellTaskOrganizer.applyTransaction(wct);
- }
- }
- }
-
- /** Get number of tasks that are marked as visible */
- int getVisibleTaskCount(int displayId) {
- return mDesktopModeTaskRepository.getVisibleTaskCount(displayId);
- }
-
- private void bringDesktopAppsToFront(int displayId, WindowContainerTransaction wct) {
- final ArraySet<Integer> activeTasks = mDesktopModeTaskRepository.getActiveTasks(displayId);
- ProtoLog.d(WM_SHELL_DESKTOP_MODE, "bringDesktopAppsToFront: tasks=%s", activeTasks.size());
-
- final List<RunningTaskInfo> taskInfos = new ArrayList<>();
- for (Integer taskId : activeTasks) {
- RunningTaskInfo taskInfo = mShellTaskOrganizer.getRunningTaskInfo(taskId);
- if (taskInfo != null) {
- taskInfos.add(taskInfo);
- }
- }
-
- if (taskInfos.isEmpty()) {
- return;
- }
-
- moveHomeTaskToFront(wct);
-
- ProtoLog.d(WM_SHELL_DESKTOP_MODE,
- "bringDesktopAppsToFront: reordering all active tasks to the front");
- final List<Integer> allTasksInZOrder =
- mDesktopModeTaskRepository.getFreeformTasksInZOrder();
- // Sort by z-order, bottom to top, so that the top-most task is reordered to the top last
- // in the WCT.
- taskInfos.sort(Comparator.comparingInt(task -> -allTasksInZOrder.indexOf(task.taskId)));
- for (RunningTaskInfo task : taskInfos) {
- wct.reorder(task.token, true);
- }
- }
-
- private void moveHomeTaskToFront(WindowContainerTransaction wct) {
- for (RunningTaskInfo task : mShellTaskOrganizer.getRunningTasks(mContext.getDisplayId())) {
- if (task.getActivityType() == ACTIVITY_TYPE_HOME) {
- wct.reorder(task.token, true /* onTop */);
- return;
- }
- }
- }
-
- /**
- * Update corner rects stored for a specific task
- * @param taskId task to update
- * @param taskCorners task's new corner handles
- */
- public void onTaskCornersChanged(int taskId, Region taskCorners) {
- mDesktopModeTaskRepository.updateTaskCorners(taskId, taskCorners);
- }
-
- /**
- * Remove corners saved for a task. Likely used due to task closure.
- * @param taskId task to remove
- */
- public void removeCornersForTask(int taskId) {
- mDesktopModeTaskRepository.removeTaskCorners(taskId);
- }
-
- /**
- * Moves a specifc task to the front.
- * @param taskInfo the task to show in front.
- */
- public void moveTaskToFront(RunningTaskInfo taskInfo) {
- WindowContainerTransaction wct = new WindowContainerTransaction();
- wct.reorder(taskInfo.token, true /* onTop */);
- if (Transitions.ENABLE_SHELL_TRANSITIONS) {
- mTransitions.startTransition(TRANSIT_TO_FRONT, wct, null);
- } else {
- mShellTaskOrganizer.applyTransaction(wct);
- }
- }
-
- /**
- * Turn desktop mode on or off
- * @param active the desired state for desktop mode setting
- */
- public void setDesktopModeActive(boolean active) {
- int value = active ? 1 : 0;
- Settings.System.putInt(mContext.getContentResolver(), Settings.System.DESKTOP_MODE, value);
- }
-
- /**
- * Returns the windowing mode of the display area with the specified displayId.
- * @param displayId
- * @return
- */
- public int getDisplayAreaWindowingMode(int displayId) {
- return mRootTaskDisplayAreaOrganizer.getDisplayAreaInfo(displayId)
- .configuration.windowConfiguration.getWindowingMode();
- }
-
- @Override
- public boolean startAnimation(@NonNull IBinder transition, @NonNull TransitionInfo info,
- @NonNull SurfaceControl.Transaction startTransaction,
- @NonNull SurfaceControl.Transaction finishTransaction,
- @NonNull Transitions.TransitionFinishCallback finishCallback) {
- // This handler should never be the sole handler, so should not animate anything.
- return false;
- }
-
- @Nullable
- @Override
- public WindowContainerTransaction handleRequest(@NonNull IBinder transition,
- @NonNull TransitionRequestInfo request) {
- RunningTaskInfo triggerTask = request.getTriggerTask();
- // Only do anything if we are in desktop mode and opening/moving-to-front a task/app in
- // freeform
- if (!DesktopModeStatus.isActive(mContext)) {
- ProtoLog.d(WM_SHELL_DESKTOP_MODE,
- "skip shell transition request: desktop mode not active");
- return null;
- }
- if (request.getType() != TRANSIT_OPEN && request.getType() != TRANSIT_TO_FRONT) {
- ProtoLog.d(WM_SHELL_DESKTOP_MODE,
- "skip shell transition request: unsupported type %s",
- WindowManager.transitTypeToString(request.getType()));
- return null;
- }
- if (triggerTask == null || triggerTask.getWindowingMode() != WINDOWING_MODE_FREEFORM) {
- ProtoLog.d(WM_SHELL_DESKTOP_MODE, "skip shell transition request: not freeform task");
- return null;
- }
- ProtoLog.d(WM_SHELL_DESKTOP_MODE, "handle shell transition request: %s", request);
-
- WindowContainerTransaction wct = new WindowContainerTransaction();
- bringDesktopAppsToFront(triggerTask.displayId, wct);
- wct.reorder(triggerTask.token, true /* onTop */);
-
- return wct;
- }
-
- /**
- * Applies the proper surface states (rounded corners) to tasks when desktop mode is active.
- * This is intended to be used when desktop mode is part of another animation but isn't, itself,
- * animating.
- */
- public void syncSurfaceState(@NonNull TransitionInfo info,
- SurfaceControl.Transaction finishTransaction) {
- // Add rounded corners to freeform windows
- final TypedArray ta = mContext.obtainStyledAttributes(
- new int[]{android.R.attr.dialogCornerRadius});
- final int cornerRadius = ta.getDimensionPixelSize(0, 0);
- ta.recycle();
- for (TransitionInfo.Change change: info.getChanges()) {
- if (change.getTaskInfo().getWindowingMode() == WINDOWING_MODE_FREEFORM) {
- finishTransaction.setCornerRadius(change.getLeash(), cornerRadius);
- }
- }
- }
-
- /**
- * A {@link ContentObserver} for listening to changes to {@link Settings.System#DESKTOP_MODE}
- */
- private final class SettingsObserver extends ContentObserver {
-
- private final Uri mDesktopModeSetting = Settings.System.getUriFor(
- Settings.System.DESKTOP_MODE);
-
- private final Context mContext;
-
- SettingsObserver(Context context, Handler handler) {
- super(handler);
- mContext = context;
- }
-
- public void observe() {
- // TODO(b/242867463): listen for setting change for all users
- mContext.getContentResolver().registerContentObserver(mDesktopModeSetting,
- false /* notifyForDescendants */, this /* observer */, UserHandle.USER_CURRENT);
- }
-
- @Override
- public void onChange(boolean selfChange, @Nullable Uri uri) {
- if (mDesktopModeSetting.equals(uri)) {
- ProtoLog.d(WM_SHELL_DESKTOP_MODE, "Received update for desktop mode setting");
- desktopModeSettingChanged();
- }
- }
-
- private void desktopModeSettingChanged() {
- boolean enabled = DesktopModeStatus.isActive(mContext);
- updateDesktopModeActive(enabled);
- }
- }
-
- /**
- * The interface for calls from outside the shell, within the host process.
- */
- @ExternalThread
- private final class DesktopModeImpl implements DesktopMode {
-
- @Override
- public void addVisibleTasksListener(
- DesktopModeTaskRepository.VisibleTasksListener listener,
- Executor callbackExecutor) {
- mMainExecutor.execute(() -> {
- DesktopModeController.this.addVisibleTasksListener(listener, callbackExecutor);
- });
- }
-
- @Override
- public void addDesktopGestureExclusionRegionListener(Consumer<Region> listener,
- Executor callbackExecutor) {
- mMainExecutor.execute(() -> {
- DesktopModeController.this.addTaskCornerListener(listener, callbackExecutor);
- });
- }
- }
-
- /**
- * The interface for calls from outside the host process.
- */
- @BinderThread
- private static class IDesktopModeImpl extends IDesktopMode.Stub
- implements ExternalInterfaceBinder {
-
- private DesktopModeController mController;
-
- IDesktopModeImpl(DesktopModeController controller) {
- mController = controller;
- }
-
- /**
- * Invalidates this instance, preventing future calls from updating the controller.
- */
- @Override
- public void invalidate() {
- mController = null;
- }
-
- @Override
- public void showDesktopApps(int displayId) {
- executeRemoteCallWithTaskPermission(mController, "showDesktopApps",
- controller -> controller.showDesktopApps(displayId));
- }
-
- @Override
- public void showDesktopApp(int taskId) throws RemoteException {
- // TODO
- }
-
- @Override
- public int getVisibleTaskCount(int displayId) throws RemoteException {
- int[] result = new int[1];
- executeRemoteCallWithTaskPermission(mController, "getVisibleTaskCount",
- controller -> result[0] = controller.getVisibleTaskCount(displayId),
- true /* blocking */
- );
- return result[0];
- }
-
- @Override
- public void onDesktopSplitSelectAnimComplete(RunningTaskInfo taskInfo) {
-
- }
-
- @Override
- public void stashDesktopApps(int displayId) throws RemoteException {
- // Stashing of desktop apps not needed. Apps always launch on desktop
- }
-
- @Override
- public void hideStashedDesktopApps(int displayId) throws RemoteException {
- // Stashing of desktop apps not needed. Apps always launch on desktop
- }
-
- @Override
- public void setTaskListener(IDesktopTaskListener listener) throws RemoteException {
- // TODO(b/261234402): move visibility from sysui state to listener
- }
- }
-}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeStatus.java b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeStatus.java
index 517f9f2aba27..77831136b0bc 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeStatus.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeStatus.java
@@ -16,14 +16,7 @@
package com.android.wm.shell.desktopmode;
-import static com.android.wm.shell.protolog.ShellProtoLogGroup.WM_SHELL_DESKTOP_MODE;
-
-import android.content.Context;
import android.os.SystemProperties;
-import android.os.UserHandle;
-import android.provider.Settings;
-
-import com.android.internal.protolog.common.ProtoLog;
/**
* Constants for desktop mode feature
@@ -31,13 +24,7 @@ import com.android.internal.protolog.common.ProtoLog;
public class DesktopModeStatus {
/**
- * Flag to indicate whether desktop mode is available on the device
- */
- private static final boolean IS_SUPPORTED = SystemProperties.getBoolean(
- "persist.wm.debug.desktop_mode", false);
-
- /**
- * Flag to indicate whether desktop mode proto 2 is available on the device
+ * Flag to indicate whether desktop mode proto is available on the device
*/
private static final boolean IS_PROTO2_ENABLED = SystemProperties.getBoolean(
"persist.wm.debug.desktop_mode_2", false);
@@ -64,28 +51,13 @@ public class DesktopModeStatus {
"persist.wm.debug.desktop_stashing", false);
/**
- * Return {@code true} if desktop mode support is enabled
- */
- public static boolean isProto1Enabled() {
- return IS_SUPPORTED;
- }
-
- /**
* Return {@code true} is desktop windowing proto 2 is enabled
*/
- public static boolean isProto2Enabled() {
+ public static boolean isEnabled() {
return IS_PROTO2_ENABLED;
}
/**
- * Return {@code true} if proto 1 or 2 is enabled.
- * Can be used to guard logic that is common for both prototypes.
- */
- public static boolean isAnyEnabled() {
- return isProto1Enabled() || isProto2Enabled();
- }
-
- /**
* Return {@code true} if veiled resizing is active. If false, fluid resizing is used.
*/
public static boolean isVeiledResizeEnabled() {
@@ -99,26 +71,4 @@ public class DesktopModeStatus {
public static boolean isStashingEnabled() {
return IS_STASHING_ENABLED;
}
- /**
- * Check if desktop mode is active
- *
- * @return {@code true} if active
- */
- public static boolean isActive(Context context) {
- if (!isAnyEnabled()) {
- return false;
- }
- if (isProto2Enabled()) {
- // Desktop mode is always active in prototype 2
- return true;
- }
- try {
- int result = Settings.System.getIntForUser(context.getContentResolver(),
- Settings.System.DESKTOP_MODE, UserHandle.USER_CURRENT);
- return result != 0;
- } catch (Exception e) {
- ProtoLog.e(WM_SHELL_DESKTOP_MODE, "Failed to read DESKTOP_MODE setting %s", e);
- return false;
- }
- }
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksController.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksController.kt
index 236dec0f555b..b918c83a5c6b 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksController.kt
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksController.kt
@@ -122,7 +122,7 @@ class DesktopTasksController(
init {
desktopMode = DesktopModeImpl()
- if (DesktopModeStatus.isProto2Enabled()) {
+ if (DesktopModeStatus.isEnabled()) {
shellInit.addInitCallback({ onInit() }, this)
}
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/freeform/FreeformTaskListener.java b/libs/WindowManager/Shell/src/com/android/wm/shell/freeform/FreeformTaskListener.java
index 22541bbd892a..a80241e0ac5c 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/freeform/FreeformTaskListener.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/freeform/FreeformTaskListener.java
@@ -68,7 +68,7 @@ public class FreeformTaskListener implements ShellTaskOrganizer.TaskListener,
private void onInit() {
mShellTaskOrganizer.addListenerForType(this, TASK_LISTENER_TYPE_FREEFORM);
- if (DesktopModeStatus.isAnyEnabled()) {
+ if (DesktopModeStatus.isEnabled()) {
mShellTaskOrganizer.addFocusListener(this);
}
}
@@ -90,7 +90,7 @@ public class FreeformTaskListener implements ShellTaskOrganizer.TaskListener,
t.apply();
}
- if (DesktopModeStatus.isAnyEnabled()) {
+ if (DesktopModeStatus.isEnabled()) {
mDesktopModeTaskRepository.ifPresent(repository -> {
repository.addOrMoveFreeformTaskToTop(taskInfo.taskId);
if (taskInfo.isVisible) {
@@ -111,7 +111,7 @@ public class FreeformTaskListener implements ShellTaskOrganizer.TaskListener,
taskInfo.taskId);
mTasks.remove(taskInfo.taskId);
- if (DesktopModeStatus.isAnyEnabled()) {
+ if (DesktopModeStatus.isEnabled()) {
mDesktopModeTaskRepository.ifPresent(repository -> {
repository.removeFreeformTask(taskInfo.taskId);
if (repository.removeActiveTask(taskInfo.taskId)) {
@@ -135,7 +135,7 @@ public class FreeformTaskListener implements ShellTaskOrganizer.TaskListener,
taskInfo.taskId);
mWindowDecorationViewModel.onTaskInfoChanged(taskInfo);
state.mTaskInfo = taskInfo;
- if (DesktopModeStatus.isAnyEnabled()) {
+ if (DesktopModeStatus.isEnabled()) {
mDesktopModeTaskRepository.ifPresent(repository -> {
if (taskInfo.isVisible) {
if (repository.addActiveTask(taskInfo.displayId, taskInfo.taskId)) {
@@ -154,7 +154,7 @@ public class FreeformTaskListener implements ShellTaskOrganizer.TaskListener,
ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TASK_ORG,
"Freeform Task Focus Changed: #%d focused=%b",
taskInfo.taskId, taskInfo.isFocused);
- if (DesktopModeStatus.isAnyEnabled() && taskInfo.isFocused) {
+ if (DesktopModeStatus.isEnabled() && taskInfo.isFocused) {
mDesktopModeTaskRepository.ifPresent(repository -> {
repository.addOrMoveFreeformTaskToTop(taskInfo.taskId);
});
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTransition.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTransition.java
index e3922d65215c..018d674e5427 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTransition.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTransition.java
@@ -1059,7 +1059,21 @@ public class PipTransition extends PipTransitionController {
private void resetPrevPip(@NonNull TransitionInfo.Change prevPipTaskChange,
@NonNull SurfaceControl.Transaction startTransaction) {
final SurfaceControl leash = prevPipTaskChange.getLeash();
- startTransaction.remove(leash);
+ final Rect bounds = prevPipTaskChange.getEndAbsBounds();
+ final Point offset = prevPipTaskChange.getEndRelOffset();
+ bounds.offset(-offset.x, -offset.y);
+
+ startTransaction.setWindowCrop(leash, null);
+ startTransaction.setMatrix(leash, 1, 0, 0, 1);
+ startTransaction.setCornerRadius(leash, 0);
+ startTransaction.setPosition(leash, bounds.left, bounds.top);
+
+ if (mHasFadeOut && prevPipTaskChange.getTaskInfo().isVisible()) {
+ if (mPipAnimationController.getCurrentAnimator() != null) {
+ mPipAnimationController.getCurrentAnimator().cancel();
+ }
+ startTransaction.setAlpha(leash, 1);
+ }
mHasFadeOut = false;
mCurrentPipTaskToken = null;
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/OWNERS b/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/OWNERS
index ec09827fa4d1..6dabb3bf6f9a 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/OWNERS
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/OWNERS
@@ -1,3 +1,4 @@
# WM shell sub-module pip owner
hwwang@google.com
mateuszc@google.com
+gabiyev@google.com
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/recents/RecentTasksController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/recents/RecentTasksController.java
index ac142e955b83..94e1b33dbf58 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/recents/RecentTasksController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/recents/RecentTasksController.java
@@ -340,7 +340,7 @@ public class RecentTasksController implements TaskStackListenerCallback,
continue;
}
- if (DesktopModeStatus.isProto2Enabled() && mDesktopModeTaskRepository.isPresent()
+ if (DesktopModeStatus.isEnabled() && mDesktopModeTaskRepository.isPresent()
&& mDesktopModeTaskRepository.get().isActiveTask(taskInfo.taskId)) {
// Freeform tasks will be added as a separate entry
freeformTasks.add(taskInfo);
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java
index 842b1bf9e8af..94fa485efd5c 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java
@@ -228,6 +228,15 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
private final Toast mSplitUnsupportedToast;
private SplitRequest mSplitRequest;
+ /**
+ * Since StageCoordinator only coordinates MainStage and SideStage, it shouldn't support
+ * CompatUI layouts. CompatUI is handled separately by MainStage and SideStage.
+ */
+ @Override
+ public boolean supportCompatUI() {
+ return false;
+ }
+
class SplitRequest {
@SplitPosition
int mActivatePosition;
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultMixedHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultMixedHandler.java
index 986560bd6053..87ceaa42ef5b 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultMixedHandler.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultMixedHandler.java
@@ -43,7 +43,6 @@ import android.window.WindowContainerTransaction;
import com.android.internal.protolog.common.ProtoLog;
import com.android.wm.shell.common.split.SplitScreenUtils;
-import com.android.wm.shell.desktopmode.DesktopModeController;
import com.android.wm.shell.desktopmode.DesktopModeStatus;
import com.android.wm.shell.desktopmode.DesktopTasksController;
import com.android.wm.shell.keyguard.KeyguardTransitionHandler;
@@ -71,7 +70,6 @@ public class DefaultMixedHandler implements Transitions.TransitionHandler,
private RecentsTransitionHandler mRecentsHandler;
private StageCoordinator mSplitHandler;
private final KeyguardTransitionHandler mKeyguardHandler;
- private DesktopModeController mDesktopModeController;
private DesktopTasksController mDesktopTasksController;
private UnfoldTransitionHandler mUnfoldHandler;
@@ -141,7 +139,6 @@ public class DefaultMixedHandler implements Transitions.TransitionHandler,
@Nullable PipTransitionController pipTransitionController,
Optional<RecentsTransitionHandler> recentsHandlerOptional,
KeyguardTransitionHandler keyguardHandler,
- Optional<DesktopModeController> desktopModeControllerOptional,
Optional<DesktopTasksController> desktopTasksControllerOptional,
Optional<UnfoldTransitionHandler> unfoldHandler) {
mPlayer = player;
@@ -161,7 +158,6 @@ public class DefaultMixedHandler implements Transitions.TransitionHandler,
if (mRecentsHandler != null) {
mRecentsHandler.addMixer(this);
}
- mDesktopModeController = desktopModeControllerOptional.orElse(null);
mDesktopTasksController = desktopTasksControllerOptional.orElse(null);
mUnfoldHandler = unfoldHandler.orElse(null);
}, this);
@@ -244,7 +240,7 @@ public class DefaultMixedHandler implements Transitions.TransitionHandler,
@Override
public Transitions.TransitionHandler handleRecentsRequest(WindowContainerTransaction outWCT) {
if (mRecentsHandler != null && (mSplitHandler.isSplitScreenVisible()
- || DesktopModeStatus.isActive(mPlayer.getContext()))) {
+ || DesktopModeStatus.isEnabled())) {
return this;
}
return null;
@@ -259,7 +255,7 @@ public class DefaultMixedHandler implements Transitions.TransitionHandler,
MixedTransition.TYPE_RECENTS_DURING_SPLIT, transition);
mixed.mLeftoversHandler = mRecentsHandler;
mActiveTransitions.add(mixed);
- } else if (DesktopModeStatus.isActive(mPlayer.getContext())) {
+ } else if (DesktopModeStatus.isEnabled()) {
ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TRANSITIONS, " Got a recents request while "
+ "desktop mode is active, so treat it as Mixed.");
final MixedTransition mixed = new MixedTransition(
@@ -666,11 +662,6 @@ public class DefaultMixedHandler implements Transitions.TransitionHandler,
if (!consumed) {
return false;
}
- //Sync desktop mode state (proto 1)
- if (mDesktopModeController != null) {
- mDesktopModeController.syncSurfaceState(info, finishTransaction);
- return true;
- }
//Sync desktop mode state (proto 2)
if (mDesktopTasksController != null) {
mDesktopTasksController.syncSurfaceState(info, finishTransaction);
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CaptionWindowDecoration.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CaptionWindowDecoration.java
index ce8191067ae9..c18973132364 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CaptionWindowDecoration.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CaptionWindowDecoration.java
@@ -64,7 +64,8 @@ public class CaptionWindowDecoration extends WindowDecoration<WindowDecorLinearL
Handler handler,
Choreographer choreographer,
SyncTransactionQueue syncQueue) {
- super(context, displayController, taskOrganizer, taskInfo, taskSurface);
+ super(context, displayController, taskOrganizer, taskInfo, taskSurface,
+ taskInfo.getConfiguration());
mHandler = handler;
mChoreographer = choreographer;
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModel.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModel.java
index 92b44d43567d..abd2ad49317b 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModel.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModel.java
@@ -69,7 +69,6 @@ import com.android.wm.shell.ShellTaskOrganizer;
import com.android.wm.shell.common.DisplayController;
import com.android.wm.shell.common.DisplayLayout;
import com.android.wm.shell.common.SyncTransactionQueue;
-import com.android.wm.shell.desktopmode.DesktopModeController;
import com.android.wm.shell.desktopmode.DesktopModeStatus;
import com.android.wm.shell.desktopmode.DesktopTasksController;
import com.android.wm.shell.desktopmode.DesktopTasksController.SnapPosition;
@@ -102,7 +101,6 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel {
private final Choreographer mMainChoreographer;
private final DisplayController mDisplayController;
private final SyncTransactionQueue mSyncQueue;
- private final Optional<DesktopModeController> mDesktopModeController;
private final Optional<DesktopTasksController> mDesktopTasksController;
private boolean mTransitionDragActive;
@@ -135,7 +133,6 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel {
ShellController shellController,
SyncTransactionQueue syncQueue,
Transitions transitions,
- Optional<DesktopModeController> desktopModeController,
Optional<DesktopTasksController> desktopTasksController,
RootTaskDisplayAreaOrganizer rootTaskDisplayAreaOrganizer
) {
@@ -149,7 +146,6 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel {
shellController,
syncQueue,
transitions,
- desktopModeController,
desktopTasksController,
new DesktopModeWindowDecoration.Factory(),
new InputMonitorFactory(),
@@ -169,7 +165,6 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel {
ShellController shellController,
SyncTransactionQueue syncQueue,
Transitions transitions,
- Optional<DesktopModeController> desktopModeController,
Optional<DesktopTasksController> desktopTasksController,
DesktopModeWindowDecoration.Factory desktopModeWindowDecorFactory,
InputMonitorFactory inputMonitorFactory,
@@ -185,7 +180,6 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel {
mDisplayController = displayController;
mSyncQueue = syncQueue;
mTransitions = transitions;
- mDesktopModeController = desktopModeController;
mDesktopTasksController = desktopTasksController;
mDesktopModeWindowDecorFactory = desktopModeWindowDecorFactory;
@@ -214,9 +208,8 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel {
public void onTaskStageChanged(int taskId, int stage, boolean visible) {
if (visible) {
DesktopModeWindowDecoration decor = mWindowDecorByTaskId.get(taskId);
- if (decor != null && DesktopModeStatus.isActive(mContext)
+ if (decor != null && DesktopModeStatus.isEnabled()
&& decor.mTaskInfo.getWindowingMode() == WINDOWING_MODE_FREEFORM) {
- mDesktopModeController.ifPresent(c -> c.setDesktopModeActive(false));
mDesktopTasksController.ifPresent(c -> c.moveToSplit(decor.mTaskInfo));
}
}
@@ -376,7 +369,6 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel {
decoration.closeHandleMenu();
}
} else if (id == R.id.desktop_button) {
- mDesktopModeController.ifPresent(c -> c.setDesktopModeActive(true));
if (mDesktopTasksController.isPresent()) {
final WindowContainerTransaction wct = new WindowContainerTransaction();
// App sometimes draws before the insets from WindowDecoration#relayout have
@@ -387,7 +379,6 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel {
}
decoration.closeHandleMenu();
} else if (id == R.id.fullscreen_button) {
- mDesktopModeController.ifPresent(c -> c.setDesktopModeActive(false));
mDesktopTasksController.ifPresent(c -> c.moveToFullscreen(mTaskId));
decoration.closeHandleMenu();
} else if (id == R.id.split_screen_button) {
@@ -465,7 +456,6 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel {
private void moveTaskToFront(RunningTaskInfo taskInfo) {
if (!taskInfo.isFocused) {
mDesktopTasksController.ifPresent(c -> c.moveTaskToFront(taskInfo));
- mDesktopModeController.ifPresent(c -> c.moveTaskToFront(taskInfo));
}
}
@@ -476,15 +466,10 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel {
@Override
public boolean handleMotionEvent(@Nullable View v, MotionEvent e) {
final RunningTaskInfo taskInfo = mTaskOrganizer.getRunningTaskInfo(mTaskId);
- if (DesktopModeStatus.isProto2Enabled()
+ if (DesktopModeStatus.isEnabled()
&& taskInfo.getWindowingMode() == WINDOWING_MODE_FULLSCREEN) {
return false;
}
- if (DesktopModeStatus.isProto1Enabled() && mDesktopModeController.isPresent()
- && mDesktopModeController.get().getDisplayAreaWindowingMode(taskInfo.displayId)
- == WINDOWING_MODE_FULLSCREEN) {
- return false;
- }
if (mGestureDetector.onTouchEvent(e)) {
return true;
}
@@ -634,7 +619,7 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel {
*/
private void handleReceivedMotionEvent(MotionEvent ev, InputMonitor inputMonitor) {
final DesktopModeWindowDecoration relevantDecor = getRelevantWindowDecor(ev);
- if (DesktopModeStatus.isProto2Enabled()) {
+ if (DesktopModeStatus.isEnabled()) {
if (relevantDecor == null
|| relevantDecor.mTaskInfo.getWindowingMode() != WINDOWING_MODE_FREEFORM
|| mTransitionDragActive) {
@@ -643,14 +628,10 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel {
}
handleEventOutsideFocusedCaption(ev, relevantDecor);
// Prevent status bar from reacting to a caption drag.
- if (DesktopModeStatus.isProto2Enabled()) {
+ if (DesktopModeStatus.isEnabled()) {
if (mTransitionDragActive) {
inputMonitor.pilferPointers();
}
- } else if (DesktopModeStatus.isProto1Enabled()) {
- if (mTransitionDragActive && !DesktopModeStatus.isActive(mContext)) {
- inputMonitor.pilferPointers();
- }
}
}
@@ -683,7 +664,7 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel {
mDragToDesktopAnimationStartBounds.set(
relevantDecor.mTaskInfo.configuration.windowConfiguration.getBounds());
boolean dragFromStatusBarAllowed = false;
- if (DesktopModeStatus.isProto2Enabled()) {
+ if (DesktopModeStatus.isEnabled()) {
// In proto2 any full screen or multi-window task can be dragged to
// freeform.
final int windowingMode = relevantDecor.mTaskInfo.getWindowingMode();
@@ -708,10 +689,8 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel {
final int statusBarHeight = getStatusBarHeight(
relevantDecor.mTaskInfo.displayId);
if (ev.getY() > 2 * statusBarHeight) {
- if (DesktopModeStatus.isProto2Enabled()) {
+ if (DesktopModeStatus.isEnabled()) {
animateToDesktop(relevantDecor, ev);
- } else if (DesktopModeStatus.isProto1Enabled()) {
- mDesktopModeController.ifPresent(c -> c.setDesktopModeActive(true));
}
mMoveToDesktopAnimator = null;
return;
@@ -902,7 +881,7 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel {
&& taskInfo.isFocused) {
return false;
}
- return DesktopModeStatus.isProto2Enabled()
+ return DesktopModeStatus.isEnabled()
&& taskInfo.getWindowingMode() != WINDOWING_MODE_PINNED
&& taskInfo.getActivityType() == ACTIVITY_TYPE_STANDARD
&& !taskInfo.configuration.windowConfiguration.isAlwaysOnTop()
@@ -984,13 +963,11 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel {
@Override
public void onTaskCornersChanged(int taskId, Region corner) {
- mDesktopModeController.ifPresent(d -> d.onTaskCornersChanged(taskId, corner));
mDesktopTasksController.ifPresent(d -> d.onTaskCornersChanged(taskId, corner));
}
@Override
public void onTaskCornersRemoved(int taskId) {
- mDesktopModeController.ifPresent(d -> d.removeCornersForTask(taskId));
mDesktopTasksController.ifPresent(d -> d.removeCornersForTask(taskId));
}
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecoration.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecoration.java
index a75dce225624..e954f3b4a1d5 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecoration.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecoration.java
@@ -104,11 +104,12 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin
ShellTaskOrganizer taskOrganizer,
ActivityManager.RunningTaskInfo taskInfo,
SurfaceControl taskSurface,
+ Configuration windowDecorConfig,
Handler handler,
Choreographer choreographer,
SyncTransactionQueue syncQueue,
RootTaskDisplayAreaOrganizer rootTaskDisplayAreaOrganizer) {
- super(context, displayController, taskOrganizer, taskInfo, taskSurface);
+ super(context, displayController, taskOrganizer, taskInfo, taskSurface, windowDecorConfig);
mHandler = handler;
mChoreographer = choreographer;
@@ -118,17 +119,6 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin
loadAppInfo();
}
- @Override
- protected Configuration getConfigurationWithOverrides(
- ActivityManager.RunningTaskInfo taskInfo) {
- Configuration configuration = taskInfo.getConfiguration();
- if (DesktopTasksController.isDesktopDensityOverrideSet()) {
- // Density is overridden for desktop tasks. Keep system density for window decoration.
- configuration.densityDpi = mContext.getResources().getConfiguration().densityDpi;
- }
- return configuration;
- }
-
void setCaptionListeners(
View.OnClickListener onCaptionButtonClickListener,
View.OnTouchListener onCaptionTouchListener,
@@ -194,6 +184,10 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin
mRelayoutParams.mShadowRadiusId = shadowRadiusID;
mRelayoutParams.mApplyStartTransactionOnDraw = applyStartTransactionOnDraw;
+ mRelayoutParams.mWindowDecorConfig = DesktopTasksController.isDesktopDensityOverrideSet()
+ ? mContext.getResources().getConfiguration() // Use system context
+ : mTaskInfo.configuration; // Use task configuration
+
mRelayoutParams.mCornerRadius =
(int) ScreenDecorationsUtils.getWindowCornerRadius(mContext);
relayout(mRelayoutParams, startT, finishT, wct, oldRootView, mResult);
@@ -428,7 +422,7 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin
.setOnTouchListener(mOnCaptionTouchListener)
.setLayoutId(mRelayoutParams.mLayoutResId)
.setCaptionPosition(mRelayoutParams.mCaptionX, mRelayoutParams.mCaptionY)
- .setWindowingButtonsVisible(DesktopModeStatus.isProto2Enabled())
+ .setWindowingButtonsVisible(DesktopModeStatus.isEnabled())
.build();
mHandleMenu.show();
}
@@ -549,9 +543,6 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin
}
private int getDesktopModeWindowDecorLayoutId(int windowingMode) {
- if (DesktopModeStatus.isProto1Enabled()) {
- return R.layout.desktop_mode_app_controls_window_decor;
- }
return windowingMode == WINDOWING_MODE_FREEFORM
? R.layout.desktop_mode_app_controls_window_decor
: R.layout.desktop_mode_focused_window_decor;
@@ -617,12 +608,17 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin
Choreographer choreographer,
SyncTransactionQueue syncQueue,
RootTaskDisplayAreaOrganizer rootTaskDisplayAreaOrganizer) {
+ final Configuration windowDecorConfig =
+ DesktopTasksController.isDesktopDensityOverrideSet()
+ ? context.getResources().getConfiguration() // Use system context
+ : taskInfo.configuration; // Use task configuration
return new DesktopModeWindowDecoration(
context,
displayController,
taskOrganizer,
taskInfo,
taskSurface,
+ windowDecorConfig,
handler,
choreographer,
syncQueue,
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/HandleMenu.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/HandleMenu.java
index ac4a597c15d1..42b1240b0d49 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/HandleMenu.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/HandleMenu.java
@@ -186,7 +186,12 @@ class HandleMenu {
// More Actions pill setup.
final View moreActionsPillView = mMoreActionsPill.mWindowViewHost.getView();
final Button closeBtn = moreActionsPillView.findViewById(R.id.close_button);
- closeBtn.setOnClickListener(mOnClickListener);
+ if (mTaskInfo.getWindowingMode() == WINDOWING_MODE_FREEFORM) {
+ closeBtn.setVisibility(View.GONE);
+ } else {
+ closeBtn.setVisibility(View.VISIBLE);
+ closeBtn.setOnClickListener(mOnClickListener);
+ }
final Button selectBtn = moreActionsPillView.findViewById(R.id.select_button);
selectBtn.setOnClickListener(mOnClickListener);
}
@@ -228,7 +233,6 @@ class HandleMenu {
/**
* Update pill layout, in case task changes have caused positioning to change.
- * @param t
*/
void relayout(SurfaceControl.Transaction t) {
if (mAppInfoPill != null) {
@@ -236,7 +240,7 @@ class HandleMenu {
t.setPosition(mAppInfoPill.mWindowSurface,
mAppInfoPillPosition.x, mAppInfoPillPosition.y);
// Only show windowing buttons in proto2. Proto1 uses a system-level mode only.
- final boolean shouldShowWindowingPill = DesktopModeStatus.isProto2Enabled();
+ final boolean shouldShowWindowingPill = DesktopModeStatus.isEnabled();
if (shouldShowWindowingPill) {
t.setPosition(mWindowingPill.mWindowSurface,
mWindowingPillPosition.x, mWindowingPillPosition.y);
@@ -245,10 +249,12 @@ class HandleMenu {
mMoreActionsPillPosition.x, mMoreActionsPillPosition.y);
}
}
+
/**
* Check a passed MotionEvent if a click has occurred on any button on this caption
* Note this should only be called when a regular onClick is not possible
* (i.e. the button was clicked through status bar layer)
+ *
* @param ev the MotionEvent to compare against.
*/
void checkClickEvent(MotionEvent ev) {
@@ -267,6 +273,7 @@ class HandleMenu {
* A valid menu input is one of the following:
* An input that happens in the menu views.
* Any input before the views have been laid out.
+ *
* @param inputPoint the input to compare against.
*/
boolean isValidMenuInput(PointF inputPoint) {
@@ -297,7 +304,6 @@ class HandleMenu {
/**
* Check if the views for handle menu can be seen.
- * @return
*/
private boolean viewsLaidOut() {
return mAppInfoPill.mWindowViewHost.getView().isLaidOut();
@@ -318,8 +324,7 @@ class HandleMenu {
R.dimen.desktop_mode_handle_menu_app_info_pill_height);
mWindowingPillHeight = loadDimensionPixelSize(resources,
R.dimen.desktop_mode_handle_menu_windowing_pill_height);
- mMoreActionsPillHeight = loadDimensionPixelSize(resources,
- R.dimen.desktop_mode_handle_menu_more_actions_pill_height);
+ mMoreActionsPillHeight = shouldShowCloseButton(resources);
mShadowRadius = loadDimensionPixelSize(resources,
R.dimen.desktop_mode_handle_menu_shadow_radius);
mCornerRadius = loadDimensionPixelSize(resources,
@@ -333,6 +338,14 @@ class HandleMenu {
return resources.getDimensionPixelSize(resourceId);
}
+ private int shouldShowCloseButton(Resources resources) {
+ return (mTaskInfo.getWindowingMode() == WINDOWING_MODE_FREEFORM)
+ ? loadDimensionPixelSize(resources,
+ R.dimen.desktop_mode_handle_menu_more_actions_pill_freeform_height)
+ : loadDimensionPixelSize(resources,
+ R.dimen.desktop_mode_handle_menu_more_actions_pill_height);
+ }
+
void close() {
mAppInfoPill.releaseView();
mAppInfoPill = null;
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/WindowDecoration.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/WindowDecoration.java
index 0b0d9d5086f4..8d76fc6c542b 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/WindowDecoration.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/WindowDecoration.java
@@ -115,6 +115,7 @@ public abstract class WindowDecoration<T extends View & TaskFocusStateConsumer>
SurfaceControl mCaptionContainerSurface;
private WindowlessWindowManager mCaptionWindowManager;
private SurfaceControlViewHost mViewHost;
+ private Configuration mWindowDecorConfig;
private final Binder mOwner = new Binder();
private final Rect mCaptionInsetsRect = new Rect();
@@ -125,8 +126,9 @@ public abstract class WindowDecoration<T extends View & TaskFocusStateConsumer>
DisplayController displayController,
ShellTaskOrganizer taskOrganizer,
RunningTaskInfo taskInfo,
- SurfaceControl taskSurface) {
- this(context, displayController, taskOrganizer, taskInfo, taskSurface,
+ SurfaceControl taskSurface,
+ Configuration windowDecorConfig) {
+ this(context, displayController, taskOrganizer, taskInfo, taskSurface, windowDecorConfig,
SurfaceControl.Builder::new, SurfaceControl.Transaction::new,
WindowContainerTransaction::new, new SurfaceControlViewHostFactory() {});
}
@@ -137,6 +139,7 @@ public abstract class WindowDecoration<T extends View & TaskFocusStateConsumer>
ShellTaskOrganizer taskOrganizer,
RunningTaskInfo taskInfo,
SurfaceControl taskSurface,
+ Configuration windowDecorConfig,
Supplier<SurfaceControl.Builder> surfaceControlBuilderSupplier,
Supplier<SurfaceControl.Transaction> surfaceControlTransactionSupplier,
Supplier<WindowContainerTransaction> windowContainerTransactionSupplier,
@@ -152,17 +155,8 @@ public abstract class WindowDecoration<T extends View & TaskFocusStateConsumer>
mSurfaceControlViewHostFactory = surfaceControlViewHostFactory;
mDisplay = mDisplayController.getDisplay(mTaskInfo.displayId);
- mDecorWindowContext = mContext.createConfigurationContext(
- getConfigurationWithOverrides(mTaskInfo));
- }
-
- /**
- * Get {@link Configuration} from supplied {@link RunningTaskInfo}.
- *
- * Allows values to be overridden before returning the configuration.
- */
- protected Configuration getConfigurationWithOverrides(RunningTaskInfo taskInfo) {
- return taskInfo.getConfiguration();
+ mWindowDecorConfig = windowDecorConfig;
+ mDecorWindowContext = mContext.createConfigurationContext(mWindowDecorConfig);
}
/**
@@ -179,7 +173,6 @@ public abstract class WindowDecoration<T extends View & TaskFocusStateConsumer>
RelayoutResult<T> outResult) {
outResult.reset();
- final Configuration oldTaskConfig = mTaskInfo.getConfiguration();
if (params.mRunningTaskInfo != null) {
mTaskInfo = params.mRunningTaskInfo;
}
@@ -198,8 +191,11 @@ public abstract class WindowDecoration<T extends View & TaskFocusStateConsumer>
outResult.mRootView = rootView;
rootView = null; // Clear it just in case we use it accidentally
- final Configuration taskConfig = getConfigurationWithOverrides(mTaskInfo);
- if (oldTaskConfig.densityDpi != taskConfig.densityDpi
+
+ final int oldDensityDpi = mWindowDecorConfig.densityDpi;
+ mWindowDecorConfig = params.mWindowDecorConfig != null ? params.mWindowDecorConfig
+ : mTaskInfo.getConfiguration();
+ if (oldDensityDpi != mWindowDecorConfig.densityDpi
|| mDisplay == null
|| mDisplay.getDisplayId() != mTaskInfo.displayId
|| oldLayoutResId != mLayoutResId) {
@@ -209,7 +205,7 @@ public abstract class WindowDecoration<T extends View & TaskFocusStateConsumer>
outResult.mRootView = null;
return;
}
- mDecorWindowContext = mContext.createConfigurationContext(taskConfig);
+ mDecorWindowContext = mContext.createConfigurationContext(mWindowDecorConfig);
if (params.mLayoutResId != 0) {
outResult.mRootView = (T) LayoutInflater.from(mDecorWindowContext)
.inflate(params.mLayoutResId, null);
@@ -222,6 +218,7 @@ public abstract class WindowDecoration<T extends View & TaskFocusStateConsumer>
}
final Resources resources = mDecorWindowContext.getResources();
+ final Configuration taskConfig = mTaskInfo.getConfiguration();
final Rect taskBounds = taskConfig.windowConfiguration.getBounds();
outResult.mWidth = taskBounds.width();
outResult.mHeight = taskBounds.height();
@@ -470,6 +467,8 @@ public abstract class WindowDecoration<T extends View & TaskFocusStateConsumer>
int mCaptionX;
int mCaptionY;
+ Configuration mWindowDecorConfig;
+
boolean mApplyStartTransactionOnDraw;
void reset() {
@@ -484,6 +483,7 @@ public abstract class WindowDecoration<T extends View & TaskFocusStateConsumer>
mCaptionY = 0;
mApplyStartTransactionOnDraw = false;
+ mWindowDecorConfig = null;
}
}
diff --git a/libs/WindowManager/Shell/tests/flicker/Android.bp b/libs/WindowManager/Shell/tests/flicker/Android.bp
index 434b008a8e83..eb650caf04e2 100644
--- a/libs/WindowManager/Shell/tests/flicker/Android.bp
+++ b/libs/WindowManager/Shell/tests/flicker/Android.bp
@@ -126,6 +126,7 @@ java_defaults {
"flickertestapplib",
"flickerlib",
"flickerlib-helpers",
+ "flickerlib-trace_processor_shell",
"platform-test-annotations",
"wm-flicker-common-app-helpers",
"wm-flicker-common-assertions",
diff --git a/libs/WindowManager/Shell/tests/flicker/AndroidTestTemplate.xml b/libs/WindowManager/Shell/tests/flicker/AndroidTestTemplate.xml
index 87b20ed6305e..5e6a6c9f56dc 100644
--- a/libs/WindowManager/Shell/tests/flicker/AndroidTestTemplate.xml
+++ b/libs/WindowManager/Shell/tests/flicker/AndroidTestTemplate.xml
@@ -73,7 +73,9 @@
<option name="shell-timeout" value="6600s"/>
<option name="test-timeout" value="6000s"/>
<option name="hidden-api-checks" value="false"/>
+ <!-- TODO(b/288396763): re-enable when PerfettoListener is fixed
<option name="device-listeners" value="android.device.collectors.PerfettoListener"/>
+ -->
<!-- PerfettoListener related arguments -->
<option name="instrumentation-arg" key="perfetto_config_text_proto" value="true"/>
<option name="instrumentation-arg"
diff --git a/libs/WindowManager/Shell/tests/flicker/manifests/AndroidManifest.xml b/libs/WindowManager/Shell/tests/flicker/manifests/AndroidManifest.xml
index 6a87de47def4..ae130b8f6f7d 100644
--- a/libs/WindowManager/Shell/tests/flicker/manifests/AndroidManifest.xml
+++ b/libs/WindowManager/Shell/tests/flicker/manifests/AndroidManifest.xml
@@ -45,9 +45,13 @@
<uses-permission android:name="android.permission.MANAGE_ACTIVITY_TASKS" />
<!-- Enable bubble notification-->
<uses-permission android:name="android.permission.STATUS_BAR_SERVICE" />
+ <!-- Allow the test to connect to perfetto trace processor -->
+ <uses-permission android:name="android.permission.INTERNET"/>
- <!-- Allow the test to write directly to /sdcard/ -->
- <application android:requestLegacyExternalStorage="true" android:largeHeap="true">
+ <!-- Allow the test to write directly to /sdcard/ and connect to trace processor -->
+ <application android:requestLegacyExternalStorage="true"
+ android:networkSecurityConfig="@xml/network_security_config"
+ android:largeHeap="true">
<uses-library android:name="android.test.runner"/>
<service android:name=".NotificationListener"
diff --git a/libs/WindowManager/Shell/tests/flicker/res/xml/network_security_config.xml b/libs/WindowManager/Shell/tests/flicker/res/xml/network_security_config.xml
new file mode 100644
index 000000000000..4bd9ca049f55
--- /dev/null
+++ b/libs/WindowManager/Shell/tests/flicker/res/xml/network_security_config.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2023 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<network-security-config>
+ <domain-config cleartextTrafficPermitted="true">
+ <domain includeSubdomains="true">localhost</domain>
+ </domain-config>
+</network-security-config>
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopModeControllerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopModeControllerTest.java
deleted file mode 100644
index 605a762a395f..000000000000
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopModeControllerTest.java
+++ /dev/null
@@ -1,531 +0,0 @@
-/*
- * Copyright (C) 2022 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.wm.shell.desktopmode;
-
-import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
-import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
-import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
-import static android.app.WindowConfiguration.WINDOW_CONFIG_BOUNDS;
-import static android.view.Display.DEFAULT_DISPLAY;
-import static android.view.WindowManager.TRANSIT_CHANGE;
-import static android.view.WindowManager.TRANSIT_CLOSE;
-import static android.view.WindowManager.TRANSIT_NONE;
-import static android.view.WindowManager.TRANSIT_OPEN;
-import static android.view.WindowManager.TRANSIT_TO_FRONT;
-import static android.window.WindowContainerTransaction.HierarchyOp.HIERARCHY_OP_TYPE_REORDER;
-
-import static com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession;
-import static com.android.wm.shell.desktopmode.DesktopTestHelpers.createFreeformTask;
-import static com.android.wm.shell.desktopmode.DesktopTestHelpers.createFullscreenTask;
-import static com.android.wm.shell.desktopmode.DesktopTestHelpers.createHomeTask;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.anyInt;
-import static org.mockito.ArgumentMatchers.eq;
-import static org.mockito.Mockito.clearInvocations;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.verifyZeroInteractions;
-import static org.mockito.Mockito.when;
-
-import android.app.ActivityManager.RunningTaskInfo;
-import android.os.Binder;
-import android.os.Handler;
-import android.os.IBinder;
-import android.testing.AndroidTestingRunner;
-import android.window.DisplayAreaInfo;
-import android.window.TransitionRequestInfo;
-import android.window.WindowContainerTransaction;
-import android.window.WindowContainerTransaction.Change;
-import android.window.WindowContainerTransaction.HierarchyOp;
-
-import androidx.test.filters.SmallTest;
-
-import com.android.dx.mockito.inline.extended.StaticMockitoSession;
-import com.android.wm.shell.MockToken;
-import com.android.wm.shell.RootTaskDisplayAreaOrganizer;
-import com.android.wm.shell.ShellTaskOrganizer;
-import com.android.wm.shell.ShellTestCase;
-import com.android.wm.shell.TestShellExecutor;
-import com.android.wm.shell.common.ShellExecutor;
-import com.android.wm.shell.sysui.ShellController;
-import com.android.wm.shell.sysui.ShellInit;
-import com.android.wm.shell.transition.Transitions;
-
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.ArgumentCaptor;
-import org.mockito.Mock;
-import org.mockito.Mockito;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-
-@SmallTest
-@RunWith(AndroidTestingRunner.class)
-public class DesktopModeControllerTest extends ShellTestCase {
-
- private static final int SECOND_DISPLAY = 2;
-
- @Mock
- private ShellController mShellController;
- @Mock
- private ShellTaskOrganizer mShellTaskOrganizer;
- @Mock
- private RootTaskDisplayAreaOrganizer mRootTaskDisplayAreaOrganizer;
- @Mock
- private ShellExecutor mTestExecutor;
- @Mock
- private Handler mMockHandler;
- @Mock
- private Transitions mTransitions;
- private DesktopModeController mController;
- private DesktopModeTaskRepository mDesktopModeTaskRepository;
- private ShellInit mShellInit;
- private StaticMockitoSession mMockitoSession;
-
- @Before
- public void setUp() {
- mMockitoSession = mockitoSession().mockStatic(DesktopModeStatus.class).startMocking();
- when(DesktopModeStatus.isProto1Enabled()).thenReturn(true);
- when(DesktopModeStatus.isActive(any())).thenReturn(true);
-
- mShellInit = Mockito.spy(new ShellInit(mTestExecutor));
-
- mDesktopModeTaskRepository = new DesktopModeTaskRepository();
-
- mController = createController();
-
- when(mShellTaskOrganizer.getRunningTasks(anyInt())).thenReturn(new ArrayList<>());
-
- mShellInit.init();
- clearInvocations(mShellTaskOrganizer);
- clearInvocations(mRootTaskDisplayAreaOrganizer);
- clearInvocations(mTransitions);
- }
-
- @After
- public void tearDown() {
- mMockitoSession.finishMocking();
- }
-
- @Test
- public void instantiate_addInitCallback() {
- verify(mShellInit).addInitCallback(any(), any());
- }
-
- @Test
- public void instantiate_flagOff_doNotAddInitCallback() {
- when(DesktopModeStatus.isProto1Enabled()).thenReturn(false);
- clearInvocations(mShellInit);
-
- createController();
-
- verify(mShellInit, never()).addInitCallback(any(), any());
- }
-
- @Test
- public void testDesktopModeEnabled_rootTdaSetToFreeform() {
- DisplayAreaInfo displayAreaInfo = createMockDisplayArea();
-
- mController.updateDesktopModeActive(true);
- WindowContainerTransaction wct = getDesktopModeSwitchTransaction();
-
- // 1 change: Root TDA windowing mode
- assertThat(wct.getChanges().size()).isEqualTo(1);
- // Verify WCT has a change for setting windowing mode to freeform
- Change change = wct.getChanges().get(displayAreaInfo.token.asBinder());
- assertThat(change).isNotNull();
- assertThat(change.getWindowingMode()).isEqualTo(WINDOWING_MODE_FREEFORM);
- }
-
- @Test
- public void testDesktopModeDisabled_rootTdaSetToFullscreen() {
- DisplayAreaInfo displayAreaInfo = createMockDisplayArea();
-
- mController.updateDesktopModeActive(false);
- WindowContainerTransaction wct = getDesktopModeSwitchTransaction();
-
- // 1 change: Root TDA windowing mode
- assertThat(wct.getChanges().size()).isEqualTo(1);
- // Verify WCT has a change for setting windowing mode to fullscreen
- Change change = wct.getChanges().get(displayAreaInfo.token.asBinder());
- assertThat(change).isNotNull();
- assertThat(change.getWindowingMode()).isEqualTo(WINDOWING_MODE_FULLSCREEN);
- }
-
- @Test
- public void testDesktopModeEnabled_windowingModeCleared() {
- createMockDisplayArea();
- RunningTaskInfo freeformTask = createFreeformTask();
- RunningTaskInfo fullscreenTask = createFullscreenTask();
- RunningTaskInfo homeTask = createHomeTask();
- when(mShellTaskOrganizer.getRunningTasks(anyInt())).thenReturn(new ArrayList<>(
- Arrays.asList(freeformTask, fullscreenTask, homeTask)));
-
- mController.updateDesktopModeActive(true);
- WindowContainerTransaction wct = getDesktopModeSwitchTransaction();
-
- // 2 changes: Root TDA windowing mode and 1 task
- assertThat(wct.getChanges().size()).isEqualTo(2);
- // No changes for tasks that are not standard or freeform
- assertThat(wct.getChanges().get(fullscreenTask.token.asBinder())).isNull();
- assertThat(wct.getChanges().get(homeTask.token.asBinder())).isNull();
- // Standard freeform task has windowing mode cleared
- Change change = wct.getChanges().get(freeformTask.token.asBinder());
- assertThat(change).isNotNull();
- assertThat(change.getWindowingMode()).isEqualTo(WINDOWING_MODE_UNDEFINED);
- }
-
- @Test
- public void testDesktopModeDisabled_windowingModeAndBoundsCleared() {
- createMockDisplayArea();
- RunningTaskInfo freeformTask = createFreeformTask();
- RunningTaskInfo fullscreenTask = createFullscreenTask();
- RunningTaskInfo homeTask = createHomeTask();
- when(mShellTaskOrganizer.getRunningTasks(anyInt())).thenReturn(new ArrayList<>(
- Arrays.asList(freeformTask, fullscreenTask, homeTask)));
-
- mController.updateDesktopModeActive(false);
- WindowContainerTransaction wct = getDesktopModeSwitchTransaction();
-
- // 3 changes: Root TDA windowing mode and 2 tasks
- assertThat(wct.getChanges().size()).isEqualTo(3);
- // No changes to home task
- assertThat(wct.getChanges().get(homeTask.token.asBinder())).isNull();
- // Standard tasks have bounds cleared
- assertThatBoundsCleared(wct.getChanges().get(freeformTask.token.asBinder()));
- assertThatBoundsCleared(wct.getChanges().get(fullscreenTask.token.asBinder()));
- // Freeform standard tasks have windowing mode cleared
- assertThat(wct.getChanges().get(
- freeformTask.token.asBinder()).getWindowingMode()).isEqualTo(
- WINDOWING_MODE_UNDEFINED);
- }
-
- @Test
- public void testDesktopModeEnabled_homeTaskBehindVisibleTask() {
- createMockDisplayArea();
- RunningTaskInfo fullscreenTask1 = createFullscreenTask();
- fullscreenTask1.isVisible = true;
- RunningTaskInfo fullscreenTask2 = createFullscreenTask();
- fullscreenTask2.isVisible = false;
- RunningTaskInfo homeTask = createHomeTask();
- when(mShellTaskOrganizer.getRunningTasks(anyInt())).thenReturn(new ArrayList<>(
- Arrays.asList(fullscreenTask1, fullscreenTask2, homeTask)));
-
- mController.updateDesktopModeActive(true);
- WindowContainerTransaction wct = getDesktopModeSwitchTransaction();
-
- // Check that there are hierarchy changes for home task and visible task
- assertThat(wct.getHierarchyOps()).hasSize(2);
- // First show home task
- HierarchyOp op1 = wct.getHierarchyOps().get(0);
- assertThat(op1.getType()).isEqualTo(HIERARCHY_OP_TYPE_REORDER);
- assertThat(op1.getContainer()).isEqualTo(homeTask.token.asBinder());
-
- // Then visible task on top of it
- HierarchyOp op2 = wct.getHierarchyOps().get(1);
- assertThat(op2.getType()).isEqualTo(HIERARCHY_OP_TYPE_REORDER);
- assertThat(op2.getContainer()).isEqualTo(fullscreenTask1.token.asBinder());
- }
-
- @Test
- public void testShowDesktopApps_allAppsInvisible_bringsToFront() {
- // Set up two active tasks on desktop, task2 is on top of task1.
- RunningTaskInfo freeformTask1 = createFreeformTask();
- mDesktopModeTaskRepository.addActiveTask(DEFAULT_DISPLAY, freeformTask1.taskId);
- mDesktopModeTaskRepository.addOrMoveFreeformTaskToTop(freeformTask1.taskId);
- mDesktopModeTaskRepository.updateVisibleFreeformTasks(
- DEFAULT_DISPLAY, freeformTask1.taskId, false /* visible */);
- RunningTaskInfo freeformTask2 = createFreeformTask();
- mDesktopModeTaskRepository.addActiveTask(DEFAULT_DISPLAY, freeformTask2.taskId);
- mDesktopModeTaskRepository.addOrMoveFreeformTaskToTop(freeformTask2.taskId);
- mDesktopModeTaskRepository.updateVisibleFreeformTasks(
- DEFAULT_DISPLAY, freeformTask2.taskId, false /* visible */);
- when(mShellTaskOrganizer.getRunningTaskInfo(freeformTask1.taskId)).thenReturn(
- freeformTask1);
- when(mShellTaskOrganizer.getRunningTaskInfo(freeformTask2.taskId)).thenReturn(
- freeformTask2);
-
- // Run show desktop apps logic
- mController.showDesktopApps(DEFAULT_DISPLAY);
-
- final WindowContainerTransaction wct = getBringAppsToFrontTransaction();
- // Check wct has reorder calls
- assertThat(wct.getHierarchyOps()).hasSize(2);
-
- // Task 1 appeared first, must be first reorder to top.
- HierarchyOp op1 = wct.getHierarchyOps().get(0);
- assertThat(op1.getType()).isEqualTo(HIERARCHY_OP_TYPE_REORDER);
- assertThat(op1.getContainer()).isEqualTo(freeformTask1.token.asBinder());
-
- // Task 2 appeared last, must be last reorder to top.
- HierarchyOp op2 = wct.getHierarchyOps().get(1);
- assertThat(op2.getType()).isEqualTo(HIERARCHY_OP_TYPE_REORDER);
- assertThat(op2.getContainer()).isEqualTo(freeformTask2.token.asBinder());
- }
-
- @Test
- public void testShowDesktopApps_appsAlreadyVisible_bringsToFront() {
- final RunningTaskInfo task1 = createFreeformTask();
- mDesktopModeTaskRepository.addActiveTask(DEFAULT_DISPLAY, task1.taskId);
- mDesktopModeTaskRepository.addOrMoveFreeformTaskToTop(task1.taskId);
- mDesktopModeTaskRepository.updateVisibleFreeformTasks(DEFAULT_DISPLAY, task1.taskId,
- true /* visible */);
- when(mShellTaskOrganizer.getRunningTaskInfo(task1.taskId)).thenReturn(task1);
- final RunningTaskInfo task2 = createFreeformTask();
- mDesktopModeTaskRepository.addActiveTask(DEFAULT_DISPLAY, task2.taskId);
- mDesktopModeTaskRepository.addOrMoveFreeformTaskToTop(task2.taskId);
- mDesktopModeTaskRepository.updateVisibleFreeformTasks(DEFAULT_DISPLAY, task2.taskId,
- true /* visible */);
- when(mShellTaskOrganizer.getRunningTaskInfo(task2.taskId)).thenReturn(task2);
-
- mController.showDesktopApps(DEFAULT_DISPLAY);
-
- final WindowContainerTransaction wct = getBringAppsToFrontTransaction();
- // Check wct has reorder calls
- assertThat(wct.getHierarchyOps()).hasSize(2);
- // Task 1 appeared first, must be first reorder to top.
- HierarchyOp op1 = wct.getHierarchyOps().get(0);
- assertThat(op1.getType()).isEqualTo(HIERARCHY_OP_TYPE_REORDER);
- assertThat(op1.getContainer()).isEqualTo(task1.token.asBinder());
-
- // Task 2 appeared last, must be last reorder to top.
- HierarchyOp op2 = wct.getHierarchyOps().get(1);
- assertThat(op2.getType()).isEqualTo(HIERARCHY_OP_TYPE_REORDER);
- assertThat(op2.getContainer()).isEqualTo(task2.token.asBinder());
- }
-
- @Test
- public void testShowDesktopApps_someAppsInvisible_reordersAll() {
- final RunningTaskInfo task1 = createFreeformTask();
- mDesktopModeTaskRepository.addActiveTask(DEFAULT_DISPLAY, task1.taskId);
- mDesktopModeTaskRepository.addOrMoveFreeformTaskToTop(task1.taskId);
- mDesktopModeTaskRepository.updateVisibleFreeformTasks(DEFAULT_DISPLAY, task1.taskId,
- false /* visible */);
- when(mShellTaskOrganizer.getRunningTaskInfo(task1.taskId)).thenReturn(task1);
- final RunningTaskInfo task2 = createFreeformTask();
- mDesktopModeTaskRepository.addActiveTask(DEFAULT_DISPLAY, task2.taskId);
- mDesktopModeTaskRepository.addOrMoveFreeformTaskToTop(task2.taskId);
- mDesktopModeTaskRepository.updateVisibleFreeformTasks(DEFAULT_DISPLAY, task2.taskId,
- true /* visible */);
- when(mShellTaskOrganizer.getRunningTaskInfo(task2.taskId)).thenReturn(task2);
-
- mController.showDesktopApps(DEFAULT_DISPLAY);
-
- final WindowContainerTransaction wct = getBringAppsToFrontTransaction();
- // Both tasks should be reordered to top, even if one was already visible.
- assertThat(wct.getHierarchyOps()).hasSize(2);
- final HierarchyOp op1 = wct.getHierarchyOps().get(0);
- assertThat(op1.getType()).isEqualTo(HIERARCHY_OP_TYPE_REORDER);
- assertThat(op1.getContainer()).isEqualTo(task1.token.asBinder());
- final HierarchyOp op2 = wct.getHierarchyOps().get(1);
- assertThat(op2.getType()).isEqualTo(HIERARCHY_OP_TYPE_REORDER);
- assertThat(op2.getContainer()).isEqualTo(task2.token.asBinder());
- }
-
- @Test
- public void testShowDesktopApps_twoDisplays_bringsToFrontOnlyOneDisplay() {
- RunningTaskInfo taskDefaultDisplay = createFreeformTask(DEFAULT_DISPLAY);
- mDesktopModeTaskRepository.addActiveTask(DEFAULT_DISPLAY, taskDefaultDisplay.taskId);
- mDesktopModeTaskRepository.addOrMoveFreeformTaskToTop(taskDefaultDisplay.taskId);
- mDesktopModeTaskRepository.updateVisibleFreeformTasks(
- DEFAULT_DISPLAY, taskDefaultDisplay.taskId, false /* visible */);
- when(mShellTaskOrganizer.getRunningTaskInfo(taskDefaultDisplay.taskId)).thenReturn(
- taskDefaultDisplay);
-
- RunningTaskInfo taskSecondDisplay = createFreeformTask(SECOND_DISPLAY);
- mDesktopModeTaskRepository.addActiveTask(SECOND_DISPLAY, taskSecondDisplay.taskId);
- mDesktopModeTaskRepository.addOrMoveFreeformTaskToTop(taskSecondDisplay.taskId);
- mDesktopModeTaskRepository.updateVisibleFreeformTasks(
- SECOND_DISPLAY, taskSecondDisplay.taskId, false /* visible */);
- when(mShellTaskOrganizer.getRunningTaskInfo(taskSecondDisplay.taskId)).thenReturn(
- taskSecondDisplay);
-
- mController.showDesktopApps(DEFAULT_DISPLAY);
-
- WindowContainerTransaction wct = getBringAppsToFrontTransaction();
- assertThat(wct.getHierarchyOps()).hasSize(1);
- HierarchyOp op = wct.getHierarchyOps().get(0);
- assertThat(op.getContainer()).isEqualTo(taskDefaultDisplay.token.asBinder());
- }
-
- @Test
- public void testGetVisibleTaskCount_noTasks_returnsZero() {
- assertThat(mController.getVisibleTaskCount(DEFAULT_DISPLAY)).isEqualTo(0);
- }
-
- @Test
- public void testGetVisibleTaskCount_twoTasks_bothVisible_returnsTwo() {
- RunningTaskInfo task1 = createFreeformTask();
- mDesktopModeTaskRepository.addActiveTask(DEFAULT_DISPLAY, task1.taskId);
- mDesktopModeTaskRepository.addOrMoveFreeformTaskToTop(task1.taskId);
- mDesktopModeTaskRepository.updateVisibleFreeformTasks(DEFAULT_DISPLAY, task1.taskId,
- true /* visible */);
-
- RunningTaskInfo task2 = createFreeformTask();
- mDesktopModeTaskRepository.addActiveTask(DEFAULT_DISPLAY, task2.taskId);
- mDesktopModeTaskRepository.addOrMoveFreeformTaskToTop(task2.taskId);
- mDesktopModeTaskRepository.updateVisibleFreeformTasks(DEFAULT_DISPLAY, task2.taskId,
- true /* visible */);
-
- assertThat(mController.getVisibleTaskCount(DEFAULT_DISPLAY)).isEqualTo(2);
- }
-
- @Test
- public void testGetVisibleTaskCount_twoTasks_oneVisible_returnsOne() {
- RunningTaskInfo task1 = createFreeformTask();
- mDesktopModeTaskRepository.addActiveTask(DEFAULT_DISPLAY, task1.taskId);
- mDesktopModeTaskRepository.addOrMoveFreeformTaskToTop(task1.taskId);
- mDesktopModeTaskRepository.updateVisibleFreeformTasks(DEFAULT_DISPLAY, task1.taskId,
- true /* visible */);
-
- RunningTaskInfo task2 = createFreeformTask();
- mDesktopModeTaskRepository.addActiveTask(DEFAULT_DISPLAY, task2.taskId);
- mDesktopModeTaskRepository.addOrMoveFreeformTaskToTop(task2.taskId);
- mDesktopModeTaskRepository.updateVisibleFreeformTasks(DEFAULT_DISPLAY, task2.taskId,
- false /* visible */);
-
- assertThat(mController.getVisibleTaskCount(DEFAULT_DISPLAY)).isEqualTo(1);
- }
-
- @Test
- public void testGetVisibleTaskCount_twoTasksVisibleOnDifferentDisplays_returnsOne() {
- RunningTaskInfo taskDefaultDisplay = createFreeformTask();
- mDesktopModeTaskRepository.addActiveTask(DEFAULT_DISPLAY, taskDefaultDisplay.taskId);
- mDesktopModeTaskRepository.addOrMoveFreeformTaskToTop(taskDefaultDisplay.taskId);
- mDesktopModeTaskRepository.updateVisibleFreeformTasks(DEFAULT_DISPLAY,
- taskDefaultDisplay.taskId,
- true /* visible */);
-
- RunningTaskInfo taskSecondDisplay = createFreeformTask();
- mDesktopModeTaskRepository.addActiveTask(SECOND_DISPLAY, taskSecondDisplay.taskId);
- mDesktopModeTaskRepository.addOrMoveFreeformTaskToTop(taskSecondDisplay.taskId);
- mDesktopModeTaskRepository.updateVisibleFreeformTasks(SECOND_DISPLAY,
- taskSecondDisplay.taskId,
- true /* visible */);
-
- assertThat(mController.getVisibleTaskCount(SECOND_DISPLAY)).isEqualTo(1);
- }
-
- @Test
- public void testHandleTransitionRequest_desktopModeNotActive_returnsNull() {
- when(DesktopModeStatus.isActive(any())).thenReturn(false);
- WindowContainerTransaction wct = mController.handleRequest(
- new Binder(),
- new TransitionRequestInfo(TRANSIT_OPEN, null /* trigger */, null /* remote */));
- assertThat(wct).isNull();
- }
-
- @Test
- public void testHandleTransitionRequest_unsupportedTransit_returnsNull() {
- WindowContainerTransaction wct = mController.handleRequest(
- new Binder(),
- new TransitionRequestInfo(TRANSIT_CLOSE, null /* trigger */, null /* remote */));
- assertThat(wct).isNull();
- }
-
- @Test
- public void testHandleTransitionRequest_notFreeform_returnsNull() {
- RunningTaskInfo trigger = new RunningTaskInfo();
- trigger.configuration.windowConfiguration.setWindowingMode(WINDOWING_MODE_FULLSCREEN);
- WindowContainerTransaction wct = mController.handleRequest(
- new Binder(),
- new TransitionRequestInfo(TRANSIT_TO_FRONT, trigger, null /* remote */));
- assertThat(wct).isNull();
- }
-
- @Test
- public void testHandleTransitionRequest_taskOpen_returnsWct() {
- RunningTaskInfo trigger = new RunningTaskInfo();
- trigger.token = new MockToken().token();
- trigger.configuration.windowConfiguration.setWindowingMode(WINDOWING_MODE_FREEFORM);
- WindowContainerTransaction wct = mController.handleRequest(
- mock(IBinder.class),
- new TransitionRequestInfo(TRANSIT_OPEN, trigger, null /* remote */));
- assertThat(wct).isNotNull();
- }
-
- @Test
- public void testHandleTransitionRequest_taskToFront_returnsWct() {
- RunningTaskInfo trigger = new RunningTaskInfo();
- trigger.token = new MockToken().token();
- trigger.configuration.windowConfiguration.setWindowingMode(WINDOWING_MODE_FREEFORM);
- WindowContainerTransaction wct = mController.handleRequest(
- mock(IBinder.class),
- new TransitionRequestInfo(TRANSIT_TO_FRONT, trigger, null /* remote */));
- assertThat(wct).isNotNull();
- }
-
- @Test
- public void testHandleTransitionRequest_taskOpen_doesNotStartAnotherTransition() {
- RunningTaskInfo trigger = new RunningTaskInfo();
- trigger.token = new MockToken().token();
- trigger.configuration.windowConfiguration.setWindowingMode(WINDOWING_MODE_FREEFORM);
- mController.handleRequest(
- mock(IBinder.class),
- new TransitionRequestInfo(TRANSIT_OPEN, trigger, null /* remote */));
- verifyZeroInteractions(mTransitions);
- }
-
- private DesktopModeController createController() {
- return new DesktopModeController(mContext, mShellInit, mShellController,
- mShellTaskOrganizer, mRootTaskDisplayAreaOrganizer, mTransitions,
- mDesktopModeTaskRepository, mMockHandler, new TestShellExecutor());
- }
-
- private DisplayAreaInfo createMockDisplayArea() {
- DisplayAreaInfo displayAreaInfo = new DisplayAreaInfo(new MockToken().token(),
- mContext.getDisplayId(), 0);
- when(mRootTaskDisplayAreaOrganizer.getDisplayAreaInfo(mContext.getDisplayId()))
- .thenReturn(displayAreaInfo);
- return displayAreaInfo;
- }
-
- private WindowContainerTransaction getDesktopModeSwitchTransaction() {
- ArgumentCaptor<WindowContainerTransaction> arg = ArgumentCaptor.forClass(
- WindowContainerTransaction.class);
- if (Transitions.ENABLE_SHELL_TRANSITIONS) {
- verify(mTransitions).startTransition(eq(TRANSIT_CHANGE), arg.capture(), any());
- } else {
- verify(mRootTaskDisplayAreaOrganizer).applyTransaction(arg.capture());
- }
- return arg.getValue();
- }
-
- private WindowContainerTransaction getBringAppsToFrontTransaction() {
- final ArgumentCaptor<WindowContainerTransaction> arg = ArgumentCaptor.forClass(
- WindowContainerTransaction.class);
- if (Transitions.ENABLE_SHELL_TRANSITIONS) {
- verify(mTransitions).startTransition(eq(TRANSIT_NONE), arg.capture(), any());
- } else {
- verify(mShellTaskOrganizer).applyTransaction(arg.capture());
- }
- return arg.getValue();
- }
-
- private void assertThatBoundsCleared(Change change) {
- assertThat((change.getWindowSetMask() & WINDOW_CONFIG_BOUNDS) != 0).isTrue();
- assertThat(change.getConfiguration().windowConfiguration.getBounds().isEmpty()).isTrue();
- }
-
-}
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTasksControllerTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTasksControllerTest.kt
index 5d87cf8b25a6..be4a287bff9d 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTasksControllerTest.kt
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTasksControllerTest.kt
@@ -107,7 +107,7 @@ class DesktopTasksControllerTest : ShellTestCase() {
@Before
fun setUp() {
mockitoSession = mockitoSession().mockStatic(DesktopModeStatus::class.java).startMocking()
- whenever(DesktopModeStatus.isProto2Enabled()).thenReturn(true)
+ whenever(DesktopModeStatus.isEnabled()).thenReturn(true)
shellInit = Mockito.spy(ShellInit(testExecutor))
desktopModeTaskRepository = DesktopModeTaskRepository()
@@ -154,7 +154,7 @@ class DesktopTasksControllerTest : ShellTestCase() {
@Test
fun instantiate_flagOff_doNotAddInitCallback() {
- whenever(DesktopModeStatus.isProto2Enabled()).thenReturn(false)
+ whenever(DesktopModeStatus.isEnabled()).thenReturn(false)
clearInvocations(shellInit)
createController()
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/recents/RecentTasksControllerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/recents/RecentTasksControllerTest.java
index 9e9e1ca341eb..40ce7859cc7f 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/recents/RecentTasksControllerTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/recents/RecentTasksControllerTest.java
@@ -257,7 +257,7 @@ public class RecentTasksControllerTest extends ShellTestCase {
public void testGetRecentTasks_hasActiveDesktopTasks_proto2Enabled_groupFreeformTasks() {
StaticMockitoSession mockitoSession = mockitoSession().mockStatic(
DesktopModeStatus.class).startMocking();
- when(DesktopModeStatus.isProto2Enabled()).thenReturn(true);
+ when(DesktopModeStatus.isEnabled()).thenReturn(true);
ActivityManager.RecentTaskInfo t1 = makeTaskInfo(1);
ActivityManager.RecentTaskInfo t2 = makeTaskInfo(2);
@@ -297,7 +297,7 @@ public class RecentTasksControllerTest extends ShellTestCase {
public void testGetRecentTasks_hasActiveDesktopTasks_proto2Disabled_doNotGroupFreeformTasks() {
StaticMockitoSession mockitoSession = mockitoSession().mockStatic(
DesktopModeStatus.class).startMocking();
- when(DesktopModeStatus.isProto2Enabled()).thenReturn(false);
+ when(DesktopModeStatus.isEnabled()).thenReturn(false);
ActivityManager.RecentTaskInfo t1 = makeTaskInfo(1);
ActivityManager.RecentTaskInfo t2 = makeTaskInfo(2);
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModelTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModelTests.java
index 7f0465a24a18..d8afe68bac22 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModelTests.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModelTests.java
@@ -55,7 +55,6 @@ import com.android.wm.shell.TestRunningTaskInfoBuilder;
import com.android.wm.shell.common.DisplayController;
import com.android.wm.shell.common.DisplayLayout;
import com.android.wm.shell.common.SyncTransactionQueue;
-import com.android.wm.shell.desktopmode.DesktopModeController;
import com.android.wm.shell.desktopmode.DesktopTasksController;
import com.android.wm.shell.sysui.ShellController;
import com.android.wm.shell.sysui.ShellInit;
@@ -88,7 +87,6 @@ public class DesktopModeWindowDecorViewModelTests extends ShellTestCase {
@Mock private DisplayController mDisplayController;
@Mock private DisplayLayout mDisplayLayout;
@Mock private SyncTransactionQueue mSyncQueue;
- @Mock private DesktopModeController mDesktopModeController;
@Mock private DesktopTasksController mDesktopTasksController;
@Mock private InputMonitor mInputMonitor;
@Mock private InputManager mInputManager;
@@ -121,7 +119,6 @@ public class DesktopModeWindowDecorViewModelTests extends ShellTestCase {
mShellController,
mSyncQueue,
mTransitions,
- Optional.of(mDesktopModeController),
Optional.of(mDesktopTasksController),
mDesktopModeWindowDecorFactory,
mMockInputMonitorFactory,
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DragPositioningCallbackUtilityTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DragPositioningCallbackUtilityTest.kt
index de46b31879ed..5c0e04aecf6c 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DragPositioningCallbackUtilityTest.kt
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DragPositioningCallbackUtilityTest.kt
@@ -76,7 +76,7 @@ class DragPositioningCallbackUtilityTest {
minHeight = MIN_HEIGHT
defaultMinSize = DEFAULT_MIN
displayId = DISPLAY_ID
- configuration.windowConfiguration.bounds = STARTING_BOUNDS
+ configuration.windowConfiguration.setBounds(STARTING_BOUNDS)
}
mockWindowDecoration.mDisplay = mockDisplay
whenever(mockDisplay.displayId).thenAnswer { DISPLAY_ID }
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/FluidResizeTaskPositionerTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/FluidResizeTaskPositionerTest.kt
index 6f0599aa8243..c0c4498e3ebf 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/FluidResizeTaskPositionerTest.kt
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/FluidResizeTaskPositionerTest.kt
@@ -88,7 +88,7 @@ class FluidResizeTaskPositionerTest : ShellTestCase() {
minHeight = MIN_HEIGHT
defaultMinSize = DEFAULT_MIN
displayId = DISPLAY_ID
- configuration.windowConfiguration.bounds = STARTING_BOUNDS
+ configuration.windowConfiguration.setBounds(STARTING_BOUNDS)
}
mockWindowDecoration.mDisplay = mockDisplay
whenever(mockDisplay.displayId).thenAnswer { DISPLAY_ID }
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/VeiledResizeTaskPositionerTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/VeiledResizeTaskPositionerTest.kt
index 3465ddd9d101..8913453aa578 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/VeiledResizeTaskPositionerTest.kt
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/VeiledResizeTaskPositionerTest.kt
@@ -104,7 +104,7 @@ class VeiledResizeTaskPositionerTest : ShellTestCase() {
minHeight = MIN_HEIGHT
defaultMinSize = DEFAULT_MIN
displayId = DISPLAY_ID
- configuration.windowConfiguration.bounds = STARTING_BOUNDS
+ configuration.windowConfiguration.setBounds(STARTING_BOUNDS)
}
mockDesktopWindowDecoration.mDisplay = mockDisplay
whenever(mockDisplay.displayId).thenAnswer { DISPLAY_ID }
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/WindowDecorationTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/WindowDecorationTests.java
index 7fc1c99bb44e..76bc25aa66ef 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/WindowDecorationTests.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/WindowDecorationTests.java
@@ -39,6 +39,7 @@ import static org.mockito.Mockito.when;
import android.app.ActivityManager;
import android.content.Context;
+import android.content.res.Configuration;
import android.content.res.Resources;
import android.graphics.Color;
import android.graphics.Point;
@@ -116,6 +117,7 @@ public class WindowDecorationTests extends ShellTestCase {
private SurfaceControl.Transaction mMockSurfaceControlFinishT;
private SurfaceControl.Transaction mMockSurfaceControlAddWindowT;
private WindowDecoration.RelayoutParams mRelayoutParams = new WindowDecoration.RelayoutParams();
+ private Configuration mWindowConfiguration = new Configuration();
private int mCaptionMenuWidthId;
private int mCaptionMenuShadowRadiusId;
private int mCaptionMenuCornerRadiusId;
@@ -296,6 +298,7 @@ public class WindowDecorationTests extends ShellTestCase {
taskInfo.isFocused = true;
// Density is 2. Shadow radius is 10px. Caption height is 64px.
taskInfo.configuration.densityDpi = DisplayMetrics.DENSITY_DEFAULT * 2;
+ mWindowConfiguration.densityDpi = taskInfo.configuration.densityDpi;
final SurfaceControl taskSurface = mock(SurfaceControl.class);
final TestWindowDecoration windowDecor = createWindowDecoration(taskInfo, taskSurface);
@@ -516,7 +519,7 @@ public class WindowDecorationTests extends ShellTestCase {
private TestWindowDecoration createWindowDecoration(
ActivityManager.RunningTaskInfo taskInfo, SurfaceControl testSurface) {
return new TestWindowDecoration(mContext, mMockDisplayController, mMockShellTaskOrganizer,
- taskInfo, testSurface,
+ taskInfo, testSurface, mWindowConfiguration,
new MockObjectSupplier<>(mMockSurfaceControlBuilders,
() -> createMockSurfaceControlBuilder(mock(SurfaceControl.class))),
new MockObjectSupplier<>(mMockSurfaceControlTransactions,
@@ -556,13 +559,15 @@ public class WindowDecorationTests extends ShellTestCase {
TestWindowDecoration(Context context, DisplayController displayController,
ShellTaskOrganizer taskOrganizer, ActivityManager.RunningTaskInfo taskInfo,
SurfaceControl taskSurface,
+ Configuration windowConfiguration,
Supplier<SurfaceControl.Builder> surfaceControlBuilderSupplier,
Supplier<SurfaceControl.Transaction> surfaceControlTransactionSupplier,
Supplier<WindowContainerTransaction> windowContainerTransactionSupplier,
SurfaceControlViewHostFactory surfaceControlViewHostFactory) {
super(context, displayController, taskOrganizer, taskInfo, taskSurface,
- surfaceControlBuilderSupplier, surfaceControlTransactionSupplier,
- windowContainerTransactionSupplier, surfaceControlViewHostFactory);
+ windowConfiguration, surfaceControlBuilderSupplier,
+ surfaceControlTransactionSupplier, windowContainerTransactionSupplier,
+ surfaceControlViewHostFactory);
}
@Override
diff --git a/libs/androidfw/tests/ConfigDescription_test.cpp b/libs/androidfw/tests/ConfigDescription_test.cpp
index ec478b0900ef..07bd17568993 100644
--- a/libs/androidfw/tests/ConfigDescription_test.cpp
+++ b/libs/androidfw/tests/ConfigDescription_test.cpp
@@ -159,17 +159,17 @@ TEST(ConfigDescriptionTest, TestGrammaticalGenderQualifier) {
EXPECT_TRUE(TestParse("feminine", &config));
EXPECT_EQ(android::ResTable_config::GRAMMATICAL_GENDER_FEMININE, config.grammaticalInflection);
EXPECT_EQ(SDK_U, config.sdkVersion);
- EXPECT_EQ(std::string("feminine-v34"), config.toString().string());
+ EXPECT_EQ(std::string("feminine-v34"), config.toString().c_str());
EXPECT_TRUE(TestParse("masculine", &config));
EXPECT_EQ(android::ResTable_config::GRAMMATICAL_GENDER_MASCULINE, config.grammaticalInflection);
EXPECT_EQ(SDK_U, config.sdkVersion);
- EXPECT_EQ(std::string("masculine-v34"), config.toString().string());
+ EXPECT_EQ(std::string("masculine-v34"), config.toString().c_str());
EXPECT_TRUE(TestParse("neuter", &config));
EXPECT_EQ(android::ResTable_config::GRAMMATICAL_GENDER_NEUTER, config.grammaticalInflection);
EXPECT_EQ(SDK_U, config.sdkVersion);
- EXPECT_EQ(std::string("neuter-v34"), config.toString().string());
+ EXPECT_EQ(std::string("neuter-v34"), config.toString().c_str());
}
} // namespace android
diff --git a/libs/androidfw/tests/ResTable_test.cpp b/libs/androidfw/tests/ResTable_test.cpp
index 945981b981a0..faac51403203 100644
--- a/libs/androidfw/tests/ResTable_test.cpp
+++ b/libs/androidfw/tests/ResTable_test.cpp
@@ -468,7 +468,7 @@ TEST_P(ResTableParameterizedTest, ShouldLoadSparseEntriesSuccessfully) {
String16 name(u"com.android.sparse:integer/foo_9");
uint32_t flags;
uint32_t resid =
- table.identifierForName(name.string(), name.size(), nullptr, 0, nullptr, 0, &flags);
+ table.identifierForName(name.c_str(), name.size(), nullptr, 0, nullptr, 0, &flags);
ASSERT_NE(0u, resid);
Res_value val;
diff --git a/libs/hwui/renderthread/VulkanManager.cpp b/libs/hwui/renderthread/VulkanManager.cpp
index e2b541aa5ecb..ee3b2e48fe4b 100644
--- a/libs/hwui/renderthread/VulkanManager.cpp
+++ b/libs/hwui/renderthread/VulkanManager.cpp
@@ -25,6 +25,7 @@
#include <android/sync.h>
#include <gui/TraceUtils.h>
#include <include/gpu/ganesh/SkSurfaceGanesh.h>
+#include <include/gpu/ganesh/vk/GrVkBackendSurface.h>
#include <ui/FatVector.h>
#include <vk/GrVkExtensions.h>
#include <vk/GrVkTypes.h>
@@ -599,7 +600,7 @@ nsecs_t VulkanManager::finishFrame(SkSurface* surface) {
surface, SkSurfaces::BackendHandleAccess::kFlushRead);
if (backendRenderTarget.isValid()) {
GrVkImageInfo info;
- if (backendRenderTarget.getVkImageInfo(&info)) {
+ if (GrBackendRenderTargets::GetVkImageInfo(backendRenderTarget, &info)) {
image = info.fImage;
} else {
ALOGE("Frame boundary: backend is not vulkan");
diff --git a/location/Android.bp b/location/Android.bp
index 46dca74e7e40..cfe0e494432c 100644
--- a/location/Android.bp
+++ b/location/Android.bp
@@ -7,18 +7,18 @@ package {
default_applicable_licenses: ["frameworks_base_license"],
}
-//location sources that will populate the new module
filegroup {
- name: "framework-location-nonupdatable-sources",
+ name: "framework-location-sources",
srcs: [
- "placeholder_java/android/location/Placeholder.java",
+ "java/**/*.java",
+ "java/**/*.aidl",
],
}
java_sdk_library {
name: "framework-location",
srcs: [
- ":framework-location-nonupdatable-sources",
+ ":framework-location-sources",
],
defaults: ["framework-non-updatable-unbundled-defaults"],
permitted_packages: [
diff --git a/location/api/current.txt b/location/api/current.txt
index d802177e249b..33effdd6cd6c 100644
--- a/location/api/current.txt
+++ b/location/api/current.txt
@@ -1 +1,725 @@
// Signature format: 2.0
+package android.location {
+
+ public class Address implements android.os.Parcelable {
+ ctor public Address(java.util.Locale);
+ method public void clearLatitude();
+ method public void clearLongitude();
+ method public int describeContents();
+ method public String getAddressLine(int);
+ method public String getAdminArea();
+ method public String getCountryCode();
+ method public String getCountryName();
+ method public android.os.Bundle getExtras();
+ method public String getFeatureName();
+ method public double getLatitude();
+ method public java.util.Locale getLocale();
+ method public String getLocality();
+ method public double getLongitude();
+ method public int getMaxAddressLineIndex();
+ method public String getPhone();
+ method public String getPostalCode();
+ method public String getPremises();
+ method public String getSubAdminArea();
+ method public String getSubLocality();
+ method public String getSubThoroughfare();
+ method public String getThoroughfare();
+ method public String getUrl();
+ method public boolean hasLatitude();
+ method public boolean hasLongitude();
+ method public void setAddressLine(int, String);
+ method public void setAdminArea(String);
+ method public void setCountryCode(String);
+ method public void setCountryName(String);
+ method public void setExtras(android.os.Bundle);
+ method public void setFeatureName(String);
+ method public void setLatitude(double);
+ method public void setLocality(String);
+ method public void setLongitude(double);
+ method public void setPhone(String);
+ method public void setPostalCode(String);
+ method public void setPremises(String);
+ method public void setSubAdminArea(String);
+ method public void setSubLocality(String);
+ method public void setSubThoroughfare(String);
+ method public void setThoroughfare(String);
+ method public void setUrl(String);
+ method public void writeToParcel(android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.location.Address> CREATOR;
+ }
+
+ @Deprecated public class Criteria implements android.os.Parcelable {
+ ctor @Deprecated public Criteria();
+ ctor @Deprecated public Criteria(android.location.Criteria);
+ method @Deprecated public int describeContents();
+ method @Deprecated public int getAccuracy();
+ method @Deprecated public int getBearingAccuracy();
+ method @Deprecated public int getHorizontalAccuracy();
+ method @Deprecated public int getPowerRequirement();
+ method @Deprecated public int getSpeedAccuracy();
+ method @Deprecated public int getVerticalAccuracy();
+ method @Deprecated public boolean isAltitudeRequired();
+ method @Deprecated public boolean isBearingRequired();
+ method @Deprecated public boolean isCostAllowed();
+ method @Deprecated public boolean isSpeedRequired();
+ method @Deprecated public void setAccuracy(int);
+ method @Deprecated public void setAltitudeRequired(boolean);
+ method @Deprecated public void setBearingAccuracy(int);
+ method @Deprecated public void setBearingRequired(boolean);
+ method @Deprecated public void setCostAllowed(boolean);
+ method @Deprecated public void setHorizontalAccuracy(int);
+ method @Deprecated public void setPowerRequirement(int);
+ method @Deprecated public void setSpeedAccuracy(int);
+ method @Deprecated public void setSpeedRequired(boolean);
+ method @Deprecated public void setVerticalAccuracy(int);
+ method @Deprecated public void writeToParcel(android.os.Parcel, int);
+ field @Deprecated public static final int ACCURACY_COARSE = 2; // 0x2
+ field @Deprecated public static final int ACCURACY_FINE = 1; // 0x1
+ field @Deprecated public static final int ACCURACY_HIGH = 3; // 0x3
+ field @Deprecated public static final int ACCURACY_LOW = 1; // 0x1
+ field @Deprecated public static final int ACCURACY_MEDIUM = 2; // 0x2
+ field @Deprecated @NonNull public static final android.os.Parcelable.Creator<android.location.Criteria> CREATOR;
+ field @Deprecated public static final int NO_REQUIREMENT = 0; // 0x0
+ field @Deprecated public static final int POWER_HIGH = 3; // 0x3
+ field @Deprecated public static final int POWER_LOW = 1; // 0x1
+ field @Deprecated public static final int POWER_MEDIUM = 2; // 0x2
+ }
+
+ public final class Geocoder {
+ ctor public Geocoder(@NonNull android.content.Context);
+ ctor public Geocoder(@NonNull android.content.Context, @NonNull java.util.Locale);
+ method @Deprecated @Nullable public java.util.List<android.location.Address> getFromLocation(@FloatRange(from=-90.0, to=90.0) double, @FloatRange(from=-180.0, to=180.0) double, @IntRange int) throws java.io.IOException;
+ method public void getFromLocation(@FloatRange(from=-90.0, to=90.0) double, @FloatRange(from=-180.0, to=180.0) double, @IntRange int, @NonNull android.location.Geocoder.GeocodeListener);
+ method @Deprecated @Nullable public java.util.List<android.location.Address> getFromLocationName(@NonNull String, @IntRange int) throws java.io.IOException;
+ method public void getFromLocationName(@NonNull String, @IntRange int, @NonNull android.location.Geocoder.GeocodeListener);
+ method @Deprecated @Nullable public java.util.List<android.location.Address> getFromLocationName(@NonNull String, @IntRange int, @FloatRange(from=-90.0, to=90.0) double, @FloatRange(from=-180.0, to=180.0) double, @FloatRange(from=-90.0, to=90.0) double, @FloatRange(from=-180.0, to=180.0) double) throws java.io.IOException;
+ method public void getFromLocationName(@NonNull String, @IntRange int, @FloatRange(from=-90.0, to=90.0) double, @FloatRange(from=-180.0, to=180.0) double, @FloatRange(from=-90.0, to=90.0) double, @FloatRange(from=-180.0, to=180.0) double, @NonNull android.location.Geocoder.GeocodeListener);
+ method public static boolean isPresent();
+ }
+
+ public static interface Geocoder.GeocodeListener {
+ method public default void onError(@Nullable String);
+ method public void onGeocode(@NonNull java.util.List<android.location.Address>);
+ }
+
+ public final class GnssAntennaInfo implements android.os.Parcelable {
+ method public int describeContents();
+ method @FloatRange(from=0.0f) public double getCarrierFrequencyMHz();
+ method @NonNull public android.location.GnssAntennaInfo.PhaseCenterOffset getPhaseCenterOffset();
+ method @Nullable public android.location.GnssAntennaInfo.SphericalCorrections getPhaseCenterVariationCorrections();
+ method @Nullable public android.location.GnssAntennaInfo.SphericalCorrections getSignalGainCorrections();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.location.GnssAntennaInfo> CREATOR;
+ }
+
+ public static class GnssAntennaInfo.Builder {
+ ctor @Deprecated public GnssAntennaInfo.Builder();
+ ctor public GnssAntennaInfo.Builder(double, @NonNull android.location.GnssAntennaInfo.PhaseCenterOffset);
+ ctor public GnssAntennaInfo.Builder(@NonNull android.location.GnssAntennaInfo);
+ method @NonNull public android.location.GnssAntennaInfo build();
+ method @NonNull public android.location.GnssAntennaInfo.Builder setCarrierFrequencyMHz(@FloatRange(from=0.0f) double);
+ method @NonNull public android.location.GnssAntennaInfo.Builder setPhaseCenterOffset(@NonNull android.location.GnssAntennaInfo.PhaseCenterOffset);
+ method @NonNull public android.location.GnssAntennaInfo.Builder setPhaseCenterVariationCorrections(@Nullable android.location.GnssAntennaInfo.SphericalCorrections);
+ method @NonNull public android.location.GnssAntennaInfo.Builder setSignalGainCorrections(@Nullable android.location.GnssAntennaInfo.SphericalCorrections);
+ }
+
+ public static interface GnssAntennaInfo.Listener {
+ method public void onGnssAntennaInfoReceived(@NonNull java.util.List<android.location.GnssAntennaInfo>);
+ }
+
+ public static final class GnssAntennaInfo.PhaseCenterOffset implements android.os.Parcelable {
+ ctor public GnssAntennaInfo.PhaseCenterOffset(double, double, double, double, double, double);
+ method public int describeContents();
+ method @FloatRange public double getXOffsetMm();
+ method @FloatRange public double getXOffsetUncertaintyMm();
+ method @FloatRange public double getYOffsetMm();
+ method @FloatRange public double getYOffsetUncertaintyMm();
+ method @FloatRange public double getZOffsetMm();
+ method @FloatRange public double getZOffsetUncertaintyMm();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.location.GnssAntennaInfo.PhaseCenterOffset> CREATOR;
+ }
+
+ public static final class GnssAntennaInfo.SphericalCorrections implements android.os.Parcelable {
+ ctor public GnssAntennaInfo.SphericalCorrections(@NonNull double[][], @NonNull double[][]);
+ method public int describeContents();
+ method @NonNull public double[][] getCorrectionUncertaintiesArray();
+ method @NonNull public double[][] getCorrectionsArray();
+ method @FloatRange(from=0.0f, to=180.0f) public double getDeltaPhi();
+ method @FloatRange(from=0.0f, to=360.0f) public double getDeltaTheta();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.location.GnssAntennaInfo.SphericalCorrections> CREATOR;
+ }
+
+ public final class GnssAutomaticGainControl implements android.os.Parcelable {
+ method public int describeContents();
+ method @IntRange(from=0) public long getCarrierFrequencyHz();
+ method public int getConstellationType();
+ method @FloatRange(from=0xffffd8f0, to=10000) public double getLevelDb();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.location.GnssAutomaticGainControl> CREATOR;
+ }
+
+ public static final class GnssAutomaticGainControl.Builder {
+ ctor public GnssAutomaticGainControl.Builder();
+ ctor public GnssAutomaticGainControl.Builder(@NonNull android.location.GnssAutomaticGainControl);
+ method @NonNull public android.location.GnssAutomaticGainControl build();
+ method @NonNull public android.location.GnssAutomaticGainControl.Builder setCarrierFrequencyHz(@IntRange(from=0) long);
+ method @NonNull public android.location.GnssAutomaticGainControl.Builder setConstellationType(int);
+ method @NonNull public android.location.GnssAutomaticGainControl.Builder setLevelDb(@FloatRange(from=0xffffd8f0, to=10000) double);
+ }
+
+ public final class GnssCapabilities implements android.os.Parcelable {
+ method public int describeContents();
+ method @NonNull public java.util.List<android.location.GnssSignalType> getGnssSignalTypes();
+ method public int hasAccumulatedDeltaRange();
+ method public boolean hasAntennaInfo();
+ method public boolean hasGeofencing();
+ method @Deprecated public boolean hasGnssAntennaInfo();
+ method public boolean hasLowPowerMode();
+ method public boolean hasMeasurementCorrections();
+ method public boolean hasMeasurementCorrectionsExcessPathLength();
+ method public boolean hasMeasurementCorrectionsForDriving();
+ method public boolean hasMeasurementCorrectionsLosSats();
+ method public boolean hasMeasurementCorrectionsReflectingPlane();
+ method public boolean hasMeasurementCorrelationVectors();
+ method public boolean hasMeasurements();
+ method public boolean hasMsa();
+ method public boolean hasMsb();
+ method public boolean hasNavigationMessages();
+ method public boolean hasOnDemandTime();
+ method public boolean hasPowerMultibandAcquisition();
+ method public boolean hasPowerMultibandTracking();
+ method public boolean hasPowerOtherModes();
+ method public boolean hasPowerSinglebandAcquisition();
+ method public boolean hasPowerSinglebandTracking();
+ method public boolean hasPowerTotal();
+ method public boolean hasSatelliteBlocklist();
+ method public boolean hasSatellitePvt();
+ method public boolean hasScheduling();
+ method public boolean hasSingleShotFix();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field public static final int CAPABILITY_SUPPORTED = 1; // 0x1
+ field public static final int CAPABILITY_UNKNOWN = 0; // 0x0
+ field public static final int CAPABILITY_UNSUPPORTED = 2; // 0x2
+ field @NonNull public static final android.os.Parcelable.Creator<android.location.GnssCapabilities> CREATOR;
+ }
+
+ public static final class GnssCapabilities.Builder {
+ ctor public GnssCapabilities.Builder();
+ ctor public GnssCapabilities.Builder(@NonNull android.location.GnssCapabilities);
+ method @NonNull public android.location.GnssCapabilities build();
+ method @NonNull public android.location.GnssCapabilities.Builder setGnssSignalTypes(@NonNull java.util.List<android.location.GnssSignalType>);
+ method @NonNull public android.location.GnssCapabilities.Builder setHasAccumulatedDeltaRange(int);
+ method @NonNull public android.location.GnssCapabilities.Builder setHasAntennaInfo(boolean);
+ method @NonNull public android.location.GnssCapabilities.Builder setHasGeofencing(boolean);
+ method @NonNull public android.location.GnssCapabilities.Builder setHasLowPowerMode(boolean);
+ method @NonNull public android.location.GnssCapabilities.Builder setHasMeasurementCorrections(boolean);
+ method @NonNull public android.location.GnssCapabilities.Builder setHasMeasurementCorrectionsExcessPathLength(boolean);
+ method @NonNull public android.location.GnssCapabilities.Builder setHasMeasurementCorrectionsForDriving(boolean);
+ method @NonNull public android.location.GnssCapabilities.Builder setHasMeasurementCorrectionsLosSats(boolean);
+ method @NonNull public android.location.GnssCapabilities.Builder setHasMeasurementCorrectionsReflectingPlane(boolean);
+ method @NonNull public android.location.GnssCapabilities.Builder setHasMeasurementCorrelationVectors(boolean);
+ method @NonNull public android.location.GnssCapabilities.Builder setHasMeasurements(boolean);
+ method @NonNull public android.location.GnssCapabilities.Builder setHasMsa(boolean);
+ method @NonNull public android.location.GnssCapabilities.Builder setHasMsb(boolean);
+ method @NonNull public android.location.GnssCapabilities.Builder setHasNavigationMessages(boolean);
+ method @NonNull public android.location.GnssCapabilities.Builder setHasOnDemandTime(boolean);
+ method @NonNull public android.location.GnssCapabilities.Builder setHasPowerMultibandAcquisition(boolean);
+ method @NonNull public android.location.GnssCapabilities.Builder setHasPowerMultibandTracking(boolean);
+ method @NonNull public android.location.GnssCapabilities.Builder setHasPowerOtherModes(boolean);
+ method @NonNull public android.location.GnssCapabilities.Builder setHasPowerSinglebandAcquisition(boolean);
+ method @NonNull public android.location.GnssCapabilities.Builder setHasPowerSinglebandTracking(boolean);
+ method @NonNull public android.location.GnssCapabilities.Builder setHasPowerTotal(boolean);
+ method @NonNull public android.location.GnssCapabilities.Builder setHasSatelliteBlocklist(boolean);
+ method @NonNull public android.location.GnssCapabilities.Builder setHasSatellitePvt(boolean);
+ method @NonNull public android.location.GnssCapabilities.Builder setHasScheduling(boolean);
+ method @NonNull public android.location.GnssCapabilities.Builder setHasSingleShotFix(boolean);
+ }
+
+ public final class GnssClock implements android.os.Parcelable {
+ method public int describeContents();
+ method public double getBiasNanos();
+ method @FloatRange(from=0.0f) public double getBiasUncertaintyNanos();
+ method public double getDriftNanosPerSecond();
+ method @FloatRange(from=0.0f) public double getDriftUncertaintyNanosPerSecond();
+ method public long getElapsedRealtimeNanos();
+ method @FloatRange(from=0.0f) public double getElapsedRealtimeUncertaintyNanos();
+ method public long getFullBiasNanos();
+ method public int getHardwareClockDiscontinuityCount();
+ method public int getLeapSecond();
+ method @FloatRange(from=0.0) public double getReferenceCarrierFrequencyHzForIsb();
+ method @NonNull public String getReferenceCodeTypeForIsb();
+ method public int getReferenceConstellationTypeForIsb();
+ method public long getTimeNanos();
+ method @FloatRange(from=0.0f) public double getTimeUncertaintyNanos();
+ method public boolean hasBiasNanos();
+ method public boolean hasBiasUncertaintyNanos();
+ method public boolean hasDriftNanosPerSecond();
+ method public boolean hasDriftUncertaintyNanosPerSecond();
+ method public boolean hasElapsedRealtimeNanos();
+ method public boolean hasElapsedRealtimeUncertaintyNanos();
+ method public boolean hasFullBiasNanos();
+ method public boolean hasLeapSecond();
+ method public boolean hasReferenceCarrierFrequencyHzForIsb();
+ method public boolean hasReferenceCodeTypeForIsb();
+ method public boolean hasReferenceConstellationTypeForIsb();
+ method public boolean hasTimeUncertaintyNanos();
+ method public void writeToParcel(android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.location.GnssClock> CREATOR;
+ }
+
+ public final class GnssMeasurement implements android.os.Parcelable {
+ method public int describeContents();
+ method public double getAccumulatedDeltaRangeMeters();
+ method public int getAccumulatedDeltaRangeState();
+ method public double getAccumulatedDeltaRangeUncertaintyMeters();
+ method @Deprecated public double getAutomaticGainControlLevelDb();
+ method @FloatRange(from=0, to=63) public double getBasebandCn0DbHz();
+ method @Deprecated public long getCarrierCycles();
+ method public float getCarrierFrequencyHz();
+ method @Deprecated public double getCarrierPhase();
+ method @Deprecated public double getCarrierPhaseUncertainty();
+ method @FloatRange(from=0, to=63) public double getCn0DbHz();
+ method @NonNull public String getCodeType();
+ method public int getConstellationType();
+ method public double getFullInterSignalBiasNanos();
+ method @FloatRange(from=0.0) public double getFullInterSignalBiasUncertaintyNanos();
+ method public int getMultipathIndicator();
+ method public double getPseudorangeRateMetersPerSecond();
+ method public double getPseudorangeRateUncertaintyMetersPerSecond();
+ method public long getReceivedSvTimeNanos();
+ method public long getReceivedSvTimeUncertaintyNanos();
+ method public double getSatelliteInterSignalBiasNanos();
+ method @FloatRange(from=0.0) public double getSatelliteInterSignalBiasUncertaintyNanos();
+ method public double getSnrInDb();
+ method public int getState();
+ method public int getSvid();
+ method public double getTimeOffsetNanos();
+ method @Deprecated public boolean hasAutomaticGainControlLevelDb();
+ method public boolean hasBasebandCn0DbHz();
+ method @Deprecated public boolean hasCarrierCycles();
+ method public boolean hasCarrierFrequencyHz();
+ method @Deprecated public boolean hasCarrierPhase();
+ method @Deprecated public boolean hasCarrierPhaseUncertainty();
+ method public boolean hasCodeType();
+ method public boolean hasFullInterSignalBiasNanos();
+ method public boolean hasFullInterSignalBiasUncertaintyNanos();
+ method public boolean hasSatelliteInterSignalBiasNanos();
+ method public boolean hasSatelliteInterSignalBiasUncertaintyNanos();
+ method public boolean hasSnrInDb();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final int ADR_STATE_CYCLE_SLIP = 4; // 0x4
+ field public static final int ADR_STATE_HALF_CYCLE_REPORTED = 16; // 0x10
+ field public static final int ADR_STATE_HALF_CYCLE_RESOLVED = 8; // 0x8
+ field public static final int ADR_STATE_RESET = 2; // 0x2
+ field public static final int ADR_STATE_UNKNOWN = 0; // 0x0
+ field public static final int ADR_STATE_VALID = 1; // 0x1
+ field @NonNull public static final android.os.Parcelable.Creator<android.location.GnssMeasurement> CREATOR;
+ field public static final int MULTIPATH_INDICATOR_DETECTED = 1; // 0x1
+ field public static final int MULTIPATH_INDICATOR_NOT_DETECTED = 2; // 0x2
+ field public static final int MULTIPATH_INDICATOR_UNKNOWN = 0; // 0x0
+ field public static final int STATE_2ND_CODE_LOCK = 65536; // 0x10000
+ field public static final int STATE_BDS_D2_BIT_SYNC = 256; // 0x100
+ field public static final int STATE_BDS_D2_SUBFRAME_SYNC = 512; // 0x200
+ field public static final int STATE_BIT_SYNC = 2; // 0x2
+ field public static final int STATE_CODE_LOCK = 1; // 0x1
+ field public static final int STATE_GAL_E1BC_CODE_LOCK = 1024; // 0x400
+ field public static final int STATE_GAL_E1B_PAGE_SYNC = 4096; // 0x1000
+ field public static final int STATE_GAL_E1C_2ND_CODE_LOCK = 2048; // 0x800
+ field public static final int STATE_GLO_STRING_SYNC = 64; // 0x40
+ field public static final int STATE_GLO_TOD_DECODED = 128; // 0x80
+ field public static final int STATE_GLO_TOD_KNOWN = 32768; // 0x8000
+ field public static final int STATE_MSEC_AMBIGUOUS = 16; // 0x10
+ field public static final int STATE_SBAS_SYNC = 8192; // 0x2000
+ field public static final int STATE_SUBFRAME_SYNC = 4; // 0x4
+ field public static final int STATE_SYMBOL_SYNC = 32; // 0x20
+ field public static final int STATE_TOW_DECODED = 8; // 0x8
+ field public static final int STATE_TOW_KNOWN = 16384; // 0x4000
+ field public static final int STATE_UNKNOWN = 0; // 0x0
+ }
+
+ public final class GnssMeasurementRequest implements android.os.Parcelable {
+ method public int describeContents();
+ method @IntRange(from=0) public int getIntervalMillis();
+ method public boolean isFullTracking();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.location.GnssMeasurementRequest> CREATOR;
+ field public static final int PASSIVE_INTERVAL = 2147483647; // 0x7fffffff
+ }
+
+ public static final class GnssMeasurementRequest.Builder {
+ ctor public GnssMeasurementRequest.Builder();
+ ctor public GnssMeasurementRequest.Builder(@NonNull android.location.GnssMeasurementRequest);
+ method @NonNull public android.location.GnssMeasurementRequest build();
+ method @NonNull public android.location.GnssMeasurementRequest.Builder setFullTracking(boolean);
+ method @NonNull public android.location.GnssMeasurementRequest.Builder setIntervalMillis(@IntRange(from=0) int);
+ }
+
+ public final class GnssMeasurementsEvent implements android.os.Parcelable {
+ method public int describeContents();
+ method @NonNull public android.location.GnssClock getClock();
+ method @NonNull public java.util.Collection<android.location.GnssAutomaticGainControl> getGnssAutomaticGainControls();
+ method @NonNull public java.util.Collection<android.location.GnssMeasurement> getMeasurements();
+ method public boolean hasIsFullTracking();
+ method public boolean isFullTracking();
+ method public void writeToParcel(android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.location.GnssMeasurementsEvent> CREATOR;
+ }
+
+ public static final class GnssMeasurementsEvent.Builder {
+ ctor public GnssMeasurementsEvent.Builder();
+ ctor public GnssMeasurementsEvent.Builder(@NonNull android.location.GnssMeasurementsEvent);
+ method @NonNull public android.location.GnssMeasurementsEvent build();
+ method @NonNull public android.location.GnssMeasurementsEvent.Builder clearIsFullTracking();
+ method @NonNull public android.location.GnssMeasurementsEvent.Builder setClock(@NonNull android.location.GnssClock);
+ method @NonNull public android.location.GnssMeasurementsEvent.Builder setGnssAutomaticGainControls(@NonNull java.util.Collection<android.location.GnssAutomaticGainControl>);
+ method @NonNull public android.location.GnssMeasurementsEvent.Builder setIsFullTracking(boolean);
+ method @NonNull public android.location.GnssMeasurementsEvent.Builder setMeasurements(@NonNull java.util.Collection<android.location.GnssMeasurement>);
+ }
+
+ public abstract static class GnssMeasurementsEvent.Callback {
+ ctor public GnssMeasurementsEvent.Callback();
+ method public void onGnssMeasurementsReceived(android.location.GnssMeasurementsEvent);
+ method @Deprecated public void onStatusChanged(int);
+ field @Deprecated public static final int STATUS_LOCATION_DISABLED = 2; // 0x2
+ field @Deprecated public static final int STATUS_NOT_ALLOWED = 3; // 0x3
+ field @Deprecated public static final int STATUS_NOT_SUPPORTED = 0; // 0x0
+ field @Deprecated public static final int STATUS_READY = 1; // 0x1
+ }
+
+ public final class GnssNavigationMessage implements android.os.Parcelable {
+ method public int describeContents();
+ method @NonNull public byte[] getData();
+ method @IntRange(from=0xffffffff, to=120) public int getMessageId();
+ method public int getStatus();
+ method @IntRange(from=1) public int getSubmessageId();
+ method @IntRange(from=1, to=200) public int getSvid();
+ method public int getType();
+ method public void writeToParcel(android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.location.GnssNavigationMessage> CREATOR;
+ field public static final int STATUS_PARITY_PASSED = 1; // 0x1
+ field public static final int STATUS_PARITY_REBUILT = 2; // 0x2
+ field public static final int STATUS_UNKNOWN = 0; // 0x0
+ field public static final int TYPE_BDS_CNAV1 = 1283; // 0x503
+ field public static final int TYPE_BDS_CNAV2 = 1284; // 0x504
+ field public static final int TYPE_BDS_D1 = 1281; // 0x501
+ field public static final int TYPE_BDS_D2 = 1282; // 0x502
+ field public static final int TYPE_GAL_F = 1538; // 0x602
+ field public static final int TYPE_GAL_I = 1537; // 0x601
+ field public static final int TYPE_GLO_L1CA = 769; // 0x301
+ field public static final int TYPE_GPS_CNAV2 = 260; // 0x104
+ field public static final int TYPE_GPS_L1CA = 257; // 0x101
+ field public static final int TYPE_GPS_L2CNAV = 258; // 0x102
+ field public static final int TYPE_GPS_L5CNAV = 259; // 0x103
+ field public static final int TYPE_IRN_L5CA = 1793; // 0x701
+ field public static final int TYPE_QZS_L1CA = 1025; // 0x401
+ field public static final int TYPE_SBS = 513; // 0x201
+ field public static final int TYPE_UNKNOWN = 0; // 0x0
+ }
+
+ public abstract static class GnssNavigationMessage.Callback {
+ ctor public GnssNavigationMessage.Callback();
+ method public void onGnssNavigationMessageReceived(android.location.GnssNavigationMessage);
+ method @Deprecated public void onStatusChanged(int);
+ field @Deprecated public static final int STATUS_LOCATION_DISABLED = 2; // 0x2
+ field @Deprecated public static final int STATUS_NOT_SUPPORTED = 0; // 0x0
+ field @Deprecated public static final int STATUS_READY = 1; // 0x1
+ }
+
+ public final class GnssSignalType implements android.os.Parcelable {
+ method @NonNull public static android.location.GnssSignalType create(int, @FloatRange(from=0.0f, fromInclusive=false) double, @NonNull String);
+ method public int describeContents();
+ method @FloatRange(from=0.0f, fromInclusive=false) public double getCarrierFrequencyHz();
+ method @NonNull public String getCodeType();
+ method public int getConstellationType();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.location.GnssSignalType> CREATOR;
+ }
+
+ public final class GnssStatus implements android.os.Parcelable {
+ method public int describeContents();
+ method @FloatRange(from=0, to=360) public float getAzimuthDegrees(@IntRange(from=0) int);
+ method @FloatRange(from=0, to=63) public float getBasebandCn0DbHz(@IntRange(from=0) int);
+ method @FloatRange(from=0) public float getCarrierFrequencyHz(@IntRange(from=0) int);
+ method @FloatRange(from=0, to=63) public float getCn0DbHz(@IntRange(from=0) int);
+ method public int getConstellationType(@IntRange(from=0) int);
+ method @FloatRange(from=0xffffffa6, to=90) public float getElevationDegrees(@IntRange(from=0) int);
+ method @IntRange(from=0) public int getSatelliteCount();
+ method @IntRange(from=1, to=206) public int getSvid(@IntRange(from=0) int);
+ method public boolean hasAlmanacData(@IntRange(from=0) int);
+ method public boolean hasBasebandCn0DbHz(@IntRange(from=0) int);
+ method public boolean hasCarrierFrequencyHz(@IntRange(from=0) int);
+ method public boolean hasEphemerisData(@IntRange(from=0) int);
+ method public boolean usedInFix(@IntRange(from=0) int);
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field public static final int CONSTELLATION_BEIDOU = 5; // 0x5
+ field public static final int CONSTELLATION_GALILEO = 6; // 0x6
+ field public static final int CONSTELLATION_GLONASS = 3; // 0x3
+ field public static final int CONSTELLATION_GPS = 1; // 0x1
+ field public static final int CONSTELLATION_IRNSS = 7; // 0x7
+ field public static final int CONSTELLATION_QZSS = 4; // 0x4
+ field public static final int CONSTELLATION_SBAS = 2; // 0x2
+ field public static final int CONSTELLATION_UNKNOWN = 0; // 0x0
+ field @NonNull public static final android.os.Parcelable.Creator<android.location.GnssStatus> CREATOR;
+ }
+
+ public static final class GnssStatus.Builder {
+ ctor public GnssStatus.Builder();
+ method @NonNull public android.location.GnssStatus.Builder addSatellite(int, @IntRange(from=1, to=200) int, @FloatRange(from=0, to=63) float, @FloatRange(from=0xffffffa6, to=90) float, @FloatRange(from=0, to=360) float, boolean, boolean, boolean, boolean, @FloatRange(from=0) float, boolean, @FloatRange(from=0, to=63) float);
+ method @NonNull public android.location.GnssStatus build();
+ method @NonNull public android.location.GnssStatus.Builder clearSatellites();
+ }
+
+ public abstract static class GnssStatus.Callback {
+ ctor public GnssStatus.Callback();
+ method public void onFirstFix(int);
+ method public void onSatelliteStatusChanged(@NonNull android.location.GnssStatus);
+ method public void onStarted();
+ method public void onStopped();
+ }
+
+ @Deprecated public final class GpsSatellite {
+ method @Deprecated public float getAzimuth();
+ method @Deprecated public float getElevation();
+ method @Deprecated public int getPrn();
+ method @Deprecated public float getSnr();
+ method @Deprecated public boolean hasAlmanac();
+ method @Deprecated public boolean hasEphemeris();
+ method @Deprecated public boolean usedInFix();
+ }
+
+ @Deprecated public final class GpsStatus {
+ method @Deprecated @NonNull public static android.location.GpsStatus create(@NonNull android.location.GnssStatus, int);
+ method @Deprecated public int getMaxSatellites();
+ method @Deprecated public Iterable<android.location.GpsSatellite> getSatellites();
+ method @Deprecated public int getTimeToFirstFix();
+ field @Deprecated public static final int GPS_EVENT_FIRST_FIX = 3; // 0x3
+ field @Deprecated public static final int GPS_EVENT_SATELLITE_STATUS = 4; // 0x4
+ field @Deprecated public static final int GPS_EVENT_STARTED = 1; // 0x1
+ field @Deprecated public static final int GPS_EVENT_STOPPED = 2; // 0x2
+ }
+
+ @Deprecated public static interface GpsStatus.Listener {
+ method @Deprecated public void onGpsStatusChanged(int);
+ }
+
+ @Deprecated public static interface GpsStatus.NmeaListener {
+ method @Deprecated public void onNmeaReceived(long, String);
+ }
+
+ public interface LocationListener {
+ method public default void onFlushComplete(int);
+ method public void onLocationChanged(@NonNull android.location.Location);
+ method public default void onLocationChanged(@NonNull java.util.List<android.location.Location>);
+ method public default void onProviderDisabled(@NonNull String);
+ method public default void onProviderEnabled(@NonNull String);
+ method @Deprecated public default void onStatusChanged(String, int, android.os.Bundle);
+ }
+
+ public class LocationManager {
+ method @Deprecated @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) public boolean addGpsStatusListener(android.location.GpsStatus.Listener);
+ method @Deprecated @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) public boolean addNmeaListener(@NonNull android.location.GpsStatus.NmeaListener);
+ method @Deprecated @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) public boolean addNmeaListener(@NonNull android.location.OnNmeaMessageListener);
+ method @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) public boolean addNmeaListener(@NonNull android.location.OnNmeaMessageListener, @Nullable android.os.Handler);
+ method @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) public boolean addNmeaListener(@NonNull java.util.concurrent.Executor, @NonNull android.location.OnNmeaMessageListener);
+ method @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public void addProximityAlert(double, double, float, long, @NonNull android.app.PendingIntent);
+ method public void addTestProvider(@NonNull String, boolean, boolean, boolean, boolean, boolean, boolean, boolean, int, int);
+ method public void addTestProvider(@NonNull String, @NonNull android.location.provider.ProviderProperties);
+ method public void addTestProvider(@NonNull String, @NonNull android.location.provider.ProviderProperties, @NonNull java.util.Set<java.lang.String>);
+ method @Deprecated public void clearTestProviderEnabled(@NonNull String);
+ method @Deprecated public void clearTestProviderLocation(@NonNull String);
+ method @Deprecated public void clearTestProviderStatus(@NonNull String);
+ method @NonNull public java.util.List<java.lang.String> getAllProviders();
+ method @Deprecated @Nullable public String getBestProvider(@NonNull android.location.Criteria, boolean);
+ method @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public void getCurrentLocation(@NonNull String, @Nullable android.os.CancellationSignal, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<android.location.Location>);
+ method @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public void getCurrentLocation(@NonNull String, @NonNull android.location.LocationRequest, @Nullable android.os.CancellationSignal, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<android.location.Location>);
+ method @Nullable public java.util.List<android.location.GnssAntennaInfo> getGnssAntennaInfos();
+ method @NonNull public android.location.GnssCapabilities getGnssCapabilities();
+ method @Nullable public String getGnssHardwareModelName();
+ method public int getGnssYearOfHardware();
+ method @Deprecated @Nullable @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) public android.location.GpsStatus getGpsStatus(@Nullable android.location.GpsStatus);
+ method @Nullable @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public android.location.Location getLastKnownLocation(@NonNull String);
+ method @Deprecated @Nullable public android.location.LocationProvider getProvider(@NonNull String);
+ method @Nullable public android.location.provider.ProviderProperties getProviderProperties(@NonNull String);
+ method @NonNull public java.util.List<java.lang.String> getProviders(boolean);
+ method @Deprecated @NonNull public java.util.List<java.lang.String> getProviders(@NonNull android.location.Criteria, boolean);
+ method public boolean hasProvider(@NonNull String);
+ method public boolean isLocationEnabled();
+ method public boolean isProviderEnabled(@NonNull String);
+ method public boolean registerAntennaInfoListener(@NonNull java.util.concurrent.Executor, @NonNull android.location.GnssAntennaInfo.Listener);
+ method @Deprecated @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) public boolean registerGnssMeasurementsCallback(@NonNull android.location.GnssMeasurementsEvent.Callback);
+ method @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) public boolean registerGnssMeasurementsCallback(@NonNull android.location.GnssMeasurementsEvent.Callback, @Nullable android.os.Handler);
+ method @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) public boolean registerGnssMeasurementsCallback(@NonNull java.util.concurrent.Executor, @NonNull android.location.GnssMeasurementsEvent.Callback);
+ method @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) public boolean registerGnssMeasurementsCallback(@NonNull android.location.GnssMeasurementRequest, @NonNull java.util.concurrent.Executor, @NonNull android.location.GnssMeasurementsEvent.Callback);
+ method @Deprecated public boolean registerGnssNavigationMessageCallback(@NonNull android.location.GnssNavigationMessage.Callback);
+ method @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) public boolean registerGnssNavigationMessageCallback(@NonNull android.location.GnssNavigationMessage.Callback, @Nullable android.os.Handler);
+ method @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) public boolean registerGnssNavigationMessageCallback(@NonNull java.util.concurrent.Executor, @NonNull android.location.GnssNavigationMessage.Callback);
+ method @Deprecated @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) public boolean registerGnssStatusCallback(@NonNull android.location.GnssStatus.Callback);
+ method @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) public boolean registerGnssStatusCallback(@NonNull android.location.GnssStatus.Callback, @Nullable android.os.Handler);
+ method @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) public boolean registerGnssStatusCallback(@NonNull java.util.concurrent.Executor, @NonNull android.location.GnssStatus.Callback);
+ method @Deprecated public void removeGpsStatusListener(android.location.GpsStatus.Listener);
+ method @Deprecated public void removeNmeaListener(@NonNull android.location.GpsStatus.NmeaListener);
+ method public void removeNmeaListener(@NonNull android.location.OnNmeaMessageListener);
+ method @RequiresPermission(anyOf={"android.permission.ACCESS_COARSE_LOCATION", "android.permission.ACCESS_FINE_LOCATION"}, apis="..22") public void removeProximityAlert(@NonNull android.app.PendingIntent);
+ method public void removeTestProvider(@NonNull String);
+ method @RequiresPermission(anyOf={"android.permission.ACCESS_COARSE_LOCATION", "android.permission.ACCESS_FINE_LOCATION"}, apis="..22") public void removeUpdates(@NonNull android.location.LocationListener);
+ method public void removeUpdates(@NonNull android.app.PendingIntent);
+ method public void requestFlush(@NonNull String, @NonNull android.location.LocationListener, int);
+ method public void requestFlush(@NonNull String, @NonNull android.app.PendingIntent, int);
+ method @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public void requestLocationUpdates(@NonNull String, long, float, @NonNull android.location.LocationListener);
+ method @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public void requestLocationUpdates(@NonNull String, long, float, @NonNull android.location.LocationListener, @Nullable android.os.Looper);
+ method @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public void requestLocationUpdates(@NonNull String, long, float, @NonNull java.util.concurrent.Executor, @NonNull android.location.LocationListener);
+ method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public void requestLocationUpdates(long, float, @NonNull android.location.Criteria, @NonNull android.location.LocationListener, @Nullable android.os.Looper);
+ method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public void requestLocationUpdates(long, float, @NonNull android.location.Criteria, @NonNull java.util.concurrent.Executor, @NonNull android.location.LocationListener);
+ method @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public void requestLocationUpdates(@NonNull String, long, float, @NonNull android.app.PendingIntent);
+ method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public void requestLocationUpdates(long, float, @NonNull android.location.Criteria, @NonNull android.app.PendingIntent);
+ method @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public void requestLocationUpdates(@NonNull String, @NonNull android.location.LocationRequest, @NonNull java.util.concurrent.Executor, @NonNull android.location.LocationListener);
+ method @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public void requestLocationUpdates(@NonNull String, @NonNull android.location.LocationRequest, @NonNull android.app.PendingIntent);
+ method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public void requestSingleUpdate(@NonNull String, @NonNull android.location.LocationListener, @Nullable android.os.Looper);
+ method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public void requestSingleUpdate(@NonNull android.location.Criteria, @NonNull android.location.LocationListener, @Nullable android.os.Looper);
+ method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public void requestSingleUpdate(@NonNull String, @NonNull android.app.PendingIntent);
+ method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public void requestSingleUpdate(@NonNull android.location.Criteria, @NonNull android.app.PendingIntent);
+ method public boolean sendExtraCommand(@NonNull String, @NonNull String, @Nullable android.os.Bundle);
+ method public void setTestProviderEnabled(@NonNull String, boolean);
+ method public void setTestProviderLocation(@NonNull String, @NonNull android.location.Location);
+ method @Deprecated public void setTestProviderStatus(@NonNull String, int, @Nullable android.os.Bundle, long);
+ method public void unregisterAntennaInfoListener(@NonNull android.location.GnssAntennaInfo.Listener);
+ method public void unregisterGnssMeasurementsCallback(@NonNull android.location.GnssMeasurementsEvent.Callback);
+ method public void unregisterGnssNavigationMessageCallback(@NonNull android.location.GnssNavigationMessage.Callback);
+ method public void unregisterGnssStatusCallback(@NonNull android.location.GnssStatus.Callback);
+ field public static final String ACTION_GNSS_CAPABILITIES_CHANGED = "android.location.action.GNSS_CAPABILITIES_CHANGED";
+ field public static final String EXTRA_GNSS_CAPABILITIES = "android.location.extra.GNSS_CAPABILITIES";
+ field public static final String EXTRA_LOCATION_ENABLED = "android.location.extra.LOCATION_ENABLED";
+ field public static final String EXTRA_PROVIDER_ENABLED = "android.location.extra.PROVIDER_ENABLED";
+ field public static final String EXTRA_PROVIDER_NAME = "android.location.extra.PROVIDER_NAME";
+ field public static final String FUSED_PROVIDER = "fused";
+ field public static final String GPS_PROVIDER = "gps";
+ field public static final String KEY_FLUSH_COMPLETE = "flushComplete";
+ field public static final String KEY_LOCATIONS = "locations";
+ field public static final String KEY_LOCATION_CHANGED = "location";
+ field public static final String KEY_PROVIDER_ENABLED = "providerEnabled";
+ field public static final String KEY_PROXIMITY_ENTERING = "entering";
+ field @Deprecated public static final String KEY_STATUS_CHANGED = "status";
+ field public static final String MODE_CHANGED_ACTION = "android.location.MODE_CHANGED";
+ field public static final String NETWORK_PROVIDER = "network";
+ field public static final String PASSIVE_PROVIDER = "passive";
+ field public static final String PROVIDERS_CHANGED_ACTION = "android.location.PROVIDERS_CHANGED";
+ }
+
+ @Deprecated public class LocationProvider {
+ method @Deprecated public int getAccuracy();
+ method @Deprecated public String getName();
+ method @Deprecated public int getPowerRequirement();
+ method @Deprecated public boolean hasMonetaryCost();
+ method @Deprecated public boolean meetsCriteria(android.location.Criteria);
+ method @Deprecated public boolean requiresCell();
+ method @Deprecated public boolean requiresNetwork();
+ method @Deprecated public boolean requiresSatellite();
+ method @Deprecated public boolean supportsAltitude();
+ method @Deprecated public boolean supportsBearing();
+ method @Deprecated public boolean supportsSpeed();
+ field @Deprecated public static final int AVAILABLE = 2; // 0x2
+ field @Deprecated public static final int OUT_OF_SERVICE = 0; // 0x0
+ field @Deprecated public static final int TEMPORARILY_UNAVAILABLE = 1; // 0x1
+ }
+
+ public final class LocationRequest implements android.os.Parcelable {
+ method public int describeContents();
+ method @IntRange(from=1) public long getDurationMillis();
+ method @IntRange(from=0) public long getIntervalMillis();
+ method @IntRange(from=0) public long getMaxUpdateDelayMillis();
+ method @IntRange(from=1, to=java.lang.Integer.MAX_VALUE) public int getMaxUpdates();
+ method @FloatRange(from=0, to=java.lang.Float.MAX_VALUE) public float getMinUpdateDistanceMeters();
+ method @IntRange(from=0) public long getMinUpdateIntervalMillis();
+ method public int getQuality();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.location.LocationRequest> CREATOR;
+ field public static final long PASSIVE_INTERVAL = 9223372036854775807L; // 0x7fffffffffffffffL
+ field public static final int QUALITY_BALANCED_POWER_ACCURACY = 102; // 0x66
+ field public static final int QUALITY_HIGH_ACCURACY = 100; // 0x64
+ field public static final int QUALITY_LOW_POWER = 104; // 0x68
+ }
+
+ public static final class LocationRequest.Builder {
+ ctor public LocationRequest.Builder(long);
+ ctor public LocationRequest.Builder(@NonNull android.location.LocationRequest);
+ method @NonNull public android.location.LocationRequest build();
+ method @NonNull public android.location.LocationRequest.Builder clearMinUpdateIntervalMillis();
+ method @NonNull public android.location.LocationRequest.Builder setDurationMillis(@IntRange(from=1) long);
+ method @NonNull public android.location.LocationRequest.Builder setIntervalMillis(@IntRange(from=0) long);
+ method @NonNull public android.location.LocationRequest.Builder setMaxUpdateDelayMillis(@IntRange(from=0) long);
+ method @NonNull public android.location.LocationRequest.Builder setMaxUpdates(@IntRange(from=1, to=java.lang.Integer.MAX_VALUE) int);
+ method @NonNull public android.location.LocationRequest.Builder setMinUpdateDistanceMeters(@FloatRange(from=0, to=java.lang.Float.MAX_VALUE) float);
+ method @NonNull public android.location.LocationRequest.Builder setMinUpdateIntervalMillis(@IntRange(from=0) long);
+ method @NonNull public android.location.LocationRequest.Builder setQuality(int);
+ }
+
+ public interface OnNmeaMessageListener {
+ method public void onNmeaMessage(String, long);
+ }
+
+ public abstract class SettingInjectorService extends android.app.Service {
+ ctor public SettingInjectorService(String);
+ method public final android.os.IBinder onBind(android.content.Intent);
+ method protected abstract boolean onGetEnabled();
+ method protected abstract String onGetSummary();
+ method public final void onStart(android.content.Intent, int);
+ method public final int onStartCommand(android.content.Intent, int, int);
+ method public static final void refreshSettings(@NonNull android.content.Context);
+ field public static final String ACTION_INJECTED_SETTING_CHANGED = "android.location.InjectedSettingChanged";
+ field public static final String ACTION_SERVICE_INTENT = "android.location.SettingInjectorService";
+ field public static final String ATTRIBUTES_NAME = "injected-location-setting";
+ field public static final String META_DATA_NAME = "android.location.SettingInjectorService";
+ }
+
+}
+
+package android.location.altitude {
+
+ public final class AltitudeConverter {
+ ctor public AltitudeConverter();
+ method @WorkerThread public void addMslAltitudeToLocation(@NonNull android.content.Context, @NonNull android.location.Location) throws java.io.IOException;
+ }
+
+}
+
+package android.location.provider {
+
+ public final class ProviderProperties implements android.os.Parcelable {
+ method public int describeContents();
+ method public int getAccuracy();
+ method public int getPowerUsage();
+ method public boolean hasAltitudeSupport();
+ method public boolean hasBearingSupport();
+ method public boolean hasCellRequirement();
+ method public boolean hasMonetaryCost();
+ method public boolean hasNetworkRequirement();
+ method public boolean hasSatelliteRequirement();
+ method public boolean hasSpeedSupport();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field public static final int ACCURACY_COARSE = 2; // 0x2
+ field public static final int ACCURACY_FINE = 1; // 0x1
+ field @NonNull public static final android.os.Parcelable.Creator<android.location.provider.ProviderProperties> CREATOR;
+ field public static final int POWER_USAGE_HIGH = 3; // 0x3
+ field public static final int POWER_USAGE_LOW = 1; // 0x1
+ field public static final int POWER_USAGE_MEDIUM = 2; // 0x2
+ }
+
+ public static final class ProviderProperties.Builder {
+ ctor public ProviderProperties.Builder();
+ ctor public ProviderProperties.Builder(@NonNull android.location.provider.ProviderProperties);
+ method @NonNull public android.location.provider.ProviderProperties build();
+ method @NonNull public android.location.provider.ProviderProperties.Builder setAccuracy(int);
+ method @NonNull public android.location.provider.ProviderProperties.Builder setHasAltitudeSupport(boolean);
+ method @NonNull public android.location.provider.ProviderProperties.Builder setHasBearingSupport(boolean);
+ method @NonNull public android.location.provider.ProviderProperties.Builder setHasCellRequirement(boolean);
+ method @NonNull public android.location.provider.ProviderProperties.Builder setHasMonetaryCost(boolean);
+ method @NonNull public android.location.provider.ProviderProperties.Builder setHasNetworkRequirement(boolean);
+ method @NonNull public android.location.provider.ProviderProperties.Builder setHasSatelliteRequirement(boolean);
+ method @NonNull public android.location.provider.ProviderProperties.Builder setHasSpeedSupport(boolean);
+ method @NonNull public android.location.provider.ProviderProperties.Builder setPowerUsage(int);
+ }
+
+}
+
diff --git a/location/api/module-lib-current.txt b/location/api/module-lib-current.txt
index d802177e249b..8c14b864005d 100644
--- a/location/api/module-lib-current.txt
+++ b/location/api/module-lib-current.txt
@@ -1 +1,11 @@
// Signature format: 2.0
+package android.location {
+
+ public class LocationManager {
+ method @RequiresPermission(allOf={android.Manifest.permission.LOCATION_HARDWARE, android.Manifest.permission.ACCESS_FINE_LOCATION}) public boolean injectLocation(@NonNull android.location.Location);
+ method @RequiresPermission(android.Manifest.permission.CONTROL_AUTOMOTIVE_GNSS) public boolean isAutomotiveGnssSuspended();
+ method @RequiresPermission(android.Manifest.permission.CONTROL_AUTOMOTIVE_GNSS) public void setAutomotiveGnssSuspended(boolean);
+ }
+
+}
+
diff --git a/location/api/module-lib-lint-baseline.txt b/location/api/module-lib-lint-baseline.txt
new file mode 100644
index 000000000000..7cd6a86853a4
--- /dev/null
+++ b/location/api/module-lib-lint-baseline.txt
@@ -0,0 +1,13 @@
+// Baseline format: 1.0
+SamShouldBeLast: android.location.LocationManager#addNmeaListener(android.location.OnNmeaMessageListener, android.os.Handler):
+ SAM-compatible parameters (such as parameter 1, "listener", in android.location.LocationManager.addNmeaListener) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
+SamShouldBeLast: android.location.LocationManager#requestLocationUpdates(String, long, float, android.location.LocationListener, android.os.Looper):
+ SAM-compatible parameters (such as parameter 4, "listener", in android.location.LocationManager.requestLocationUpdates) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
+SamShouldBeLast: android.location.LocationManager#requestLocationUpdates(android.location.LocationRequest, android.location.LocationListener, android.os.Looper):
+ SAM-compatible parameters (such as parameter 2, "listener", in android.location.LocationManager.requestLocationUpdates) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
+SamShouldBeLast: android.location.LocationManager#requestLocationUpdates(long, float, android.location.Criteria, android.location.LocationListener, android.os.Looper):
+ SAM-compatible parameters (such as parameter 4, "listener", in android.location.LocationManager.requestLocationUpdates) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
+SamShouldBeLast: android.location.LocationManager#requestSingleUpdate(String, android.location.LocationListener, android.os.Looper):
+ SAM-compatible parameters (such as parameter 2, "listener", in android.location.LocationManager.requestSingleUpdate) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
+SamShouldBeLast: android.location.LocationManager#requestSingleUpdate(android.location.Criteria, android.location.LocationListener, android.os.Looper):
+ SAM-compatible parameters (such as parameter 2, "listener", in android.location.LocationManager.requestSingleUpdate) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
diff --git a/location/api/system-current.txt b/location/api/system-current.txt
index d802177e249b..a1d6ab5798e1 100644
--- a/location/api/system-current.txt
+++ b/location/api/system-current.txt
@@ -1 +1,646 @@
// Signature format: 2.0
+package android.location {
+
+ public abstract class BatchedLocationCallback {
+ ctor public BatchedLocationCallback();
+ method public void onLocationBatch(java.util.List<android.location.Location>);
+ }
+
+ public final class CorrelationVector implements android.os.Parcelable {
+ method public int describeContents();
+ method @FloatRange(from=0.0f) public double getFrequencyOffsetMetersPerSecond();
+ method @NonNull public int[] getMagnitude();
+ method @FloatRange(from=0.0f) public double getSamplingStartMeters();
+ method @FloatRange(from=0.0f, fromInclusive=false) public double getSamplingWidthMeters();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.location.CorrelationVector> CREATOR;
+ }
+
+ public static final class CorrelationVector.Builder {
+ ctor public CorrelationVector.Builder();
+ method @NonNull public android.location.CorrelationVector build();
+ method @NonNull public android.location.CorrelationVector.Builder setFrequencyOffsetMetersPerSecond(@FloatRange(from=0.0f) double);
+ method @NonNull public android.location.CorrelationVector.Builder setMagnitude(@NonNull int[]);
+ method @NonNull public android.location.CorrelationVector.Builder setSamplingStartMeters(@FloatRange(from=0.0f) double);
+ method @NonNull public android.location.CorrelationVector.Builder setSamplingWidthMeters(@FloatRange(from=0.0f, fromInclusive=false) double);
+ }
+
+ public final class Country implements android.os.Parcelable {
+ ctor public Country(@NonNull String, int);
+ method public int describeContents();
+ method @NonNull public String getCountryCode();
+ method public int getSource();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field public static final int COUNTRY_SOURCE_LOCALE = 3; // 0x3
+ field public static final int COUNTRY_SOURCE_LOCATION = 1; // 0x1
+ field public static final int COUNTRY_SOURCE_NETWORK = 0; // 0x0
+ field public static final int COUNTRY_SOURCE_SIM = 2; // 0x2
+ field @NonNull public static final android.os.Parcelable.Creator<android.location.Country> CREATOR;
+ }
+
+ public class CountryDetector {
+ method public void registerCountryDetectorCallback(@NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<android.location.Country>);
+ method public void unregisterCountryDetectorCallback(@NonNull java.util.function.Consumer<android.location.Country>);
+ }
+
+ public final class GnssCapabilities implements android.os.Parcelable {
+ method @Deprecated public boolean hasMeasurementCorrectionsReflectingPane();
+ method @Deprecated public boolean hasNavMessages();
+ method @Deprecated public boolean hasSatelliteBlacklist();
+ }
+
+ public final class GnssExcessPathInfo implements android.os.Parcelable {
+ method public int describeContents();
+ method @FloatRange(from=0.0f) public float getAttenuationDb();
+ method @FloatRange(from=0.0f) public float getExcessPathLengthMeters();
+ method @FloatRange(from=0.0f) public float getExcessPathLengthUncertaintyMeters();
+ method @NonNull public android.location.GnssReflectingPlane getReflectingPlane();
+ method public boolean hasAttenuation();
+ method public boolean hasExcessPathLength();
+ method public boolean hasExcessPathLengthUncertainty();
+ method public boolean hasReflectingPlane();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.location.GnssExcessPathInfo> CREATOR;
+ }
+
+ public static final class GnssExcessPathInfo.Builder {
+ ctor public GnssExcessPathInfo.Builder();
+ method @NonNull public android.location.GnssExcessPathInfo build();
+ method @NonNull public android.location.GnssExcessPathInfo.Builder clearAttenuationDb();
+ method @NonNull public android.location.GnssExcessPathInfo.Builder clearExcessPathLengthMeters();
+ method @NonNull public android.location.GnssExcessPathInfo.Builder clearExcessPathLengthUncertaintyMeters();
+ method @NonNull public android.location.GnssExcessPathInfo.Builder setAttenuationDb(@FloatRange(from=0.0f) float);
+ method @NonNull public android.location.GnssExcessPathInfo.Builder setExcessPathLengthMeters(@FloatRange(from=0.0f) float);
+ method @NonNull public android.location.GnssExcessPathInfo.Builder setExcessPathLengthUncertaintyMeters(@FloatRange(from=0.0f) float);
+ method @NonNull public android.location.GnssExcessPathInfo.Builder setReflectingPlane(@Nullable android.location.GnssReflectingPlane);
+ }
+
+ public final class GnssMeasurement implements android.os.Parcelable {
+ method @Nullable public java.util.Collection<android.location.CorrelationVector> getCorrelationVectors();
+ method @Nullable public android.location.SatellitePvt getSatellitePvt();
+ method public boolean hasCorrelationVectors();
+ method public boolean hasSatellitePvt();
+ }
+
+ public final class GnssMeasurementCorrections implements android.os.Parcelable {
+ method public int describeContents();
+ method @FloatRange(from=-1000.0F, to=10000.0f) public double getAltitudeMeters();
+ method @FloatRange(from=0.0f, to=360.0f) public float getEnvironmentBearingDegrees();
+ method @FloatRange(from=0.0f, to=180.0f) public float getEnvironmentBearingUncertaintyDegrees();
+ method @FloatRange(from=0.0f) public double getHorizontalPositionUncertaintyMeters();
+ method @FloatRange(from=-90.0F, to=90.0f) public double getLatitudeDegrees();
+ method @FloatRange(from=-180.0F, to=180.0f) public double getLongitudeDegrees();
+ method @NonNull public java.util.List<android.location.GnssSingleSatCorrection> getSingleSatelliteCorrectionList();
+ method @IntRange(from=0) public long getToaGpsNanosecondsOfWeek();
+ method @FloatRange(from=0.0f) public double getVerticalPositionUncertaintyMeters();
+ method public boolean hasEnvironmentBearing();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.location.GnssMeasurementCorrections> CREATOR;
+ }
+
+ public static final class GnssMeasurementCorrections.Builder {
+ ctor public GnssMeasurementCorrections.Builder();
+ method @NonNull public android.location.GnssMeasurementCorrections build();
+ method @NonNull public android.location.GnssMeasurementCorrections.Builder setAltitudeMeters(@FloatRange(from=-1000.0F, to=10000.0f) double);
+ method @NonNull public android.location.GnssMeasurementCorrections.Builder setEnvironmentBearingDegrees(@FloatRange(from=0.0f, to=360.0f) float);
+ method @NonNull public android.location.GnssMeasurementCorrections.Builder setEnvironmentBearingUncertaintyDegrees(@FloatRange(from=0.0f, to=180.0f) float);
+ method @NonNull public android.location.GnssMeasurementCorrections.Builder setHorizontalPositionUncertaintyMeters(@FloatRange(from=0.0f) double);
+ method @NonNull public android.location.GnssMeasurementCorrections.Builder setLatitudeDegrees(@FloatRange(from=-90.0F, to=90.0f) double);
+ method @NonNull public android.location.GnssMeasurementCorrections.Builder setLongitudeDegrees(@FloatRange(from=-180.0F, to=180.0f) double);
+ method @NonNull public android.location.GnssMeasurementCorrections.Builder setSingleSatelliteCorrectionList(@NonNull java.util.List<android.location.GnssSingleSatCorrection>);
+ method @NonNull public android.location.GnssMeasurementCorrections.Builder setToaGpsNanosecondsOfWeek(@IntRange(from=0) long);
+ method @NonNull public android.location.GnssMeasurementCorrections.Builder setVerticalPositionUncertaintyMeters(@FloatRange(from=0.0f) double);
+ }
+
+ public final class GnssMeasurementRequest implements android.os.Parcelable {
+ method @NonNull public android.os.WorkSource getWorkSource();
+ method public boolean isCorrelationVectorOutputsEnabled();
+ }
+
+ public static final class GnssMeasurementRequest.Builder {
+ method @NonNull public android.location.GnssMeasurementRequest.Builder setCorrelationVectorOutputsEnabled(boolean);
+ method @NonNull @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS) public android.location.GnssMeasurementRequest.Builder setWorkSource(@Nullable android.os.WorkSource);
+ }
+
+ public final class GnssReflectingPlane implements android.os.Parcelable {
+ method public int describeContents();
+ method @FloatRange(from=-1000.0F, to=10000.0f) public double getAltitudeMeters();
+ method @FloatRange(from=0.0f, to=360.0f) public double getAzimuthDegrees();
+ method @FloatRange(from=-90.0F, to=90.0f) public double getLatitudeDegrees();
+ method @FloatRange(from=-180.0F, to=180.0f) public double getLongitudeDegrees();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.location.GnssReflectingPlane> CREATOR;
+ }
+
+ public static final class GnssReflectingPlane.Builder {
+ ctor public GnssReflectingPlane.Builder();
+ method @NonNull public android.location.GnssReflectingPlane build();
+ method @NonNull public android.location.GnssReflectingPlane.Builder setAltitudeMeters(@FloatRange(from=-1000.0F, to=10000.0f) double);
+ method @NonNull public android.location.GnssReflectingPlane.Builder setAzimuthDegrees(@FloatRange(from=0.0f, to=360.0f) double);
+ method @NonNull public android.location.GnssReflectingPlane.Builder setLatitudeDegrees(@FloatRange(from=-90.0F, to=90.0f) double);
+ method @NonNull public android.location.GnssReflectingPlane.Builder setLongitudeDegrees(@FloatRange(from=-180.0F, to=180.0f) double);
+ }
+
+ public final class GnssRequest implements android.os.Parcelable {
+ method public int describeContents();
+ method public boolean isFullTracking();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.location.GnssRequest> CREATOR;
+ }
+
+ public static final class GnssRequest.Builder {
+ ctor public GnssRequest.Builder();
+ ctor public GnssRequest.Builder(@NonNull android.location.GnssRequest);
+ method @NonNull public android.location.GnssRequest build();
+ method @NonNull public android.location.GnssRequest.Builder setFullTracking(boolean);
+ }
+
+ public final class GnssSingleSatCorrection implements android.os.Parcelable {
+ method public int describeContents();
+ method @FloatRange(from=0.0f, fromInclusive=false) public float getCarrierFrequencyHz();
+ method @FloatRange(from=0.0f) public float getCombinedAttenuationDb();
+ method public int getConstellationType();
+ method @FloatRange(from=0.0f) public float getExcessPathLengthMeters();
+ method @FloatRange(from=0.0f) public float getExcessPathLengthUncertaintyMeters();
+ method @NonNull public java.util.List<android.location.GnssExcessPathInfo> getGnssExcessPathInfoList();
+ method @FloatRange(from=0.0f, to=1.0f) public float getProbabilityLineOfSight();
+ method @Deprecated @Nullable public android.location.GnssReflectingPlane getReflectingPlane();
+ method @IntRange(from=0) public int getSatelliteId();
+ method public boolean hasCombinedAttenuation();
+ method public boolean hasExcessPathLength();
+ method public boolean hasExcessPathLengthUncertainty();
+ method @Deprecated public boolean hasReflectingPlane();
+ method public boolean hasValidSatelliteLineOfSight();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.location.GnssSingleSatCorrection> CREATOR;
+ }
+
+ public static final class GnssSingleSatCorrection.Builder {
+ ctor public GnssSingleSatCorrection.Builder();
+ method @NonNull public android.location.GnssSingleSatCorrection build();
+ method @NonNull public android.location.GnssSingleSatCorrection.Builder clearCombinedAttenuationDb();
+ method @NonNull public android.location.GnssSingleSatCorrection.Builder clearExcessPathLengthMeters();
+ method @NonNull public android.location.GnssSingleSatCorrection.Builder clearExcessPathLengthUncertaintyMeters();
+ method @NonNull public android.location.GnssSingleSatCorrection.Builder clearProbabilityLineOfSight();
+ method @NonNull public android.location.GnssSingleSatCorrection.Builder setCarrierFrequencyHz(@FloatRange(from=0.0f, fromInclusive=false) float);
+ method @NonNull public android.location.GnssSingleSatCorrection.Builder setCombinedAttenuationDb(@FloatRange(from=0.0f) float);
+ method @NonNull public android.location.GnssSingleSatCorrection.Builder setConstellationType(int);
+ method @NonNull public android.location.GnssSingleSatCorrection.Builder setExcessPathLengthMeters(@FloatRange(from=0.0f) float);
+ method @NonNull public android.location.GnssSingleSatCorrection.Builder setExcessPathLengthUncertaintyMeters(@FloatRange(from=0.0f) float);
+ method @NonNull public android.location.GnssSingleSatCorrection.Builder setGnssExcessPathInfoList(@NonNull java.util.List<android.location.GnssExcessPathInfo>);
+ method @NonNull public android.location.GnssSingleSatCorrection.Builder setProbabilityLineOfSight(@FloatRange(from=0.0f, to=1.0f) float);
+ method @Deprecated @NonNull public android.location.GnssSingleSatCorrection.Builder setReflectingPlane(@Nullable android.location.GnssReflectingPlane);
+ method @NonNull public android.location.GnssSingleSatCorrection.Builder setSatelliteId(@IntRange(from=0) int);
+ }
+
+ @Deprecated public class GpsClock implements android.os.Parcelable {
+ method @Deprecated public int describeContents();
+ method @Deprecated public double getBiasInNs();
+ method @Deprecated public double getBiasUncertaintyInNs();
+ method @Deprecated public double getDriftInNsPerSec();
+ method @Deprecated public double getDriftUncertaintyInNsPerSec();
+ method @Deprecated public long getFullBiasInNs();
+ method @Deprecated public short getLeapSecond();
+ method @Deprecated public long getTimeInNs();
+ method @Deprecated public double getTimeUncertaintyInNs();
+ method @Deprecated public byte getType();
+ method @Deprecated public boolean hasBiasInNs();
+ method @Deprecated public boolean hasBiasUncertaintyInNs();
+ method @Deprecated public boolean hasDriftInNsPerSec();
+ method @Deprecated public boolean hasDriftUncertaintyInNsPerSec();
+ method @Deprecated public boolean hasFullBiasInNs();
+ method @Deprecated public boolean hasLeapSecond();
+ method @Deprecated public boolean hasTimeUncertaintyInNs();
+ method @Deprecated public void reset();
+ method @Deprecated public void resetBiasInNs();
+ method @Deprecated public void resetBiasUncertaintyInNs();
+ method @Deprecated public void resetDriftInNsPerSec();
+ method @Deprecated public void resetDriftUncertaintyInNsPerSec();
+ method @Deprecated public void resetFullBiasInNs();
+ method @Deprecated public void resetLeapSecond();
+ method @Deprecated public void resetTimeUncertaintyInNs();
+ method @Deprecated public void set(android.location.GpsClock);
+ method @Deprecated public void setBiasInNs(double);
+ method @Deprecated public void setBiasUncertaintyInNs(double);
+ method @Deprecated public void setDriftInNsPerSec(double);
+ method @Deprecated public void setDriftUncertaintyInNsPerSec(double);
+ method @Deprecated public void setFullBiasInNs(long);
+ method @Deprecated public void setLeapSecond(short);
+ method @Deprecated public void setTimeInNs(long);
+ method @Deprecated public void setTimeUncertaintyInNs(double);
+ method @Deprecated public void setType(byte);
+ method @Deprecated public void writeToParcel(android.os.Parcel, int);
+ field @Deprecated @NonNull public static final android.os.Parcelable.Creator<android.location.GpsClock> CREATOR;
+ field @Deprecated public static final byte TYPE_GPS_TIME = 2; // 0x2
+ field @Deprecated public static final byte TYPE_LOCAL_HW_TIME = 1; // 0x1
+ field @Deprecated public static final byte TYPE_UNKNOWN = 0; // 0x0
+ }
+
+ @Deprecated public class GpsMeasurement implements android.os.Parcelable {
+ method @Deprecated public int describeContents();
+ method @Deprecated public double getAccumulatedDeltaRangeInMeters();
+ method @Deprecated public short getAccumulatedDeltaRangeState();
+ method @Deprecated public double getAccumulatedDeltaRangeUncertaintyInMeters();
+ method @Deprecated public double getAzimuthInDeg();
+ method @Deprecated public double getAzimuthUncertaintyInDeg();
+ method @Deprecated public int getBitNumber();
+ method @Deprecated public long getCarrierCycles();
+ method @Deprecated public float getCarrierFrequencyInHz();
+ method @Deprecated public double getCarrierPhase();
+ method @Deprecated public double getCarrierPhaseUncertainty();
+ method @Deprecated public double getCn0InDbHz();
+ method @Deprecated public double getCodePhaseInChips();
+ method @Deprecated public double getCodePhaseUncertaintyInChips();
+ method @Deprecated public double getDopplerShiftInHz();
+ method @Deprecated public double getDopplerShiftUncertaintyInHz();
+ method @Deprecated public double getElevationInDeg();
+ method @Deprecated public double getElevationUncertaintyInDeg();
+ method @Deprecated public byte getLossOfLock();
+ method @Deprecated public byte getMultipathIndicator();
+ method @Deprecated public byte getPrn();
+ method @Deprecated public double getPseudorangeInMeters();
+ method @Deprecated public double getPseudorangeRateInMetersPerSec();
+ method @Deprecated public double getPseudorangeRateUncertaintyInMetersPerSec();
+ method @Deprecated public double getPseudorangeUncertaintyInMeters();
+ method @Deprecated public long getReceivedGpsTowInNs();
+ method @Deprecated public long getReceivedGpsTowUncertaintyInNs();
+ method @Deprecated public double getSnrInDb();
+ method @Deprecated public short getState();
+ method @Deprecated public short getTimeFromLastBitInMs();
+ method @Deprecated public double getTimeOffsetInNs();
+ method @Deprecated public boolean hasAzimuthInDeg();
+ method @Deprecated public boolean hasAzimuthUncertaintyInDeg();
+ method @Deprecated public boolean hasBitNumber();
+ method @Deprecated public boolean hasCarrierCycles();
+ method @Deprecated public boolean hasCarrierFrequencyInHz();
+ method @Deprecated public boolean hasCarrierPhase();
+ method @Deprecated public boolean hasCarrierPhaseUncertainty();
+ method @Deprecated public boolean hasCodePhaseInChips();
+ method @Deprecated public boolean hasCodePhaseUncertaintyInChips();
+ method @Deprecated public boolean hasDopplerShiftInHz();
+ method @Deprecated public boolean hasDopplerShiftUncertaintyInHz();
+ method @Deprecated public boolean hasElevationInDeg();
+ method @Deprecated public boolean hasElevationUncertaintyInDeg();
+ method @Deprecated public boolean hasPseudorangeInMeters();
+ method @Deprecated public boolean hasPseudorangeUncertaintyInMeters();
+ method @Deprecated public boolean hasSnrInDb();
+ method @Deprecated public boolean hasTimeFromLastBitInMs();
+ method @Deprecated public boolean isPseudorangeRateCorrected();
+ method @Deprecated public boolean isUsedInFix();
+ method @Deprecated public void reset();
+ method @Deprecated public void resetAzimuthInDeg();
+ method @Deprecated public void resetAzimuthUncertaintyInDeg();
+ method @Deprecated public void resetBitNumber();
+ method @Deprecated public void resetCarrierCycles();
+ method @Deprecated public void resetCarrierFrequencyInHz();
+ method @Deprecated public void resetCarrierPhase();
+ method @Deprecated public void resetCarrierPhaseUncertainty();
+ method @Deprecated public void resetCodePhaseInChips();
+ method @Deprecated public void resetCodePhaseUncertaintyInChips();
+ method @Deprecated public void resetDopplerShiftInHz();
+ method @Deprecated public void resetDopplerShiftUncertaintyInHz();
+ method @Deprecated public void resetElevationInDeg();
+ method @Deprecated public void resetElevationUncertaintyInDeg();
+ method @Deprecated public void resetPseudorangeInMeters();
+ method @Deprecated public void resetPseudorangeUncertaintyInMeters();
+ method @Deprecated public void resetSnrInDb();
+ method @Deprecated public void resetTimeFromLastBitInMs();
+ method @Deprecated public void set(android.location.GpsMeasurement);
+ method @Deprecated public void setAccumulatedDeltaRangeInMeters(double);
+ method @Deprecated public void setAccumulatedDeltaRangeState(short);
+ method @Deprecated public void setAccumulatedDeltaRangeUncertaintyInMeters(double);
+ method @Deprecated public void setAzimuthInDeg(double);
+ method @Deprecated public void setAzimuthUncertaintyInDeg(double);
+ method @Deprecated public void setBitNumber(int);
+ method @Deprecated public void setCarrierCycles(long);
+ method @Deprecated public void setCarrierFrequencyInHz(float);
+ method @Deprecated public void setCarrierPhase(double);
+ method @Deprecated public void setCarrierPhaseUncertainty(double);
+ method @Deprecated public void setCn0InDbHz(double);
+ method @Deprecated public void setCodePhaseInChips(double);
+ method @Deprecated public void setCodePhaseUncertaintyInChips(double);
+ method @Deprecated public void setDopplerShiftInHz(double);
+ method @Deprecated public void setDopplerShiftUncertaintyInHz(double);
+ method @Deprecated public void setElevationInDeg(double);
+ method @Deprecated public void setElevationUncertaintyInDeg(double);
+ method @Deprecated public void setLossOfLock(byte);
+ method @Deprecated public void setMultipathIndicator(byte);
+ method @Deprecated public void setPrn(byte);
+ method @Deprecated public void setPseudorangeInMeters(double);
+ method @Deprecated public void setPseudorangeRateInMetersPerSec(double);
+ method @Deprecated public void setPseudorangeRateUncertaintyInMetersPerSec(double);
+ method @Deprecated public void setPseudorangeUncertaintyInMeters(double);
+ method @Deprecated public void setReceivedGpsTowInNs(long);
+ method @Deprecated public void setReceivedGpsTowUncertaintyInNs(long);
+ method @Deprecated public void setSnrInDb(double);
+ method @Deprecated public void setState(short);
+ method @Deprecated public void setTimeFromLastBitInMs(short);
+ method @Deprecated public void setTimeOffsetInNs(double);
+ method @Deprecated public void setUsedInFix(boolean);
+ method @Deprecated public void writeToParcel(android.os.Parcel, int);
+ field @Deprecated public static final short ADR_STATE_CYCLE_SLIP = 4; // 0x4
+ field @Deprecated public static final short ADR_STATE_RESET = 2; // 0x2
+ field @Deprecated public static final short ADR_STATE_UNKNOWN = 0; // 0x0
+ field @Deprecated public static final short ADR_STATE_VALID = 1; // 0x1
+ field @Deprecated @NonNull public static final android.os.Parcelable.Creator<android.location.GpsMeasurement> CREATOR;
+ field @Deprecated public static final byte LOSS_OF_LOCK_CYCLE_SLIP = 2; // 0x2
+ field @Deprecated public static final byte LOSS_OF_LOCK_OK = 1; // 0x1
+ field @Deprecated public static final byte LOSS_OF_LOCK_UNKNOWN = 0; // 0x0
+ field @Deprecated public static final byte MULTIPATH_INDICATOR_DETECTED = 1; // 0x1
+ field @Deprecated public static final byte MULTIPATH_INDICATOR_NOT_USED = 2; // 0x2
+ field @Deprecated public static final byte MULTIPATH_INDICATOR_UNKNOWN = 0; // 0x0
+ field @Deprecated public static final short STATE_BIT_SYNC = 2; // 0x2
+ field @Deprecated public static final short STATE_CODE_LOCK = 1; // 0x1
+ field @Deprecated public static final short STATE_MSEC_AMBIGUOUS = 16; // 0x10
+ field @Deprecated public static final short STATE_SUBFRAME_SYNC = 4; // 0x4
+ field @Deprecated public static final short STATE_TOW_DECODED = 8; // 0x8
+ field @Deprecated public static final short STATE_UNKNOWN = 0; // 0x0
+ }
+
+ @Deprecated public class GpsMeasurementsEvent implements android.os.Parcelable {
+ ctor @Deprecated public GpsMeasurementsEvent(android.location.GpsClock, android.location.GpsMeasurement[]);
+ method @Deprecated public int describeContents();
+ method @Deprecated @NonNull public android.location.GpsClock getClock();
+ method @Deprecated @NonNull public java.util.Collection<android.location.GpsMeasurement> getMeasurements();
+ method @Deprecated public void writeToParcel(android.os.Parcel, int);
+ field @Deprecated @NonNull public static final android.os.Parcelable.Creator<android.location.GpsMeasurementsEvent> CREATOR;
+ field @Deprecated public static final int STATUS_GPS_LOCATION_DISABLED = 2; // 0x2
+ field @Deprecated public static final int STATUS_NOT_SUPPORTED = 0; // 0x0
+ field @Deprecated public static final int STATUS_READY = 1; // 0x1
+ }
+
+ @Deprecated public static interface GpsMeasurementsEvent.Listener {
+ method @Deprecated public void onGpsMeasurementsReceived(android.location.GpsMeasurementsEvent);
+ method @Deprecated public void onStatusChanged(int);
+ }
+
+ @Deprecated public class GpsNavigationMessage implements android.os.Parcelable {
+ method @Deprecated public int describeContents();
+ method @Deprecated @NonNull public byte[] getData();
+ method @Deprecated public short getMessageId();
+ method @Deprecated public byte getPrn();
+ method @Deprecated public short getStatus();
+ method @Deprecated public short getSubmessageId();
+ method @Deprecated public byte getType();
+ method @Deprecated public void reset();
+ method @Deprecated public void set(android.location.GpsNavigationMessage);
+ method @Deprecated public void setData(byte[]);
+ method @Deprecated public void setMessageId(short);
+ method @Deprecated public void setPrn(byte);
+ method @Deprecated public void setStatus(short);
+ method @Deprecated public void setSubmessageId(short);
+ method @Deprecated public void setType(byte);
+ method @Deprecated public void writeToParcel(android.os.Parcel, int);
+ field @Deprecated @NonNull public static final android.os.Parcelable.Creator<android.location.GpsNavigationMessage> CREATOR;
+ field @Deprecated public static final short STATUS_PARITY_PASSED = 1; // 0x1
+ field @Deprecated public static final short STATUS_PARITY_REBUILT = 2; // 0x2
+ field @Deprecated public static final short STATUS_UNKNOWN = 0; // 0x0
+ field @Deprecated public static final byte TYPE_CNAV2 = 4; // 0x4
+ field @Deprecated public static final byte TYPE_L1CA = 1; // 0x1
+ field @Deprecated public static final byte TYPE_L2CNAV = 2; // 0x2
+ field @Deprecated public static final byte TYPE_L5CNAV = 3; // 0x3
+ field @Deprecated public static final byte TYPE_UNKNOWN = 0; // 0x0
+ }
+
+ @Deprecated public class GpsNavigationMessageEvent implements android.os.Parcelable {
+ ctor @Deprecated public GpsNavigationMessageEvent(android.location.GpsNavigationMessage);
+ method @Deprecated public int describeContents();
+ method @Deprecated @NonNull public android.location.GpsNavigationMessage getNavigationMessage();
+ method @Deprecated public void writeToParcel(android.os.Parcel, int);
+ field @Deprecated @NonNull public static final android.os.Parcelable.Creator<android.location.GpsNavigationMessageEvent> CREATOR;
+ field @Deprecated public static int STATUS_GPS_LOCATION_DISABLED;
+ field @Deprecated public static int STATUS_NOT_SUPPORTED;
+ field @Deprecated public static int STATUS_READY;
+ }
+
+ @Deprecated public static interface GpsNavigationMessageEvent.Listener {
+ method @Deprecated public void onGpsNavigationMessageReceived(android.location.GpsNavigationMessageEvent);
+ method @Deprecated public void onStatusChanged(int);
+ }
+
+ public final class LastLocationRequest implements android.os.Parcelable {
+ method public int describeContents();
+ method public boolean isAdasGnssBypass();
+ method public boolean isHiddenFromAppOps();
+ method public boolean isLocationSettingsIgnored();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.location.LastLocationRequest> CREATOR;
+ }
+
+ public static final class LastLocationRequest.Builder {
+ ctor public LastLocationRequest.Builder();
+ ctor public LastLocationRequest.Builder(@NonNull android.location.LastLocationRequest);
+ method @NonNull public android.location.LastLocationRequest build();
+ method @NonNull @RequiresPermission(android.Manifest.permission.LOCATION_BYPASS) public android.location.LastLocationRequest.Builder setAdasGnssBypass(boolean);
+ method @NonNull @RequiresPermission(android.Manifest.permission.UPDATE_APP_OPS_STATS) public android.location.LastLocationRequest.Builder setHiddenFromAppOps(boolean);
+ method @NonNull @RequiresPermission(android.Manifest.permission.LOCATION_BYPASS) public android.location.LastLocationRequest.Builder setLocationSettingsIgnored(boolean);
+ }
+
+ public class LocationManager {
+ method @RequiresPermission(allOf={android.Manifest.permission.LOCATION_HARDWARE, android.Manifest.permission.INTERACT_ACROSS_USERS}) public void addProviderRequestChangedListener(@NonNull java.util.concurrent.Executor, @NonNull android.location.provider.ProviderRequest.ChangedListener);
+ method @Deprecated @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) public void flushGnssBatch();
+ method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public void getCurrentLocation(@NonNull android.location.LocationRequest, @Nullable android.os.CancellationSignal, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<android.location.Location>);
+ method @Nullable public String getExtraLocationControllerPackage();
+ method @Deprecated public int getGnssBatchSize();
+ method @Nullable @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public android.location.Location getLastKnownLocation(@NonNull String, @NonNull android.location.LastLocationRequest);
+ method @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) public void injectGnssMeasurementCorrections(@NonNull android.location.GnssMeasurementCorrections);
+ method public boolean isAdasGnssLocationEnabled();
+ method public boolean isExtraLocationControllerPackageEnabled();
+ method public boolean isLocationEnabledForUser(@NonNull android.os.UserHandle);
+ method public boolean isProviderEnabledForUser(@NonNull String, @NonNull android.os.UserHandle);
+ method @Deprecated @RequiresPermission(android.Manifest.permission.READ_DEVICE_CONFIG) public boolean isProviderPackage(@NonNull String);
+ method @RequiresPermission(android.Manifest.permission.READ_DEVICE_CONFIG) public boolean isProviderPackage(@Nullable String, @NonNull String, @Nullable String);
+ method @Deprecated @RequiresPermission(allOf={android.Manifest.permission.LOCATION_HARDWARE, android.Manifest.permission.UPDATE_APP_OPS_STATS}) public boolean registerGnssBatchedLocationCallback(long, boolean, @NonNull android.location.BatchedLocationCallback, @Nullable android.os.Handler);
+ method @Deprecated @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) public boolean registerGnssMeasurementsCallback(@NonNull android.location.GnssRequest, @NonNull java.util.concurrent.Executor, @NonNull android.location.GnssMeasurementsEvent.Callback);
+ method @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) public void removeProviderRequestChangedListener(@NonNull android.location.provider.ProviderRequest.ChangedListener);
+ method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public void requestLocationUpdates(@Nullable android.location.LocationRequest, @NonNull android.location.LocationListener, @Nullable android.os.Looper);
+ method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public void requestLocationUpdates(@Nullable android.location.LocationRequest, @NonNull java.util.concurrent.Executor, @NonNull android.location.LocationListener);
+ method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public void requestLocationUpdates(@Nullable android.location.LocationRequest, @NonNull android.app.PendingIntent);
+ method @RequiresPermission(android.Manifest.permission.LOCATION_BYPASS) public void setAdasGnssLocationEnabled(boolean);
+ method @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) public void setExtraLocationControllerPackage(@Nullable String);
+ method @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) public void setExtraLocationControllerPackageEnabled(boolean);
+ method @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public void setLocationEnabledForUser(boolean, @NonNull android.os.UserHandle);
+ method @Deprecated @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public boolean setProviderEnabledForUser(@NonNull String, boolean, @NonNull android.os.UserHandle);
+ method @Deprecated @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) public boolean unregisterGnssBatchedLocationCallback(@NonNull android.location.BatchedLocationCallback);
+ field public static final String ACTION_ADAS_GNSS_ENABLED_CHANGED = "android.location.action.ADAS_GNSS_ENABLED_CHANGED";
+ field public static final String EXTRA_ADAS_GNSS_ENABLED = "android.location.extra.ADAS_GNSS_ENABLED";
+ field @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) public static final String GPS_HARDWARE_PROVIDER = "gps_hardware";
+ }
+
+ public final class LocationRequest implements android.os.Parcelable {
+ method @Deprecated @NonNull public static android.location.LocationRequest create();
+ method @Deprecated @NonNull public static android.location.LocationRequest createFromDeprecatedCriteria(@NonNull android.location.Criteria, long, float, boolean);
+ method @Deprecated @NonNull public static android.location.LocationRequest createFromDeprecatedProvider(@NonNull String, long, float, boolean);
+ method @Deprecated public long getExpireAt();
+ method @Deprecated public long getExpireIn();
+ method @Deprecated public long getFastestInterval();
+ method @Deprecated public boolean getHideFromAppOps();
+ method @Deprecated public long getInterval();
+ method @Deprecated public int getNumUpdates();
+ method @Deprecated @NonNull public String getProvider();
+ method @Deprecated public float getSmallestDisplacement();
+ method @NonNull public android.os.WorkSource getWorkSource();
+ method public boolean isAdasGnssBypass();
+ method public boolean isHiddenFromAppOps();
+ method public boolean isLocationSettingsIgnored();
+ method public boolean isLowPower();
+ method @Deprecated public boolean isLowPowerMode();
+ method @Deprecated @NonNull public android.location.LocationRequest setExpireAt(long);
+ method @Deprecated @NonNull public android.location.LocationRequest setExpireIn(long);
+ method @Deprecated @NonNull public android.location.LocationRequest setFastestInterval(long);
+ method @Deprecated public void setHideFromAppOps(boolean);
+ method @Deprecated @NonNull public android.location.LocationRequest setInterval(long);
+ method @Deprecated @NonNull @RequiresPermission(android.Manifest.permission.LOCATION_BYPASS) public android.location.LocationRequest setLocationSettingsIgnored(boolean);
+ method @Deprecated @NonNull public android.location.LocationRequest setLowPowerMode(boolean);
+ method @Deprecated @NonNull public android.location.LocationRequest setNumUpdates(int);
+ method @Deprecated @NonNull public android.location.LocationRequest setProvider(@NonNull String);
+ method @Deprecated @NonNull public android.location.LocationRequest setQuality(int);
+ method @Deprecated @NonNull public android.location.LocationRequest setSmallestDisplacement(float);
+ method @Deprecated public void setWorkSource(@Nullable android.os.WorkSource);
+ field @Deprecated public static final int ACCURACY_BLOCK = 102; // 0x66
+ field @Deprecated public static final int ACCURACY_CITY = 104; // 0x68
+ field @Deprecated public static final int ACCURACY_FINE = 100; // 0x64
+ field @Deprecated public static final int POWER_HIGH = 203; // 0xcb
+ field @Deprecated public static final int POWER_LOW = 201; // 0xc9
+ field @Deprecated public static final int POWER_NONE = 200; // 0xc8
+ }
+
+ public static final class LocationRequest.Builder {
+ method @NonNull @RequiresPermission(android.Manifest.permission.LOCATION_BYPASS) public android.location.LocationRequest.Builder setAdasGnssBypass(boolean);
+ method @NonNull @RequiresPermission(android.Manifest.permission.UPDATE_APP_OPS_STATS) public android.location.LocationRequest.Builder setHiddenFromAppOps(boolean);
+ method @NonNull @RequiresPermission(android.Manifest.permission.LOCATION_BYPASS) public android.location.LocationRequest.Builder setLocationSettingsIgnored(boolean);
+ method @NonNull @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) public android.location.LocationRequest.Builder setLowPower(boolean);
+ method @NonNull @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS) public android.location.LocationRequest.Builder setWorkSource(@Nullable android.os.WorkSource);
+ }
+
+ public final class SatellitePvt implements android.os.Parcelable {
+ method public int describeContents();
+ method @Nullable public android.location.SatellitePvt.ClockInfo getClockInfo();
+ method public int getEphemerisSource();
+ method @FloatRange public double getIonoDelayMeters();
+ method @IntRange(from=0, to=1023) public int getIssueOfDataClock();
+ method @IntRange(from=0, to=1023) public int getIssueOfDataEphemeris();
+ method @Nullable public android.location.SatellitePvt.PositionEcef getPositionEcef();
+ method @IntRange(from=0) public long getTimeOfClockSeconds();
+ method @IntRange(from=0) public long getTimeOfEphemerisSeconds();
+ method @FloatRange public double getTropoDelayMeters();
+ method @Nullable public android.location.SatellitePvt.VelocityEcef getVelocityEcef();
+ method public boolean hasIono();
+ method public boolean hasIssueOfDataClock();
+ method public boolean hasIssueOfDataEphemeris();
+ method public boolean hasPositionVelocityClockInfo();
+ method public boolean hasTimeOfClockSeconds();
+ method public boolean hasTimeOfEphemerisSeconds();
+ method public boolean hasTropo();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.location.SatellitePvt> CREATOR;
+ field public static final int EPHEMERIS_SOURCE_DEMODULATED = 0; // 0x0
+ field public static final int EPHEMERIS_SOURCE_OTHER = 3; // 0x3
+ field public static final int EPHEMERIS_SOURCE_SERVER_LONG_TERM = 2; // 0x2
+ field public static final int EPHEMERIS_SOURCE_SERVER_NORMAL = 1; // 0x1
+ }
+
+ public static final class SatellitePvt.Builder {
+ ctor public SatellitePvt.Builder();
+ method @NonNull public android.location.SatellitePvt build();
+ method @NonNull public android.location.SatellitePvt.Builder setClockInfo(@NonNull android.location.SatellitePvt.ClockInfo);
+ method @NonNull public android.location.SatellitePvt.Builder setEphemerisSource(int);
+ method @NonNull public android.location.SatellitePvt.Builder setIonoDelayMeters(@FloatRange(from=0.0f, to=100.0f) double);
+ method @NonNull public android.location.SatellitePvt.Builder setIssueOfDataClock(@IntRange(from=0, to=1023) int);
+ method @NonNull public android.location.SatellitePvt.Builder setIssueOfDataEphemeris(@IntRange(from=0, to=1023) int);
+ method @NonNull public android.location.SatellitePvt.Builder setPositionEcef(@NonNull android.location.SatellitePvt.PositionEcef);
+ method @NonNull public android.location.SatellitePvt.Builder setTimeOfClockSeconds(@IntRange(from=0) long);
+ method @NonNull public android.location.SatellitePvt.Builder setTimeOfEphemerisSeconds(@IntRange(from=0) long);
+ method @NonNull public android.location.SatellitePvt.Builder setTropoDelayMeters(@FloatRange(from=0.0f, to=100.0f) double);
+ method @NonNull public android.location.SatellitePvt.Builder setVelocityEcef(@NonNull android.location.SatellitePvt.VelocityEcef);
+ }
+
+ public static final class SatellitePvt.ClockInfo implements android.os.Parcelable {
+ ctor public SatellitePvt.ClockInfo(double, double, double);
+ method public int describeContents();
+ method @FloatRange public double getClockDriftMetersPerSecond();
+ method @FloatRange public double getHardwareCodeBiasMeters();
+ method @FloatRange public double getTimeCorrectionMeters();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.location.SatellitePvt.ClockInfo> CREATOR;
+ }
+
+ public static final class SatellitePvt.PositionEcef implements android.os.Parcelable {
+ ctor public SatellitePvt.PositionEcef(double, double, double, double);
+ method public int describeContents();
+ method @FloatRange(from=0.0f, fromInclusive=false) public double getUreMeters();
+ method @FloatRange public double getXMeters();
+ method @FloatRange public double getYMeters();
+ method @FloatRange public double getZMeters();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.location.SatellitePvt.PositionEcef> CREATOR;
+ }
+
+ public static final class SatellitePvt.VelocityEcef implements android.os.Parcelable {
+ ctor public SatellitePvt.VelocityEcef(double, double, double, double);
+ method public int describeContents();
+ method @FloatRange(from=0.0f, fromInclusive=false) public double getUreRateMetersPerSecond();
+ method @FloatRange public double getXMetersPerSecond();
+ method @FloatRange public double getYMetersPerSecond();
+ method @FloatRange public double getZMetersPerSecond();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.location.SatellitePvt.VelocityEcef> CREATOR;
+ }
+
+}
+
+package android.location.provider {
+
+ public abstract class LocationProviderBase {
+ ctor public LocationProviderBase(@NonNull android.content.Context, @NonNull String, @NonNull android.location.provider.ProviderProperties);
+ method @Nullable public final android.os.IBinder getBinder();
+ method @NonNull public android.location.provider.ProviderProperties getProperties();
+ method public boolean isAllowed();
+ method public abstract void onFlush(@NonNull android.location.provider.LocationProviderBase.OnFlushCompleteCallback);
+ method public abstract void onSendExtraCommand(@NonNull String, @Nullable android.os.Bundle);
+ method public abstract void onSetRequest(@NonNull android.location.provider.ProviderRequest);
+ method public void reportLocation(@NonNull android.location.Location);
+ method public void reportLocations(@NonNull java.util.List<android.location.Location>);
+ method public void setAllowed(boolean);
+ method public void setProperties(@NonNull android.location.provider.ProviderProperties);
+ field public static final String ACTION_FUSED_PROVIDER = "com.android.location.service.FusedLocationProvider";
+ field public static final String ACTION_GNSS_PROVIDER = "android.location.provider.action.GNSS_PROVIDER";
+ field public static final String ACTION_NETWORK_PROVIDER = "com.android.location.service.v3.NetworkLocationProvider";
+ }
+
+ public static interface LocationProviderBase.OnFlushCompleteCallback {
+ method public void onFlushComplete();
+ }
+
+ public final class ProviderRequest implements android.os.Parcelable {
+ method public int describeContents();
+ method @IntRange(from=0) public long getIntervalMillis();
+ method @IntRange(from=0) public long getMaxUpdateDelayMillis();
+ method public int getQuality();
+ method @NonNull public android.os.WorkSource getWorkSource();
+ method public boolean isActive();
+ method public boolean isLocationSettingsIgnored();
+ method public boolean isLowPower();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.location.provider.ProviderRequest> CREATOR;
+ field @NonNull public static final android.location.provider.ProviderRequest EMPTY_REQUEST;
+ field public static final long INTERVAL_DISABLED = 9223372036854775807L; // 0x7fffffffffffffffL
+ }
+
+ public static final class ProviderRequest.Builder {
+ ctor public ProviderRequest.Builder();
+ method @NonNull public android.location.provider.ProviderRequest build();
+ method @NonNull public android.location.provider.ProviderRequest.Builder setIntervalMillis(@IntRange(from=0) long);
+ method @NonNull public android.location.provider.ProviderRequest.Builder setLocationSettingsIgnored(boolean);
+ method @NonNull public android.location.provider.ProviderRequest.Builder setLowPower(boolean);
+ method @NonNull public android.location.provider.ProviderRequest.Builder setMaxUpdateDelayMillis(@IntRange(from=0) long);
+ method @NonNull public android.location.provider.ProviderRequest.Builder setQuality(int);
+ method @NonNull public android.location.provider.ProviderRequest.Builder setWorkSource(@NonNull android.os.WorkSource);
+ }
+
+ public static interface ProviderRequest.ChangedListener {
+ method public void onProviderRequestChanged(@NonNull String, @NonNull android.location.provider.ProviderRequest);
+ }
+
+}
+
diff --git a/location/api/system-lint-baseline.txt b/location/api/system-lint-baseline.txt
new file mode 100644
index 000000000000..a5e5752d7cf5
--- /dev/null
+++ b/location/api/system-lint-baseline.txt
@@ -0,0 +1,11 @@
+// Baseline format: 1.0
+SamShouldBeLast: android.location.LocationManager#addNmeaListener(android.location.OnNmeaMessageListener, android.os.Handler):
+ SAM-compatible parameters (such as parameter 1, "listener", in android.location.LocationManager.addNmeaListener) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
+SamShouldBeLast: android.location.LocationManager#requestLocationUpdates(String, long, float, android.location.LocationListener, android.os.Looper):
+ SAM-compatible parameters (such as parameter 4, "listener", in android.location.LocationManager.requestLocationUpdates) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
+SamShouldBeLast: android.location.LocationManager#requestLocationUpdates(long, float, android.location.Criteria, android.location.LocationListener, android.os.Looper):
+ SAM-compatible parameters (such as parameter 4, "listener", in android.location.LocationManager.requestLocationUpdates) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
+SamShouldBeLast: android.location.LocationManager#requestSingleUpdate(String, android.location.LocationListener, android.os.Looper):
+ SAM-compatible parameters (such as parameter 2, "listener", in android.location.LocationManager.requestSingleUpdate) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
+SamShouldBeLast: android.location.LocationManager#requestSingleUpdate(android.location.Criteria, android.location.LocationListener, android.os.Looper):
+ SAM-compatible parameters (such as parameter 2, "listener", in android.location.LocationManager.requestSingleUpdate) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
diff --git a/location/api/system-removed.txt b/location/api/system-removed.txt
index d802177e249b..2755a9ff33c8 100644
--- a/location/api/system-removed.txt
+++ b/location/api/system-removed.txt
@@ -1 +1,15 @@
// Signature format: 2.0
+package android.location {
+
+ public class LocationManager {
+ method @Deprecated public boolean addGpsMeasurementListener(android.location.GpsMeasurementsEvent.Listener);
+ method @Deprecated public boolean addGpsNavigationMessageListener(android.location.GpsNavigationMessageEvent.Listener);
+ method @Deprecated @RequiresPermission(android.Manifest.permission.READ_DEVICE_CONFIG) public boolean isProviderPackage(@Nullable String, @NonNull String);
+ method @Deprecated public void removeGpsMeasurementListener(android.location.GpsMeasurementsEvent.Listener);
+ method @Deprecated public void removeGpsNavigationMessageListener(android.location.GpsNavigationMessageEvent.Listener);
+ method @Deprecated @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) public void setLocationControllerExtraPackage(String);
+ method @Deprecated @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) public void setLocationControllerExtraPackageEnabled(boolean);
+ }
+
+}
+
diff --git a/location/api/test-current.txt b/location/api/test-current.txt
index d802177e249b..bdcb00a93b95 100644
--- a/location/api/test-current.txt
+++ b/location/api/test-current.txt
@@ -1 +1,104 @@
// Signature format: 2.0
+package android.location {
+
+ public final class GnssClock implements android.os.Parcelable {
+ ctor public GnssClock();
+ method public void reset();
+ method public void resetBiasNanos();
+ method public void resetBiasUncertaintyNanos();
+ method public void resetDriftNanosPerSecond();
+ method public void resetDriftUncertaintyNanosPerSecond();
+ method public void resetElapsedRealtimeNanos();
+ method public void resetElapsedRealtimeUncertaintyNanos();
+ method public void resetFullBiasNanos();
+ method public void resetLeapSecond();
+ method public void resetReferenceCarrierFrequencyHzForIsb();
+ method public void resetReferenceCodeTypeForIsb();
+ method public void resetReferenceConstellationTypeForIsb();
+ method public void resetTimeUncertaintyNanos();
+ method public void set(android.location.GnssClock);
+ method public void setBiasNanos(double);
+ method public void setBiasUncertaintyNanos(@FloatRange(from=0.0f) double);
+ method public void setDriftNanosPerSecond(double);
+ method public void setDriftUncertaintyNanosPerSecond(@FloatRange(from=0.0f) double);
+ method public void setElapsedRealtimeNanos(long);
+ method public void setElapsedRealtimeUncertaintyNanos(@FloatRange(from=0.0f) double);
+ method public void setFullBiasNanos(long);
+ method public void setHardwareClockDiscontinuityCount(int);
+ method public void setLeapSecond(int);
+ method public void setReferenceCarrierFrequencyHzForIsb(@FloatRange(from=0.0) double);
+ method public void setReferenceCodeTypeForIsb(@NonNull String);
+ method public void setReferenceConstellationTypeForIsb(int);
+ method public void setTimeNanos(long);
+ method public void setTimeUncertaintyNanos(@FloatRange(from=0.0f) double);
+ }
+
+ public final class GnssMeasurement implements android.os.Parcelable {
+ ctor public GnssMeasurement();
+ method public void reset();
+ method public void resetAutomaticGainControlLevel();
+ method public void resetBasebandCn0DbHz();
+ method @Deprecated public void resetCarrierCycles();
+ method public void resetCarrierFrequencyHz();
+ method @Deprecated public void resetCarrierPhase();
+ method @Deprecated public void resetCarrierPhaseUncertainty();
+ method public void resetCodeType();
+ method public void resetCorrelationVectors();
+ method public void resetFullInterSignalBiasNanos();
+ method public void resetFullInterSignalBiasUncertaintyNanos();
+ method public void resetSatelliteInterSignalBiasNanos();
+ method public void resetSatelliteInterSignalBiasUncertaintyNanos();
+ method public void resetSatellitePvt();
+ method public void resetSnrInDb();
+ method public void set(android.location.GnssMeasurement);
+ method public void setAccumulatedDeltaRangeMeters(double);
+ method public void setAccumulatedDeltaRangeState(int);
+ method public void setAccumulatedDeltaRangeUncertaintyMeters(double);
+ method @Deprecated public void setAutomaticGainControlLevelInDb(double);
+ method public void setBasebandCn0DbHz(double);
+ method @Deprecated public void setCarrierCycles(long);
+ method public void setCarrierFrequencyHz(float);
+ method @Deprecated public void setCarrierPhase(double);
+ method @Deprecated public void setCarrierPhaseUncertainty(double);
+ method public void setCn0DbHz(double);
+ method public void setCodeType(@NonNull String);
+ method public void setConstellationType(int);
+ method public void setCorrelationVectors(@Nullable java.util.Collection<android.location.CorrelationVector>);
+ method public void setFullInterSignalBiasNanos(double);
+ method public void setFullInterSignalBiasUncertaintyNanos(@FloatRange(from=0.0) double);
+ method public void setMultipathIndicator(int);
+ method public void setPseudorangeRateMetersPerSecond(double);
+ method public void setPseudorangeRateUncertaintyMetersPerSecond(double);
+ method public void setReceivedSvTimeNanos(long);
+ method public void setReceivedSvTimeUncertaintyNanos(long);
+ method public void setSatelliteInterSignalBiasNanos(double);
+ method public void setSatelliteInterSignalBiasUncertaintyNanos(@FloatRange(from=0.0) double);
+ method public void setSatellitePvt(@Nullable android.location.SatellitePvt);
+ method public void setSnrInDb(double);
+ method public void setState(int);
+ method public void setSvid(int);
+ method public void setTimeOffsetNanos(double);
+ field public static final int ADR_STATE_ALL = 31; // 0x1f
+ }
+
+ public final class GnssNavigationMessage implements android.os.Parcelable {
+ ctor public GnssNavigationMessage();
+ method public void reset();
+ method public void set(android.location.GnssNavigationMessage);
+ method public void setData(byte[]);
+ method public void setMessageId(@IntRange(from=0xffffffff, to=120) int);
+ method public void setStatus(int);
+ method public void setSubmessageId(@IntRange(from=1) int);
+ method public void setSvid(@IntRange(from=1, to=200) int);
+ method public void setType(int);
+ }
+
+ public class LocationManager {
+ method @NonNull public String[] getBackgroundThrottlingWhitelist();
+ method @NonNull public android.os.PackageTagsList getIgnoreSettingsAllowlist();
+ method @Deprecated @NonNull public String[] getIgnoreSettingsWhitelist();
+ method @Deprecated @Nullable @RequiresPermission(android.Manifest.permission.READ_DEVICE_CONFIG) public java.util.List<java.lang.String> getProviderPackages(@NonNull String);
+ }
+
+}
+
diff --git a/location/api/test-lint-baseline.txt b/location/api/test-lint-baseline.txt
new file mode 100644
index 000000000000..189588e4bafb
--- /dev/null
+++ b/location/api/test-lint-baseline.txt
@@ -0,0 +1,54 @@
+// Baseline format: 1.0
+GetterSetterNames: android.location.GnssClock#setBiasNanos(double):
+ Symmetric method for `hasBiasNanos` must be named `setHasBiasNanos`; was `setBiasNanos`
+GetterSetterNames: android.location.GnssClock#setBiasUncertaintyNanos(double):
+ Symmetric method for `hasBiasUncertaintyNanos` must be named `setHasBiasUncertaintyNanos`; was `setBiasUncertaintyNanos`
+GetterSetterNames: android.location.GnssClock#setDriftNanosPerSecond(double):
+ Symmetric method for `hasDriftNanosPerSecond` must be named `setHasDriftNanosPerSecond`; was `setDriftNanosPerSecond`
+GetterSetterNames: android.location.GnssClock#setDriftUncertaintyNanosPerSecond(double):
+ Symmetric method for `hasDriftUncertaintyNanosPerSecond` must be named `setHasDriftUncertaintyNanosPerSecond`; was `setDriftUncertaintyNanosPerSecond`
+GetterSetterNames: android.location.GnssClock#setElapsedRealtimeNanos(long):
+ Symmetric method for `hasElapsedRealtimeNanos` must be named `setHasElapsedRealtimeNanos`; was `setElapsedRealtimeNanos`
+GetterSetterNames: android.location.GnssClock#setElapsedRealtimeUncertaintyNanos(double):
+ Symmetric method for `hasElapsedRealtimeUncertaintyNanos` must be named `setHasElapsedRealtimeUncertaintyNanos`; was `setElapsedRealtimeUncertaintyNanos`
+GetterSetterNames: android.location.GnssClock#setFullBiasNanos(long):
+ Symmetric method for `hasFullBiasNanos` must be named `setHasFullBiasNanos`; was `setFullBiasNanos`
+GetterSetterNames: android.location.GnssClock#setLeapSecond(int):
+ Symmetric method for `hasLeapSecond` must be named `setHasLeapSecond`; was `setLeapSecond`
+GetterSetterNames: android.location.GnssClock#setReferenceCarrierFrequencyHzForIsb(double):
+ Symmetric method for `hasReferenceCarrierFrequencyHzForIsb` must be named `setHasReferenceCarrierFrequencyHzForIsb`; was `setReferenceCarrierFrequencyHzForIsb`
+GetterSetterNames: android.location.GnssClock#setReferenceCodeTypeForIsb(String):
+ Symmetric method for `hasReferenceCodeTypeForIsb` must be named `setHasReferenceCodeTypeForIsb`; was `setReferenceCodeTypeForIsb`
+GetterSetterNames: android.location.GnssClock#setReferenceConstellationTypeForIsb(int):
+ Symmetric method for `hasReferenceConstellationTypeForIsb` must be named `setHasReferenceConstellationTypeForIsb`; was `setReferenceConstellationTypeForIsb`
+GetterSetterNames: android.location.GnssClock#setTimeUncertaintyNanos(double):
+ Symmetric method for `hasTimeUncertaintyNanos` must be named `setHasTimeUncertaintyNanos`; was `setTimeUncertaintyNanos`
+GetterSetterNames: android.location.GnssMeasurement#setBasebandCn0DbHz(double):
+ Symmetric method for `hasBasebandCn0DbHz` must be named `setHasBasebandCn0DbHz`; was `setBasebandCn0DbHz`
+GetterSetterNames: android.location.GnssMeasurement#setCarrierFrequencyHz(float):
+ Symmetric method for `hasCarrierFrequencyHz` must be named `setHasCarrierFrequencyHz`; was `setCarrierFrequencyHz`
+GetterSetterNames: android.location.GnssMeasurement#setCodeType(String):
+ Symmetric method for `hasCodeType` must be named `setHasCodeType`; was `setCodeType`
+GetterSetterNames: android.location.GnssMeasurement#setCorrelationVectors(java.util.Collection<android.location.CorrelationVector>):
+ Symmetric method for `hasCorrelationVectors` must be named `setHasCorrelationVectors`; was `setCorrelationVectors`
+GetterSetterNames: android.location.GnssMeasurement#setFullInterSignalBiasNanos(double):
+ Symmetric method for `hasFullInterSignalBiasNanos` must be named `setHasFullInterSignalBiasNanos`; was `setFullInterSignalBiasNanos`
+GetterSetterNames: android.location.GnssMeasurement#setFullInterSignalBiasUncertaintyNanos(double):
+ Symmetric method for `hasFullInterSignalBiasUncertaintyNanos` must be named `setHasFullInterSignalBiasUncertaintyNanos`; was `setFullInterSignalBiasUncertaintyNanos`
+GetterSetterNames: android.location.GnssMeasurement#setSatelliteInterSignalBiasNanos(double):
+ Symmetric method for `hasSatelliteInterSignalBiasNanos` must be named `setHasSatelliteInterSignalBiasNanos`; was `setSatelliteInterSignalBiasNanos`
+GetterSetterNames: android.location.GnssMeasurement#setSatelliteInterSignalBiasUncertaintyNanos(double):
+ Symmetric method for `hasSatelliteInterSignalBiasUncertaintyNanos` must be named `setHasSatelliteInterSignalBiasUncertaintyNanos`; was `setSatelliteInterSignalBiasUncertaintyNanos`
+GetterSetterNames: android.location.GnssMeasurement#setSatellitePvt(android.location.SatellitePvt):
+ Symmetric method for `hasSatellitePvt` must be named `setHasSatellitePvt`; was `setSatellitePvt`
+GetterSetterNames: android.location.GnssMeasurement#setSnrInDb(double):
+ Symmetric method for `hasSnrInDb` must be named `setHasSnrInDb`; was `setSnrInDb`
+
+MissingNullability: android.location.GnssClock#set(android.location.GnssClock) parameter #0:
+ Missing nullability on parameter `clock` in method `set`
+MissingNullability: android.location.GnssMeasurement#set(android.location.GnssMeasurement) parameter #0:
+ Missing nullability on parameter `measurement` in method `set`
+MissingNullability: android.location.GnssNavigationMessage#set(android.location.GnssNavigationMessage) parameter #0:
+ Missing nullability on parameter `navigationMessage` in method `set`
+MissingNullability: android.location.GnssNavigationMessage#setData(byte[]) parameter #0:
+ Missing nullability on parameter `value` in method `setData`
diff --git a/location/java/Android.bp b/location/java/Android.bp
deleted file mode 100644
index 543f2b1ab4a8..000000000000
--- a/location/java/Android.bp
+++ /dev/null
@@ -1,17 +0,0 @@
-package {
- // See: http://go/android-license-faq
- // A large-scale-change added 'default_applicable_licenses' to import
- // all of the 'license_kinds' from "frameworks_base_license"
- // to get the below license kinds:
- // SPDX-license-identifier-Apache-2.0
- default_applicable_licenses: ["frameworks_base_license"],
-}
-
-filegroup {
- name: "framework-location-sources",
- srcs: [
- "**/*.java",
- "**/*.aidl",
- ],
- visibility: ["//frameworks/base"],
-}
diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java
index e2f407294458..842542f4f43b 100644
--- a/media/java/android/media/AudioManager.java
+++ b/media/java/android/media/AudioManager.java
@@ -4945,7 +4945,9 @@ public class AudioManager {
synchronized (this) {
while (!mQuit) {
final long timeToWait = timeOutTime - java.lang.System.currentTimeMillis();
- if (timeToWait < 0) { break; }
+ if (timeToWait <= 0) {
+ break;
+ }
this.wait(timeToWait);
}
}
diff --git a/media/java/android/media/AudioSystem.java b/media/java/android/media/AudioSystem.java
index 3f013de8dad6..61b5fd5fb0ec 100644
--- a/media/java/android/media/AudioSystem.java
+++ b/media/java/android/media/AudioSystem.java
@@ -29,6 +29,7 @@ import android.content.pm.PackageManager;
import android.media.audio.common.AidlConversion;
import android.media.audiofx.AudioEffect;
import android.media.audiopolicy.AudioMix;
+import android.media.audiopolicy.AudioMixingRule;
import android.media.audiopolicy.AudioProductStrategy;
import android.os.Build;
import android.os.IBinder;
@@ -1955,6 +1956,11 @@ public class AudioSystem
/** @hide */
public static native int registerPolicyMixes(ArrayList<AudioMix> mixes, boolean register);
+ /** @hide */
+ public static native int updatePolicyMixes(
+ AudioMix[] mixes,
+ AudioMixingRule[] updatedMixingRules);
+
/** @hide see AudioPolicy.setUidDeviceAffinities() */
public static native int setUidDeviceAffinities(int uid, @NonNull int[] types,
@NonNull String[] addresses);
diff --git a/media/java/android/media/IAudioService.aidl b/media/java/android/media/IAudioService.aidl
index e45ef404995c..0e7718b060bc 100644
--- a/media/java/android/media/IAudioService.aidl
+++ b/media/java/android/media/IAudioService.aidl
@@ -54,6 +54,8 @@ import android.media.IVolumeController;
import android.media.PlayerBase;
import android.media.VolumeInfo;
import android.media.VolumePolicy;
+import android.media.audiopolicy.AudioMix;
+import android.media.audiopolicy.AudioMixingRule;
import android.media.audiopolicy.AudioPolicyConfig;
import android.media.audiopolicy.AudioProductStrategy;
import android.media.audiopolicy.AudioVolumeGroup;
@@ -356,6 +358,11 @@ interface IAudioService {
int removeMixForPolicy(in AudioPolicyConfig policyConfig, in IAudioPolicyCallback pcb);
+ @EnforcePermission("MODIFY_AUDIO_ROUTING")
+ int updateMixingRulesForPolicy(in AudioMix[] mixesToUpdate,
+ in AudioMixingRule[] updatedMixingRules,
+ in IAudioPolicyCallback pcb);
+
int setFocusPropertiesForPolicy(int duckingBehavior, in IAudioPolicyCallback pcb);
void setVolumePolicy(in VolumePolicy policy);
diff --git a/media/java/android/media/MediaMetadataRetriever.java b/media/java/android/media/MediaMetadataRetriever.java
index ea261852bb9f..1de08810307e 100644
--- a/media/java/android/media/MediaMetadataRetriever.java
+++ b/media/java/android/media/MediaMetadataRetriever.java
@@ -1155,7 +1155,7 @@ public class MediaMetadataRetriever implements AutoCloseable {
public static final int OPTION_CLOSEST = 0x03;
/** @hide */
- @IntDef(flag = true, prefix = { "OPTION_" }, value = {
+ @IntDef(flag = false, prefix = { "OPTION_" }, value = {
OPTION_PREVIOUS_SYNC,
OPTION_NEXT_SYNC,
OPTION_CLOSEST_SYNC,
diff --git a/media/java/android/media/RingtoneManager.java b/media/java/android/media/RingtoneManager.java
index c4f2159a23dc..12db8c0824db 100644
--- a/media/java/android/media/RingtoneManager.java
+++ b/media/java/android/media/RingtoneManager.java
@@ -30,6 +30,7 @@ import android.content.ContentProvider;
import android.content.ContentResolver;
import android.content.ContentUris;
import android.content.Context;
+import android.content.Intent;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.UserInfo;
import android.content.res.AssetFileDescriptor;
@@ -120,6 +121,53 @@ public class RingtoneManager {
public static final String ACTION_RINGTONE_PICKER = "android.intent.action.RINGTONE_PICKER";
/**
+ * Given to the ringtone picker as a string that represents the category of ringtone picker that
+ * should be used. This value should also be returned once a ringtone is selected.
+ * <p>
+ * The categories are:
+ * <li>{@link #CATEGORY_RINGTONE_PICKER_SOUND}
+ * <li>{@link #CATEGORY_RINGTONE_PICKER_VIBRATION}
+ * <li>{@link #CATEGORY_RINGTONE_PICKER_RINGTONE}
+ * <li>{@link Intent#CATEGORY_DEFAULT}
+ *
+ * <p> If the category is {@link Intent#CATEGORY_DEFAULT} or absent, then the picker will
+ * default to a sound-only ringtone picker.
+ *
+ * <p> If the selected category was not supported, then the returned category will be null.
+ *
+ * @hide
+ */
+ public static final String EXTRA_RINGTONE_PICKER_CATEGORY =
+ "android.intent.extra.ringtone.RINGTONE_PICKER_CATEGORY";
+
+ /**
+ * A sound-only ringtone picker.
+ *
+ * @hide
+ * @see #EXTRA_RINGTONE_PICKER_CATEGORY
+ */
+ public static final String CATEGORY_RINGTONE_PICKER_SOUND =
+ "android.net.category.RINGTONE_PICKER_SOUND";
+
+ /**
+ * A vibration-only ringtone picker.
+ *
+ * @hide
+ * @see #EXTRA_RINGTONE_PICKER_CATEGORY
+ */
+ public static final String CATEGORY_RINGTONE_PICKER_VIBRATION =
+ "android.net.category.RINGTONE_PICKER_VIBRATION";
+
+ /**
+ * A combined sound and vibration ringtone picker.
+ *
+ * @hide
+ * @see #EXTRA_RINGTONE_PICKER_CATEGORY
+ */
+ public static final String CATEGORY_RINGTONE_PICKER_RINGTONE =
+ "android.net.category.RINGTONE_PICKER_RINGTONE";
+
+ /**
* Given to the ringtone picker as a boolean. Whether to show an item for
* "Default".
*
@@ -160,6 +208,18 @@ public class RingtoneManager {
*/
public static final String EXTRA_RINGTONE_EXISTING_URI =
"android.intent.extra.ringtone.EXISTING_URI";
+
+ /**
+ * Similar to #EXTRA_RINGTONE_EXISTING_URI but the {@link Uri} can include both sound and
+ * vibration.
+ * <p>This can include silent sound/vibration explicitly by setting that part of the URI to
+ * null.
+ *
+ * @hide
+ * @see #ACTION_RINGTONE_PICKER
+ */
+ public static final String EXTRA_RINGTONE_EXISTING_RINGTONE_URI =
+ "android.intent.extra.ringtone.RINGTONE_EXISTING_RINGTONE_URI";
/**
* Given to the ringtone picker as a {@link Uri}. The {@link Uri} of the
diff --git a/media/java/android/media/audiopolicy/AudioMix.aidl b/media/java/android/media/audiopolicy/AudioMix.aidl
new file mode 100644
index 000000000000..d17a644c93a1
--- /dev/null
+++ b/media/java/android/media/audiopolicy/AudioMix.aidl
@@ -0,0 +1,3 @@
+package android.media.audiopolicy;
+
+parcelable AudioMix; \ No newline at end of file
diff --git a/media/java/android/media/audiopolicy/AudioMix.java b/media/java/android/media/audiopolicy/AudioMix.java
index d0270d3d3246..48b476651c91 100644
--- a/media/java/android/media/audiopolicy/AudioMix.java
+++ b/media/java/android/media/audiopolicy/AudioMix.java
@@ -21,12 +21,15 @@ import static android.media.AudioSystem.isRemoteSubmixDevice;
import android.annotation.IntDef;
import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.annotation.SystemApi;
import android.compat.annotation.UnsupportedAppUsage;
import android.media.AudioDeviceInfo;
import android.media.AudioFormat;
import android.media.AudioSystem;
import android.os.Build;
+import android.os.Parcel;
+import android.os.Parcelable;
import com.android.internal.annotations.VisibleForTesting;
@@ -38,12 +41,12 @@ import java.util.Objects;
* @hide
*/
@SystemApi
-public class AudioMix {
+public class AudioMix implements Parcelable {
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
- private AudioMixingRule mRule;
+ private @NonNull AudioMixingRule mRule;
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
- private AudioFormat mFormat;
+ private @NonNull AudioFormat mFormat;
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
private int mRouteFlags;
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
@@ -54,7 +57,7 @@ public class AudioMix {
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
int mCallbackFlags;
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
- String mDeviceAddress;
+ @NonNull String mDeviceAddress;
// initialized in constructor, read by AudioPolicyConfig
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
@@ -63,10 +66,11 @@ public class AudioMix {
/**
* All parameters are guaranteed valid through the Builder.
*/
- private AudioMix(AudioMixingRule rule, AudioFormat format, int routeFlags, int callbackFlags,
- int deviceType, String deviceAddress) {
- mRule = rule;
- mFormat = format;
+ private AudioMix(@NonNull AudioMixingRule rule, @NonNull AudioFormat format,
+ int routeFlags, int callbackFlags,
+ int deviceType, @Nullable String deviceAddress) {
+ mRule = Objects.requireNonNull(rule);
+ mFormat = Objects.requireNonNull(format);
mRouteFlags = routeFlags;
mMixType = rule.getTargetMixType();
mCallbackFlags = callbackFlags;
@@ -187,6 +191,15 @@ public class AudioMix {
}
/** @hide */
+ public void setAudioMixingRule(@NonNull AudioMixingRule rule) {
+ if (mRule.getTargetMixType() != rule.getTargetMixType()) {
+ throw new UnsupportedOperationException(
+ "Target mix role of updated rule doesn't match the mix role of the AudioMix");
+ }
+ mRule = Objects.requireNonNull(rule);
+ }
+
+ /** @hide */
public String getRegistration() {
return mDeviceAddress;
}
@@ -269,6 +282,49 @@ public class AudioMix {
return Objects.hash(mRouteFlags, mRule, mMixType, mFormat);
}
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(@NonNull Parcel dest, int flags) {
+ // write mix route flags
+ dest.writeInt(mRouteFlags);
+ // write callback flags
+ dest.writeInt(mCallbackFlags);
+ // write device information
+ dest.writeInt(mDeviceSystemType);
+ dest.writeString8(mDeviceAddress);
+ mFormat.writeToParcel(dest, flags);
+ mRule.writeToParcel(dest, flags);
+ }
+
+ public static final @NonNull Parcelable.Creator<AudioMix> CREATOR = new Parcelable.Creator<>() {
+ /**
+ * Rebuilds an AudioMix previously stored with writeToParcel().
+ *
+ * @param p Parcel object to read the AudioMix from
+ * @return a new AudioMix created from the data in the parcel
+ */
+ public AudioMix createFromParcel(Parcel p) {
+ final AudioMix.Builder mixBuilder = new AudioMix.Builder();
+ // read mix route flags
+ mixBuilder.setRouteFlags(p.readInt());
+ // read callback flags
+ mixBuilder.setCallbackFlags(p.readInt());
+ // read device information
+ mixBuilder.setDevice(p.readInt(), p.readString8());
+ mixBuilder.setFormat(AudioFormat.CREATOR.createFromParcel(p));
+ mixBuilder.setMixingRule(AudioMixingRule.CREATOR.createFromParcel(p));
+ return mixBuilder.build();
+ }
+
+ public AudioMix[] newArray(int size) {
+ return new AudioMix[size];
+ }
+ };
+
/** @hide */
@IntDef(flag = true,
value = { ROUTE_FLAG_RENDER, ROUTE_FLAG_LOOP_BACK } )
@@ -298,7 +354,7 @@ public class AudioMix {
* @param rule a non-null {@link AudioMixingRule} instance.
* @throws IllegalArgumentException
*/
- public Builder(AudioMixingRule rule)
+ public Builder(@NonNull AudioMixingRule rule)
throws IllegalArgumentException {
if (rule == null) {
throw new IllegalArgumentException("Illegal null AudioMixingRule argument");
@@ -313,7 +369,7 @@ public class AudioMix {
* @return the same Builder instance.
* @throws IllegalArgumentException
*/
- Builder setMixingRule(AudioMixingRule rule)
+ Builder setMixingRule(@NonNull AudioMixingRule rule)
throws IllegalArgumentException {
if (rule == null) {
throw new IllegalArgumentException("Illegal null AudioMixingRule argument");
@@ -358,7 +414,7 @@ public class AudioMix {
* @return the same Builder instance.
* @throws IllegalArgumentException
*/
- public Builder setFormat(AudioFormat format)
+ public Builder setFormat(@NonNull AudioFormat format)
throws IllegalArgumentException {
if (format == null) {
throw new IllegalArgumentException("Illegal null AudioFormat argument");
diff --git a/media/java/android/media/audiopolicy/AudioMixingRule.aidl b/media/java/android/media/audiopolicy/AudioMixingRule.aidl
new file mode 100644
index 000000000000..5c06538b74c2
--- /dev/null
+++ b/media/java/android/media/audiopolicy/AudioMixingRule.aidl
@@ -0,0 +1,3 @@
+package android.media.audiopolicy;
+
+parcelable AudioMixingRule; \ No newline at end of file
diff --git a/media/java/android/media/audiopolicy/AudioMixingRule.java b/media/java/android/media/audiopolicy/AudioMixingRule.java
index 9c0b825fbfa3..e5debb8132ea 100644
--- a/media/java/android/media/audiopolicy/AudioMixingRule.java
+++ b/media/java/android/media/audiopolicy/AudioMixingRule.java
@@ -26,8 +26,11 @@ import android.media.AudioAttributes;
import android.media.MediaRecorder;
import android.os.Build;
import android.os.Parcel;
+import android.os.Parcelable;
import android.util.Log;
+import com.android.internal.annotations.VisibleForTesting;
+
import java.lang.annotation.Retention;
import java.util.ArrayList;
import java.util.Collection;
@@ -50,7 +53,7 @@ import java.util.Set;
* </pre>
*/
@SystemApi
-public class AudioMixingRule {
+public class AudioMixingRule implements Parcelable {
private AudioMixingRule(int mixType, Collection<AudioMixMatchCriterion> criteria,
boolean allowPrivilegedMediaPlaybackCapture,
@@ -130,7 +133,7 @@ public class AudioMixingRule {
RULE_EXCLUSION_MASK | RULE_MATCH_AUDIO_SESSION_ID;
/** @hide */
- public static final class AudioMixMatchCriterion {
+ public static final class AudioMixMatchCriterion implements Parcelable {
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
final AudioAttributes mAttr;
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
@@ -139,18 +142,44 @@ public class AudioMixingRule {
final int mRule;
/** input parameters must be valid */
- AudioMixMatchCriterion(AudioAttributes attributes, int rule) {
+ @VisibleForTesting
+ public AudioMixMatchCriterion(AudioAttributes attributes, int rule) {
mAttr = attributes;
mIntProp = Integer.MIN_VALUE;
mRule = rule;
}
/** input parameters must be valid */
- AudioMixMatchCriterion(Integer intProp, int rule) {
+ @VisibleForTesting
+ public AudioMixMatchCriterion(Integer intProp, int rule) {
mAttr = null;
mIntProp = intProp.intValue();
mRule = rule;
}
+ private AudioMixMatchCriterion(@NonNull Parcel in) {
+ Objects.requireNonNull(in);
+ mRule = in.readInt();
+ final int match_rule = mRule & ~RULE_EXCLUSION_MASK;
+ switch (match_rule) {
+ case RULE_MATCH_ATTRIBUTE_USAGE:
+ case RULE_MATCH_ATTRIBUTE_CAPTURE_PRESET:
+ mAttr = AudioAttributes.CREATOR.createFromParcel(in);
+ mIntProp = Integer.MIN_VALUE;
+ break;
+ case RULE_MATCH_UID:
+ case RULE_MATCH_USERID:
+ case RULE_MATCH_AUDIO_SESSION_ID:
+ mIntProp = in.readInt();
+ mAttr = null;
+ break;
+ default:
+ // assume there was in int value to read as for now they come in pair
+ in.readInt();
+ throw new IllegalArgumentException(
+ "Illegal rule value " + mRule + " in parcel");
+ }
+ }
+
@Override
public int hashCode() {
return Objects.hash(mAttr, mIntProp, mRule);
@@ -170,7 +199,13 @@ public class AudioMixingRule {
&& Objects.equals(mAttr, other.mAttr);
}
- void writeToParcel(Parcel dest) {
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(@NonNull Parcel dest, int flags) {
dest.writeInt(mRule);
final int match_rule = mRule & ~RULE_EXCLUSION_MASK;
switch (match_rule) {
@@ -190,6 +225,22 @@ public class AudioMixingRule {
}
}
+ public static final @NonNull Parcelable.Creator<AudioMixMatchCriterion> CREATOR =
+ new Parcelable.Creator<>() {
+ /**
+ * Rebuilds an AudioMixMatchCriterion previously stored with writeToParcel().
+ *
+ * @param p Parcel object to read the AudioMix from
+ * @return a new AudioMixMatchCriterion created from the data in the parcel
+ */
+ public AudioMixMatchCriterion createFromParcel(Parcel p) {
+ return new AudioMixMatchCriterion(p);
+ }
+ public AudioMixMatchCriterion[] newArray(int size) {
+ return new AudioMixMatchCriterion[size];
+ }
+ };
+
public AudioAttributes getAudioAttributes() { return mAttr; }
public int getIntProp() { return mIntProp; }
public int getRule() { return mRule; }
@@ -605,13 +656,14 @@ public class AudioMixingRule {
if (!(property instanceof AudioAttributes)) {
throw new IllegalArgumentException("Invalid AudioAttributes argument");
}
- return addRuleInternal((AudioAttributes) property, null, rule);
+ return addRuleInternal(
+ new AudioMixMatchCriterion((AudioAttributes) property, rule));
} else {
// implies integer match rule
if (!(property instanceof Integer)) {
throw new IllegalArgumentException("Invalid Integer argument");
}
- return addRuleInternal(null, (Integer) property, rule);
+ return addRuleInternal(new AudioMixMatchCriterion((Integer) property, rule));
}
}
@@ -636,12 +688,13 @@ public class AudioMixingRule {
* @return the same Builder instance.
* @throws IllegalArgumentException
*/
- private Builder addRuleInternal(AudioAttributes attrToMatch, Integer intProp, int rule)
+ private Builder addRuleInternal(AudioMixMatchCriterion criterion)
throws IllegalArgumentException {
// If mix type is invalid and added rule is valid only for the players / recorders,
// adjust the mix type accordingly.
// Otherwise, if the mix type was already deduced or set explicitly, verify the rule
// is valid for the mix type.
+ final int rule = criterion.mRule;
if (mTargetMixType == AudioMix.MIX_TYPE_INVALID) {
if (isPlayerRule(rule)) {
mTargetMixType = AudioMix.MIX_TYPE_PLAYERS;
@@ -655,51 +708,16 @@ public class AudioMixingRule {
}
synchronized (mCriteria) {
int oppositeRule = rule ^ RULE_EXCLUSION_MASK;
- if (mCriteria.stream().anyMatch(criterion -> criterion.mRule == oppositeRule)) {
+ if (mCriteria.stream().anyMatch(
+ otherCriterion -> otherCriterion.mRule == oppositeRule)) {
throw new IllegalArgumentException("AudioMixingRule cannot contain RULE_MATCH_*"
+ " and RULE_EXCLUDE_* for the same dimension.");
}
- int ruleWithoutExclusion = rule & ~RULE_EXCLUSION_MASK;
- switch (ruleWithoutExclusion) {
- case RULE_MATCH_ATTRIBUTE_USAGE:
- case RULE_MATCH_ATTRIBUTE_CAPTURE_PRESET:
- mCriteria.add(new AudioMixMatchCriterion(attrToMatch, rule));
- break;
- case RULE_MATCH_UID:
- case RULE_MATCH_USERID:
- case RULE_MATCH_AUDIO_SESSION_ID:
- mCriteria.add(new AudioMixMatchCriterion(intProp, rule));
- break;
- default:
- throw new IllegalStateException("Unreachable code in addRuleInternal()");
- }
+ mCriteria.add(criterion);
}
return this;
}
- Builder addRuleFromParcel(Parcel in) throws IllegalArgumentException {
- final int rule = in.readInt();
- final int match_rule = rule & ~RULE_EXCLUSION_MASK;
- AudioAttributes attr = null;
- Integer intProp = null;
- switch (match_rule) {
- case RULE_MATCH_ATTRIBUTE_USAGE:
- case RULE_MATCH_ATTRIBUTE_CAPTURE_PRESET:
- attr = AudioAttributes.CREATOR.createFromParcel(in);
- break;
- case RULE_MATCH_UID:
- case RULE_MATCH_USERID:
- case RULE_MATCH_AUDIO_SESSION_ID:
- intProp = new Integer(in.readInt());
- break;
- default:
- // assume there was in int value to read as for now they come in pair
- in.readInt();
- throw new IllegalArgumentException("Illegal rule value " + rule + " in parcel");
- }
- return addRuleInternal(attr, intProp, rule);
- }
-
/**
* Combines all of the matching and exclusion rules that have been set and return a new
* {@link AudioMixingRule} object.
@@ -717,4 +735,52 @@ public class AudioMixingRule {
mVoiceCommunicationCaptureAllowed);
}
}
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(@NonNull Parcel dest, int flags) {
+ // write opt-out respect
+ dest.writeBoolean(mAllowPrivilegedPlaybackCapture);
+ // write voice communication capture allowed flag
+ dest.writeBoolean(mVoiceCommunicationCaptureAllowed);
+ // write specified mix type
+ dest.writeInt(mTargetMixType);
+ // write mix rules
+ dest.writeInt(mCriteria.size());
+ for (AudioMixingRule.AudioMixMatchCriterion criterion : mCriteria) {
+ criterion.writeToParcel(dest, flags);
+ }
+ }
+
+ public static final @NonNull Parcelable.Creator<AudioMixingRule> CREATOR =
+ new Parcelable.Creator<>() {
+
+ @Override
+ public AudioMixingRule createFromParcel(Parcel source) {
+ AudioMixingRule.Builder ruleBuilder = new AudioMixingRule.Builder();
+ // read opt-out respect
+ ruleBuilder.allowPrivilegedPlaybackCapture(source.readBoolean());
+ // read voice capture allowed flag
+ ruleBuilder.voiceCommunicationCaptureAllowed(source.readBoolean());
+ // read specified mix type
+ ruleBuilder.setTargetMixRole(source.readInt());
+ // read mix rules
+ int nbRules = source.readInt();
+ for (int j = 0; j < nbRules; j++) {
+ // read the matching rules
+ ruleBuilder.addRuleInternal(
+ AudioMixMatchCriterion.CREATOR.createFromParcel(source));
+ }
+ return ruleBuilder.build();
+ }
+
+ @Override
+ public AudioMixingRule[] newArray(int size) {
+ return new AudioMixingRule[size];
+ }
+ };
}
diff --git a/media/java/android/media/audiopolicy/AudioPolicy.java b/media/java/android/media/audiopolicy/AudioPolicy.java
index 3e5de821b47d..e9a6ed4dcf08 100644
--- a/media/java/android/media/audiopolicy/AudioPolicy.java
+++ b/media/java/android/media/audiopolicy/AudioPolicy.java
@@ -44,6 +44,7 @@ import android.os.Message;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.util.Log;
+import android.util.Pair;
import android.util.Slog;
import com.android.internal.annotations.GuardedBy;
@@ -408,6 +409,39 @@ public class AudioPolicy {
}
/**
+ * Update {@link AudioMixingRule}-s of already registered {@link AudioMix}-es.
+ *
+ * @param mixingRuleUpdates - {@link List} of {@link Pair}-s, each pair containing
+ * {@link AudioMix} to update and its new corresponding {@link AudioMixingRule}.
+ *
+ * @return {@link AudioManager#SUCCESS} if the update was successful,
+ * {@link AudioManager#ERROR} otherwise.
+ */
+ @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING)
+ public int updateMixingRules(
+ @NonNull List<Pair<AudioMix, AudioMixingRule>> mixingRuleUpdates) {
+ Objects.requireNonNull(mixingRuleUpdates);
+
+ IAudioService service = getService();
+ try {
+ synchronized (mLock) {
+ final int status = service.updateMixingRulesForPolicy(
+ mixingRuleUpdates.stream().map(p -> p.first).toArray(AudioMix[]::new),
+ mixingRuleUpdates.stream().map(p -> p.second).toArray(
+ AudioMixingRule[]::new),
+ cb());
+ if (status == AudioManager.SUCCESS) {
+ mConfig.updateMixingRules(mixingRuleUpdates);
+ }
+ return status;
+ }
+ } catch (RemoteException e) {
+ Log.e(TAG, "Received remote exeception in updateMixingRules call: ", e);
+ return AudioManager.ERROR;
+ }
+ }
+
+ /**
* @hide
* Configures the audio framework so that all audio streams originating from the given UID
* can only come from a set of audio devices.
diff --git a/media/java/android/media/audiopolicy/AudioPolicyConfig.java b/media/java/android/media/audiopolicy/AudioPolicyConfig.java
index 7a85d21bf144..d277c7dfbea4 100644
--- a/media/java/android/media/audiopolicy/AudioPolicyConfig.java
+++ b/media/java/android/media/audiopolicy/AudioPolicyConfig.java
@@ -17,16 +17,17 @@
package android.media.audiopolicy;
import android.annotation.NonNull;
-import android.media.AudioFormat;
import android.media.audiopolicy.AudioMixingRule.AudioMixMatchCriterion;
import android.os.Parcel;
import android.os.Parcelable;
import android.util.Log;
+import android.util.Pair;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import java.util.ArrayList;
+import java.util.List;
import java.util.Objects;
/**
@@ -85,72 +86,20 @@ public class AudioPolicyConfig implements Parcelable {
public void writeToParcel(Parcel dest, int flags) {
dest.writeInt(mMixes.size());
for (AudioMix mix : mMixes) {
- // write mix route flags
- dest.writeInt(mix.getRouteFlags());
- // write callback flags
- dest.writeInt(mix.mCallbackFlags);
- // write device information
- dest.writeInt(mix.mDeviceSystemType);
- dest.writeString(mix.mDeviceAddress);
- // write mix format
- dest.writeInt(mix.getFormat().getSampleRate());
- dest.writeInt(mix.getFormat().getEncoding());
- dest.writeInt(mix.getFormat().getChannelMask());
- // write opt-out respect
- dest.writeBoolean(mix.getRule().allowPrivilegedMediaPlaybackCapture());
- // write voice communication capture allowed flag
- dest.writeBoolean(mix.getRule().voiceCommunicationCaptureAllowed());
- // write specified mix type
- dest.writeInt(mix.getRule().getTargetMixRole());
- // write mix rules
- final ArrayList<AudioMixMatchCriterion> criteria = mix.getRule().getCriteria();
- dest.writeInt(criteria.size());
- for (AudioMixMatchCriterion criterion : criteria) {
- criterion.writeToParcel(dest);
- }
+ mix.writeToParcel(dest, flags);
}
}
private AudioPolicyConfig(Parcel in) {
- mMixes = new ArrayList<AudioMix>();
int nbMixes = in.readInt();
+ mMixes = new ArrayList<>(nbMixes);
for (int i = 0 ; i < nbMixes ; i++) {
- final AudioMix.Builder mixBuilder = new AudioMix.Builder();
- // read mix route flags
- int routeFlags = in.readInt();
- mixBuilder.setRouteFlags(routeFlags);
- // read callback flags
- mixBuilder.setCallbackFlags(in.readInt());
- // read device information
- mixBuilder.setDevice(in.readInt(), in.readString());
- // read mix format
- int sampleRate = in.readInt();
- int encoding = in.readInt();
- int channelMask = in.readInt();
- final AudioFormat format = new AudioFormat.Builder().setSampleRate(sampleRate)
- .setChannelMask(channelMask).setEncoding(encoding).build();
- mixBuilder.setFormat(format);
-
- AudioMixingRule.Builder ruleBuilder = new AudioMixingRule.Builder();
- // read opt-out respect
- ruleBuilder.allowPrivilegedPlaybackCapture(in.readBoolean());
- // read voice capture allowed flag
- ruleBuilder.voiceCommunicationCaptureAllowed(in.readBoolean());
- // read specified mix type
- ruleBuilder.setTargetMixRole(in.readInt());
- // read mix rules
- int nbRules = in.readInt();
- for (int j = 0 ; j < nbRules ; j++) {
- // read the matching rules
- ruleBuilder.addRuleFromParcel(in);
- }
- mixBuilder.setMixingRule(ruleBuilder.build());
- mMixes.add(mixBuilder.build());
+ mMixes.add(AudioMix.CREATOR.createFromParcel(in));
}
}
- public static final @android.annotation.NonNull Parcelable.Creator<AudioPolicyConfig> CREATOR
- = new Parcelable.Creator<AudioPolicyConfig>() {
+ public static final @android.annotation.NonNull Parcelable.Creator<AudioPolicyConfig> CREATOR =
+ new Parcelable.Creator<>() {
/**
* Rebuilds an AudioPolicyConfig previously stored with writeToParcel().
* @param p Parcel object to read the AudioPolicyConfig from
@@ -309,6 +258,23 @@ public class AudioPolicyConfig implements Parcelable {
}
}
+ /**
+ * Update audio mixing rules for already registered {@link AudioMix}-es.
+ *
+ * @param audioMixingRuleUpdates {@link List} of {@link Pair}-s containing {@link AudioMix} to
+ * be updated and the new {@link AudioMixingRule}.
+ */
+ public void updateMixingRules(
+ @NonNull List<Pair<AudioMix, AudioMixingRule>> audioMixingRuleUpdates) {
+ Objects.requireNonNull(audioMixingRuleUpdates).forEach(
+ update -> updateMixingRule(update.first, update.second));
+ }
+
+ private void updateMixingRule(AudioMix audioMixToUpdate, AudioMixingRule audioMixingRule) {
+ mMixes.stream().filter(audioMixToUpdate::equals).findAny().ifPresent(
+ mix -> mix.setAudioMixingRule(audioMixingRule));
+ }
+
private static String mixTypeId(int type) {
if (type == AudioMix.MIX_TYPE_PLAYERS) return "p";
else if (type == AudioMix.MIX_TYPE_RECORDERS) return "r";
diff --git a/media/tests/AudioPolicyTest/src/com/android/audiopolicytest/AudioMixUnitTests.java b/media/tests/AudioPolicyTest/src/com/android/audiopolicytest/AudioMixUnitTests.java
deleted file mode 100644
index a26398ac198a..000000000000
--- a/media/tests/AudioPolicyTest/src/com/android/audiopolicytest/AudioMixUnitTests.java
+++ /dev/null
@@ -1,274 +0,0 @@
-/*
- * Copyright (C) 2023 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.audiopolicytest;
-
-import static android.media.AudioFormat.CHANNEL_OUT_MONO;
-import static android.media.AudioFormat.CHANNEL_OUT_STEREO;
-import static android.media.AudioFormat.ENCODING_PCM_16BIT;
-import static android.media.audiopolicy.AudioMixingRule.MIX_ROLE_INJECTOR;
-import static android.media.audiopolicy.AudioMixingRule.MIX_ROLE_PLAYERS;
-import static android.media.audiopolicy.AudioMixingRule.RULE_MATCH_AUDIO_SESSION_ID;
-import static android.media.audiopolicy.AudioMixingRule.RULE_MATCH_UID;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertThrows;
-
-import android.media.AudioFormat;
-import android.media.AudioSystem;
-import android.media.audiopolicy.AudioMix;
-import android.media.audiopolicy.AudioMixingRule;
-import android.media.audiopolicy.AudioPolicyConfig;
-import android.os.Parcel;
-import android.platform.test.annotations.Presubmit;
-
-import androidx.test.ext.junit.runners.AndroidJUnit4;
-
-import com.google.common.testing.EqualsTester;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * Unit tests for AudioMix.
- *
- * Run with "atest AudioMixUnitTests".
- */
-@Presubmit
-@RunWith(AndroidJUnit4.class)
-public class AudioMixUnitTests {
- private static final AudioFormat OUTPUT_FORMAT_STEREO_44KHZ_PCM =
- new AudioFormat.Builder()
- .setSampleRate(44000)
- .setChannelMask(CHANNEL_OUT_STEREO)
- .setEncoding(ENCODING_PCM_16BIT).build();
- private static final AudioFormat OUTPUT_FORMAT_MONO_16KHZ_PCM =
- new AudioFormat.Builder()
- .setSampleRate(16000)
- .setChannelMask(CHANNEL_OUT_MONO)
- .setEncoding(ENCODING_PCM_16BIT).build();
- private static final AudioFormat INPUT_FORMAT_MONO_16KHZ_PCM =
- new AudioFormat.Builder()
- .setSampleRate(16000)
- .setChannelMask(AudioFormat.CHANNEL_IN_MONO)
- .setEncoding(ENCODING_PCM_16BIT).build();
-
- @Test
- public void testEquals() {
- final EqualsTester equalsTester = new EqualsTester();
-
- // --- Equality group 1
- final AudioMix playbackAudioMixWithSessionId42AndUid123 =
- new AudioMix.Builder(new AudioMixingRule.Builder()
- .setTargetMixRole(MIX_ROLE_PLAYERS)
- .addMixRule(RULE_MATCH_AUDIO_SESSION_ID, 42)
- .addMixRule(RULE_MATCH_UID, 123).build())
- .setFormat(OUTPUT_FORMAT_STEREO_44KHZ_PCM)
- .setRouteFlags(AudioMix.ROUTE_FLAG_LOOP_BACK).build();
- final AudioMix playbackAudioMixWithUid123AndSessionId42 =
- new AudioMix.Builder(new AudioMixingRule.Builder()
- .setTargetMixRole(MIX_ROLE_PLAYERS)
- .addMixRule(RULE_MATCH_UID, 123)
- .addMixRule(RULE_MATCH_AUDIO_SESSION_ID, 42).build())
- .setFormat(OUTPUT_FORMAT_STEREO_44KHZ_PCM)
- .setRouteFlags(AudioMix.ROUTE_FLAG_LOOP_BACK).build();
- equalsTester.addEqualityGroup(
- playbackAudioMixWithSessionId42AndUid123,
- playbackAudioMixWithUid123AndSessionId42,
- writeToAndFromParcel(playbackAudioMixWithSessionId42AndUid123),
- writeToAndFromParcel(playbackAudioMixWithUid123AndSessionId42));
-
- // --- Equality group 2
- final AudioMix recordingAudioMixWithSessionId42AndUid123 =
- new AudioMix.Builder(new AudioMixingRule.Builder()
- .setTargetMixRole(MIX_ROLE_INJECTOR)
- .addMixRule(RULE_MATCH_AUDIO_SESSION_ID, 42)
- .addMixRule(RULE_MATCH_UID, 123).build())
- .setFormat(INPUT_FORMAT_MONO_16KHZ_PCM)
- .setRouteFlags(AudioMix.ROUTE_FLAG_LOOP_BACK).build();
- final AudioMix recordingAudioMixWithUid123AndSessionId42 =
- new AudioMix.Builder(new AudioMixingRule.Builder()
- .setTargetMixRole(MIX_ROLE_INJECTOR)
- .addMixRule(RULE_MATCH_AUDIO_SESSION_ID, 42)
- .addMixRule(RULE_MATCH_UID, 123).build())
- .setFormat(INPUT_FORMAT_MONO_16KHZ_PCM)
- .setRouteFlags(AudioMix.ROUTE_FLAG_LOOP_BACK).build();
- equalsTester.addEqualityGroup(recordingAudioMixWithSessionId42AndUid123,
- recordingAudioMixWithUid123AndSessionId42,
- writeToAndFromParcel(recordingAudioMixWithSessionId42AndUid123),
- writeToAndFromParcel(recordingAudioMixWithUid123AndSessionId42));
-
- // --- Equality group 3
- final AudioMix recordingAudioMixWithSessionId42AndUid123Render =
- new AudioMix.Builder(new AudioMixingRule.Builder()
- .setTargetMixRole(MIX_ROLE_PLAYERS)
- .addMixRule(RULE_MATCH_AUDIO_SESSION_ID, 42)
- .addMixRule(RULE_MATCH_UID, 123).build())
- .setFormat(INPUT_FORMAT_MONO_16KHZ_PCM)
- .setRouteFlags(
- AudioMix.ROUTE_FLAG_LOOP_BACK | AudioMix.ROUTE_FLAG_RENDER).build();
- equalsTester.addEqualityGroup(recordingAudioMixWithSessionId42AndUid123Render,
- writeToAndFromParcel(recordingAudioMixWithSessionId42AndUid123Render));
-
- // --- Equality group 4
- final AudioMix playbackAudioMixWithUid123 =
- new AudioMix.Builder(new AudioMixingRule.Builder()
- .setTargetMixRole(MIX_ROLE_PLAYERS)
- .addMixRule(RULE_MATCH_UID, 123).build())
- .setFormat(OUTPUT_FORMAT_MONO_16KHZ_PCM)
- .setRouteFlags(AudioMix.ROUTE_FLAG_LOOP_BACK).build();
- equalsTester.addEqualityGroup(playbackAudioMixWithUid123,
- writeToAndFromParcel(playbackAudioMixWithUid123));
-
- // --- Equality group 5
- final AudioMix playbackAudioMixWithUid42 =
- new AudioMix.Builder(new AudioMixingRule.Builder()
- .setTargetMixRole(MIX_ROLE_PLAYERS)
- .addMixRule(RULE_MATCH_UID, 42).build())
- .setFormat(OUTPUT_FORMAT_MONO_16KHZ_PCM)
- .setRouteFlags(AudioMix.ROUTE_FLAG_LOOP_BACK).build();
- equalsTester.addEqualityGroup(playbackAudioMixWithUid42,
- writeToAndFromParcel(playbackAudioMixWithUid42));
-
- equalsTester.testEquals();
- }
-
- @Test
- public void buildRenderToRemoteSubmix_success() {
- final String deviceAddress = "address";
- final AudioMix audioMix = new AudioMix.Builder(new AudioMixingRule.Builder()
- .setTargetMixRole(MIX_ROLE_PLAYERS)
- .addMixRule(RULE_MATCH_UID, 42).build())
- .setFormat(OUTPUT_FORMAT_MONO_16KHZ_PCM)
- .setRouteFlags(AudioMix.ROUTE_FLAG_RENDER)
- .setDevice(AudioSystem.DEVICE_OUT_REMOTE_SUBMIX, /*address=*/deviceAddress).build();
-
- assertEquals(deviceAddress, audioMix.getRegistration());
- assertEquals(OUTPUT_FORMAT_MONO_16KHZ_PCM, audioMix.getFormat());
- assertEquals(AudioMix.ROUTE_FLAG_RENDER, audioMix.getRouteFlags());
- }
-
- @Test
- public void buildLoopbackAndRenderToRemoteSubmix_success() {
- final String deviceAddress = "address";
- final AudioMix audioMix = new AudioMix.Builder(new AudioMixingRule.Builder()
- .setTargetMixRole(MIX_ROLE_PLAYERS)
- .addMixRule(RULE_MATCH_UID, 42).build())
- .setFormat(OUTPUT_FORMAT_MONO_16KHZ_PCM)
- .setRouteFlags(AudioMix.ROUTE_FLAG_LOOP_BACK_RENDER)
- .setDevice(AudioSystem.DEVICE_OUT_REMOTE_SUBMIX, /*address=*/deviceAddress).build();
-
- assertEquals(deviceAddress, audioMix.getRegistration());
- assertEquals(OUTPUT_FORMAT_MONO_16KHZ_PCM, audioMix.getFormat());
- assertEquals(AudioMix.ROUTE_FLAG_LOOP_BACK_RENDER, audioMix.getRouteFlags());
- }
-
- @Test
- public void buildRenderToSpeaker_success() {
- final AudioMix audioMix = new AudioMix.Builder(new AudioMixingRule.Builder()
- .setTargetMixRole(MIX_ROLE_PLAYERS)
- .addMixRule(RULE_MATCH_UID, 42).build())
- .setFormat(OUTPUT_FORMAT_MONO_16KHZ_PCM)
- .setRouteFlags(AudioMix.ROUTE_FLAG_RENDER)
- .setDevice(AudioSystem.DEVICE_OUT_SPEAKER, /*address=*/"").build();
-
- assertEquals(OUTPUT_FORMAT_MONO_16KHZ_PCM, audioMix.getFormat());
- assertEquals(AudioMix.ROUTE_FLAG_RENDER, audioMix.getRouteFlags());
- }
-
- @Test
- public void buildLoopbackForPlayerMix_success() {
- final AudioMix audioMix = new AudioMix.Builder(new AudioMixingRule.Builder()
- .setTargetMixRole(MIX_ROLE_PLAYERS)
- .addMixRule(RULE_MATCH_UID, 42).build())
- .setFormat(OUTPUT_FORMAT_MONO_16KHZ_PCM)
- .setRouteFlags(AudioMix.ROUTE_FLAG_LOOP_BACK).build();
-
- assertEquals(OUTPUT_FORMAT_MONO_16KHZ_PCM, audioMix.getFormat());
- assertEquals(AudioMix.ROUTE_FLAG_LOOP_BACK, audioMix.getRouteFlags());
- }
-
- @Test
- public void buildLoopbackForInjectorMix_success() {
- final AudioMix audioMix = new AudioMix.Builder(new AudioMixingRule.Builder()
- .setTargetMixRole(MIX_ROLE_INJECTOR)
- .addMixRule(RULE_MATCH_UID, 42).build())
- .setFormat(OUTPUT_FORMAT_MONO_16KHZ_PCM)
- .setRouteFlags(AudioMix.ROUTE_FLAG_LOOP_BACK).build();
-
- assertEquals(OUTPUT_FORMAT_MONO_16KHZ_PCM, audioMix.getFormat());
- assertEquals(AudioMix.ROUTE_FLAG_LOOP_BACK, audioMix.getRouteFlags());
- }
-
- @Test
- public void buildLoopbackWithIncompatibleDevice_throws() {
- assertThrows(IllegalArgumentException.class, () -> new AudioMix.Builder(
- new AudioMixingRule.Builder()
- .setTargetMixRole(MIX_ROLE_PLAYERS)
- .addMixRule(RULE_MATCH_UID, 42).build())
- .setFormat(OUTPUT_FORMAT_MONO_16KHZ_PCM)
- .setRouteFlags(AudioMix.ROUTE_FLAG_LOOP_BACK)
- .setDevice(AudioSystem.DEVICE_OUT_SPEAKER, /*address=*/"").build());
- }
-
- @Test
- public void buildRenderWithoutDevice_throws() {
- assertThrows(IllegalArgumentException.class, () -> new AudioMix.Builder(
- new AudioMixingRule.Builder()
- .setTargetMixRole(MIX_ROLE_PLAYERS)
- .addMixRule(RULE_MATCH_UID, 42).build())
- .setFormat(OUTPUT_FORMAT_MONO_16KHZ_PCM)
- .setRouteFlags(AudioMix.ROUTE_FLAG_RENDER).build());
- }
-
- @Test
- public void buildRenderWithInputDevice_throws() {
- assertThrows(IllegalArgumentException.class, () -> new AudioMix.Builder(
- new AudioMixingRule.Builder()
- .setTargetMixRole(MIX_ROLE_PLAYERS)
- .addMixRule(RULE_MATCH_UID, 42).build())
- .setFormat(OUTPUT_FORMAT_MONO_16KHZ_PCM)
- .setRouteFlags(AudioMix.ROUTE_FLAG_RENDER)
- .setDevice(AudioSystem.DEVICE_IN_BUILTIN_MIC, /*address=*/"").build());
- }
-
- @Test
- public void buildRenderWithInjectorMix_throws() {
- assertThrows(IllegalArgumentException.class, () -> new AudioMix.Builder(
- new AudioMixingRule.Builder()
- .setTargetMixRole(MIX_ROLE_INJECTOR)
- .addMixRule(RULE_MATCH_UID, 42).build())
- .setFormat(OUTPUT_FORMAT_MONO_16KHZ_PCM)
- .setRouteFlags(AudioMix.ROUTE_FLAG_RENDER)
- .setDevice(AudioSystem.DEVICE_OUT_SPEAKER, /*address=*/"").build());
- }
-
-
-
- private static AudioMix writeToAndFromParcel(AudioMix audioMix) {
- AudioPolicyConfig apc = new AudioPolicyConfig(new ArrayList<>(List.of(audioMix)));
- Parcel parcel = Parcel.obtain();
- apc.writeToParcel(parcel, /*flags=*/0);
- parcel.setDataPosition(0);
- AudioMix unmarshalledMix =
- AudioPolicyConfig.CREATOR.createFromParcel(parcel).getMixes().get(0);
- parcel.recycle();
- return unmarshalledMix;
- }
-}
diff --git a/media/tests/AudioPolicyTest/src/com/android/audiopolicytest/AudioMixingRuleUnitTests.java b/media/tests/AudioPolicyTest/src/com/android/audiopolicytest/AudioMixingRuleUnitTests.java
deleted file mode 100644
index 3cbfd50ff859..000000000000
--- a/media/tests/AudioPolicyTest/src/com/android/audiopolicytest/AudioMixingRuleUnitTests.java
+++ /dev/null
@@ -1,322 +0,0 @@
-/*
- * Copyright (C) 2022 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.audiopolicytest;
-
-import static android.media.AudioAttributes.USAGE_MEDIA;
-import static android.media.MediaRecorder.AudioSource.VOICE_RECOGNITION;
-import static android.media.audiopolicy.AudioMixingRule.MIX_ROLE_INJECTOR;
-import static android.media.audiopolicy.AudioMixingRule.MIX_ROLE_PLAYERS;
-import static android.media.audiopolicy.AudioMixingRule.RULE_EXCLUDE_ATTRIBUTE_CAPTURE_PRESET;
-import static android.media.audiopolicy.AudioMixingRule.RULE_EXCLUDE_ATTRIBUTE_USAGE;
-import static android.media.audiopolicy.AudioMixingRule.RULE_EXCLUDE_AUDIO_SESSION_ID;
-import static android.media.audiopolicy.AudioMixingRule.RULE_EXCLUDE_UID;
-import static android.media.audiopolicy.AudioMixingRule.RULE_MATCH_ATTRIBUTE_CAPTURE_PRESET;
-import static android.media.audiopolicy.AudioMixingRule.RULE_MATCH_ATTRIBUTE_USAGE;
-import static android.media.audiopolicy.AudioMixingRule.RULE_MATCH_AUDIO_SESSION_ID;
-import static android.media.audiopolicy.AudioMixingRule.RULE_MATCH_UID;
-
-import static org.hamcrest.MatcherAssert.assertThat;
-import static org.hamcrest.collection.IsCollectionWithSize.hasSize;
-import static org.hamcrest.collection.IsIterableContainingInAnyOrder.containsInAnyOrder;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertThrows;
-
-
-import android.media.AudioAttributes;
-import android.media.audiopolicy.AudioMixingRule;
-import android.media.audiopolicy.AudioMixingRule.AudioMixMatchCriterion;
-import android.platform.test.annotations.Presubmit;
-
-import androidx.test.ext.junit.runners.AndroidJUnit4;
-
-import org.hamcrest.CustomTypeSafeMatcher;
-import org.hamcrest.Description;
-import org.hamcrest.Matcher;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-/**
- * Unit tests for AudioPolicy.
- *
- * Run with "atest AudioMixingRuleUnitTests".
- */
-@Presubmit
-@RunWith(AndroidJUnit4.class)
-public class AudioMixingRuleUnitTests {
- private static final AudioAttributes USAGE_MEDIA_AUDIO_ATTRIBUTES =
- new AudioAttributes.Builder().setUsage(USAGE_MEDIA).build();
- private static final AudioAttributes CAPTURE_PRESET_VOICE_RECOGNITION_AUDIO_ATTRIBUTES =
- new AudioAttributes.Builder().setCapturePreset(VOICE_RECOGNITION).build();
- private static final int TEST_UID = 42;
- private static final int OTHER_UID = 77;
- private static final int TEST_SESSION_ID = 1234;
-
- @Test
- public void testConstructValidRule() {
- AudioMixingRule rule = new AudioMixingRule.Builder()
- .addMixRule(RULE_MATCH_ATTRIBUTE_USAGE, USAGE_MEDIA_AUDIO_ATTRIBUTES)
- .addMixRule(RULE_MATCH_UID, TEST_UID)
- .excludeMixRule(RULE_MATCH_AUDIO_SESSION_ID, TEST_SESSION_ID)
- .build();
-
- // Based on the rules, the mix type should fall back to MIX_ROLE_PLAYERS,
- // since the rules are valid for both MIX_ROLE_PLAYERS & MIX_ROLE_INJECTOR.
- assertEquals(rule.getTargetMixRole(), MIX_ROLE_PLAYERS);
- assertThat(rule.getCriteria(), containsInAnyOrder(
- isAudioMixMatchUsageCriterion(USAGE_MEDIA),
- isAudioMixMatchUidCriterion(TEST_UID),
- isAudioMixExcludeSessionCriterion(TEST_SESSION_ID)));
- }
-
- @Test
- public void testConstructRuleWithConflictingCriteriaFails() {
- assertThrows(IllegalArgumentException.class,
- () -> new AudioMixingRule.Builder()
- .addMixRule(RULE_MATCH_ATTRIBUTE_USAGE, USAGE_MEDIA_AUDIO_ATTRIBUTES)
- .addMixRule(RULE_MATCH_UID, TEST_UID)
- // Conflicts with previous criterion.
- .addMixRule(RULE_EXCLUDE_UID, OTHER_UID)
- .build());
- }
-
- @Test
- public void testRuleBuilderDedupsCriteria() {
- AudioMixingRule rule = new AudioMixingRule.Builder()
- .addMixRule(RULE_MATCH_ATTRIBUTE_USAGE, USAGE_MEDIA_AUDIO_ATTRIBUTES)
- .addMixRule(RULE_MATCH_UID, TEST_UID)
- // Identical to previous criterion.
- .addMixRule(RULE_MATCH_UID, TEST_UID)
- // Identical to first criterion.
- .addMixRule(RULE_MATCH_ATTRIBUTE_USAGE, USAGE_MEDIA_AUDIO_ATTRIBUTES)
- .build();
-
- assertThat(rule.getCriteria(), hasSize(2));
- assertThat(rule.getCriteria(), containsInAnyOrder(
- isAudioMixMatchUsageCriterion(USAGE_MEDIA),
- isAudioMixMatchUidCriterion(TEST_UID)));
- }
-
- @Test
- public void failsWhenAddAttributeRuleCalledWithInvalidType() {
- assertThrows(IllegalArgumentException.class,
- () -> new AudioMixingRule.Builder()
- // Rule match attribute usage requires AudioAttributes, not
- // just the int enum value of the usage.
- .addMixRule(RULE_MATCH_ATTRIBUTE_USAGE, USAGE_MEDIA)
- .build());
- }
-
- @Test
- public void failsWhenExcludeAttributeRuleCalledWithInvalidType() {
- assertThrows(IllegalArgumentException.class,
- () -> new AudioMixingRule.Builder()
- // Rule match attribute usage requires AudioAttributes, not
- // just the int enum value of the usage.
- .excludeMixRule(RULE_MATCH_ATTRIBUTE_USAGE, USAGE_MEDIA)
- .build());
- }
-
- @Test
- public void failsWhenAddIntRuleCalledWithInvalidType() {
- assertThrows(IllegalArgumentException.class,
- () -> new AudioMixingRule.Builder()
- // Rule match uid requires Integer not AudioAttributes.
- .addMixRule(RULE_MATCH_UID, USAGE_MEDIA_AUDIO_ATTRIBUTES)
- .build());
- }
-
- @Test
- public void failsWhenExcludeIntRuleCalledWithInvalidType() {
- assertThrows(IllegalArgumentException.class,
- () -> new AudioMixingRule.Builder()
- // Rule match uid requires Integer not AudioAttributes.
- .excludeMixRule(RULE_MATCH_UID, USAGE_MEDIA_AUDIO_ATTRIBUTES)
- .build());
- }
-
- @Test
- public void injectorMixTypeDeductionWithGenericRuleSucceeds() {
- AudioMixingRule rule = new AudioMixingRule.Builder()
- // UID rule can be used both with MIX_ROLE_PLAYERS and MIX_ROLE_INJECTOR.
- .addMixRule(RULE_MATCH_UID, TEST_UID)
- // Capture preset rule is only valid for injector, MIX_ROLE_INJECTOR should
- // be deduced.
- .addMixRule(RULE_MATCH_ATTRIBUTE_CAPTURE_PRESET,
- CAPTURE_PRESET_VOICE_RECOGNITION_AUDIO_ATTRIBUTES)
- .build();
-
- assertEquals(rule.getTargetMixRole(), MIX_ROLE_INJECTOR);
- assertThat(rule.getCriteria(), containsInAnyOrder(
- isAudioMixMatchUidCriterion(TEST_UID),
- isAudioMixMatchCapturePresetCriterion(VOICE_RECOGNITION)));
- }
-
- @Test
- public void settingTheMixTypeToIncompatibleInjectorMixFails() {
- assertThrows(IllegalArgumentException.class,
- () -> new AudioMixingRule.Builder()
- .addMixRule(RULE_MATCH_ATTRIBUTE_CAPTURE_PRESET,
- CAPTURE_PRESET_VOICE_RECOGNITION_AUDIO_ATTRIBUTES)
- // Capture preset cannot be defined for MIX_ROLE_PLAYERS.
- .setTargetMixRole(MIX_ROLE_PLAYERS)
- .build());
- }
-
- @Test
- public void addingPlayersOnlyRuleWithInjectorsOnlyRuleFails() {
- assertThrows(IllegalArgumentException.class,
- () -> new AudioMixingRule.Builder()
- // MIX_ROLE_PLAYERS only rule.
- .addMixRule(RULE_MATCH_ATTRIBUTE_USAGE, USAGE_MEDIA_AUDIO_ATTRIBUTES)
- // MIX ROLE_INJECTOR only rule.
- .addMixRule(RULE_MATCH_ATTRIBUTE_CAPTURE_PRESET,
- CAPTURE_PRESET_VOICE_RECOGNITION_AUDIO_ATTRIBUTES)
- .build());
- }
-
- @Test
- public void sessionIdRuleCompatibleWithPlayersMix() {
- int sessionId = 42;
- AudioMixingRule rule = new AudioMixingRule.Builder()
- .addMixRule(RULE_MATCH_AUDIO_SESSION_ID, sessionId)
- .setTargetMixRole(MIX_ROLE_PLAYERS)
- .build();
-
- assertEquals(rule.getTargetMixRole(), MIX_ROLE_PLAYERS);
- assertThat(rule.getCriteria(), containsInAnyOrder(isAudioMixSessionCriterion(sessionId)));
- }
-
- @Test
- public void sessionIdRuleCompatibleWithInjectorMix() {
- AudioMixingRule rule = new AudioMixingRule.Builder()
- .addMixRule(RULE_MATCH_AUDIO_SESSION_ID, TEST_SESSION_ID)
- .setTargetMixRole(MIX_ROLE_INJECTOR)
- .build();
-
- assertEquals(rule.getTargetMixRole(), MIX_ROLE_INJECTOR);
- assertThat(rule.getCriteria(),
- containsInAnyOrder(isAudioMixSessionCriterion(TEST_SESSION_ID)));
- }
-
- @Test
- public void audioMixingRuleWithNoRulesFails() {
- assertThrows(IllegalArgumentException.class,
- () -> new AudioMixingRule.Builder().build());
- }
-
-
- private static Matcher isAudioMixUidCriterion(int uid, boolean exclude) {
- return new CustomTypeSafeMatcher<AudioMixMatchCriterion>("uid mix criterion") {
- @Override
- public boolean matchesSafely(AudioMixMatchCriterion item) {
- int expectedRule = exclude ? RULE_EXCLUDE_UID : RULE_MATCH_UID;
- return item.getRule() == expectedRule && item.getIntProp() == uid;
- }
-
- @Override
- public void describeMismatchSafely(
- AudioMixMatchCriterion item, Description mismatchDescription) {
- mismatchDescription.appendText(
- String.format("is not %s criterion with uid %d",
- exclude ? "exclude" : "match", uid));
- }
- };
- }
-
- private static Matcher isAudioMixMatchUidCriterion(int uid) {
- return isAudioMixUidCriterion(uid, /*exclude=*/ false);
- }
-
- private static Matcher isAudioMixCapturePresetCriterion(int audioSource, boolean exclude) {
- return new CustomTypeSafeMatcher<AudioMixMatchCriterion>("uid mix criterion") {
- @Override
- public boolean matchesSafely(AudioMixMatchCriterion item) {
- int expectedRule = exclude
- ? RULE_EXCLUDE_ATTRIBUTE_CAPTURE_PRESET
- : RULE_MATCH_ATTRIBUTE_CAPTURE_PRESET;
- AudioAttributes attributes = item.getAudioAttributes();
- return item.getRule() == expectedRule
- && attributes != null && attributes.getCapturePreset() == audioSource;
- }
-
- @Override
- public void describeMismatchSafely(
- AudioMixMatchCriterion item, Description mismatchDescription) {
- mismatchDescription.appendText(
- String.format("is not %s criterion with capture preset %d",
- exclude ? "exclude" : "match", audioSource));
- }
- };
- }
-
- private static Matcher isAudioMixMatchCapturePresetCriterion(int audioSource) {
- return isAudioMixCapturePresetCriterion(audioSource, /*exclude=*/ false);
- }
-
- private static Matcher isAudioMixUsageCriterion(int usage, boolean exclude) {
- return new CustomTypeSafeMatcher<AudioMixMatchCriterion>("usage mix criterion") {
- @Override
- public boolean matchesSafely(AudioMixMatchCriterion item) {
- int expectedRule =
- exclude ? RULE_EXCLUDE_ATTRIBUTE_USAGE : RULE_MATCH_ATTRIBUTE_USAGE;
- AudioAttributes attributes = item.getAudioAttributes();
- return item.getRule() == expectedRule
- && attributes != null && attributes.getUsage() == usage;
- }
-
- @Override
- public void describeMismatchSafely(
- AudioMixMatchCriterion item, Description mismatchDescription) {
- mismatchDescription.appendText(
- String.format("is not %s criterion with usage %d",
- exclude ? "exclude" : "match", usage));
- }
- };
- }
-
- private static Matcher isAudioMixMatchUsageCriterion(int usage) {
- return isAudioMixUsageCriterion(usage, /*exclude=*/ false);
- }
-
- private static Matcher isAudioMixSessionCriterion(int sessionId, boolean exclude) {
- return new CustomTypeSafeMatcher<AudioMixMatchCriterion>("sessionId mix criterion") {
- @Override
- public boolean matchesSafely(AudioMixMatchCriterion item) {
- int excludeRule =
- exclude ? RULE_EXCLUDE_AUDIO_SESSION_ID : RULE_MATCH_AUDIO_SESSION_ID;
- return item.getRule() == excludeRule && item.getIntProp() == sessionId;
- }
-
- @Override
- public void describeMismatchSafely(
- AudioMixMatchCriterion item, Description mismatchDescription) {
- mismatchDescription.appendText(
- String.format("is not %s criterion with session id %d",
- exclude ? "exclude" : "match", sessionId));
- }
- };
- }
-
- private static Matcher isAudioMixSessionCriterion(int sessionId) {
- return isAudioMixSessionCriterion(sessionId, /*exclude=*/ false);
- }
-
- private static Matcher isAudioMixExcludeSessionCriterion(int sessionId) {
- return isAudioMixSessionCriterion(sessionId, /*exclude=*/ true);
- }
-
-}
diff --git a/packages/CompanionDeviceManager/res/values-th/strings.xml b/packages/CompanionDeviceManager/res/values-th/strings.xml
index cb01f2d0d9ac..5d491dba2e9e 100644
--- a/packages/CompanionDeviceManager/res/values-th/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-th/strings.xml
@@ -26,7 +26,7 @@
<string name="profile_name_glasses" msgid="3506504967216601277">"อุปกรณ์"</string>
<string name="summary_glasses" msgid="2872254734959842579">"แอปนี้จะได้รับสิทธิ์ดังต่อไปนี้ใน<xliff:g id="DEVICE_NAME">%1$s</xliff:g>ของคุณ"</string>
<string name="title_app_streaming" msgid="2270331024626446950">"อนุญาตให้ &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; เข้าถึงข้อมูลนี้จากโทรศัพท์ของคุณ"</string>
- <string name="helper_title_app_streaming" msgid="4151687003439969765">"บริการหลายอุปกรณ์"</string>
+ <string name="helper_title_app_streaming" msgid="4151687003439969765">"บริการข้ามอุปกรณ์"</string>
<string name="helper_summary_app_streaming" msgid="2396773196949578425">"<xliff:g id="APP_NAME">%1$s</xliff:g> กำลังขอสิทธิ์ในนามของ <xliff:g id="DISPLAY_NAME">%2$s</xliff:g> เพื่อสตรีมแอประหว่างอุปกรณ์ต่างๆ ของคุณ"</string>
<string name="title_automotive_projection" msgid="3296005598978412847"></string>
<string name="summary_automotive_projection" msgid="8683801274662496164"></string>
diff --git a/packages/CredentialManager/res/values-el/strings.xml b/packages/CredentialManager/res/values-el/strings.xml
index 4d97803f4dbb..8d06765099a9 100644
--- a/packages/CredentialManager/res/values-el/strings.xml
+++ b/packages/CredentialManager/res/values-el/strings.xml
@@ -53,7 +53,7 @@
<string name="save_password_on_other_device_title" msgid="5829084591948321207">"Θέλετε να αποθηκεύσετε τον κωδικό πρόσβασης σε κάποια άλλη συσκευή;"</string>
<string name="save_sign_in_on_other_device_title" msgid="2827990118560134692">"Θέλετε να αποθηκεύσετε τα στοιχεία σύνδεσης σε κάποια άλλη συσκευή;"</string>
<string name="use_provider_for_all_title" msgid="4201020195058980757">"Να χρησιμοποιηθεί το <xliff:g id="PROVIDERINFODISPLAYNAME">%1$s</xliff:g> για όλες τις συνδέσεις σας;"</string>
- <string name="use_provider_for_all_description" msgid="1998772715863958997">"Αυτός ο διαχειριστής κωδικών πρόσβασης για τον χρήστη <xliff:g id="USERNAME">%1$s</xliff:g> θα αποθηκεύει τους κωδικούς πρόσβασης και τα κλειδιά πρόσβασης, για πιο εύκολη πρόσβαση"</string>
+ <string name="use_provider_for_all_description" msgid="1998772715863958997">"Αυτός ο διαχειριστής κωδικών πρόσβασης για τον χρήστη <xliff:g id="USERNAME">%1$s</xliff:g> θα αποθηκεύει τους κωδικούς και τα κλειδιά πρόσβασης, για πιο εύκολη σύνδεση"</string>
<string name="set_as_default" msgid="4415328591568654603">"Ορισμός ως προεπιλογής"</string>
<string name="settings" msgid="6536394145760913145">"Ρυθμίσεις"</string>
<string name="use_once" msgid="9027366575315399714">"Χρήση μία φορά"</string>
diff --git a/packages/CredentialManager/res/values-fa/strings.xml b/packages/CredentialManager/res/values-fa/strings.xml
index 88afea4d1641..a6e0d3d11eee 100644
--- a/packages/CredentialManager/res/values-fa/strings.xml
+++ b/packages/CredentialManager/res/values-fa/strings.xml
@@ -56,7 +56,7 @@
<string name="use_provider_for_all_description" msgid="1998772715863958997">"این مدیر گذرواژه برای <xliff:g id="USERNAME">%1$s</xliff:g> گذرکلیدها و گذرواژه‌های شما را ذخیره می‌کند تا به‌راحتی بتوانید به سیستم وارد شوید"</string>
<string name="set_as_default" msgid="4415328591568654603">"تنظیم به‌عنوان پیش‌فرض"</string>
<string name="settings" msgid="6536394145760913145">"تنظیمات"</string>
- <string name="use_once" msgid="9027366575315399714">"یک‌بار استفاده"</string>
+ <string name="use_once" msgid="9027366575315399714">"این بار استفاده شود"</string>
<string name="more_options_usage_passwords_passkeys" msgid="3470113942332934279">"<xliff:g id="PASSWORDSNUMBER">%1$s</xliff:g> گذرواژه • <xliff:g id="PASSKEYSNUMBER">%2$s</xliff:g> گذرکلید"</string>
<string name="more_options_usage_passwords" msgid="1632047277723187813">"<xliff:g id="PASSWORDSNUMBER">%1$s</xliff:g> گذرواژه"</string>
<string name="more_options_usage_passkeys" msgid="5390320437243042237">"<xliff:g id="PASSKEYSNUMBER">%1$s</xliff:g> گذرکلید"</string>
diff --git a/packages/CredentialManager/res/values-hi/strings.xml b/packages/CredentialManager/res/values-hi/strings.xml
index d986a935fad4..05d21e013d27 100644
--- a/packages/CredentialManager/res/values-hi/strings.xml
+++ b/packages/CredentialManager/res/values-hi/strings.xml
@@ -56,7 +56,7 @@
<string name="use_provider_for_all_description" msgid="1998772715863958997">"<xliff:g id="USERNAME">%1$s</xliff:g> के लिए यह पासवर्ड मैनेजर, आपके पासवर्ड और पासकी सेव करेगा, ताकि आपको साइन इन करने में आसानी हो"</string>
<string name="set_as_default" msgid="4415328591568654603">"डिफ़ॉल्ट के तौर पर सेट करें"</string>
<string name="settings" msgid="6536394145760913145">"सेटिंग"</string>
- <string name="use_once" msgid="9027366575315399714">"इसका इस्तेमाल एक बार किया जा सकता है"</string>
+ <string name="use_once" msgid="9027366575315399714">"एक बार इस्तेमाल करें"</string>
<string name="more_options_usage_passwords_passkeys" msgid="3470113942332934279">"<xliff:g id="PASSWORDSNUMBER">%1$s</xliff:g> पासवर्ड • <xliff:g id="PASSKEYSNUMBER">%2$s</xliff:g> पासकी"</string>
<string name="more_options_usage_passwords" msgid="1632047277723187813">"<xliff:g id="PASSWORDSNUMBER">%1$s</xliff:g> पासवर्ड"</string>
<string name="more_options_usage_passkeys" msgid="5390320437243042237">"<xliff:g id="PASSKEYSNUMBER">%1$s</xliff:g> पासकी"</string>
diff --git a/packages/CredentialManager/res/values-ka/strings.xml b/packages/CredentialManager/res/values-ka/strings.xml
index b597a9a227eb..ed42f3afcfe0 100644
--- a/packages/CredentialManager/res/values-ka/strings.xml
+++ b/packages/CredentialManager/res/values-ka/strings.xml
@@ -52,7 +52,7 @@
<string name="create_passkey_in_other_device_title" msgid="2360053098931886245">"გსურთ სხვა მოწყობილობაზე წვდომის გასაღებების შექმნა?"</string>
<string name="save_password_on_other_device_title" msgid="5829084591948321207">"გსურთ სხვა მოწყობილობაზე პაროლის შენახვა?"</string>
<string name="save_sign_in_on_other_device_title" msgid="2827990118560134692">"გსურთ სხვა მოწყობილობაზე ავტორიზაციის მონაცემების შენახვა?"</string>
- <string name="use_provider_for_all_title" msgid="4201020195058980757">"გსურთ, გამოიყენოთ<xliff:g id="PROVIDERINFODISPLAYNAME">%1$s</xliff:g> სისტემაში ყველა შესვლისთვის?"</string>
+ <string name="use_provider_for_all_title" msgid="4201020195058980757">"გსურთ, გამოიყენოთ <xliff:g id="PROVIDERINFODISPLAYNAME">%1$s</xliff:g> სისტემაში ყველა შესვლისთვის?"</string>
<string name="use_provider_for_all_description" msgid="1998772715863958997">"მოცემული პაროლების მმართველი <xliff:g id="USERNAME">%1$s</xliff:g>-ისთვის შეინახავს თქვენს პაროლებს და წვდომის გასაღებს, რომლებიც დაგეხმარებათ სისტემაში მარტივად შესვლაში"</string>
<string name="set_as_default" msgid="4415328591568654603">"ნაგულისხმევად დაყენება"</string>
<string name="settings" msgid="6536394145760913145">"პარამეტრები"</string>
diff --git a/packages/CredentialManager/res/values-kn/strings.xml b/packages/CredentialManager/res/values-kn/strings.xml
index ae680a068933..7447ab629f72 100644
--- a/packages/CredentialManager/res/values-kn/strings.xml
+++ b/packages/CredentialManager/res/values-kn/strings.xml
@@ -52,7 +52,7 @@
<string name="create_passkey_in_other_device_title" msgid="2360053098931886245">"ಇನ್ನೊಂದು ಸಾಧನದಲ್ಲಿ ಪಾಸ್‌ಕೀ ಅನ್ನು ರಚಿಸಬೇಕೆ?"</string>
<string name="save_password_on_other_device_title" msgid="5829084591948321207">"ಇನ್ನೊಂದು ಸಾಧನದಲ್ಲಿ ಪಾಸ್‌ವರ್ಡ್ ಉಳಿಸಬೇಕೆ?"</string>
<string name="save_sign_in_on_other_device_title" msgid="2827990118560134692">"ಮತ್ತೊಂದು ಸಾಧನದಲ್ಲಿ ಸೈನ್-ಇನ್ ಅನ್ನು ಉಳಿಸಬೇಕೆ?"</string>
- <string name="use_provider_for_all_title" msgid="4201020195058980757">"ನಿಮ್ಮ ಎಲ್ಲಾ ಸೈನ್-ಇನ್‌ಗಳಿಗಾಗಿ <xliff:g id="PROVIDERINFODISPLAYNAME">%1$s</xliff:g> ಅನ್ನು ಬಳಸುವುದೇ?"</string>
+ <string name="use_provider_for_all_title" msgid="4201020195058980757">"ನಿಮ್ಮ ಎಲ್ಲಾ ಸೈನ್-ಇನ್‌ಗಳಿಗಾಗಿ <xliff:g id="PROVIDERINFODISPLAYNAME">%1$s</xliff:g> ಅನ್ನು ಬಳಸಬೇಕೇ?"</string>
<string name="use_provider_for_all_description" msgid="1998772715863958997">"<xliff:g id="USERNAME">%1$s</xliff:g> ಗಾಗಿ ಈ ಪಾಸ್‌ವರ್ಡ್ ನಿರ್ವಾಹಕವು ನಿಮಗೆ ಸುಲಭವಾಗಿ ಸೈನ್ ಇನ್ ಮಾಡುವುದಕ್ಕೆ ಸಹಾಯ ಮಾಡಲು ನಿಮ್ಮ ಪಾಸ್‌ವರ್ಡ್‌ಗಳು ಮತ್ತು ಪಾಸ್‌ಕೀಗಳನ್ನು ಸಂಗ್ರಹಿಸುತ್ತದೆ"</string>
<string name="set_as_default" msgid="4415328591568654603">"ಡೀಫಾಲ್ಟ್ ಆಗಿ ಸೆಟ್ ಮಾಡಿ"</string>
<string name="settings" msgid="6536394145760913145">"ಸೆಟ್ಟಿಂಗ್‌ಗಳು"</string>
diff --git a/packages/CredentialManager/res/values-lt/strings.xml b/packages/CredentialManager/res/values-lt/strings.xml
index d5f5f7f10578..c3b941bfa10e 100644
--- a/packages/CredentialManager/res/values-lt/strings.xml
+++ b/packages/CredentialManager/res/values-lt/strings.xml
@@ -52,7 +52,7 @@
<string name="create_passkey_in_other_device_title" msgid="2360053098931886245">"Sukurti „passkey“ kitame įrenginyje?"</string>
<string name="save_password_on_other_device_title" msgid="5829084591948321207">"Išsaugoti slaptažodį kitame įrenginyje?"</string>
<string name="save_sign_in_on_other_device_title" msgid="2827990118560134692">"Išsaugoti prisijungimo duomenis kitame įrenginyje?"</string>
- <string name="use_provider_for_all_title" msgid="4201020195058980757">"Naudoti <xliff:g id="PROVIDERINFODISPLAYNAME">%1$s</xliff:g> visada prisijungiant?"</string>
+ <string name="use_provider_for_all_title" msgid="4201020195058980757">"Naudoti „<xliff:g id="PROVIDERINFODISPLAYNAME">%1$s</xliff:g>“ visada prisijungiant?"</string>
<string name="use_provider_for_all_description" msgid="1998772715863958997">"Šioje <xliff:g id="USERNAME">%1$s</xliff:g> Slaptažodžių tvarkyklėje bus saugomi jūsų slaptažodžiai ir prieigos raktai, kad galėtumėte lengvai prisijungti"</string>
<string name="set_as_default" msgid="4415328591568654603">"Nustatyti kaip numatytąjį"</string>
<string name="settings" msgid="6536394145760913145">"Nustatymai"</string>
diff --git a/packages/CredentialManager/res/values-mk/strings.xml b/packages/CredentialManager/res/values-mk/strings.xml
index 0755c9cdfa48..1f456bfd392f 100644
--- a/packages/CredentialManager/res/values-mk/strings.xml
+++ b/packages/CredentialManager/res/values-mk/strings.xml
@@ -56,7 +56,7 @@
<string name="use_provider_for_all_description" msgid="1998772715863958997">"Овој управник со лозинки за <xliff:g id="USERNAME">%1$s</xliff:g> ќе ги складира вашите лозинки и криптографски клучеви за да ви помогне лесно да се најавите"</string>
<string name="set_as_default" msgid="4415328591568654603">"Постави како стандардна опција"</string>
<string name="settings" msgid="6536394145760913145">"Поставки"</string>
- <string name="use_once" msgid="9027366575315399714">"Употребете еднаш"</string>
+ <string name="use_once" msgid="9027366575315399714">"Употреби го еднаш"</string>
<string name="more_options_usage_passwords_passkeys" msgid="3470113942332934279">"Лозинки: <xliff:g id="PASSWORDSNUMBER">%1$s</xliff:g> • Криптографски клучеви: <xliff:g id="PASSKEYSNUMBER">%2$s</xliff:g>"</string>
<string name="more_options_usage_passwords" msgid="1632047277723187813">"<xliff:g id="PASSWORDSNUMBER">%1$s</xliff:g> лозинки"</string>
<string name="more_options_usage_passkeys" msgid="5390320437243042237">"Криптографски клучеви: <xliff:g id="PASSKEYSNUMBER">%1$s</xliff:g>"</string>
diff --git a/packages/CredentialManager/res/values-sk/strings.xml b/packages/CredentialManager/res/values-sk/strings.xml
index 8168b5178f80..90805a40e002 100644
--- a/packages/CredentialManager/res/values-sk/strings.xml
+++ b/packages/CredentialManager/res/values-sk/strings.xml
@@ -53,7 +53,7 @@
<string name="save_password_on_other_device_title" msgid="5829084591948321207">"Chcete uložiť heslo v inom zariadení?"</string>
<string name="save_sign_in_on_other_device_title" msgid="2827990118560134692">"Chcete uložiť prihlasovacie údaje v inom zariadení?"</string>
<string name="use_provider_for_all_title" msgid="4201020195058980757">"Chcete pre všetky svoje prihlasovacie údaje použiť <xliff:g id="PROVIDERINFODISPLAYNAME">%1$s</xliff:g>?"</string>
- <string name="use_provider_for_all_description" msgid="1998772715863958997">"Tento správca hesiel poskytovateľa <xliff:g id="USERNAME">%1$s</xliff:g> uchová vaše heslá a prístupové kľúče, aby vám pomohol ľahšie sa prihlasovať"</string>
+ <string name="use_provider_for_all_description" msgid="1998772715863958997">"Tento správca hesiel pre účet <xliff:g id="USERNAME">%1$s</xliff:g> bude uchovávať vaše heslá a prístupové kľúče, aby ste sa mohli ľahšie prihlasovať"</string>
<string name="set_as_default" msgid="4415328591568654603">"Nastaviť ako predvolené"</string>
<string name="settings" msgid="6536394145760913145">"Nastavenia"</string>
<string name="use_once" msgid="9027366575315399714">"Použiť raz"</string>
diff --git a/packages/EncryptedLocalTransport/Android.bp b/packages/EncryptedLocalTransport/Android.bp
index 09e563076c95..9ae6d9648979 100644
--- a/packages/EncryptedLocalTransport/Android.bp
+++ b/packages/EncryptedLocalTransport/Android.bp
@@ -27,9 +27,6 @@ android_app {
name: "EncryptedLocalTransport",
defaults: ["platform_app_defaults"],
srcs: ["src/**/*.java"],
- optimize: {
- proguard_flags_files: ["proguard.flags"],
- },
static_libs: ["LocalTransport"],
platform_apis: true,
certificate: "platform",
diff --git a/packages/EncryptedLocalTransport/proguard.flags b/packages/EncryptedLocalTransport/proguard.flags
deleted file mode 100644
index e4ce3c524e35..000000000000
--- a/packages/EncryptedLocalTransport/proguard.flags
+++ /dev/null
@@ -1,2 +0,0 @@
--keep class com.android.localTransport.EncryptedLocalTransport
--keep class com.android.localTransport.EncryptedLocalTransportService
diff --git a/packages/Keyguard/proguard.flags b/packages/Keyguard/proguard.flags
deleted file mode 100644
index fb74b64cb92b..000000000000
--- a/packages/Keyguard/proguard.flags
+++ /dev/null
@@ -1,27 +0,0 @@
--keep public class * {
- public void setBackgroundAlpha(float);
- public float getBackgroundAlpha();
- public void setContentAlpha(float);
- public float getContentAlpha();
- public void setAlpha(float);
- public float getAlpha();
- public void setAlpha(int);
- public int getAlpha();
- public void setRotationX(float);
- public float getRotationX();
- public void setRotationY(float);
- public float getRotationY();
- public void setPivotX(float);
- public float getPivotX();
- public void setPivotY(float);
- public float getPivotY();
- public void setScaleX(float);
- public float getScaleX();
- public void setScaleY(float);
- public float getScaleY();
- public void setTranslationX(float);
- public float getTranslationX();
- public void setTranslationY(float);
- public float getTranslationY();
-}
-
diff --git a/packages/LocalTransport/Android.bp b/packages/LocalTransport/Android.bp
index d4fa1915a140..e7a273b83a7d 100644
--- a/packages/LocalTransport/Android.bp
+++ b/packages/LocalTransport/Android.bp
@@ -27,9 +27,7 @@ android_app {
name: "LocalTransport",
defaults: ["platform_app_defaults"],
srcs: ["src/**/*.java"],
- optimize: {
- proguard_flags_files: ["proguard.flags"],
- },
+ libs: ["keepanno-annotations"],
platform_apis: true,
certificate: "platform",
privileged: true,
diff --git a/packages/LocalTransport/proguard.flags b/packages/LocalTransport/proguard.flags
deleted file mode 100644
index c1f51b892d40..000000000000
--- a/packages/LocalTransport/proguard.flags
+++ /dev/null
@@ -1,5 +0,0 @@
--keep class com.android.localTransport.LocalTransport
--keep class com.android.localTransport.LocalTransportParameters
--keep class com.android.localTransport.LocalTransportService
-
-
diff --git a/packages/LocalTransport/src/com/android/localtransport/LocalTransport.java b/packages/LocalTransport/src/com/android/localtransport/LocalTransport.java
index 73f87302dd05..933be11bfaf1 100644
--- a/packages/LocalTransport/src/com/android/localtransport/LocalTransport.java
+++ b/packages/LocalTransport/src/com/android/localtransport/LocalTransport.java
@@ -38,6 +38,9 @@ import android.util.ArrayMap;
import android.util.Base64;
import android.util.Log;
+import com.android.tools.r8.keepanno.annotations.KeepTarget;
+import com.android.tools.r8.keepanno.annotations.UsesReflection;
+
import libcore.io.IoUtils;
import java.io.BufferedOutputStream;
@@ -127,6 +130,13 @@ public class LocalTransport extends BackupTransport {
return mParameters;
}
+
+ @UsesReflection({
+ // As the runtime class name is used to generate the returned name, and the returned
+ // name may be used used with reflection, generate the necessary keep rules.
+ @KeepTarget(classConstant = LocalTransport.class),
+ @KeepTarget(extendsClassConstant = LocalTransport.class)
+ })
@Override
public String name() {
return new ComponentName(mContext, this.getClass()).flattenToShortString();
diff --git a/packages/PackageInstaller/res/values-it/strings.xml b/packages/PackageInstaller/res/values-it/strings.xml
index 03e3925955a7..9ee0882028a7 100644
--- a/packages/PackageInstaller/res/values-it/strings.xml
+++ b/packages/PackageInstaller/res/values-it/strings.xml
@@ -50,7 +50,7 @@
<string name="out_of_space_dlg_text" msgid="8727714096031856231">"Impossibile installare <xliff:g id="APP_NAME">%1$s</xliff:g>. Libera dello spazio e riprova."</string>
<string name="app_not_found_dlg_title" msgid="5107924008597470285">"App non trovata"</string>
<string name="app_not_found_dlg_text" msgid="5219983779377811611">"Impossibile trovare l\'applicazione nell\'elenco di applicazioni installate."</string>
- <string name="user_is_not_allowed_dlg_title" msgid="6915293433252210232">"Non autorizzate"</string>
+ <string name="user_is_not_allowed_dlg_title" msgid="6915293433252210232">"Non autorizzata"</string>
<string name="user_is_not_allowed_dlg_text" msgid="3468447791330611681">"L\'utente corrente non è autorizzato a eseguire questa disinstallazione."</string>
<string name="generic_error_dlg_title" msgid="5863195085927067752">"Errore"</string>
<string name="generic_error_dlg_text" msgid="5287861443265795232">"Impossibile disinstallare l\'app."</string>
diff --git a/packages/SettingsLib/Android.bp b/packages/SettingsLib/Android.bp
index 3d35bad68a73..5dcb9d2f6e77 100644
--- a/packages/SettingsLib/Android.bp
+++ b/packages/SettingsLib/Android.bp
@@ -8,7 +8,6 @@ package {
}
android_library {
-
name: "SettingsLib",
static_libs: [
@@ -26,44 +25,20 @@ android_library {
"iconloader",
"WifiTrackerLibRes",
- "SettingsLibHelpUtils",
- "SettingsLibRestrictedLockUtils",
- "SettingsLibActionBarShadow",
- "SettingsLibAppPreference",
- "SettingsLibSearchWidget",
- "SettingsLibSettingsSpinner",
- "SettingsLibIllustrationPreference",
- "SettingsLibLayoutPreference",
- "SettingsLibMainSwitchPreference",
- "SettingsLibActionButtonsPreference",
- "SettingsLibEntityHeaderWidgets",
- "SettingsLibBarChartPreference",
- "SettingsLibProgressBar",
- "SettingsLibAdaptiveIcon",
- "SettingsLibRadioButtonPreference",
- "SettingsLibSelectorWithWidgetPreference",
+ "SettingsLibDeviceStateRotationLock",
"SettingsLibDisplayUtils",
- "SettingsLibUtils",
"SettingsLibEmergencyNumber",
- "SettingsLibTopIntroPreference",
- "SettingsLibBannerMessagePreference",
- "SettingsLibFooterPreference",
- "SettingsLibUsageProgressBarPreference",
- "SettingsLibCollapsingToolbarBaseActivity",
- "SettingsLibTwoTargetPreference",
- "SettingsLibSettingsTransition",
- "SettingsLibButtonPreference",
- "SettingsLibDeviceStateRotationLock",
- "SettingsLibProfileSelector",
+ "SettingsLibSearchWidget",
+ "SettingsLibUtils",
+ "SettingsLibWidget",
"setupdesign",
"zxing-core-1.7",
"androidx.room_room-runtime",
"settingslib_flags_lib",
-
],
plugins: ["androidx.room_room-compiler-plugin"],
-
+ use_resource_processor: true,
resource_dirs: ["res"],
srcs: [
@@ -72,6 +47,43 @@ android_library {
],
}
+// Group all the libraries with namespace "com.android.settingslib.widget", to allow SettingsLib to
+// set use_resource_processor = true.
+// We can remove SettingsLibWidget when all these libraries have its own namespace.
+android_library {
+ name: "SettingsLibWidget",
+ visibility: ["//visibility:private"],
+ manifest: "AndroidManifest-SettingsLibWidget.xml",
+ static_libs: [
+ "SettingsLibActionBarShadow",
+ "SettingsLibActionButtonsPreference",
+ "SettingsLibAdaptiveIcon",
+ "SettingsLibAppPreference",
+ "SettingsLibBannerMessagePreference",
+ "SettingsLibBarChartPreference",
+ "SettingsLibButtonPreference",
+ "SettingsLibCollapsingToolbarBaseActivity",
+ "SettingsLibEntityHeaderWidgets",
+ "SettingsLibFooterPreference",
+ "SettingsLibHelpUtils",
+ "SettingsLibIllustrationPreference",
+ "SettingsLibLayoutPreference",
+ "SettingsLibMainSwitchPreference",
+ "SettingsLibProfileSelector",
+ "SettingsLibProgressBar",
+ "SettingsLibRadioButtonPreference",
+ "SettingsLibRestrictedLockUtils",
+ "SettingsLibSelectorWithWidgetPreference",
+ "SettingsLibSettingsSpinner",
+ "SettingsLibSettingsTransition",
+ "SettingsLibTopIntroPreference",
+ "SettingsLibTwoTargetPreference",
+ "SettingsLibUsageProgressBarPreference",
+ ],
+
+ resource_dirs: [],
+}
+
// NOTE: Keep this module in sync with ./common.mk
java_defaults {
name: "SettingsLibDefaults",
diff --git a/packages/SettingsLib/AndroidManifest-SettingsLibWidget.xml b/packages/SettingsLib/AndroidManifest-SettingsLibWidget.xml
new file mode 100644
index 000000000000..38a7d6ace1f8
--- /dev/null
+++ b/packages/SettingsLib/AndroidManifest-SettingsLibWidget.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2023 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<manifest package="com.android.settingslib.widget" />
diff --git a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/scaffold/CustomizedAppBar.kt b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/scaffold/CustomizedAppBar.kt
index 90a723f707da..b77368a429ae 100644
--- a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/scaffold/CustomizedAppBar.kt
+++ b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/scaffold/CustomizedAppBar.kt
@@ -253,6 +253,7 @@ private fun SingleRowTopAppBar(
hideTitleSemantics = false,
navigationIcon = navigationIcon,
actions = actionsRow,
+ titleScaleDisabled = false,
)
}
}
@@ -426,6 +427,7 @@ private fun TwoRowsTopAppBar(
* accessibility services at the same time, when animating between collapsed / expanded states.
* @param navigationIcon a navigation icon [Composable]
* @param actions actions [Composable]
+ * @param titleScaleDisabled whether the title font scaling is disabled. Default is disabled.
*/
@Composable
private fun TopAppBarLayout(
@@ -443,6 +445,7 @@ private fun TopAppBarLayout(
hideTitleSemantics: Boolean,
navigationIcon: @Composable () -> Unit,
actions: @Composable () -> Unit,
+ titleScaleDisabled: Boolean = true,
) {
Layout(
{
@@ -466,9 +469,12 @@ private fun TopAppBarLayout(
ProvideTextStyle(value = titleTextStyle) {
CompositionLocalProvider(
LocalContentColor provides titleContentColor,
- // Disable the title font scaling by only passing the density but not the
- // font scale.
- LocalDensity provides Density(density = LocalDensity.current.density),
+ LocalDensity provides with(LocalDensity.current) {
+ Density(
+ density = density,
+ fontScale = if (titleScaleDisabled) 1f else fontScale,
+ )
+ },
content = title
)
}
diff --git a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/scaffold/SearchScaffold.kt b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/scaffold/SearchScaffold.kt
index d437e3579354..696e8776ccd7 100644
--- a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/scaffold/SearchScaffold.kt
+++ b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/scaffold/SearchScaffold.kt
@@ -18,6 +18,7 @@ package com.android.settingslib.spa.widget.scaffold
import androidx.activity.compose.BackHandler
import androidx.appcompat.R
+import androidx.compose.foundation.focusable
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.RowScope
@@ -96,7 +97,8 @@ fun SearchScaffold(
Modifier
.padding(paddingValues.horizontalValues())
.padding(top = paddingValues.calculateTopPadding())
- .fillMaxSize(),
+ .focusable()
+ .fillMaxSize()
) {
content(
paddingValues.calculateBottomPadding(),
diff --git a/packages/SettingsLib/res/values-af/strings.xml b/packages/SettingsLib/res/values-af/strings.xml
index 8e4c6a43701d..9b82c13ce21b 100644
--- a/packages/SettingsLib/res/values-af/strings.xml
+++ b/packages/SettingsLib/res/values-af/strings.xml
@@ -403,7 +403,6 @@
<string name="force_resizable_activities_summary" msgid="2490382056981583062">"Maak die groottes van alle aktiwiteite verstelbaar vir veelvuldige vensters, ongeag manifeswaardes."</string>
<string name="enable_freeform_support" msgid="7599125687603914253">"Aktiveer vormvrye vensters"</string>
<string name="enable_freeform_support_summary" msgid="1822862728719276331">"Aktiveer steun vir eksperimentele vormvrye vensters."</string>
- <string name="desktop_mode" msgid="2389067840550544462">"Rekenaarmodus"</string>
<string name="local_backup_password_title" msgid="4631017948933578709">"Werkskerm-rugsteunwagwoord"</string>
<string name="local_backup_password_summary_none" msgid="7646898032616361714">"Volle rekenaarrugsteune word nie tans beskerm nie"</string>
<string name="local_backup_password_summary_change" msgid="1707357670383995567">"Tik om die wagwoord vir volledige rekenaarrugsteune te verander of te verwyder"</string>
diff --git a/packages/SettingsLib/res/values-am/strings.xml b/packages/SettingsLib/res/values-am/strings.xml
index 6011eb1630ad..bd025ec8950e 100644
--- a/packages/SettingsLib/res/values-am/strings.xml
+++ b/packages/SettingsLib/res/values-am/strings.xml
@@ -403,7 +403,6 @@
<string name="force_resizable_activities_summary" msgid="2490382056981583062">"የዝርዝር ሰነድ እሴቶች ምንም ይሁኑ ምን ለበርካታ መስኮቶች ሁሉንም እንቅስቃሴዎች መጠናቸው የሚቀየሩ እንዲሆኑ ያደርጋቸዋል።"</string>
<string name="enable_freeform_support" msgid="7599125687603914253">"የነጻ ቅርጽ መስኮቶችን ያንቁ"</string>
<string name="enable_freeform_support_summary" msgid="1822862728719276331">"የሙከራ ነፃ መልክ መስኮቶች ድጋፍን አንቃ"</string>
- <string name="desktop_mode" msgid="2389067840550544462">"የዴስክቶፕ ሁነታ"</string>
<string name="local_backup_password_title" msgid="4631017948933578709">"የዴስክቶፕ መጠባበቂያ ይለፍ ቃል"</string>
<string name="local_backup_password_summary_none" msgid="7646898032616361714">"ዴስክቶፕ ሙሉ ምትኬዎች በአሁኑ ሰዓት አልተጠበቁም"</string>
<string name="local_backup_password_summary_change" msgid="1707357670383995567">"የዴስክቶፕ ሙሉ ምትኬዎች የይለፍ ቃሉን ለመለወጥ ወይም ለማስወገድ ነካ ያድርጉ"</string>
diff --git a/packages/SettingsLib/res/values-ar/strings.xml b/packages/SettingsLib/res/values-ar/strings.xml
index 40c92e57c660..f5ab801a4c9e 100644
--- a/packages/SettingsLib/res/values-ar/strings.xml
+++ b/packages/SettingsLib/res/values-ar/strings.xml
@@ -403,7 +403,6 @@
<string name="force_resizable_activities_summary" msgid="2490382056981583062">"السماح بتغيير حجم جميع الأنشطة لتناسب تعدد النوافذ، بغض النظر عن قيم البيان"</string>
<string name="enable_freeform_support" msgid="7599125687603914253">"تفعيل النوافذ الحرة"</string>
<string name="enable_freeform_support_summary" msgid="1822862728719276331">"إتاحة استخدام النوافذ الحرة التجريبية"</string>
- <string name="desktop_mode" msgid="2389067840550544462">"وضع سطح المكتب"</string>
<string name="local_backup_password_title" msgid="4631017948933578709">"كلمة مرور احتياطية للكمبيوتر"</string>
<string name="local_backup_password_summary_none" msgid="7646898032616361714">"النُسخ الاحتياطية الكاملة لسطح المكتب غير محمية في الوقت الحالي."</string>
<string name="local_backup_password_summary_change" msgid="1707357670383995567">"انقر لتغيير كلمة مرور النسخ الاحتياطية الكاملة لسطح المكتب أو إزالتها."</string>
diff --git a/packages/SettingsLib/res/values-as/strings.xml b/packages/SettingsLib/res/values-as/strings.xml
index ef72afcd40a3..a0a52b5ec262 100644
--- a/packages/SettingsLib/res/values-as/strings.xml
+++ b/packages/SettingsLib/res/values-as/strings.xml
@@ -403,7 +403,6 @@
<string name="force_resizable_activities_summary" msgid="2490382056981583062">"মেনিফেষ্টৰ মান যিয়েই নহওক, মাল্টি-ৱিণ্ডৰ বাবে আটাইবোৰ কাৰ্যকলাপৰ আকাৰ সলনি কৰিব পৰা কৰক।"</string>
<string name="enable_freeform_support" msgid="7599125687603914253">"ফ্ৰিফৰ্ম ৱিণ্ড\'জ সক্ষম কৰক"</string>
<string name="enable_freeform_support_summary" msgid="1822862728719276331">"পৰীক্ষামূলক ফ্ৰী-ফৰ্ম ৱিণ্ড’বোৰৰ বাবে সহায়তা সক্ষম কৰক৷"</string>
- <string name="desktop_mode" msgid="2389067840550544462">"ডেস্কটপ ম’ড"</string>
<string name="local_backup_password_title" msgid="4631017948933578709">"ডেস্কটপ বেকআপ পাছৱৰ্ড"</string>
<string name="local_backup_password_summary_none" msgid="7646898032616361714">"ডেস্কটপৰ পূৰ্ণ বেকআপ এতিয়ালৈকে সংৰক্ষিত অৱস্থাত নাই"</string>
<string name="local_backup_password_summary_change" msgid="1707357670383995567">"ডেস্কটপ সম্পূৰ্ণ বেকআপৰ বাবে পাছৱৰ্ডটো সলনি কৰিবলৈ বা আঁতৰাবলৈ টিপক"</string>
diff --git a/packages/SettingsLib/res/values-az/strings.xml b/packages/SettingsLib/res/values-az/strings.xml
index a76f8ba83698..cb515bfa9234 100644
--- a/packages/SettingsLib/res/values-az/strings.xml
+++ b/packages/SettingsLib/res/values-az/strings.xml
@@ -403,7 +403,6 @@
<string name="force_resizable_activities_summary" msgid="2490382056981583062">"Manifest dəyərindən asılı olmayaraq çoxpəncərəli rejimdə pəncərə ölçüsünün dəyişdirilməsinə icazə verilsin"</string>
<string name="enable_freeform_support" msgid="7599125687603914253">"İxtiyari formada pəncərə yaradılsın"</string>
<string name="enable_freeform_support_summary" msgid="1822862728719276331">"Eksperimental olaraq ixtiyari formada pəncərə yaradılsın"</string>
- <string name="desktop_mode" msgid="2389067840550544462">"Masaüstü rejimi"</string>
<string name="local_backup_password_title" msgid="4631017948933578709">"Masaüstü rezerv parolu"</string>
<string name="local_backup_password_summary_none" msgid="7646898032616361714">"Masaüstü tam rezervlər hazırda qorunmayıblar."</string>
<string name="local_backup_password_summary_change" msgid="1707357670383995567">"Masaüstünün tam rezerv kopyalanması üçün parolu dəyişmək və ya silmək üçün basın"</string>
diff --git a/packages/SettingsLib/res/values-b+sr+Latn/strings.xml b/packages/SettingsLib/res/values-b+sr+Latn/strings.xml
index 4d7a5fe897f6..011967493a0e 100644
--- a/packages/SettingsLib/res/values-b+sr+Latn/strings.xml
+++ b/packages/SettingsLib/res/values-b+sr+Latn/strings.xml
@@ -403,7 +403,6 @@
<string name="force_resizable_activities_summary" msgid="2490382056981583062">"Omogućava promenu veličine svih aktivnosti za režim sa više prozora, bez obzira na vrednosti manifesta."</string>
<string name="enable_freeform_support" msgid="7599125687603914253">"Omogući prozore proizvoljnog formata"</string>
<string name="enable_freeform_support_summary" msgid="1822862728719276331">"Omogućava podršku za eksperimentalne prozore proizvoljnog formata."</string>
- <string name="desktop_mode" msgid="2389067840550544462">"Režim za računare"</string>
<string name="local_backup_password_title" msgid="4631017948933578709">"Lozinka rezervne kopije za računar"</string>
<string name="local_backup_password_summary_none" msgid="7646898032616361714">"Rezervne kopije čitavog sistema trenutno nisu zaštićene"</string>
<string name="local_backup_password_summary_change" msgid="1707357670383995567">"Dodirnite da biste promenili ili uklonili lozinku za pravljenje rezervnih kopija čitavog sistema na računaru"</string>
diff --git a/packages/SettingsLib/res/values-be/strings.xml b/packages/SettingsLib/res/values-be/strings.xml
index f46adf8dc649..b46debff8c66 100644
--- a/packages/SettingsLib/res/values-be/strings.xml
+++ b/packages/SettingsLib/res/values-be/strings.xml
@@ -403,7 +403,6 @@
<string name="force_resizable_activities_summary" msgid="2490382056981583062">"Зрабіць усе віды дзейнасці даступнымі для змены памеру ў рэжыме некалькіх вокнаў, незалежна ад значэнняў маніфеста."</string>
<string name="enable_freeform_support" msgid="7599125687603914253">"Уключыць адвольную форму вокнаў"</string>
<string name="enable_freeform_support_summary" msgid="1822862728719276331">"Уключыць падтрымку для эксперыментальнай адвольнай формы акна."</string>
- <string name="desktop_mode" msgid="2389067840550544462">"Рэжым працоўнага стала"</string>
<string name="local_backup_password_title" msgid="4631017948933578709">"Пароль для рэз. копіі ПК"</string>
<string name="local_backup_password_summary_none" msgid="7646898032616361714">"Поўнае рэзервовае капіраванне працоўнага стала зараз не абаронена"</string>
<string name="local_backup_password_summary_change" msgid="1707357670383995567">"Краніце, каб змяніць або выдаліць пароль для поўнага рэзервовага капіравання працоўнага стала"</string>
diff --git a/packages/SettingsLib/res/values-bg/strings.xml b/packages/SettingsLib/res/values-bg/strings.xml
index fa3cba2eb0a7..592f6178e74d 100644
--- a/packages/SettingsLib/res/values-bg/strings.xml
+++ b/packages/SettingsLib/res/values-bg/strings.xml
@@ -403,7 +403,6 @@
<string name="force_resizable_activities_summary" msgid="2490382056981583062">"Дава възможност за преоразмеряване на всички активности в режима за няколко прозореца независимо от стойностите в манифеста."</string>
<string name="enable_freeform_support" msgid="7599125687603914253">"Активиране на прозорците в свободна форма"</string>
<string name="enable_freeform_support_summary" msgid="1822862728719276331">"Активиране на поддръжката за експерименталните прозорци в свободна форма."</string>
- <string name="desktop_mode" msgid="2389067840550544462">"Режим за компютри"</string>
<string name="local_backup_password_title" msgid="4631017948933578709">"Парола за резервни копия"</string>
<string name="local_backup_password_summary_none" msgid="7646898032616361714">"Понастоящем пълните резервни копия за настолен компютър не са защитени"</string>
<string name="local_backup_password_summary_change" msgid="1707357670383995567">"Докоснете, за да промените или премахнете паролата за пълни резервни копия на настолния компютър"</string>
diff --git a/packages/SettingsLib/res/values-bn/strings.xml b/packages/SettingsLib/res/values-bn/strings.xml
index d3dc359f11d7..3fafee31d634 100644
--- a/packages/SettingsLib/res/values-bn/strings.xml
+++ b/packages/SettingsLib/res/values-bn/strings.xml
@@ -403,7 +403,6 @@
<string name="force_resizable_activities_summary" msgid="2490382056981583062">"ম্যানিফেস্ট মানগুলির নির্বিশেষে মাল্টি-উইন্ডোর জন্য সমস্ত ক্রিয়াকলাপগুলির আকার পরিবর্তনযোগ্য করুন৷"</string>
<string name="enable_freeform_support" msgid="7599125687603914253">"ফ্রি-ফর্ম উইন্ডো চালু করুন"</string>
<string name="enable_freeform_support_summary" msgid="1822862728719276331">"পরীক্ষামূলক ফ্রি-ফর্ম উইন্ডোগুলির জন্য সহায়তা সক্ষম করুন৷"</string>
- <string name="desktop_mode" msgid="2389067840550544462">"\'ডেস্কটপ\' মোড"</string>
<string name="local_backup_password_title" msgid="4631017948933578709">"ডেস্কটপ ব্যাকআপ পাসওয়ার্ড"</string>
<string name="local_backup_password_summary_none" msgid="7646898032616361714">"ডেস্কটপ পূর্ণ ব্যাকআপ বর্তমানে সুরক্ষিত নয়"</string>
<string name="local_backup_password_summary_change" msgid="1707357670383995567">"ডেস্কটপের সম্পূর্ণ ব্যাকআপের পাসওয়ার্ডটি পরিবর্তন করতে বা মুছে ফেলতে আলতো চাপুন"</string>
diff --git a/packages/SettingsLib/res/values-bs/strings.xml b/packages/SettingsLib/res/values-bs/strings.xml
index 0487e29cb401..5f7bd2c3cfa5 100644
--- a/packages/SettingsLib/res/values-bs/strings.xml
+++ b/packages/SettingsLib/res/values-bs/strings.xml
@@ -403,7 +403,6 @@
<string name="force_resizable_activities_summary" msgid="2490382056981583062">"Omogućava mijenjanje veličine svih aktivnosti za prikaz s više prozora, bez obzira na prikazane vrijednosti"</string>
<string name="enable_freeform_support" msgid="7599125687603914253">"Omogući prozore nepravilnih oblika"</string>
<string name="enable_freeform_support_summary" msgid="1822862728719276331">"Omogućava podršku za eksperimentalne prozore nepravilnih oblika."</string>
- <string name="desktop_mode" msgid="2389067840550544462">"Način rada radne površine"</string>
<string name="local_backup_password_title" msgid="4631017948933578709">"Lozinka sigurnosne kopije za računar"</string>
<string name="local_backup_password_summary_none" msgid="7646898032616361714">"Potpune sigurnosne kopije za računare trenutno nisu zaštićene"</string>
<string name="local_backup_password_summary_change" msgid="1707357670383995567">"Dodirnite da promijenite ili uklonite lozinku za potpune rezervne kopije s radne površine"</string>
diff --git a/packages/SettingsLib/res/values-ca/strings.xml b/packages/SettingsLib/res/values-ca/strings.xml
index 62938eb9c677..7143f99207c9 100644
--- a/packages/SettingsLib/res/values-ca/strings.xml
+++ b/packages/SettingsLib/res/values-ca/strings.xml
@@ -403,7 +403,6 @@
<string name="force_resizable_activities_summary" msgid="2490382056981583062">"Permet ajustar la mida de totes les activitats per al mode multifinestra, independentment dels valors del manifest"</string>
<string name="enable_freeform_support" msgid="7599125687603914253">"Activa les finestres amb format lliure"</string>
<string name="enable_freeform_support_summary" msgid="1822862728719276331">"Activa la compatibilitat amb finestres experimentals amb format lliure"</string>
- <string name="desktop_mode" msgid="2389067840550544462">"Mode d\'escriptori"</string>
<string name="local_backup_password_title" msgid="4631017948933578709">"Contrasenya per a còpies d\'ordinador"</string>
<string name="local_backup_password_summary_none" msgid="7646898032616361714">"Les còpies de seguretat completes d\'ordinador no estan protegides"</string>
<string name="local_backup_password_summary_change" msgid="1707357670383995567">"Toca per canviar o suprimir la contrasenya per a les còpies de seguretat completes de l\'ordinador"</string>
diff --git a/packages/SettingsLib/res/values-cs/strings.xml b/packages/SettingsLib/res/values-cs/strings.xml
index d6aa84e2a6fe..34e65e63c8e8 100644
--- a/packages/SettingsLib/res/values-cs/strings.xml
+++ b/packages/SettingsLib/res/values-cs/strings.xml
@@ -403,7 +403,6 @@
<string name="force_resizable_activities_summary" msgid="2490382056981583062">"Umožní změnu velikosti všech aktivit na několik oken (bez ohledu na hodnoty manifestu)"</string>
<string name="enable_freeform_support" msgid="7599125687603914253">"Aktivovat okna s volným tvarem"</string>
<string name="enable_freeform_support_summary" msgid="1822862728719276331">"Aktivuje podporu experimentálních oken s volným tvarem"</string>
- <string name="desktop_mode" msgid="2389067840550544462">"Režim počítače"</string>
<string name="local_backup_password_title" msgid="4631017948933578709">"Heslo pro zálohy v počítači"</string>
<string name="local_backup_password_summary_none" msgid="7646898032616361714">"Úplné zálohy v počítači nejsou v současné době chráněny"</string>
<string name="local_backup_password_summary_change" msgid="1707357670383995567">"Tuto možnost vyberte, chcete-li změnit nebo odebrat heslo pro úplné zálohy do počítače"</string>
diff --git a/packages/SettingsLib/res/values-da/strings.xml b/packages/SettingsLib/res/values-da/strings.xml
index d1b02227f75a..381c3cc630ea 100644
--- a/packages/SettingsLib/res/values-da/strings.xml
+++ b/packages/SettingsLib/res/values-da/strings.xml
@@ -403,7 +403,6 @@
<string name="force_resizable_activities_summary" msgid="2490382056981583062">"Tillad, at alle aktiviteter kan tilpasses flere vinduer uafhængigt af manifestværdier"</string>
<string name="enable_freeform_support" msgid="7599125687603914253">"Aktivér vinduer i frit format"</string>
<string name="enable_freeform_support_summary" msgid="1822862728719276331">"Aktivér understøttelse af eksperimentelle vinduer i frit format"</string>
- <string name="desktop_mode" msgid="2389067840550544462">"Computertilstand"</string>
<string name="local_backup_password_title" msgid="4631017948933578709">"Kode til lokal backup"</string>
<string name="local_backup_password_summary_none" msgid="7646898032616361714">"Lokale komplette backups er i øjeblikket ikke beskyttet"</string>
<string name="local_backup_password_summary_change" msgid="1707357670383995567">"Tryk for at skifte eller fjerne adgangskoden til fuld lokal backup"</string>
diff --git a/packages/SettingsLib/res/values-de/strings.xml b/packages/SettingsLib/res/values-de/strings.xml
index a74374a2e10f..b53d19181148 100644
--- a/packages/SettingsLib/res/values-de/strings.xml
+++ b/packages/SettingsLib/res/values-de/strings.xml
@@ -403,7 +403,6 @@
<string name="force_resizable_activities_summary" msgid="2490382056981583062">"Die Größe aller Aktivitäten darf, ungeachtet der Manifestwerte, für die Mehrfensterdarstellung angepasst werden"</string>
<string name="enable_freeform_support" msgid="7599125687603914253">"Freiform-Fenster zulassen"</string>
<string name="enable_freeform_support_summary" msgid="1822862728719276331">"Unterstützung für experimentelle Freiform-Fenster aktivieren"</string>
- <string name="desktop_mode" msgid="2389067840550544462">"Desktopmodus"</string>
<string name="local_backup_password_title" msgid="4631017948933578709">"Passwort für Desktop-Sicherung"</string>
<string name="local_backup_password_summary_none" msgid="7646898032616361714">"Vollständige Desktop-Sicherungen sind momentan nicht passwortgeschützt"</string>
<string name="local_backup_password_summary_change" msgid="1707357670383995567">"Zum Ändern oder Entfernen des Passworts für vollständige Desktop-Sicherungen tippen"</string>
diff --git a/packages/SettingsLib/res/values-el/strings.xml b/packages/SettingsLib/res/values-el/strings.xml
index 9f000bbcb2eb..b4cc7aa2630e 100644
--- a/packages/SettingsLib/res/values-el/strings.xml
+++ b/packages/SettingsLib/res/values-el/strings.xml
@@ -403,7 +403,6 @@
<string name="force_resizable_activities_summary" msgid="2490382056981583062">"Να έχουν όλες οι δραστηριότητες δυνατότητα αλλαγής μεγέθους για την προβολή πολλαπλών παραθύρων, ανεξάρτητα από τις τιμές του μανιφέστου."</string>
<string name="enable_freeform_support" msgid="7599125687603914253">"Ενεργοποίηση παραθύρων ελεύθερης μορφής"</string>
<string name="enable_freeform_support_summary" msgid="1822862728719276331">"Ενεργοποίηση υποστήριξης για πειραματικά παράθυρα ελεύθερης μορφής."</string>
- <string name="desktop_mode" msgid="2389067840550544462">"Λειτ. επιφάνειας εργασίας"</string>
<string name="local_backup_password_title" msgid="4631017948933578709">"Εφ/κός κωδικός desktop"</string>
<string name="local_backup_password_summary_none" msgid="7646898032616361714">"Τα πλήρη αντίγραφα ασφαλείας επιφάνειας εργασίας δεν προστατεύονται αυτήν τη στιγμή"</string>
<string name="local_backup_password_summary_change" msgid="1707357670383995567">"Πατήστε για αλλαγή ή κατάργηση του κωδικού πρόσβασης για τα πλήρη αντίγραφα ασφαλείας επιφάνειας εργασίας"</string>
diff --git a/packages/SettingsLib/res/values-en-rAU/strings.xml b/packages/SettingsLib/res/values-en-rAU/strings.xml
index 5bb58d1fe2b5..9fd825bf4e7f 100644
--- a/packages/SettingsLib/res/values-en-rAU/strings.xml
+++ b/packages/SettingsLib/res/values-en-rAU/strings.xml
@@ -403,7 +403,6 @@
<string name="force_resizable_activities_summary" msgid="2490382056981583062">"Make all activities resizeable for multi-window, regardless of manifest values."</string>
<string name="enable_freeform_support" msgid="7599125687603914253">"Enable freeform windows"</string>
<string name="enable_freeform_support_summary" msgid="1822862728719276331">"Enable support for experimental freeform windows."</string>
- <string name="desktop_mode" msgid="2389067840550544462">"Desktop mode"</string>
<string name="local_backup_password_title" msgid="4631017948933578709">"Desktop backup password"</string>
<string name="local_backup_password_summary_none" msgid="7646898032616361714">"Desktop full backups aren\'t currently protected"</string>
<string name="local_backup_password_summary_change" msgid="1707357670383995567">"Tap to change or remove the password for desktop full backups"</string>
diff --git a/packages/SettingsLib/res/values-en-rCA/strings.xml b/packages/SettingsLib/res/values-en-rCA/strings.xml
index 5b1e86f1ccc7..546e5d238f54 100644
--- a/packages/SettingsLib/res/values-en-rCA/strings.xml
+++ b/packages/SettingsLib/res/values-en-rCA/strings.xml
@@ -403,7 +403,6 @@
<string name="force_resizable_activities_summary" msgid="2490382056981583062">"Make all activities resizable for multi-window, regardless of manifest values."</string>
<string name="enable_freeform_support" msgid="7599125687603914253">"Enable freeform windows"</string>
<string name="enable_freeform_support_summary" msgid="1822862728719276331">"Enable support for experimental freeform windows."</string>
- <string name="desktop_mode" msgid="2389067840550544462">"Desktop mode"</string>
<string name="local_backup_password_title" msgid="4631017948933578709">"Desktop backup password"</string>
<string name="local_backup_password_summary_none" msgid="7646898032616361714">"Desktop full backups aren’t currently protected"</string>
<string name="local_backup_password_summary_change" msgid="1707357670383995567">"Tap to change or remove the password for desktop full backups"</string>
diff --git a/packages/SettingsLib/res/values-en-rGB/strings.xml b/packages/SettingsLib/res/values-en-rGB/strings.xml
index 5bb58d1fe2b5..9fd825bf4e7f 100644
--- a/packages/SettingsLib/res/values-en-rGB/strings.xml
+++ b/packages/SettingsLib/res/values-en-rGB/strings.xml
@@ -403,7 +403,6 @@
<string name="force_resizable_activities_summary" msgid="2490382056981583062">"Make all activities resizeable for multi-window, regardless of manifest values."</string>
<string name="enable_freeform_support" msgid="7599125687603914253">"Enable freeform windows"</string>
<string name="enable_freeform_support_summary" msgid="1822862728719276331">"Enable support for experimental freeform windows."</string>
- <string name="desktop_mode" msgid="2389067840550544462">"Desktop mode"</string>
<string name="local_backup_password_title" msgid="4631017948933578709">"Desktop backup password"</string>
<string name="local_backup_password_summary_none" msgid="7646898032616361714">"Desktop full backups aren\'t currently protected"</string>
<string name="local_backup_password_summary_change" msgid="1707357670383995567">"Tap to change or remove the password for desktop full backups"</string>
diff --git a/packages/SettingsLib/res/values-en-rIN/strings.xml b/packages/SettingsLib/res/values-en-rIN/strings.xml
index 5bb58d1fe2b5..9fd825bf4e7f 100644
--- a/packages/SettingsLib/res/values-en-rIN/strings.xml
+++ b/packages/SettingsLib/res/values-en-rIN/strings.xml
@@ -403,7 +403,6 @@
<string name="force_resizable_activities_summary" msgid="2490382056981583062">"Make all activities resizeable for multi-window, regardless of manifest values."</string>
<string name="enable_freeform_support" msgid="7599125687603914253">"Enable freeform windows"</string>
<string name="enable_freeform_support_summary" msgid="1822862728719276331">"Enable support for experimental freeform windows."</string>
- <string name="desktop_mode" msgid="2389067840550544462">"Desktop mode"</string>
<string name="local_backup_password_title" msgid="4631017948933578709">"Desktop backup password"</string>
<string name="local_backup_password_summary_none" msgid="7646898032616361714">"Desktop full backups aren\'t currently protected"</string>
<string name="local_backup_password_summary_change" msgid="1707357670383995567">"Tap to change or remove the password for desktop full backups"</string>
diff --git a/packages/SettingsLib/res/values-en-rXC/strings.xml b/packages/SettingsLib/res/values-en-rXC/strings.xml
index 8f4ba0ee077f..8256cc953794 100644
--- a/packages/SettingsLib/res/values-en-rXC/strings.xml
+++ b/packages/SettingsLib/res/values-en-rXC/strings.xml
@@ -403,7 +403,6 @@
<string name="force_resizable_activities_summary" msgid="2490382056981583062">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‎‏‎‎‎‏‎‏‎‎‎‏‏‏‏‏‎‎‏‏‏‎‏‎‏‎‎‏‎‎‏‎‏‎‎‎‏‎‏‎‏‏‎‎‏‎‎‏‏‎‏‎‏‎‎‏‏‎‏‎‏‏‎‎Make all activities resizable for multi-window, regardless of manifest values.‎‏‎‎‏‎"</string>
<string name="enable_freeform_support" msgid="7599125687603914253">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‏‎‏‎‎‏‎‏‏‏‎‏‎‏‏‎‎‎‎‏‎‎‏‎‎‎‏‏‎‏‎‎‎‎‏‏‎‏‎‎‏‎‏‏‎‏‎‏‏‎‎‏‏‎‎‎‎‎‏‏‎‏‎Enable freeform windows‎‏‎‎‏‎"</string>
<string name="enable_freeform_support_summary" msgid="1822862728719276331">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‎‏‏‏‎‎‏‎‏‎‎‏‏‎‎‎‎‎‏‏‎‏‏‏‏‏‏‏‏‏‎‎‏‏‎‏‎‏‏‏‎‎‏‏‏‎‎‏‎‎‏‏‎‎‏‎‎‏‎‏‎‏‏‎Enable support for experimental freeform windows.‎‏‎‎‏‎"</string>
- <string name="desktop_mode" msgid="2389067840550544462">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‎‏‎‎‎‎‏‎‎‏‎‎‏‏‏‏‎‏‎‏‏‎‎‏‎‎‎‏‎‏‏‎‎‎‎‏‏‎‎‎‏‎‏‎‎‏‏‎‎‏‎‎‏‎‎‎‏‎‎‏‏‏‎‎Desktop mode‎‏‎‎‏‎"</string>
<string name="local_backup_password_title" msgid="4631017948933578709">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‎‎‎‎‎‎‎‏‎‎‎‏‎‎‏‎‏‎‏‏‏‎‎‏‎‎‏‎‎‏‏‏‎‏‎‎‏‎‏‎‏‎‎‏‎‎‏‏‎‏‏‏‏‏‏‏‎‏‎‏‎‏‎Desktop backup password‎‏‎‎‏‎"</string>
<string name="local_backup_password_summary_none" msgid="7646898032616361714">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‏‎‏‎‏‎‎‎‎‏‏‏‏‏‎‎‏‏‏‏‎‏‎‎‏‏‏‏‏‎‏‏‏‎‎‎‏‏‏‎‏‏‏‎‏‏‎‏‎‎‏‏‏‎‏‏‏‏‎‎‏‎‎Desktop full backups aren’t currently protected‎‏‎‎‏‎"</string>
<string name="local_backup_password_summary_change" msgid="1707357670383995567">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‎‏‏‎‏‏‏‏‎‏‏‎‎‎‏‏‏‎‎‎‎‎‎‏‏‎‎‎‎‎‏‎‏‎‏‎‏‏‏‏‏‎‎‎‏‏‎‏‏‎‎‏‎‏‎‏‎‏‎‏‏‏‏‎Tap to change or remove the password for desktop full backups‎‏‎‎‏‎"</string>
diff --git a/packages/SettingsLib/res/values-es-rUS/strings.xml b/packages/SettingsLib/res/values-es-rUS/strings.xml
index 9015ed5a916f..ff9f7aeba4bf 100644
--- a/packages/SettingsLib/res/values-es-rUS/strings.xml
+++ b/packages/SettingsLib/res/values-es-rUS/strings.xml
@@ -403,7 +403,6 @@
<string name="force_resizable_activities_summary" msgid="2490382056981583062">"Permitir que todas las actividades puedan cambiar de tamaño para el modo multiventana, sin importar los valores del manifiesto."</string>
<string name="enable_freeform_support" msgid="7599125687603914253">"Habilitar ventanas de forma libre"</string>
<string name="enable_freeform_support_summary" msgid="1822862728719276331">"Permite la compatibilidad con ventanas de forma libre experimentales."</string>
- <string name="desktop_mode" msgid="2389067840550544462">"Modo de escritorio"</string>
<string name="local_backup_password_title" msgid="4631017948933578709">"Contraseñas"</string>
<string name="local_backup_password_summary_none" msgid="7646898032616361714">"Tus copias de seguridad de escritorio no están protegidas por contraseña."</string>
<string name="local_backup_password_summary_change" msgid="1707357670383995567">"Presiona para cambiar o quitar la contraseña de las copias de seguridad completas de tu escritorio."</string>
diff --git a/packages/SettingsLib/res/values-es/strings.xml b/packages/SettingsLib/res/values-es/strings.xml
index 4ee27537119d..abf60d8386ed 100644
--- a/packages/SettingsLib/res/values-es/strings.xml
+++ b/packages/SettingsLib/res/values-es/strings.xml
@@ -403,7 +403,6 @@
<string name="force_resizable_activities_summary" msgid="2490382056981583062">"Permite que todas las actividades puedan cambiar de tamaño en multiventana independientemente de los valores de manifiesto"</string>
<string name="enable_freeform_support" msgid="7599125687603914253">"Habilitar ventanas de forma libre"</string>
<string name="enable_freeform_support_summary" msgid="1822862728719276331">"Permite la compatibilidad con ventanas de forma libre experimentales"</string>
- <string name="desktop_mode" msgid="2389067840550544462">"Modo Escritorio"</string>
<string name="local_backup_password_title" msgid="4631017948933578709">"Contraseña para copias de ordenador"</string>
<string name="local_backup_password_summary_none" msgid="7646898032616361714">"Las copias de seguridad completas de ordenador no están protegidas"</string>
<string name="local_backup_password_summary_change" msgid="1707357670383995567">"Toca para cambiar o quitar la contraseña de las copias de seguridad completas del escritorio"</string>
diff --git a/packages/SettingsLib/res/values-et/strings.xml b/packages/SettingsLib/res/values-et/strings.xml
index 466746619e6f..4e70a53e4727 100644
--- a/packages/SettingsLib/res/values-et/strings.xml
+++ b/packages/SettingsLib/res/values-et/strings.xml
@@ -403,7 +403,6 @@
<string name="force_resizable_activities_summary" msgid="2490382056981583062">"Muudetakse kõigi tegevuste suurused mitme aknaga vaates muudetavaks (manifesti väärtustest olenemata)."</string>
<string name="enable_freeform_support" msgid="7599125687603914253">"Luba vabas vormis aknad"</string>
<string name="enable_freeform_support_summary" msgid="1822862728719276331">"Lubatakse katseliste vabavormis akende tugi."</string>
- <string name="desktop_mode" msgid="2389067840550544462">"Lauaarvuti režiim"</string>
<string name="local_backup_password_title" msgid="4631017948933578709">"Arvutivarunduse parool"</string>
<string name="local_backup_password_summary_none" msgid="7646898032616361714">"Täielikud arvutivarundused pole praegu kaitstud"</string>
<string name="local_backup_password_summary_change" msgid="1707357670383995567">"Puudutage täielike arvutivarunduste parooli muutmiseks või eemaldamiseks"</string>
diff --git a/packages/SettingsLib/res/values-eu/strings.xml b/packages/SettingsLib/res/values-eu/strings.xml
index d9c4ee7c5ec1..8dd60071ad54 100644
--- a/packages/SettingsLib/res/values-eu/strings.xml
+++ b/packages/SettingsLib/res/values-eu/strings.xml
@@ -403,7 +403,6 @@
<string name="force_resizable_activities_summary" msgid="2490382056981583062">"Eman aukera jarduera guztien tamaina doitzeko, hainbat leihotan erabili ahal izan daitezen, ezarritako balioak kontuan izan gabe"</string>
<string name="enable_freeform_support" msgid="7599125687603914253">"Gaitu estilo libreko leihoak"</string>
<string name="enable_freeform_support_summary" msgid="1822862728719276331">"Onartu estilo libreko leiho esperimentalak"</string>
- <string name="desktop_mode" msgid="2389067840550544462">"Ordenagailuetarako modua"</string>
<string name="local_backup_password_title" msgid="4631017948933578709">"Babeskopien pasahitz lokala"</string>
<string name="local_backup_password_summary_none" msgid="7646898032616361714">"Une honetan, ordenagailuko babeskopia osoak ez daude babestuta"</string>
<string name="local_backup_password_summary_change" msgid="1707357670383995567">"Ordenagailuko eduki guztiaren babeskopia egiteko erabiltzen den pasahitza aldatzeko edo kentzeko, sakatu hau"</string>
diff --git a/packages/SettingsLib/res/values-fa/strings.xml b/packages/SettingsLib/res/values-fa/strings.xml
index 1d538648369e..beaaa3922557 100644
--- a/packages/SettingsLib/res/values-fa/strings.xml
+++ b/packages/SettingsLib/res/values-fa/strings.xml
@@ -403,7 +403,6 @@
<string name="force_resizable_activities_summary" msgid="2490382056981583062">"بدون توجه به مقادیر مانیفست، اندازه همه فعالیت‌ها برای حالت چند پنجره‌ای می‌تواند تغییر کند."</string>
<string name="enable_freeform_support" msgid="7599125687603914253">"فعال کردن پنجره‌های آزاد"</string>
<string name="enable_freeform_support_summary" msgid="1822862728719276331">"فعال کردن پشتیبانی برای پنجره‌های آزاد آزمایشی."</string>
- <string name="desktop_mode" msgid="2389067840550544462">"حالت رایانه"</string>
<string name="local_backup_password_title" msgid="4631017948933578709">"گذرواژه پشتیبان‌گیری محلی"</string>
<string name="local_backup_password_summary_none" msgid="7646898032616361714">"پشتیبان‌گیری کامل رایانه درحال حاضر محافظت نمی‌شود"</string>
<string name="local_backup_password_summary_change" msgid="1707357670383995567">"برای تغییر یا حذف گذرواژه برای نسخه‌های پشتیبان کامل رایانه‌ای ضربه بزنید"</string>
diff --git a/packages/SettingsLib/res/values-fi/strings.xml b/packages/SettingsLib/res/values-fi/strings.xml
index 579771b986d9..ec1c1f1843dd 100644
--- a/packages/SettingsLib/res/values-fi/strings.xml
+++ b/packages/SettingsLib/res/values-fi/strings.xml
@@ -403,7 +403,6 @@
<string name="force_resizable_activities_summary" msgid="2490382056981583062">"Pakota kaikki toiminnot hyväksymään koon muuttaminen usean ikkunan tilassa luettelon arvoista riippumatta"</string>
<string name="enable_freeform_support" msgid="7599125687603914253">"Ota käyttöön vapaamuotoiset ikkunat"</string>
<string name="enable_freeform_support_summary" msgid="1822862728719276331">"Ota kokeellisten vapaamuotoisten ikkunoiden tuki käyttöön"</string>
- <string name="desktop_mode" msgid="2389067840550544462">"Työpöytätila"</string>
<string name="local_backup_password_title" msgid="4631017948933578709">"Varmuuskop. salasana"</string>
<string name="local_backup_password_summary_none" msgid="7646898032616361714">"Tietokoneen kaikkien tietojen varmuuskopiointia ei ole tällä hetkellä suojattu"</string>
<string name="local_backup_password_summary_change" msgid="1707357670383995567">"Vaihda tai poista tietokoneen kaikkien tietojen varmuuskopioinnin salasana koskettamalla."</string>
diff --git a/packages/SettingsLib/res/values-fr-rCA/strings.xml b/packages/SettingsLib/res/values-fr-rCA/strings.xml
index f3c92e16276a..f48bfcb4eb75 100644
--- a/packages/SettingsLib/res/values-fr-rCA/strings.xml
+++ b/packages/SettingsLib/res/values-fr-rCA/strings.xml
@@ -403,7 +403,6 @@
<string name="force_resizable_activities_summary" msgid="2490382056981583062">"Permet de redimensionner toutes les activités pour le mode multi-fenêtre, indépendamment des valeurs du fichier manifeste."</string>
<string name="enable_freeform_support" msgid="7599125687603914253">"Activer les fenêtres de forme libre"</string>
<string name="enable_freeform_support_summary" msgid="1822862728719276331">"Activer la compatibilité avec les fenêtres de forme libre expérimentales."</string>
- <string name="desktop_mode" msgid="2389067840550544462">"Mode Bureau"</string>
<string name="local_backup_password_title" msgid="4631017948933578709">"Mot de passe sauvegarde PC"</string>
<string name="local_backup_password_summary_none" msgid="7646898032616361714">"Les sauvegardes complètes sur PC ne sont pas protégées actuellement"</string>
<string name="local_backup_password_summary_change" msgid="1707357670383995567">"Touchez pour modifier ou supprimer le mot de passe utilisé pour les sauvegardes complètes sur ordinateur."</string>
diff --git a/packages/SettingsLib/res/values-fr/strings.xml b/packages/SettingsLib/res/values-fr/strings.xml
index 8e84b0b5ed52..ca5edfe44227 100644
--- a/packages/SettingsLib/res/values-fr/strings.xml
+++ b/packages/SettingsLib/res/values-fr/strings.xml
@@ -403,7 +403,6 @@
<string name="force_resizable_activities_summary" msgid="2490382056981583062">"Rendre toutes les activités redimensionnables pour le mode multifenêtre, indépendamment des valeurs du fichier manifeste"</string>
<string name="enable_freeform_support" msgid="7599125687603914253">"Activer les fenêtres de forme libre"</string>
<string name="enable_freeform_support_summary" msgid="1822862728719276331">"Activer la compatibilité avec les fenêtres de forme libre expérimentales"</string>
- <string name="desktop_mode" msgid="2389067840550544462">"Mode ordinateur"</string>
<string name="local_backup_password_title" msgid="4631017948933578709">"Mot de passe de sauvegarde ordi"</string>
<string name="local_backup_password_summary_none" msgid="7646898032616361714">"Les sauvegardes complètes sur ordi ne sont actuellement pas protégées"</string>
<string name="local_backup_password_summary_change" msgid="1707357670383995567">"Appuyez pour modifier ou supprimer le mot de passe des sauvegardes complètes sur ordi."</string>
diff --git a/packages/SettingsLib/res/values-gl/strings.xml b/packages/SettingsLib/res/values-gl/strings.xml
index d78ab179b737..61b01f63e687 100644
--- a/packages/SettingsLib/res/values-gl/strings.xml
+++ b/packages/SettingsLib/res/values-gl/strings.xml
@@ -403,7 +403,6 @@
<string name="force_resizable_activities_summary" msgid="2490382056981583062">"Permite axustar o tamaño de todas as actividades para o modo multiventá, independentemente dos valores do manifesto"</string>
<string name="enable_freeform_support" msgid="7599125687603914253">"Activar ventás de forma libre"</string>
<string name="enable_freeform_support_summary" msgid="1822862728719276331">"Activa a compatibilidade con ventás de forma libre experimentais"</string>
- <string name="desktop_mode" msgid="2389067840550544462">"Modo de escritorio"</string>
<string name="local_backup_password_title" msgid="4631017948933578709">"Contrasinal para copias"</string>
<string name="local_backup_password_summary_none" msgid="7646898032616361714">"As copias de seguranza de ordenador completas non están protexidas"</string>
<string name="local_backup_password_summary_change" msgid="1707357670383995567">"Toca para cambiar ou quitar o contrasinal para as copias de seguranza completas de ordenador"</string>
diff --git a/packages/SettingsLib/res/values-gu/strings.xml b/packages/SettingsLib/res/values-gu/strings.xml
index 2301bfd887c2..981cf57d734e 100644
--- a/packages/SettingsLib/res/values-gu/strings.xml
+++ b/packages/SettingsLib/res/values-gu/strings.xml
@@ -174,7 +174,7 @@
<string name="launch_defaults_some" msgid="3631650616557252926">"કેટલાંક ડિફોલ્ટ્સ સેટ કરેલ છે"</string>
<string name="launch_defaults_none" msgid="8049374306261262709">"કોઈ ડિફૉલ્ટ સેટ કરેલા નથી"</string>
<string name="tts_settings" msgid="8130616705989351312">"ટેક્સ્ટ ટૂ સ્પીચ સેટિંગ"</string>
- <string name="tts_settings_title" msgid="7602210956640483039">"ટેક્સ્ટ ટુ સ્પીચ આઉટપુટ"</string>
+ <string name="tts_settings_title" msgid="7602210956640483039">"ટેક્સ્ટ ટૂ સ્પીચ આઉટપુટ"</string>
<string name="tts_default_rate_title" msgid="3964187817364304022">"સ્પીચ રેટ"</string>
<string name="tts_default_rate_summary" msgid="3781937042151716987">"ટેક્સ્ટ બોલાયેલ છે તે ઝડપ"</string>
<string name="tts_default_pitch_title" msgid="6988592215554485479">"પિચ"</string>
@@ -403,7 +403,6 @@
<string name="force_resizable_activities_summary" msgid="2490382056981583062">"મૅનિફેસ્ટ મૂલ્યોને ધ્યાનમાં લીધા સિવાય, તમામ પ્રવૃત્તિઓને મલ્ટી-વિન્ડો માટે ફરીથી કદ બદલી શકે તેવી બનાવો."</string>
<string name="enable_freeform_support" msgid="7599125687603914253">"ફ્રીફોર્મ વિન્ડો ચાલુ કરો"</string>
<string name="enable_freeform_support_summary" msgid="1822862728719276331">"પ્રાયોગિક ફ્રીફોર્મ વિન્ડો માટે સપોર્ટને ચાલુ કરો."</string>
- <string name="desktop_mode" msgid="2389067840550544462">"ડેસ્કટૉપ મોડ"</string>
<string name="local_backup_password_title" msgid="4631017948933578709">"ડેસ્કટૉપ બૅકઅપ પાસવર્ડ"</string>
<string name="local_backup_password_summary_none" msgid="7646898032616361714">"ડેસ્કટૉપ સંપૂર્ણ બૅકઅપ હાલમાં સુરક્ષિત નથી"</string>
<string name="local_backup_password_summary_change" msgid="1707357670383995567">"ડેસ્કટૉપ સંપૂર્ણ બેકઅપ્સ માટેનો પાસવર્ડ બદલવા અથવા દૂર કરવા માટે ટૅચ કરો"</string>
diff --git a/packages/SettingsLib/res/values-hi/strings.xml b/packages/SettingsLib/res/values-hi/strings.xml
index 363793c2a8ce..9be1cd68b789 100644
--- a/packages/SettingsLib/res/values-hi/strings.xml
+++ b/packages/SettingsLib/res/values-hi/strings.xml
@@ -403,7 +403,6 @@
<string name="force_resizable_activities_summary" msgid="2490382056981583062">"सभी गतिविधियों को मल्टी-विंडो (एक से ज़्यादा ऐप्लिकेशन, एक साथ) के लिए साइज़ बदलने लायक बनाएं, चाहे उनकी मेनिफ़ेस्ट वैल्यू कुछ भी हो."</string>
<string name="enable_freeform_support" msgid="7599125687603914253">"फ़्रीफ़ॉर्म विंडो (एक साथ कई विंडो दिखाना) चालू करें"</string>
<string name="enable_freeform_support_summary" msgid="1822862728719276331">"फ़्रीफ़ॉर्म विंडो आज़माने की सुविधा चालू करें."</string>
- <string name="desktop_mode" msgid="2389067840550544462">"डेस्कटॉप मोड"</string>
<string name="local_backup_password_title" msgid="4631017948933578709">"डेस्‍कटॉप बैकअप पासवर्ड"</string>
<string name="local_backup_password_summary_none" msgid="7646898032616361714">"डेस्‍कटॉप का पूरा बैकअप फ़िलहाल सुरक्षित नहीं है"</string>
<string name="local_backup_password_summary_change" msgid="1707357670383995567">"डेस्कटॉप के पूरे बैक अप का पासवर्ड बदलने या हटाने के लिए टैप करें"</string>
diff --git a/packages/SettingsLib/res/values-hr/strings.xml b/packages/SettingsLib/res/values-hr/strings.xml
index 8be767609dc5..8a0114a0d636 100644
--- a/packages/SettingsLib/res/values-hr/strings.xml
+++ b/packages/SettingsLib/res/values-hr/strings.xml
@@ -403,7 +403,6 @@
<string name="force_resizable_activities_summary" msgid="2490382056981583062">"Omogući mijenjanje veličine svih aktivnosti za više prozora, neovisno o vrijednostima manifesta."</string>
<string name="enable_freeform_support" msgid="7599125687603914253">"Omogući prozore slobodnog oblika"</string>
<string name="enable_freeform_support_summary" msgid="1822862728719276331">"Omogućuje podršku za eksperimentalne prozore slobodnog oblika."</string>
- <string name="desktop_mode" msgid="2389067840550544462">"Stolni način rada"</string>
<string name="local_backup_password_title" msgid="4631017948933578709">"Zaporka sigurnosne kopije"</string>
<string name="local_backup_password_summary_none" msgid="7646898032616361714">"Potpune sigurnosne kopije na stolnom računalu trenutačno nisu zaštićene"</string>
<string name="local_backup_password_summary_change" msgid="1707357670383995567">"Dodirnite da biste promijenili ili uklonili zaporku za potpune sigurnosne kopije na računalu"</string>
diff --git a/packages/SettingsLib/res/values-hu/strings.xml b/packages/SettingsLib/res/values-hu/strings.xml
index 6885a07cc71e..b5e1e01587b5 100644
--- a/packages/SettingsLib/res/values-hu/strings.xml
+++ b/packages/SettingsLib/res/values-hu/strings.xml
@@ -403,7 +403,6 @@
<string name="force_resizable_activities_summary" msgid="2490382056981583062">"Legyen az összes tevékenység átméretezhető a többablakos megjelenítés érdekében a jegyzékértékektől függetlenül."</string>
<string name="enable_freeform_support" msgid="7599125687603914253">"Szabad formájú ablakok engedélyezése"</string>
<string name="enable_freeform_support_summary" msgid="1822862728719276331">"Kísérleti, szabad formájú ablakok támogatásának engedélyezése."</string>
- <string name="desktop_mode" msgid="2389067840550544462">"Asztali üzemmód"</string>
<string name="local_backup_password_title" msgid="4631017948933578709">"Asztali mentés jelszava"</string>
<string name="local_backup_password_summary_none" msgid="7646898032616361714">"Az asztali teljes biztonsági mentések jelenleg nem védettek."</string>
<string name="local_backup_password_summary_change" msgid="1707357670383995567">"Koppintson ide az asztali teljes mentések jelszavának módosításához vagy eltávolításához"</string>
diff --git a/packages/SettingsLib/res/values-hy/strings.xml b/packages/SettingsLib/res/values-hy/strings.xml
index c77769e83cf0..9808f709fdcb 100644
--- a/packages/SettingsLib/res/values-hy/strings.xml
+++ b/packages/SettingsLib/res/values-hy/strings.xml
@@ -403,7 +403,6 @@
<string name="force_resizable_activities_summary" msgid="2490382056981583062">"Բոլոր ակտիվությունների չափերը բազմապատուհան ռեժիմի համար դարձնել փոփոխելի՝ մանիֆեստի արժեքներից անկախ:"</string>
<string name="enable_freeform_support" msgid="7599125687603914253">"Ակտիվացնել կամայական ձևի պատուհանները"</string>
<string name="enable_freeform_support_summary" msgid="1822862728719276331">"Միացնել ազատ ձևի փորձնական պատուհանների աջակցումը:"</string>
- <string name="desktop_mode" msgid="2389067840550544462">"Համակարգչի ռեժիմ"</string>
<string name="local_backup_password_title" msgid="4631017948933578709">"Աշխատասեղանի պահուստավորման գաղտնաբառ"</string>
<string name="local_backup_password_summary_none" msgid="7646898032616361714">"Աշխատասեղանի ամբողջական պահուստավորումները այժմ պաշտպանված չեն"</string>
<string name="local_backup_password_summary_change" msgid="1707357670383995567">"Հպեք՝ աշխատասեղանի ամբողջական պահուստավորման գաղտնաբառը փոխելու կամ հեռացնելու համար"</string>
diff --git a/packages/SettingsLib/res/values-in/strings.xml b/packages/SettingsLib/res/values-in/strings.xml
index 2168e8fd8482..7d70b88844ba 100644
--- a/packages/SettingsLib/res/values-in/strings.xml
+++ b/packages/SettingsLib/res/values-in/strings.xml
@@ -403,7 +403,6 @@
<string name="force_resizable_activities_summary" msgid="2490382056981583062">"Membuat semua aktivitas dapat diubah ukurannya untuk banyak jendela, terlepas dari nilai manifes."</string>
<string name="enable_freeform_support" msgid="7599125687603914253">"Aktifkan jendela berformat bebas"</string>
<string name="enable_freeform_support_summary" msgid="1822862728719276331">"Aktifkan dukungan untuk jendela eksperimental berformat bebas."</string>
- <string name="desktop_mode" msgid="2389067840550544462">"Mode desktop"</string>
<string name="local_backup_password_title" msgid="4631017948933578709">"Sandi cadangan desktop"</string>
<string name="local_backup_password_summary_none" msgid="7646898032616361714">"Saat ini cadangan desktop penuh tidak dilindungi"</string>
<string name="local_backup_password_summary_change" msgid="1707357670383995567">"Ketuk guna mengubah atau menghapus sandi untuk cadangan lengkap desktop"</string>
diff --git a/packages/SettingsLib/res/values-is/strings.xml b/packages/SettingsLib/res/values-is/strings.xml
index 46eb90c93312..650f76d990f4 100644
--- a/packages/SettingsLib/res/values-is/strings.xml
+++ b/packages/SettingsLib/res/values-is/strings.xml
@@ -403,7 +403,6 @@
<string name="force_resizable_activities_summary" msgid="2490382056981583062">"Gera stærð allrar virkni breytanlega svo að hún henti fyrir marga glugga, óháð gildum í upplýsingaskrá."</string>
<string name="enable_freeform_support" msgid="7599125687603914253">"Virkja glugga með frjálsu sniði"</string>
<string name="enable_freeform_support_summary" msgid="1822862728719276331">"Virkja stuðning við glugga með frjálsu sniði á tilraunastigi."</string>
- <string name="desktop_mode" msgid="2389067840550544462">"Skjáborðsstilling"</string>
<string name="local_backup_password_title" msgid="4631017948933578709">"Aðgangsorð tölvuafritunar"</string>
<string name="local_backup_password_summary_none" msgid="7646898032616361714">"Heildarafritun á tölvu er ekki varin sem stendur."</string>
<string name="local_backup_password_summary_change" msgid="1707357670383995567">"Ýttu til að breyta eða fjarlægja aðgangsorðið fyrir heildarafritun á tölvu"</string>
diff --git a/packages/SettingsLib/res/values-it/strings.xml b/packages/SettingsLib/res/values-it/strings.xml
index bbe04122f033..d783bf1b4e71 100644
--- a/packages/SettingsLib/res/values-it/strings.xml
+++ b/packages/SettingsLib/res/values-it/strings.xml
@@ -403,7 +403,6 @@
<string name="force_resizable_activities_summary" msgid="2490382056981583062">"Rendi il formato di tutte le attività modificabile per la modalità multi-finestra, indipendentemente dai valori manifest"</string>
<string name="enable_freeform_support" msgid="7599125687603914253">"Attiva finestre a forma libera"</string>
<string name="enable_freeform_support_summary" msgid="1822862728719276331">"Attiva il supporto delle finestre a forma libera sperimentali"</string>
- <string name="desktop_mode" msgid="2389067840550544462">"Modalità desktop"</string>
<string name="local_backup_password_title" msgid="4631017948933578709">"Password di backup desktop"</string>
<string name="local_backup_password_summary_none" msgid="7646898032616361714">"I backup desktop completi non sono attualmente protetti"</string>
<string name="local_backup_password_summary_change" msgid="1707357670383995567">"Tocca per modificare o rimuovere la password per i backup desktop completi"</string>
diff --git a/packages/SettingsLib/res/values-iw/strings.xml b/packages/SettingsLib/res/values-iw/strings.xml
index 85e3a53dbfb1..fc83630c30cb 100644
--- a/packages/SettingsLib/res/values-iw/strings.xml
+++ b/packages/SettingsLib/res/values-iw/strings.xml
@@ -403,7 +403,6 @@
<string name="force_resizable_activities_summary" msgid="2490382056981583062">"מאפשר יכולת קביעת גודל של כל הפעילויות לריבוי חלונות, ללא התחשבות בערכי המניפסט."</string>
<string name="enable_freeform_support" msgid="7599125687603914253">"הפעלת האפשרות לשנות את הגודל והמיקום של החלונות"</string>
<string name="enable_freeform_support_summary" msgid="1822862728719276331">"הפעלת תמיכה בתכונה הניסיונית של שינוי הגודל והמיקום של החלונות."</string>
- <string name="desktop_mode" msgid="2389067840550544462">"ממשק המחשב"</string>
<string name="local_backup_password_title" msgid="4631017948933578709">"סיסמת גיבוי שולחן העבודה"</string>
<string name="local_backup_password_summary_none" msgid="7646898032616361714">"גיבויים מלאים בשולחן העבודה אינם מוגנים כעת"</string>
<string name="local_backup_password_summary_change" msgid="1707357670383995567">"יש להקיש כדי לשנות או להסיר את הסיסמה לגיבויים מלאים בשולחן העבודה"</string>
diff --git a/packages/SettingsLib/res/values-ja/strings.xml b/packages/SettingsLib/res/values-ja/strings.xml
index 71e70ba9ed5e..3f090830de40 100644
--- a/packages/SettingsLib/res/values-ja/strings.xml
+++ b/packages/SettingsLib/res/values-ja/strings.xml
@@ -403,7 +403,6 @@
<string name="force_resizable_activities_summary" msgid="2490382056981583062">"マニフェストの値に関係なく、マルチウィンドウですべてのアクティビティのサイズを変更できるようにします。"</string>
<string name="enable_freeform_support" msgid="7599125687603914253">"フリーフォーム ウィンドウを有効にする"</string>
<string name="enable_freeform_support_summary" msgid="1822862728719276331">"試験運用機能のフリーフォーム ウィンドウのサポートを有効にします。"</string>
- <string name="desktop_mode" msgid="2389067840550544462">"デスクトップ モード"</string>
<string name="local_backup_password_title" msgid="4631017948933578709">"PC バックアップ パスワード"</string>
<string name="local_backup_password_summary_none" msgid="7646898032616361714">"デスクトップのフルバックアップは現在保護されていません"</string>
<string name="local_backup_password_summary_change" msgid="1707357670383995567">"デスクトップのフルバックアップ用のパスワードを変更または削除する場合にタップします"</string>
diff --git a/packages/SettingsLib/res/values-ka/strings.xml b/packages/SettingsLib/res/values-ka/strings.xml
index fa7db4ad901d..ed7c8d7cd207 100644
--- a/packages/SettingsLib/res/values-ka/strings.xml
+++ b/packages/SettingsLib/res/values-ka/strings.xml
@@ -403,7 +403,6 @@
<string name="force_resizable_activities_summary" msgid="2490382056981583062">"მანიფესტის მნიშვნელობების მიუხედავად, მრავალი ფანჯრის რეჟიმისთვის ყველა აქტივობის ზომაცვლადად გადაქცევა."</string>
<string name="enable_freeform_support" msgid="7599125687603914253">"თავისუფალი ფორმის მქონე ფანჯრების ჩართვა"</string>
<string name="enable_freeform_support_summary" msgid="1822862728719276331">"თავისუფალი ფორმის მქონე ფანჯრების მხარდაჭერის ექსპერიმენტული ფუნქციის ჩართვა."</string>
- <string name="desktop_mode" msgid="2389067840550544462">"დესკტოპის რეჟიმი"</string>
<string name="local_backup_password_title" msgid="4631017948933578709">"დესკტოპის სარეზერვო ასლის პაროლი"</string>
<string name="local_backup_password_summary_none" msgid="7646898032616361714">"დესკტოპის სრული სარეზერვო ასლები ამჟამად დაცული არ არის"</string>
<string name="local_backup_password_summary_change" msgid="1707357670383995567">"შეეხეთ დესკტოპის სრული სარეზერვო ასლების პაროლის შესაცვლელად ან წასაშლელად"</string>
diff --git a/packages/SettingsLib/res/values-kk/strings.xml b/packages/SettingsLib/res/values-kk/strings.xml
index efac4e830270..982000f68852 100644
--- a/packages/SettingsLib/res/values-kk/strings.xml
+++ b/packages/SettingsLib/res/values-kk/strings.xml
@@ -403,7 +403,6 @@
<string name="force_resizable_activities_summary" msgid="2490382056981583062">"Манифест мәндеріне қарамастан, бірнеше терезе режимінде барлық әрекеттердің өлшемін өзгертуге рұқсат беру"</string>
<string name="enable_freeform_support" msgid="7599125687603914253">"Еркін пішінді терезелерге рұқсат беру"</string>
<string name="enable_freeform_support_summary" msgid="1822862728719276331">"Еркін пішінді терезелерді құру эксперименттік функиясын қосу"</string>
- <string name="desktop_mode" msgid="2389067840550544462">"Компьютер режимі"</string>
<string name="local_backup_password_title" msgid="4631017948933578709">"Компьютердегі сақтық көшірме құпия сөзі"</string>
<string name="local_backup_password_summary_none" msgid="7646898032616361714">"Компьютердегі толық сақтық көшірмелер қазір қорғалмаған."</string>
<string name="local_backup_password_summary_change" msgid="1707357670383995567">"Үстелдік компьютердің толық сақтық көшірмелерінің кілтсөзін өзгерту немесе жою үшін түртіңіз"</string>
diff --git a/packages/SettingsLib/res/values-km/strings.xml b/packages/SettingsLib/res/values-km/strings.xml
index 11c71cac8158..26bb1e27661c 100644
--- a/packages/SettingsLib/res/values-km/strings.xml
+++ b/packages/SettingsLib/res/values-km/strings.xml
@@ -403,7 +403,6 @@
<string name="force_resizable_activities_summary" msgid="2490382056981583062">"ធ្វើឲ្យសកម្មភាពទាំងអស់អាចប្តូរទំហំបានសម្រាប់ពហុវិនដូ ដោយមិនគិតពីតម្លៃមេនីហ្វេសថ៍។"</string>
<string name="enable_freeform_support" msgid="7599125687603914253">"បើកដំណើរការផ្ទាំងវិនដូទម្រង់សេរី"</string>
<string name="enable_freeform_support_summary" msgid="1822862728719276331">"បើកឱ្យអាចប្រើផ្ទាំងវិនដូទម្រង់សេរីពិសោធន៍។"</string>
- <string name="desktop_mode" msgid="2389067840550544462">"មុខងារកុំព្យូទ័រ"</string>
<string name="local_backup_password_title" msgid="4631017948933578709">"ពាក្យ​សម្ងាត់​បម្រុង​ទុក​លើកុំព្យូទ័រ"</string>
<string name="local_backup_password_summary_none" msgid="7646898032616361714">"បច្ចុប្បន្ន ការ​បម្រុង​ទុក​ពេញលេញនៅលើកុំព្យូទ័រមិន​ត្រូវ​បាន​ការពារ​ទេ"</string>
<string name="local_backup_password_summary_change" msgid="1707357670383995567">"ប៉ះដើម្បីប្ដូរ ឬយកពាក្យសម្ងាត់ចេញសម្រាប់ការបម្រុងទុកពេញលេញលើកុំព្យូទ័រ"</string>
diff --git a/packages/SettingsLib/res/values-kn/strings.xml b/packages/SettingsLib/res/values-kn/strings.xml
index fa3dbaf3a0d6..5a09396480e7 100644
--- a/packages/SettingsLib/res/values-kn/strings.xml
+++ b/packages/SettingsLib/res/values-kn/strings.xml
@@ -403,7 +403,6 @@
<string name="force_resizable_activities_summary" msgid="2490382056981583062">"ಮ್ಯಾನಿಫೆಸ್ಟ್ ಮೌಲ್ಯಗಳನ್ನು ಪರಿಗಣಿಸದೇ, ಬಹು-ವಿಂಡೊಗೆ ಎಲ್ಲಾ ಚಟುವಟಿಕೆಗಳನ್ನು ಮರುಗಾತ್ರಗೊಳಿಸುವಂತೆ ಮಾಡಿ."</string>
<string name="enable_freeform_support" msgid="7599125687603914253">"ಮುಕ್ತಸ್ವರೂಪದ ವಿಂಡೊಗಳನ್ನು ಸಕ್ರಿಯಗೊಳಿಸಿ"</string>
<string name="enable_freeform_support_summary" msgid="1822862728719276331">"ಪ್ರಾಯೋಗಿಕ ಫ್ರೀಫಾರ್ಮ್ ವಿಂಡೊಗಳಿಗೆ ಬೆಂಬಲವನ್ನು ಸಕ್ರಿಯಗೊಳಿಸಿ."</string>
- <string name="desktop_mode" msgid="2389067840550544462">"ಡೆಸ್ಕ್‌ಟಾಪ್ ಮೋಡ್"</string>
<string name="local_backup_password_title" msgid="4631017948933578709">"ಡೆಸ್ಕ್‌ಟಾಪ್ ಬ್ಯಾಕಪ್ ಪಾಸ್‌ವರ್ಡ್"</string>
<string name="local_backup_password_summary_none" msgid="7646898032616361714">"ಡೆಸ್ಕ್‌ಟಾಪ್‌‌ನ ಪೂರ್ಣ ಬ್ಯಾಕಪ್‌‌ಗಳನ್ನು ಪ್ರಸ್ತುತ ರಕ್ಷಿಸಲಾಗಿಲ್ಲ"</string>
<string name="local_backup_password_summary_change" msgid="1707357670383995567">"ಡೆಸ್ಕ್‌ಟಾಪ್‌ನ ಪೂರ್ಣ ಬ್ಯಾಕಪ್‌ಗಳಿಗೆ ಪಾಸ್‌ವರ್ಡ್‌ ಬದಲಾಯಿಸಲು ಅಥವಾ ತೆಗೆದುಹಾಕಲು ಟ್ಯಾಪ್ ಮಾಡಿ"</string>
diff --git a/packages/SettingsLib/res/values-ko/strings.xml b/packages/SettingsLib/res/values-ko/strings.xml
index f4841338ec6d..1c5fd76ad7b6 100644
--- a/packages/SettingsLib/res/values-ko/strings.xml
+++ b/packages/SettingsLib/res/values-ko/strings.xml
@@ -403,7 +403,6 @@
<string name="force_resizable_activities_summary" msgid="2490382056981583062">"모든 활동을 매니페스트 값에 관계없이 멀티 윈도우용으로 크기 조정 가능하도록 설정"</string>
<string name="enable_freeform_support" msgid="7599125687603914253">"자유 형식 창 사용"</string>
<string name="enable_freeform_support_summary" msgid="1822862728719276331">"자유 형식 창 지원 사용"</string>
- <string name="desktop_mode" msgid="2389067840550544462">"데스크톱 모드"</string>
<string name="local_backup_password_title" msgid="4631017948933578709">"데스크톱 백업 비밀번호"</string>
<string name="local_backup_password_summary_none" msgid="7646898032616361714">"데스크톱 전체 백업에 비밀번호가 설정되어 있지 않음"</string>
<string name="local_backup_password_summary_change" msgid="1707357670383995567">"데스크톱 전체 백업에 대한 비밀번호를 변경하거나 삭제하려면 탭하세요."</string>
diff --git a/packages/SettingsLib/res/values-ky/strings.xml b/packages/SettingsLib/res/values-ky/strings.xml
index bde9b08cf716..4ad4306286bd 100644
--- a/packages/SettingsLib/res/values-ky/strings.xml
+++ b/packages/SettingsLib/res/values-ky/strings.xml
@@ -403,7 +403,6 @@
<string name="force_resizable_activities_summary" msgid="2490382056981583062">"Бир нече терезе режиминде өлчөмдү өзгөртүүгө уруксат берет (манифесттин маанилерине карабастан)"</string>
<string name="enable_freeform_support" msgid="7599125687603914253">"Эркин формадагы терезелерди түзүүнү иштетүү"</string>
<string name="enable_freeform_support_summary" msgid="1822862728719276331">"Эркин формадагы терезелерди түзүү боюнча сынамык функциясы иштетилет."</string>
- <string name="desktop_mode" msgid="2389067840550544462">"Компьютер режими"</string>
<string name="local_backup_password_title" msgid="4631017948933578709">"Камдык көчүрмөнүн сырсөзү"</string>
<string name="local_backup_password_summary_none" msgid="7646898032616361714">"Толук камдык көчүрмөлөр учурда корголгон эмес"</string>
<string name="local_backup_password_summary_change" msgid="1707357670383995567">"Иш тактасынын камдалган сырсөзүн өзгөртүү же алып салуу үчүн таптап коюңуз"</string>
diff --git a/packages/SettingsLib/res/values-lo/strings.xml b/packages/SettingsLib/res/values-lo/strings.xml
index 2f4e7ff6dd5e..fe8b4db7db09 100644
--- a/packages/SettingsLib/res/values-lo/strings.xml
+++ b/packages/SettingsLib/res/values-lo/strings.xml
@@ -403,7 +403,6 @@
<string name="force_resizable_activities_summary" msgid="2490382056981583062">"ເຮັດໃຫ້ທຸກການ​ເຄື່ອນ​ໄຫວສາມາດປັບຂະໜາດໄດ້ສຳລັບຫຼາຍໜ້າຈໍ, ໂດຍບໍ່ຄຳນຶງເຖິງຄ່າ manifest."</string>
<string name="enable_freeform_support" msgid="7599125687603914253">"ເປີດໃຊ້ໜ້າຈໍຮູບແບບອິດສະຫຼະ"</string>
<string name="enable_freeform_support_summary" msgid="1822862728719276331">"ເປີດໃຊ້ການຮອງຮັບໜ້າຈໍຮູບແບບອິດສະຫຼະແບບທົດລອງ."</string>
- <string name="desktop_mode" msgid="2389067840550544462">"ໂໝດເດັສທັອບ"</string>
<string name="local_backup_password_title" msgid="4631017948933578709">"ລະຫັດຜ່ານການສຳຮອງຂໍ້ມູນເດັສທັອບ"</string>
<string name="local_backup_password_summary_none" msgid="7646898032616361714">"ການ​ສຳຮອງ​ຂໍ້ມູນ​ເຕັມຮູບແບບ​ໃນ​ເດັສທັອບ​ຍັງ​ບໍ່​ໄດ້​ຮັບ​ການ​ປ້ອງກັນ​ໃນ​ເວລາ​ນີ້"</string>
<string name="local_backup_password_summary_change" msgid="1707357670383995567">"ແຕະເພື່ອປ່ຽນ ຫຼື ລຶບລະຫັດຂອງການສຳຮອງຂໍ້ມູນເຕັມຮູບແບບໃນເດັສທັອບ"</string>
diff --git a/packages/SettingsLib/res/values-lt/strings.xml b/packages/SettingsLib/res/values-lt/strings.xml
index 59ab47b7b0d4..e4546e1db323 100644
--- a/packages/SettingsLib/res/values-lt/strings.xml
+++ b/packages/SettingsLib/res/values-lt/strings.xml
@@ -403,7 +403,6 @@
<string name="force_resizable_activities_summary" msgid="2490382056981583062">"Nustatyti, kad visus veiksmus būtų galima atlikti kelių dydžių languose, nepaisant aprašo verčių."</string>
<string name="enable_freeform_support" msgid="7599125687603914253">"Įgalinti laisvos formos langus"</string>
<string name="enable_freeform_support_summary" msgid="1822862728719276331">"Įgalinti eksperimentinių laisvos formos langų palaikymą."</string>
- <string name="desktop_mode" msgid="2389067840550544462">"Stalinio komp. režimas"</string>
<string name="local_backup_password_title" msgid="4631017948933578709">"Viet. atsrg. kop. slapt."</string>
<string name="local_backup_password_summary_none" msgid="7646898032616361714">"Šiuo metu visos vietinės atsarginės kopijos neapsaugotos"</string>
<string name="local_backup_password_summary_change" msgid="1707357670383995567">"Jei norite pakeisti ar pašalinti visų stalinio kompiuterio atsarginių kopijų slaptažodį, palieskite"</string>
diff --git a/packages/SettingsLib/res/values-lv/strings.xml b/packages/SettingsLib/res/values-lv/strings.xml
index a04bd54094de..e9410a20ba5a 100644
--- a/packages/SettingsLib/res/values-lv/strings.xml
+++ b/packages/SettingsLib/res/values-lv/strings.xml
@@ -403,7 +403,6 @@
<string name="force_resizable_activities_summary" msgid="2490382056981583062">"Pielāgot visas darbības vairāku logu režīmam neatkarīgi no vērtībām manifestā."</string>
<string name="enable_freeform_support" msgid="7599125687603914253">"Iespējot brīvās formas logus"</string>
<string name="enable_freeform_support_summary" msgid="1822862728719276331">"Iespējot eksperimentālo brīvās formas logu atbalstu."</string>
- <string name="desktop_mode" msgid="2389067840550544462">"Darbvirsmas režīms"</string>
<string name="local_backup_password_title" msgid="4631017948933578709">"Datora dublējuma parole"</string>
<string name="local_backup_password_summary_none" msgid="7646898032616361714">"Darbvirsmas pilnie dublējumi pašlaik nav aizsargāti."</string>
<string name="local_backup_password_summary_change" msgid="1707357670383995567">"Pieskarieties, lai mainītu vai noņemtu paroli pilniem datora dublējumiem."</string>
diff --git a/packages/SettingsLib/res/values-mk/strings.xml b/packages/SettingsLib/res/values-mk/strings.xml
index 37a448fac04e..4866e6ad8f08 100644
--- a/packages/SettingsLib/res/values-mk/strings.xml
+++ b/packages/SettingsLib/res/values-mk/strings.xml
@@ -403,7 +403,6 @@
<string name="force_resizable_activities_summary" msgid="2490382056981583062">"Сите активности ќе имаат променлива големина во режимот со повеќе прозорци, независно од вредностите на манифестот."</string>
<string name="enable_freeform_support" msgid="7599125687603914253">"Овозможи прозорци со слободна форма"</string>
<string name="enable_freeform_support_summary" msgid="1822862728719276331">"Овозможи поддршка за експериментални прозорци со слободна форма."</string>
- <string name="desktop_mode" msgid="2389067840550544462">"Режим за компјутер"</string>
<string name="local_backup_password_title" msgid="4631017948933578709">"Лозинка за бекап на компјутер"</string>
<string name="local_backup_password_summary_none" msgid="7646898032616361714">"Целосниот бекап на компјутерот во моментов не е заштитен"</string>
<string name="local_backup_password_summary_change" msgid="1707357670383995567">"Допрете за да се промени или отстрани лозинката за целосен бекап на компјутерот"</string>
diff --git a/packages/SettingsLib/res/values-ml/strings.xml b/packages/SettingsLib/res/values-ml/strings.xml
index 452a9959740d..78a3968bb0d5 100644
--- a/packages/SettingsLib/res/values-ml/strings.xml
+++ b/packages/SettingsLib/res/values-ml/strings.xml
@@ -403,7 +403,6 @@
<string name="force_resizable_activities_summary" msgid="2490382056981583062">"മാനിഫെസ്റ്റ് മൂല്യങ്ങൾ പരിഗണിക്കാതെ, എല്ലാ ആക്ടിവിറ്റികളെയും മൾട്ടി-വിൻഡോയ്ക്കായി വലുപ്പം മാറ്റുക."</string>
<string name="enable_freeform_support" msgid="7599125687603914253">"ഫ്രീഫോം വിൻഡോകൾ പ്രവർത്തനക്ഷമമാക്കുക"</string>
<string name="enable_freeform_support_summary" msgid="1822862728719276331">"പരീക്ഷണാത്മക ഫ്രീഫോം വിൻഡോകൾക്കുള്ള പിന്തുണ പ്രവർത്തനക്ഷമമാക്കുക."</string>
- <string name="desktop_mode" msgid="2389067840550544462">"ഡെസ്‌ക്ടോപ്പ് മോഡ്"</string>
<string name="local_backup_password_title" msgid="4631017948933578709">"ഡെ‌സ്‌ക്ടോപ്പ് ബാക്കപ്പ് പാസ്‌വേഡ്"</string>
<string name="local_backup_password_summary_none" msgid="7646898032616361714">"ഡെസ്‌ക്‌ടോപ്പ് പൂർണ്ണ ബാക്കപ്പുകൾ നിലവിൽ പരിരക്ഷിച്ചിട്ടില്ല"</string>
<string name="local_backup_password_summary_change" msgid="1707357670383995567">"ഡെസ്‌ക്‌ടോപ്പ് പൂർണ്ണ ബാക്കപ്പുകൾക്കായി പാസ്‌വേഡുകൾ മാറ്റാനോ നീക്കംചെയ്യാനോ ടാപ്പുചെയ്യുക"</string>
diff --git a/packages/SettingsLib/res/values-mn/strings.xml b/packages/SettingsLib/res/values-mn/strings.xml
index 6dfce5abac79..31f190ddd4fc 100644
--- a/packages/SettingsLib/res/values-mn/strings.xml
+++ b/packages/SettingsLib/res/values-mn/strings.xml
@@ -403,7 +403,6 @@
<string name="force_resizable_activities_summary" msgid="2490382056981583062">"Тодорхойлогч файлын утгыг үл хамааран, бүх үйл ажиллагааны хэмжээг олон цонхонд өөрчилж болохуйц болгоно уу."</string>
<string name="enable_freeform_support" msgid="7599125687603914253">"Чөлөөт хэлбэрийн цонхыг идэвхжүүлэх"</string>
<string name="enable_freeform_support_summary" msgid="1822862728719276331">"Туршилтын чөлөөт хэлбэрийн цонхны дэмжлэгийг идэвхжүүлнэ үү."</string>
- <string name="desktop_mode" msgid="2389067840550544462">"Дэлгэцийн горим"</string>
<string name="local_backup_password_title" msgid="4631017948933578709">"Компьютерын нөөцлөлтийн нууц үг"</string>
<string name="local_backup_password_summary_none" msgid="7646898032616361714">"Компьютерын бүрэн нөөцлөлт одоогоор хамгаалалтгүй байна"</string>
<string name="local_backup_password_summary_change" msgid="1707357670383995567">"Компьютерийн бүтэн нөөцлөлтийн нууц үгийг өөрчлөх, устгах бол дарна уу"</string>
diff --git a/packages/SettingsLib/res/values-mr/strings.xml b/packages/SettingsLib/res/values-mr/strings.xml
index 4db523ae311f..e5852ed726f1 100644
--- a/packages/SettingsLib/res/values-mr/strings.xml
+++ b/packages/SettingsLib/res/values-mr/strings.xml
@@ -403,7 +403,6 @@
<string name="force_resizable_activities_summary" msgid="2490382056981583062">"मॅनिफेस्‍ट मूल्ये काहीही असू देत, एकाहून अधिक विंडोसाठी सर्व अ‍ॅक्टिव्हिटीचा आकार बदलण्यायोग्य करा."</string>
<string name="enable_freeform_support" msgid="7599125687603914253">"freeform windows सुरू करा"</string>
<string name="enable_freeform_support_summary" msgid="1822862728719276331">"प्रायोगिक freeform windows साठी सपोर्ट सुरू करा."</string>
- <string name="desktop_mode" msgid="2389067840550544462">"डेस्कटॉप मोड"</string>
<string name="local_backup_password_title" msgid="4631017948933578709">"डेस्कटॉप बॅकअप पासवर्ड"</string>
<string name="local_backup_password_summary_none" msgid="7646898032616361714">"डेस्कटॉप पूर्ण बॅक अप सध्या संरक्षित नाहीत"</string>
<string name="local_backup_password_summary_change" msgid="1707357670383995567">"डेस्कटॉपच्या पूर्ण बॅकअपसाठी असलेला पासवर्ड बदलण्यासाठी किंवा काढण्यासाठी टॅप करा"</string>
diff --git a/packages/SettingsLib/res/values-ms/strings.xml b/packages/SettingsLib/res/values-ms/strings.xml
index ef2181298f4a..ca07d2bba3e3 100644
--- a/packages/SettingsLib/res/values-ms/strings.xml
+++ b/packages/SettingsLib/res/values-ms/strings.xml
@@ -403,7 +403,6 @@
<string name="force_resizable_activities_summary" msgid="2490382056981583062">"Bolehkan semua saiz aktiviti diubah untuk berbilang tetingkap, tanpa mengambil kira nilai manifes."</string>
<string name="enable_freeform_support" msgid="7599125687603914253">"Dayakan tetingkap bentuk bebas"</string>
<string name="enable_freeform_support_summary" msgid="1822862728719276331">"Dayakan sokongan untuk tetingkap bentuk bebas percubaan."</string>
- <string name="desktop_mode" msgid="2389067840550544462">"Mod desktop"</string>
<string name="local_backup_password_title" msgid="4631017948933578709">"Kata laluan sandaran komputer meja"</string>
<string name="local_backup_password_summary_none" msgid="7646898032616361714">"Sandaran penuh komputer meja tidak dilindungi pada masa ini"</string>
<string name="local_backup_password_summary_change" msgid="1707357670383995567">"Ketik untuk menukar atau mengalih keluar kata laluan untuk sandaran penuh desktop"</string>
diff --git a/packages/SettingsLib/res/values-my/strings.xml b/packages/SettingsLib/res/values-my/strings.xml
index 2e4a6c451966..0b9b3d1cefc0 100644
--- a/packages/SettingsLib/res/values-my/strings.xml
+++ b/packages/SettingsLib/res/values-my/strings.xml
@@ -403,7 +403,6 @@
<string name="force_resizable_activities_summary" msgid="2490382056981583062">"သတ်မှတ်တန်ဖိုး မည်သို့ပင်ရှိစေ ဝင်းဒိုးများ၏ လုပ်ဆောင်မှုအားလုံးကို အရွယ်အစားပြင်သည်။"</string>
<string name="enable_freeform_support" msgid="7599125687603914253">"ပုံစံမျိုးစုံ ဝင်းဒိုးများ ဖွင့်ရန်"</string>
<string name="enable_freeform_support_summary" msgid="1822862728719276331">"ပုံစံမျိုးစုံဝင်းဒိုးများ စမ်းသပ်ခြင်းအတွက် ပံ့ပိုးမှုကို ဖွင့်သည်"</string>
- <string name="desktop_mode" msgid="2389067840550544462">"ဒက်စ်တော့မုဒ်"</string>
<string name="local_backup_password_title" msgid="4631017948933578709">"ဒက်စ်တော့ အရန်စကားဝှက်"</string>
<string name="local_backup_password_summary_none" msgid="7646898032616361714">"ဒက်စ်တော့ အရန်သိမ်းဆည်းခြင်းအားလုံးကို လောလောဆယ် ကာကွယ်မထားပါ"</string>
<string name="local_backup_password_summary_change" msgid="1707357670383995567">"ဒက်စ်တော့ အပြည့်အဝ အရန်သိမ်းခြင်းအတွက် စကားဝှက်ကို ပြောင်းရန် သို့မဟုတ် ဖယ်ရှားရန် တို့ပါ။"</string>
diff --git a/packages/SettingsLib/res/values-nb/strings.xml b/packages/SettingsLib/res/values-nb/strings.xml
index e871ab9f41e7..e68a2b78394d 100644
--- a/packages/SettingsLib/res/values-nb/strings.xml
+++ b/packages/SettingsLib/res/values-nb/strings.xml
@@ -403,7 +403,6 @@
<string name="force_resizable_activities_summary" msgid="2490382056981583062">"Gjør at alle aktiviteter kan endre størrelse for flervindusmodus, uavhengig av manifestverdier."</string>
<string name="enable_freeform_support" msgid="7599125687603914253">"Slå på vinduer i fritt format"</string>
<string name="enable_freeform_support_summary" msgid="1822862728719276331">"Slå på støtte for vinduer i eksperimentelt fritt format."</string>
- <string name="desktop_mode" msgid="2389067840550544462">"Skrivebordmodus"</string>
<string name="local_backup_password_title" msgid="4631017948933578709">"Passord for sikkerhetskopiering på datamaskin"</string>
<string name="local_backup_password_summary_none" msgid="7646898032616361714">"Fullstendig sikkerhetskopiering på datamaskin er ikke beskyttet"</string>
<string name="local_backup_password_summary_change" msgid="1707357670383995567">"Trykk for å endre eller fjerne passordet for fullstendige sikkerhetskopier på datamaskinen"</string>
diff --git a/packages/SettingsLib/res/values-ne/strings.xml b/packages/SettingsLib/res/values-ne/strings.xml
index a48dd1e3ea12..e52b880a2919 100644
--- a/packages/SettingsLib/res/values-ne/strings.xml
+++ b/packages/SettingsLib/res/values-ne/strings.xml
@@ -403,7 +403,6 @@
<string name="force_resizable_activities_summary" msgid="2490382056981583062">"तोकिएको नियमको ख्याल नगरी एपलाई एकभन्दा बढी विन्डोमा रिसाइज गर्न सकिने बनाइयोस्।"</string>
<string name="enable_freeform_support" msgid="7599125687603914253">"फ्रिफर्म विन्डोहरू अन गरियोस्"</string>
<string name="enable_freeform_support_summary" msgid="1822862728719276331">"प्रयोगात्मक फ्रिफर्म विन्डोहरू चल्ने बनाइयोस्"</string>
- <string name="desktop_mode" msgid="2389067840550544462">"डेस्कटप मोड"</string>
<string name="local_backup_password_title" msgid="4631017948933578709">"डेस्कटप ब्याकअप पासवर्ड"</string>
<string name="local_backup_password_summary_none" msgid="7646898032616361714">"हाल डेस्कटपका सबै ब्याकअप पासवर्ड सुरक्षित छैनन्"</string>
<string name="local_backup_password_summary_change" msgid="1707357670383995567">"डेस्कटप पूर्ण ब्याकअपको लागि पासवर्ड बदल्न वा हटाउन ट्याप गर्नुहोस्"</string>
diff --git a/packages/SettingsLib/res/values-nl/strings.xml b/packages/SettingsLib/res/values-nl/strings.xml
index dfc3389717a9..0d52d9d2b661 100644
--- a/packages/SettingsLib/res/values-nl/strings.xml
+++ b/packages/SettingsLib/res/values-nl/strings.xml
@@ -403,7 +403,6 @@
<string name="force_resizable_activities_summary" msgid="2490382056981583062">"Maak het formaat van alle activiteiten aanpasbaar, ongeacht de manifestwaarden"</string>
<string name="enable_freeform_support" msgid="7599125687603914253">"Vensters met vrije vorm aanzetten"</string>
<string name="enable_freeform_support_summary" msgid="1822862728719276331">"Zet ondersteuning voor vensters met experimentele vrije vorm aan"</string>
- <string name="desktop_mode" msgid="2389067840550544462">"Desktopmodus"</string>
<string name="local_backup_password_title" msgid="4631017948933578709">"Wachtwoord desktopback-up"</string>
<string name="local_backup_password_summary_none" msgid="7646898032616361714">"Volledige back-ups naar desktops zijn momenteel niet beveiligd"</string>
<string name="local_backup_password_summary_change" msgid="1707357670383995567">"Tik om het wachtwoord voor volledige back-ups naar desktops te wijzigen of te verwijderen"</string>
diff --git a/packages/SettingsLib/res/values-or/strings.xml b/packages/SettingsLib/res/values-or/strings.xml
index a29fb0fb984a..eb54cba0ae41 100644
--- a/packages/SettingsLib/res/values-or/strings.xml
+++ b/packages/SettingsLib/res/values-or/strings.xml
@@ -403,7 +403,6 @@
<string name="force_resizable_activities_summary" msgid="2490382056981583062">"ମାନିଫେଷ୍ଟ ମୂଲ୍ୟ ଯାହା ହୋଇଥାଉ ନା କାହିଁକି, ଏକାଧିକ-ୱିଣ୍ଡୋ ପାଇଁ ସମସ୍ତ କାର୍ଯ୍ୟକଳାପକୁ ରିସାଇଜ କରନ୍ତୁ।"</string>
<string name="enable_freeform_support" msgid="7599125687603914253">"ଫ୍ରିଫର୍ମ ୱିଣ୍ଡୋକୁ ସକ୍ଷମ କରନ୍ତୁ"</string>
<string name="enable_freeform_support_summary" msgid="1822862728719276331">"ପରୀକ୍ଷାମୂଳକ ଫ୍ରିଫର୍ମ ୱିଣ୍ଡୋଗୁଡ଼ିକ ପାଇଁ ସପୋର୍ଟକୁ ସକ୍ଷମ କରନ୍ତୁ।"</string>
- <string name="desktop_mode" msgid="2389067840550544462">"ଡେସ୍କଟପ ମୋଡ"</string>
<string name="local_backup_password_title" msgid="4631017948933578709">"ଡେସ୍କଟପ ବେକଅପ ପାସୱାର୍ଡ"</string>
<string name="local_backup_password_summary_none" msgid="7646898032616361714">"ଡେସ୍କଟପ୍‌ର ସମ୍ପୂର୍ଣ୍ଣ ବ୍ୟାକଅପ୍‌ଗୁଡ଼ିକ ବର୍ତ୍ତମାନ ସୁରକ୍ଷିତ ନୁହେଁ"</string>
<string name="local_backup_password_summary_change" msgid="1707357670383995567">"ଡେସ୍କଟପ୍‌ର ସମ୍ପୂର୍ଣ୍ଣ ବ୍ୟାକ୍‌ଅପ୍‌ ପାଇଁ ପାସ୍‌ୱର୍ଡ ବଦଳାଇବା କିମ୍ୱା କାଢ଼ିଦେବା ନିମନ୍ତେ ଟାପ୍‌ କରନ୍ତୁ"</string>
diff --git a/packages/SettingsLib/res/values-pa/strings.xml b/packages/SettingsLib/res/values-pa/strings.xml
index 917d5f8254ac..b0faa808d4ea 100644
--- a/packages/SettingsLib/res/values-pa/strings.xml
+++ b/packages/SettingsLib/res/values-pa/strings.xml
@@ -403,7 +403,6 @@
<string name="force_resizable_activities_summary" msgid="2490382056981583062">"ਮੈਨੀਫ਼ੈਸਟ ਮੁੱਲਾਂ ਦੀ ਪਰਵਾਹ ਕੀਤੇ ਬਿਨਾਂ, ਮਲਟੀ-ਵਿੰਡੋ ਲਈ ਸਾਰੀਆਂ ਸਰਗਰਮੀਆਂ ਨੂੰ ਆਕਾਰ ਬਦਲਣਯੋਗ ਬਣਾਓ।"</string>
<string name="enable_freeform_support" msgid="7599125687603914253">"ਫ੍ਰੀਫਾਰਮ ਵਿੰਡੋਜ਼ ਨੂੰ ਚਾਲੂ ਕਰੋ"</string>
<string name="enable_freeform_support_summary" msgid="1822862728719276331">"ਪ੍ਰਯੋਗਮਈ ਫ੍ਰੀਫਾਰਮ ਵਿੰਡੋਜ਼ ਲਈ ਸਮਰਥਨ ਨੂੰ ਚਾਲੂ ਕਰੋ।"</string>
- <string name="desktop_mode" msgid="2389067840550544462">"ਡੈਸਕਟਾਪ ਮੋਡ"</string>
<string name="local_backup_password_title" msgid="4631017948933578709">"ਡੈਸਕਟਾਪ ਬੈਕਅੱਪ ਪਾਸਵਰਡ"</string>
<string name="local_backup_password_summary_none" msgid="7646898032616361714">"ਡੈਸਕਟਾਪ ਦੇ ਪੂਰੇ ਬੈਕਅੱਪ ਇਸ ਵੇਲੇ ਸੁਰੱਖਿਅਤ ਨਹੀਂ ਹਨ"</string>
<string name="local_backup_password_summary_change" msgid="1707357670383995567">"ਡੈਸਕਟਾਪ ਦੇ ਮੁਕੰਮਲ ਬੈਕਅੱਪਾਂ ਲਈ ਪਾਸਵਰਡ ਨੂੰ ਬਦਲਣ ਜਾਂ ਹਟਾਉਣ ਲਈ ਟੈਪ ਕਰੋ"</string>
diff --git a/packages/SettingsLib/res/values-pl/strings.xml b/packages/SettingsLib/res/values-pl/strings.xml
index 0bf5b70fc37d..cdc5ba26b37b 100644
--- a/packages/SettingsLib/res/values-pl/strings.xml
+++ b/packages/SettingsLib/res/values-pl/strings.xml
@@ -403,7 +403,6 @@
<string name="force_resizable_activities_summary" msgid="2490382056981583062">"Zezwalaj na zmianę rozmiaru wszystkich okien aktywności w trybie wielu okien niezależnie od ustawień w pliku manifestu"</string>
<string name="enable_freeform_support" msgid="7599125687603914253">"Włącz dowolny rozmiar okien"</string>
<string name="enable_freeform_support_summary" msgid="1822862728719276331">"Włącz obsługę eksperymentalnej funkcji dowolnego rozmiaru okien"</string>
- <string name="desktop_mode" msgid="2389067840550544462">"Tryb pulpitu"</string>
<string name="local_backup_password_title" msgid="4631017948933578709">"Hasło kopii zapasowej"</string>
<string name="local_backup_password_summary_none" msgid="7646898032616361714">"Pełne kopie zapasowe na komputerze nie są obecnie chronione"</string>
<string name="local_backup_password_summary_change" msgid="1707357670383995567">"Dotknij, by zmienić lub usunąć hasło pełnych kopii zapasowych na komputerze."</string>
diff --git a/packages/SettingsLib/res/values-pt-rBR/strings.xml b/packages/SettingsLib/res/values-pt-rBR/strings.xml
index 9af28a6454fa..f1784bcc3c58 100644
--- a/packages/SettingsLib/res/values-pt-rBR/strings.xml
+++ b/packages/SettingsLib/res/values-pt-rBR/strings.xml
@@ -403,7 +403,6 @@
<string name="force_resizable_activities_summary" msgid="2490382056981583062">"Tornar todas as atividades redimensionáveis para várias janelas, independentemente dos valores do manifesto"</string>
<string name="enable_freeform_support" msgid="7599125687603914253">"Ativar janelas de forma livre"</string>
<string name="enable_freeform_support_summary" msgid="1822862728719276331">"Ativar a compatibilidade com janelas experimentais de forma livre"</string>
- <string name="desktop_mode" msgid="2389067840550544462">"Modo área de trabalho"</string>
<string name="local_backup_password_title" msgid="4631017948933578709">"Senha de backup local"</string>
<string name="local_backup_password_summary_none" msgid="7646898032616361714">"Os backups completos não estão protegidos no momento"</string>
<string name="local_backup_password_summary_change" msgid="1707357670383995567">"Toque para alterar ou remover a senha de backups completos do desktop"</string>
diff --git a/packages/SettingsLib/res/values-pt-rPT/strings.xml b/packages/SettingsLib/res/values-pt-rPT/strings.xml
index 53221eded5f5..c510e2b63bb3 100644
--- a/packages/SettingsLib/res/values-pt-rPT/strings.xml
+++ b/packages/SettingsLib/res/values-pt-rPT/strings.xml
@@ -403,7 +403,6 @@
<string name="force_resizable_activities_summary" msgid="2490382056981583062">"Tornar todas as atividades redimensionáveis para várias janelas, independentemente dos valores do manifesto."</string>
<string name="enable_freeform_support" msgid="7599125687603914253">"Ativar janelas de forma livre"</string>
<string name="enable_freeform_support_summary" msgid="1822862728719276331">"Ativar a compatibilidade com janelas de forma livre experimentais."</string>
- <string name="desktop_mode" msgid="2389067840550544462">"Ambiente de trabalho"</string>
<string name="local_backup_password_title" msgid="4631017948933578709">"Palavra-passe cópia do computador"</string>
<string name="local_backup_password_summary_none" msgid="7646898032616361714">"As cópias de segurança completas no ambiente de trabalho não estão atualmente protegidas"</string>
<string name="local_backup_password_summary_change" msgid="1707357670383995567">"Tocar para alterar ou remover a palavra-passe para cópias de segurança completas no ambiente de trabalho"</string>
diff --git a/packages/SettingsLib/res/values-pt/strings.xml b/packages/SettingsLib/res/values-pt/strings.xml
index 9af28a6454fa..f1784bcc3c58 100644
--- a/packages/SettingsLib/res/values-pt/strings.xml
+++ b/packages/SettingsLib/res/values-pt/strings.xml
@@ -403,7 +403,6 @@
<string name="force_resizable_activities_summary" msgid="2490382056981583062">"Tornar todas as atividades redimensionáveis para várias janelas, independentemente dos valores do manifesto"</string>
<string name="enable_freeform_support" msgid="7599125687603914253">"Ativar janelas de forma livre"</string>
<string name="enable_freeform_support_summary" msgid="1822862728719276331">"Ativar a compatibilidade com janelas experimentais de forma livre"</string>
- <string name="desktop_mode" msgid="2389067840550544462">"Modo área de trabalho"</string>
<string name="local_backup_password_title" msgid="4631017948933578709">"Senha de backup local"</string>
<string name="local_backup_password_summary_none" msgid="7646898032616361714">"Os backups completos não estão protegidos no momento"</string>
<string name="local_backup_password_summary_change" msgid="1707357670383995567">"Toque para alterar ou remover a senha de backups completos do desktop"</string>
diff --git a/packages/SettingsLib/res/values-ro/strings.xml b/packages/SettingsLib/res/values-ro/strings.xml
index db0993eca934..447bb63a18cc 100644
--- a/packages/SettingsLib/res/values-ro/strings.xml
+++ b/packages/SettingsLib/res/values-ro/strings.xml
@@ -403,7 +403,6 @@
<string name="force_resizable_activities_summary" msgid="2490382056981583062">"Permite redimensionarea tuturor activităților pentru modul cu ferestre multiple, indiferent de valorile manifestului."</string>
<string name="enable_freeform_support" msgid="7599125687603914253">"Activează ferestrele cu formă liberă"</string>
<string name="enable_freeform_support_summary" msgid="1822862728719276331">"Activează compatibilitatea pentru ferestrele experimentale cu formă liberă."</string>
- <string name="desktop_mode" msgid="2389067840550544462">"Modul desktop"</string>
<string name="local_backup_password_title" msgid="4631017948933578709">"Parolă backup computer"</string>
<string name="local_backup_password_summary_none" msgid="7646898032616361714">"În prezent, backupurile complete pe computer nu sunt protejate"</string>
<string name="local_backup_password_summary_change" msgid="1707357670383995567">"Atinge ca să modifici sau să elimini parola pentru backupurile complete pe desktop"</string>
diff --git a/packages/SettingsLib/res/values-ru/strings.xml b/packages/SettingsLib/res/values-ru/strings.xml
index e9f7b0ae7e7e..f10e8e7a144a 100644
--- a/packages/SettingsLib/res/values-ru/strings.xml
+++ b/packages/SettingsLib/res/values-ru/strings.xml
@@ -403,7 +403,6 @@
<string name="force_resizable_activities_summary" msgid="2490382056981583062">"Разрешить изменение размера окон в многооконном режиме (независимо от значений в манифесте)"</string>
<string name="enable_freeform_support" msgid="7599125687603914253">"Разрешить создание окон произвольной формы"</string>
<string name="enable_freeform_support_summary" msgid="1822862728719276331">"Включить экспериментальную функцию создания окон произвольной формы"</string>
- <string name="desktop_mode" msgid="2389067840550544462">"Режим компьютера"</string>
<string name="local_backup_password_title" msgid="4631017948933578709">"Пароль для резервного копирования"</string>
<string name="local_backup_password_summary_none" msgid="7646898032616361714">"Полные локальные резервные копии в настоящее время не защищены"</string>
<string name="local_backup_password_summary_change" msgid="1707357670383995567">"Нажмите, чтобы изменить или удалить пароль для резервного копирования"</string>
diff --git a/packages/SettingsLib/res/values-si/strings.xml b/packages/SettingsLib/res/values-si/strings.xml
index d3bdd56d2889..51bd3c14d829 100644
--- a/packages/SettingsLib/res/values-si/strings.xml
+++ b/packages/SettingsLib/res/values-si/strings.xml
@@ -403,7 +403,6 @@
<string name="force_resizable_activities_summary" msgid="2490382056981583062">"මැනිෆෙස්ට් අගයන් නොසලකා, සියලු ක්‍රියාකාරකම් බහු-කවුළුව සඳහා ප්‍රතිප්‍රමාණ කළ හැකි බවට පත් කරන්න."</string>
<string name="enable_freeform_support" msgid="7599125687603914253">"අනියම් හැඩැති කවුළු සබල කරන්න"</string>
<string name="enable_freeform_support_summary" msgid="1822862728719276331">"පරීක්ෂණාත්මක අනියම් හැඩැති කවුළු සඳහා සහාය සබල කරන්න."</string>
- <string name="desktop_mode" msgid="2389067840550544462">"ඩෙස්ක්ටොප් ප්‍රකාරය"</string>
<string name="local_backup_password_title" msgid="4631017948933578709">"ඩෙස්ක්ටොප් උපස්ථ මුරපදය"</string>
<string name="local_backup_password_summary_none" msgid="7646898032616361714">"ඩෙස්ක්ටොප් සම්පූර්ණ උපස්ථ දැනට ආරක්ෂා කර නොමැත"</string>
<string name="local_backup_password_summary_change" msgid="1707357670383995567">"ඩෙස්ක්ටොප් සම්පූර්ණ උපස්ථ සඳහා මුරපදය වෙනස් කිරීමට හෝ ඉවත් කිරීමට තට්ටු කරන්න"</string>
diff --git a/packages/SettingsLib/res/values-sk/strings.xml b/packages/SettingsLib/res/values-sk/strings.xml
index b34fe9d18cc6..691872842fd5 100644
--- a/packages/SettingsLib/res/values-sk/strings.xml
+++ b/packages/SettingsLib/res/values-sk/strings.xml
@@ -403,7 +403,6 @@
<string name="force_resizable_activities_summary" msgid="2490382056981583062">"Umožniť zmeniť veľkosť všetkých aktivít na niekoľko okien (bez ohľadu na hodnoty manifestu)"</string>
<string name="enable_freeform_support" msgid="7599125687603914253">"Povoliť okná s voľným tvarom"</string>
<string name="enable_freeform_support_summary" msgid="1822862728719276331">"Povoliť podporu pre experimentálne okná s voľným tvarom"</string>
- <string name="desktop_mode" msgid="2389067840550544462">"Režim počítača"</string>
<string name="local_backup_password_title" msgid="4631017948933578709">"Heslo pre zálohy v počítači"</string>
<string name="local_backup_password_summary_none" msgid="7646898032616361714">"Úplné zálohy v počítači nie sú momentálne chránené"</string>
<string name="local_backup_password_summary_change" msgid="1707357670383995567">"Klepnutím zmeníte alebo odstránite heslo pre úplné zálohy do počítača"</string>
diff --git a/packages/SettingsLib/res/values-sl/strings.xml b/packages/SettingsLib/res/values-sl/strings.xml
index b142a6c86409..cf174e1d73f4 100644
--- a/packages/SettingsLib/res/values-sl/strings.xml
+++ b/packages/SettingsLib/res/values-sl/strings.xml
@@ -403,7 +403,6 @@
<string name="force_resizable_activities_summary" msgid="2490382056981583062">"Poskrbi, da je ne glede na vrednosti v manifestu mogoče vsem aktivnostim spremeniti velikost za način z več okni."</string>
<string name="enable_freeform_support" msgid="7599125687603914253">"Omogoči okna svobodne oblike"</string>
<string name="enable_freeform_support_summary" msgid="1822862728719276331">"Omogoči podporo za poskusna okna svobodne oblike."</string>
- <string name="desktop_mode" msgid="2389067840550544462">"Namizni način"</string>
<string name="local_backup_password_title" msgid="4631017948933578709">"Geslo za varnostno kopijo namizja"</string>
<string name="local_backup_password_summary_none" msgid="7646898032616361714">"Popolne varnostne kopije namizja trenutno niso zaščitene."</string>
<string name="local_backup_password_summary_change" msgid="1707357670383995567">"Dotaknite se, če želite spremeniti ali odstraniti geslo za popolno varnostno kopiranje namizja"</string>
diff --git a/packages/SettingsLib/res/values-sq/strings.xml b/packages/SettingsLib/res/values-sq/strings.xml
index b27b6bdd5249..7802704e4649 100644
--- a/packages/SettingsLib/res/values-sq/strings.xml
+++ b/packages/SettingsLib/res/values-sq/strings.xml
@@ -403,7 +403,6 @@
<string name="force_resizable_activities_summary" msgid="2490382056981583062">"Bëj që të gjitha aktivitetet të kenë madhësi të ndryshueshme për përdorimin me shumë dritare, pavarësisht vlerave të manifestit."</string>
<string name="enable_freeform_support" msgid="7599125687603914253">"Aktivizo dritaret me formë të lirë"</string>
<string name="enable_freeform_support_summary" msgid="1822862728719276331">"Aktivizo mbështetjen për dritaret eksperimentale me formë të lirë."</string>
- <string name="desktop_mode" msgid="2389067840550544462">"Modaliteti i desktopit"</string>
<string name="local_backup_password_title" msgid="4631017948933578709">"Fjalëkalimi rezervë i kompjuterit"</string>
<string name="local_backup_password_summary_none" msgid="7646898032616361714">"Rezervimet e plota në kompjuter nuk janë të mbrojtura aktualisht"</string>
<string name="local_backup_password_summary_change" msgid="1707357670383995567">"Trokit për të ndryshuar ose hequr fjalëkalimin për rezervime të plota të desktopit"</string>
diff --git a/packages/SettingsLib/res/values-sr/strings.xml b/packages/SettingsLib/res/values-sr/strings.xml
index 286e908f3314..eb10b550f97b 100644
--- a/packages/SettingsLib/res/values-sr/strings.xml
+++ b/packages/SettingsLib/res/values-sr/strings.xml
@@ -403,7 +403,6 @@
<string name="force_resizable_activities_summary" msgid="2490382056981583062">"Омогућава промену величине свих активности за режим са више прозора, без обзира на вредности манифеста."</string>
<string name="enable_freeform_support" msgid="7599125687603914253">"Омогући прозоре произвољног формата"</string>
<string name="enable_freeform_support_summary" msgid="1822862728719276331">"Омогућава подршку за експерименталне прозоре произвољног формата."</string>
- <string name="desktop_mode" msgid="2389067840550544462">"Режим за рачунаре"</string>
<string name="local_backup_password_title" msgid="4631017948933578709">"Лозинка резервне копије за рачунар"</string>
<string name="local_backup_password_summary_none" msgid="7646898032616361714">"Резервне копије читавог система тренутно нису заштићене"</string>
<string name="local_backup_password_summary_change" msgid="1707357670383995567">"Додирните да бисте променили или уклонили лозинку за прављење резервних копија читавог система на рачунару"</string>
diff --git a/packages/SettingsLib/res/values-sv/strings.xml b/packages/SettingsLib/res/values-sv/strings.xml
index e2f7017732ec..256b4e9aacee 100644
--- a/packages/SettingsLib/res/values-sv/strings.xml
+++ b/packages/SettingsLib/res/values-sv/strings.xml
@@ -403,7 +403,6 @@
<string name="force_resizable_activities_summary" msgid="2490382056981583062">"Gör det möjligt att ändra storleken på alla aktiviteter i flerfönsterläge, oavsett manifestvärden."</string>
<string name="enable_freeform_support" msgid="7599125687603914253">"Aktivera frihandsfönster"</string>
<string name="enable_freeform_support_summary" msgid="1822862728719276331">"Aktivera stöd för experimentella frihandsfönster."</string>
- <string name="desktop_mode" msgid="2389067840550544462">"Datorläge"</string>
<string name="local_backup_password_title" msgid="4631017948933578709">"Lösenord för säkerhetskopia av datorn"</string>
<string name="local_backup_password_summary_none" msgid="7646898032616361714">"De fullständiga säkerhetskopiorna av datorn är för närvarande inte skyddade"</string>
<string name="local_backup_password_summary_change" msgid="1707357670383995567">"Tryck om du vill ändra eller ta bort lösenordet för fullständig säkerhetskopiering av datorn"</string>
diff --git a/packages/SettingsLib/res/values-sw/strings.xml b/packages/SettingsLib/res/values-sw/strings.xml
index f66684a8b233..e23dbcb314d5 100644
--- a/packages/SettingsLib/res/values-sw/strings.xml
+++ b/packages/SettingsLib/res/values-sw/strings.xml
@@ -403,7 +403,6 @@
<string name="force_resizable_activities_summary" msgid="2490382056981583062">"Fanya shughuli zote ziweze kubadilishwa ukubwa kwenye madirisha mengi, bila kuzingatia thamani za faili ya maelezo."</string>
<string name="enable_freeform_support" msgid="7599125687603914253">"Washa madirisha yenye muundo huru"</string>
<string name="enable_freeform_support_summary" msgid="1822862728719276331">"Ruhusu uwezo wa kutumia madirisha ya majaribio yenye muundo huru."</string>
- <string name="desktop_mode" msgid="2389067840550544462">"Hali ya kompyuta ya mezani"</string>
<string name="local_backup_password_title" msgid="4631017948933578709">"Nenosiri la hifadhi rudufu ya eneo kazi"</string>
<string name="local_backup_password_summary_none" msgid="7646898032616361714">"Hifadhi rudufu kamili za eneo kazi hazijalindwa kwa sasa"</string>
<string name="local_backup_password_summary_change" msgid="1707357670383995567">"Gusa ili ubadilishe au uondoe nenosiri la hifadhi rudufu kamili za eneo kazi"</string>
diff --git a/packages/SettingsLib/res/values-ta/strings.xml b/packages/SettingsLib/res/values-ta/strings.xml
index 22d4febc8e02..365c3dafca93 100644
--- a/packages/SettingsLib/res/values-ta/strings.xml
+++ b/packages/SettingsLib/res/values-ta/strings.xml
@@ -403,7 +403,6 @@
<string name="force_resizable_activities_summary" msgid="2490382056981583062">"மேனிஃபெஸ்ட் மதிப்புகளைப் பொருட்படுத்தாமல், பல சாளரத்திற்கு எல்லா செயல்பாடுகளையும் அளவுமாறக்கூடியதாக அமை."</string>
<string name="enable_freeform_support" msgid="7599125687603914253">"குறிப்பிட்ட வடிவமில்லாத சாளரங்களை இயக்கு"</string>
<string name="enable_freeform_support_summary" msgid="1822862728719276331">"சாளரங்களை அளவுமாற்ற மற்றும் எங்கும் நகர்த்த அனுமதிக்கும் பரிசோதனைக்குரிய அம்சத்திற்கான ஆதரவை இயக்கு."</string>
- <string name="desktop_mode" msgid="2389067840550544462">"டெஸ்க்டாப் பயன்முறை"</string>
<string name="local_backup_password_title" msgid="4631017948933578709">"டெஸ்க்டாப் காப்புப்பிரதி கடவுச்சொல்"</string>
<string name="local_backup_password_summary_none" msgid="7646898032616361714">"டெஸ்க்டாப்பின் முழு காப்புப்பிரதிகள் தற்போது பாதுகாக்கப்படவில்லை"</string>
<string name="local_backup_password_summary_change" msgid="1707357670383995567">"டெஸ்க்டாப்பின் முழுக் காப்புப் பிரதிகளுக்கான கடவுச்சொல்லை மாற்ற அல்லது அகற்ற, தட்டவும்"</string>
diff --git a/packages/SettingsLib/res/values-te/strings.xml b/packages/SettingsLib/res/values-te/strings.xml
index dc5bacd700fa..d1c464c21378 100644
--- a/packages/SettingsLib/res/values-te/strings.xml
+++ b/packages/SettingsLib/res/values-te/strings.xml
@@ -403,7 +403,6 @@
<string name="force_resizable_activities_summary" msgid="2490382056981583062">"మానిఫెస్ట్ విలువలతో సంబంధం లేకుండా అన్ని యాక్టివిటీస్‌ను పలు రకాల విండోల్లో సరిపోయేటట్లు సైజ్‌ మార్చగలిగేలా చేస్తుంది."</string>
<string name="enable_freeform_support" msgid="7599125687603914253">"స్వతంత్ర రూప విండోలను ఎనేబుల్ చేయండి"</string>
<string name="enable_freeform_support_summary" msgid="1822862728719276331">"ప్రయోగాత్మక స్వతంత్ర రూప విండోల కోసం సపోర్ట్‌ను ఎనేబుల్ చేస్తుంది."</string>
- <string name="desktop_mode" msgid="2389067840550544462">"డెస్క్‌టాప్ మోడ్"</string>
<string name="local_backup_password_title" msgid="4631017948933578709">"డెస్క్‌టాప్ బ్యాకప్ పాస్‌వర్డ్"</string>
<string name="local_backup_password_summary_none" msgid="7646898032616361714">"డెస్క్‌టాప్ పూర్తి బ్యాకప్‌లు ప్రస్తుతం రక్షించబడలేదు"</string>
<string name="local_backup_password_summary_change" msgid="1707357670383995567">"డెస్క్‌టాప్ పూర్తి బ్యాకప్‌ల కోసం పాస్‌వర్డ్‌ను మార్చడానికి లేదా తీసివేయడానికి నొక్కండి"</string>
diff --git a/packages/SettingsLib/res/values-th/strings.xml b/packages/SettingsLib/res/values-th/strings.xml
index 7dd346a9d730..bc6840bdc2d7 100644
--- a/packages/SettingsLib/res/values-th/strings.xml
+++ b/packages/SettingsLib/res/values-th/strings.xml
@@ -403,7 +403,6 @@
<string name="force_resizable_activities_summary" msgid="2490382056981583062">"ทำให้กิจกรรมทั้งหมดปรับขนาดได้สำหรับหน้าต่างหลายบาน โดยไม่คำนึงถึงค่าในไฟล์ Manifest"</string>
<string name="enable_freeform_support" msgid="7599125687603914253">"เปิดใช้หน้าต่างรูปแบบอิสระ"</string>
<string name="enable_freeform_support_summary" msgid="1822862728719276331">"เปิดการสนับสนุนหน้าต่างรูปแบบอิสระแบบทดลอง"</string>
- <string name="desktop_mode" msgid="2389067840550544462">"โหมดเดสก์ท็อป"</string>
<string name="local_backup_password_title" msgid="4631017948933578709">"รหัสผ่านการสำรองข้อมูลในเดสก์ท็อป"</string>
<string name="local_backup_password_summary_none" msgid="7646898032616361714">"การสำรองข้อมูลเต็มรูปแบบในเดสก์ท็อปไม่ได้รับการป้องกันในขณะนี้"</string>
<string name="local_backup_password_summary_change" msgid="1707357670383995567">"แตะเพื่อเปลี่ยนแปลงหรือลบรหัสผ่านสำหรับการสำรองข้อมูลเต็มรูปแบบในเดสก์ท็อป"</string>
diff --git a/packages/SettingsLib/res/values-tl/strings.xml b/packages/SettingsLib/res/values-tl/strings.xml
index 8ad8fd732b04..4360b9fa027c 100644
--- a/packages/SettingsLib/res/values-tl/strings.xml
+++ b/packages/SettingsLib/res/values-tl/strings.xml
@@ -403,7 +403,6 @@
<string name="force_resizable_activities_summary" msgid="2490382056981583062">"Gawing nare-resize ang lahat ng aktibidad para sa multi-window, anuman ang mga value ng manifest."</string>
<string name="enable_freeform_support" msgid="7599125687603914253">"I-enable ang mga freeform window"</string>
<string name="enable_freeform_support_summary" msgid="1822862728719276331">"I-enable ang suporta para sa mga pang-eksperimentong freeform window."</string>
- <string name="desktop_mode" msgid="2389067840550544462">"Desktop mode"</string>
<string name="local_backup_password_title" msgid="4631017948933578709">"Password ng pag-backup ng desktop"</string>
<string name="local_backup_password_summary_none" msgid="7646898032616361714">"Kasalukuyang hindi pinoprotektahan ang mga buong pag-backup ng desktop"</string>
<string name="local_backup_password_summary_change" msgid="1707357670383995567">"I-tap upang baguhin o alisin ang password para sa mga kumpletong pag-back up sa desktop"</string>
diff --git a/packages/SettingsLib/res/values-tr/strings.xml b/packages/SettingsLib/res/values-tr/strings.xml
index 0af470d98433..206df8f5a8ce 100644
--- a/packages/SettingsLib/res/values-tr/strings.xml
+++ b/packages/SettingsLib/res/values-tr/strings.xml
@@ -403,7 +403,6 @@
<string name="force_resizable_activities_summary" msgid="2490382056981583062">"Manifest değerlerinden bağımsız olarak, tüm etkinlikleri birden fazla pencerede yeniden boyutlandırılabilir yap."</string>
<string name="enable_freeform_support" msgid="7599125687603914253">"Serbest biçimli pencereleri etkinleştir"</string>
<string name="enable_freeform_support_summary" msgid="1822862728719276331">"Deneysel serbest biçimli pencere desteğini etkinleştir."</string>
- <string name="desktop_mode" msgid="2389067840550544462">"Masaüstü modu"</string>
<string name="local_backup_password_title" msgid="4631017948933578709">"Masaüstü yedekleme şifresi"</string>
<string name="local_backup_password_summary_none" msgid="7646898032616361714">"Masaüstü tam yedeklemeleri şu an korunmuyor"</string>
<string name="local_backup_password_summary_change" msgid="1707357670383995567">"Masaüstü tam yedeklemelerinin şifresini değiştirmek veya kaldırmak için dokunun"</string>
diff --git a/packages/SettingsLib/res/values-uk/strings.xml b/packages/SettingsLib/res/values-uk/strings.xml
index 3b8492369fe8..2bc80df469db 100644
--- a/packages/SettingsLib/res/values-uk/strings.xml
+++ b/packages/SettingsLib/res/values-uk/strings.xml
@@ -403,7 +403,6 @@
<string name="force_resizable_activities_summary" msgid="2490382056981583062">"Масштабувати активність на кілька вікон, незалежно від значень у файлі маніфесту."</string>
<string name="enable_freeform_support" msgid="7599125687603914253">"Увімкнути вікна довільного формату"</string>
<string name="enable_freeform_support_summary" msgid="1822862728719276331">"Увімкнути експериментальні вікна довільного формату."</string>
- <string name="desktop_mode" msgid="2389067840550544462">"Режим комп’ютера"</string>
<string name="local_backup_password_title" msgid="4631017948933578709">"Пароль рез. копії на ПК"</string>
<string name="local_backup_password_summary_none" msgid="7646898032616361714">"Повні резервні копії на комп’ютері наразі не захищені"</string>
<string name="local_backup_password_summary_change" msgid="1707357670383995567">"Торкніться, щоб змінити або видалити пароль для повного резервного копіювання на комп’ютер"</string>
diff --git a/packages/SettingsLib/res/values-ur/strings.xml b/packages/SettingsLib/res/values-ur/strings.xml
index 9f7d18ea58f0..b8bef4c14fbb 100644
--- a/packages/SettingsLib/res/values-ur/strings.xml
+++ b/packages/SettingsLib/res/values-ur/strings.xml
@@ -403,7 +403,6 @@
<string name="force_resizable_activities_summary" msgid="2490382056981583062">"مینی فیسٹ اقدار سے قطع نظر، ملٹی ونڈو کیلئے تمام سرگرمیوں کو ری سائز ایبل بنائیں۔"</string>
<string name="enable_freeform_support" msgid="7599125687603914253">"‏freeform ونڈوز فعال کریں"</string>
<string name="enable_freeform_support_summary" msgid="1822862728719276331">"تجرباتی فری فارم ونڈوز کیلئے سپورٹ فعال کریں۔"</string>
- <string name="desktop_mode" msgid="2389067840550544462">"ڈیسک ٹاپ موڈ"</string>
<string name="local_backup_password_title" msgid="4631017948933578709">"ڈیسک ٹاپ کا بیک اپ پاس ورڈ"</string>
<string name="local_backup_password_summary_none" msgid="7646898032616361714">"ڈیسک ٹاپ کے مکمل بیک اپس فی الحال محفوظ کیے ہوئے نہیں ہیں"</string>
<string name="local_backup_password_summary_change" msgid="1707357670383995567">"ڈیسک ٹاپ کے مکمل بیک اپس کیلئے پاس ورڈ کو تبدیل کرنے یا ہٹانے کیلئے تھپتھپائیں"</string>
diff --git a/packages/SettingsLib/res/values-uz/strings.xml b/packages/SettingsLib/res/values-uz/strings.xml
index b9c17fcafb1e..57c59e1725fe 100644
--- a/packages/SettingsLib/res/values-uz/strings.xml
+++ b/packages/SettingsLib/res/values-uz/strings.xml
@@ -403,7 +403,6 @@
<string name="force_resizable_activities_summary" msgid="2490382056981583062">"Manifest qiymatidan qat’i nazar barcha harakatlarni ko‘p oynali rejimga moslashtirish."</string>
<string name="enable_freeform_support" msgid="7599125687603914253">"Erkin shakldagi oynalarni yoqish"</string>
<string name="enable_freeform_support_summary" msgid="1822862728719276331">"Erkin shakldagi oynalar yaratish uchun mo‘ljallangan tajribaviy funksiyani yoqish."</string>
- <string name="desktop_mode" msgid="2389067840550544462">"Desktop rejimi"</string>
<string name="local_backup_password_title" msgid="4631017948933578709">"Zaxira nusxa uchun parol"</string>
<string name="local_backup_password_summary_none" msgid="7646898032616361714">"Kompyuterdagi zaxira nusxalar hozirgi vaqtda himoyalanmagan"</string>
<string name="local_backup_password_summary_change" msgid="1707357670383995567">"Ish stoli to‘liq zaxira nusxalari parolini o‘zgartirish yoki o‘chirish uchun bu yerni bosing"</string>
diff --git a/packages/SettingsLib/res/values-vi/strings.xml b/packages/SettingsLib/res/values-vi/strings.xml
index 0eaaf219c340..9877249adca5 100644
--- a/packages/SettingsLib/res/values-vi/strings.xml
+++ b/packages/SettingsLib/res/values-vi/strings.xml
@@ -403,7 +403,6 @@
<string name="force_resizable_activities_summary" msgid="2490382056981583062">"Cho phép thay đổi kích thước của tất cả các hoạt động cho nhiều cửa sổ, bất kể giá trị tệp kê khai là gì."</string>
<string name="enable_freeform_support" msgid="7599125687603914253">"Bật cửa sổ dạng tự do"</string>
<string name="enable_freeform_support_summary" msgid="1822862728719276331">"Bật tính năng hỗ trợ cửa sổ dạng tự do thử nghiệm."</string>
- <string name="desktop_mode" msgid="2389067840550544462">"Chế độ máy tính"</string>
<string name="local_backup_password_title" msgid="4631017948933578709">"Mật khẩu cho bản sao lưu qua máy tính"</string>
<string name="local_backup_password_summary_none" msgid="7646898032616361714">"Các bản sao lưu đầy đủ qua máy tính hiện không được bảo vệ"</string>
<string name="local_backup_password_summary_change" msgid="1707357670383995567">"Nhấn để thay đổi hoặc xóa mật khẩu dành cho các bản sao lưu đầy đủ vào máy tính"</string>
diff --git a/packages/SettingsLib/res/values-zh-rCN/strings.xml b/packages/SettingsLib/res/values-zh-rCN/strings.xml
index 74ab016e1e25..a210e6c02250 100644
--- a/packages/SettingsLib/res/values-zh-rCN/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rCN/strings.xml
@@ -403,7 +403,6 @@
<string name="force_resizable_activities_summary" msgid="2490382056981583062">"将所有 activity 设为可配合多窗口环境调整大小(无论清单值是什么)。"</string>
<string name="enable_freeform_support" msgid="7599125687603914253">"启用可自由调整的窗口"</string>
<string name="enable_freeform_support_summary" msgid="1822862728719276331">"启用可自由调整的窗口这一实验性功能。"</string>
- <string name="desktop_mode" msgid="2389067840550544462">"桌面模式"</string>
<string name="local_backup_password_title" msgid="4631017948933578709">"桌面备份密码"</string>
<string name="local_backup_password_summary_none" msgid="7646898032616361714">"桌面完整备份当前未设置密码保护"</string>
<string name="local_backup_password_summary_change" msgid="1707357670383995567">"点按即可更改或移除用于保护桌面完整备份的密码"</string>
diff --git a/packages/SettingsLib/res/values-zh-rHK/strings.xml b/packages/SettingsLib/res/values-zh-rHK/strings.xml
index 21f6d51540fa..f78b141eb3f9 100644
--- a/packages/SettingsLib/res/values-zh-rHK/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rHK/strings.xml
@@ -403,7 +403,6 @@
<string name="force_resizable_activities_summary" msgid="2490382056981583062">"在任何資訊清單值下,允許系統配合多重視窗環境調整所有活動的尺寸。"</string>
<string name="enable_freeform_support" msgid="7599125687603914253">"啟用自由形態視窗"</string>
<string name="enable_freeform_support_summary" msgid="1822862728719276331">"啟用實驗版自由形態視窗的支援功能。"</string>
- <string name="desktop_mode" msgid="2389067840550544462">"桌面模式"</string>
<string name="local_backup_password_title" msgid="4631017948933578709">"桌面電腦備份密碼"</string>
<string name="local_backup_password_summary_none" msgid="7646898032616361714">"桌面電腦的完整備份目前未受保護"</string>
<string name="local_backup_password_summary_change" msgid="1707357670383995567">"輕按即可變更或移除桌面電腦完整備份的密碼"</string>
diff --git a/packages/SettingsLib/res/values-zh-rTW/strings.xml b/packages/SettingsLib/res/values-zh-rTW/strings.xml
index 09f8d134ef94..a66a0293d25b 100644
--- a/packages/SettingsLib/res/values-zh-rTW/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rTW/strings.xml
@@ -403,7 +403,6 @@
<string name="force_resizable_activities_summary" msgid="2490382056981583062">"將所有活動設為可配合多重視窗環境調整大小 (無論資訊清單值為何)。"</string>
<string name="enable_freeform_support" msgid="7599125687603914253">"啟用自由形式視窗"</string>
<string name="enable_freeform_support_summary" msgid="1822862728719276331">"啟用實驗版自由形式視窗的支援功能。"</string>
- <string name="desktop_mode" msgid="2389067840550544462">"電腦模式"</string>
<string name="local_backup_password_title" msgid="4631017948933578709">"電腦備份密碼"</string>
<string name="local_backup_password_summary_none" msgid="7646898032616361714">"目前尚未設定密碼來保護完整的備份檔案 (透過電腦備份的檔案)"</string>
<string name="local_backup_password_summary_change" msgid="1707357670383995567">"輕觸即可變更或移除電腦完整備份的密碼"</string>
diff --git a/packages/SettingsLib/res/values-zu/strings.xml b/packages/SettingsLib/res/values-zu/strings.xml
index 5de118c0379f..45b8c543ad72 100644
--- a/packages/SettingsLib/res/values-zu/strings.xml
+++ b/packages/SettingsLib/res/values-zu/strings.xml
@@ -403,7 +403,6 @@
<string name="force_resizable_activities_summary" msgid="2490382056981583062">"Yenza yonke imisebenzi ibe nosayizi abasha kumawindi amaningi, ngokunganaki amavelu e-manifest."</string>
<string name="enable_freeform_support" msgid="7599125687603914253">"Nika amandla amawindi e-freeform"</string>
<string name="enable_freeform_support_summary" msgid="1822862728719276331">"Nika amandla usekelo lwe-windows yokuhlola kwe-freeform."</string>
- <string name="desktop_mode" msgid="2389067840550544462">"Imodi yedeskithophu"</string>
<string name="local_backup_password_title" msgid="4631017948933578709">"Iphasiwedi yokusekela ngokulondoloza ye-Desktop"</string>
<string name="local_backup_password_summary_none" msgid="7646898032616361714">"Ukusekela ngokulondoloza okugcwele kwe-Desktop akuvikelekile okwamanje."</string>
<string name="local_backup_password_summary_change" msgid="1707357670383995567">"Thepha ukushintsha noma ukususa iphasiwedi yokwenziwa kwezipele ngokugcwele kwideskithophu"</string>
diff --git a/packages/SettingsLib/res/values/strings.xml b/packages/SettingsLib/res/values/strings.xml
index 0acce0385f2f..ec24ab78c616 100644
--- a/packages/SettingsLib/res/values/strings.xml
+++ b/packages/SettingsLib/res/values/strings.xml
@@ -954,9 +954,6 @@
<!-- UI debug setting: enable freeform window support summary [CHAR LIMIT=150] -->
<string name="enable_freeform_support_summary">Enable support for experimental freeform windows.</string>
- <!-- UI debug setting: enable desktop mode [CHAR LIMIT=25] -->
- <string name="desktop_mode">Desktop mode</string>
-
<!-- Local (desktop) backup password menu title [CHAR LIMIT=25] -->
<string name="local_backup_password_title">Desktop backup password</string>
<!-- Summary text of the "local backup password" setting when the user has not supplied a password -->
diff --git a/packages/SettingsLib/src/com/android/settingslib/RestrictedSwitchPreference.java b/packages/SettingsLib/src/com/android/settingslib/RestrictedSwitchPreference.java
index af06d7304160..b1d1ea5eda42 100644
--- a/packages/SettingsLib/src/com/android/settingslib/RestrictedSwitchPreference.java
+++ b/packages/SettingsLib/src/com/android/settingslib/RestrictedSwitchPreference.java
@@ -126,10 +126,10 @@ public class RestrictedSwitchPreference extends SwitchPreference {
switchSummary = isChecked()
? getUpdatableEnterpriseString(
getContext(), ENABLED_BY_ADMIN_SWITCH_SUMMARY,
- R.string.enabled_by_admin)
+ com.android.settingslib.widget.R.string.enabled_by_admin)
: getUpdatableEnterpriseString(
getContext(), DISABLED_BY_ADMIN_SWITCH_SUMMARY,
- R.string.disabled_by_admin);
+ com.android.settingslib.widget.R.string.disabled_by_admin);
} else {
switchSummary = mRestrictedSwitchSummary;
}
diff --git a/packages/SettingsLib/src/com/android/settingslib/applications/ApplicationsState.java b/packages/SettingsLib/src/com/android/settingslib/applications/ApplicationsState.java
index 6eb2f3834858..96bb4b586dfc 100644
--- a/packages/SettingsLib/src/com/android/settingslib/applications/ApplicationsState.java
+++ b/packages/SettingsLib/src/com/android/settingslib/applications/ApplicationsState.java
@@ -1776,7 +1776,8 @@ public class ApplicationsState {
final int userId = UserHandle.getUserId(this.info.uid);
if (UserManager.get(context).isManagedProfile(userId)) {
this.labelDescription = context.getString(
- com.android.settingslib.R.string.accessibility_work_profile_app_description,
+ com.android.settingslib.utils.R
+ .string.accessibility_work_profile_app_description,
this.label);
} else {
this.labelDescription = this.label;
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/BroadcastDialog.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/BroadcastDialog.java
index cb4eba422366..f5257b070392 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/BroadcastDialog.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/BroadcastDialog.java
@@ -46,7 +46,8 @@ public class BroadcastDialog extends AlertDialog {
View layout = View.inflate(mContext, R.layout.broadcast_dialog, null);
final Window window = getWindow();
window.setContentView(layout);
- window.setWindowAnimations(R.style.Theme_AlertDialog_SettingsLib);
+ window.setWindowAnimations(
+ com.android.settingslib.widget.R.style.Theme_AlertDialog_SettingsLib);
TextView title = layout.findViewById(R.id.dialog_title);
TextView subTitle = layout.findViewById(R.id.dialog_subtitle);
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java
index 00397f0e646d..64c271bb7bc7 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java
@@ -760,6 +760,14 @@ public class CachedBluetoothDevice implements Comparable<CachedBluetoothDevice>
void onAudioModeChanged() {
dispatchAttributesChanged();
}
+
+ /**
+ * Notify that the audio category has changed.
+ */
+ public void onAudioDeviceCategoryChanged() {
+ dispatchAttributesChanged();
+ }
+
/**
* Get the device status as active or non-active per Bluetooth profile.
*
diff --git a/packages/SettingsLib/src/com/android/settingslib/inputmethod/InputMethodPreference.java b/packages/SettingsLib/src/com/android/settingslib/inputmethod/InputMethodPreference.java
index 1f4cafce835f..d53c3a7aafa6 100644
--- a/packages/SettingsLib/src/com/android/settingslib/inputmethod/InputMethodPreference.java
+++ b/packages/SettingsLib/src/com/android/settingslib/inputmethod/InputMethodPreference.java
@@ -153,7 +153,7 @@ public class InputMethodPreference extends PrimarySwitchPreference
}
final ImageView icon = holder.itemView.findViewById(android.R.id.icon);
final int iconSize = getContext().getResources().getDimensionPixelSize(
- R.dimen.secondary_app_icon_size);
+ com.android.settingslib.widget.R.dimen.secondary_app_icon_size);
if (icon != null && iconSize > 0) {
ViewGroup.LayoutParams params = icon.getLayoutParams();
params.height = iconSize;
diff --git a/packages/SettingsLib/src/com/android/settingslib/notification/ConversationIconFactory.java b/packages/SettingsLib/src/com/android/settingslib/notification/ConversationIconFactory.java
index ebdfbeade99d..251cd3615897 100644
--- a/packages/SettingsLib/src/com/android/settingslib/notification/ConversationIconFactory.java
+++ b/packages/SettingsLib/src/com/android/settingslib/notification/ConversationIconFactory.java
@@ -32,7 +32,6 @@ import android.util.IconDrawableFactory;
import android.util.Log;
import com.android.launcher3.icons.BaseIconFactory;
-import com.android.settingslib.R;
import com.android.settingslib.Utils;
/**
@@ -81,7 +80,7 @@ public class ConversationIconFactory extends BaseIconFactory {
mPackageManager = pm;
mIconDrawableFactory = iconDrawableFactory;
mImportantConversationColor = context.getResources().getColor(
- R.color.important_conversation, null);
+ com.android.launcher3.icons.R.color.important_conversation, null);
}
/**
diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPointPreference.java b/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPointPreference.java
index 21eb35abe32c..2d6f0587fbf7 100644
--- a/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPointPreference.java
+++ b/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPointPreference.java
@@ -167,7 +167,8 @@ public class AccessPointPreference extends Preference {
ImageView frictionImageView = (ImageView) view.findViewById(R.id.friction_icon);
bindFrictionImage(frictionImageView);
- final View divider = view.findViewById(R.id.two_target_divider);
+ final View divider =
+ view.findViewById(com.android.settingslib.widget.R.id.two_target_divider);
divider.setVisibility(shouldShowDivider() ? View.VISIBLE : View.INVISIBLE);
}
diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiStatusTracker.java b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiStatusTracker.java
index c45d77471932..015356e013b7 100644
--- a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiStatusTracker.java
+++ b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiStatusTracker.java
@@ -331,7 +331,8 @@ public class WifiStatusTracker {
return;
} else if (!isDefaultNetwork && mDefaultNetworkCapabilities != null
&& mDefaultNetworkCapabilities.hasTransport(TRANSPORT_CELLULAR)) {
- statusLabel = mContext.getString(R.string.wifi_connected_low_quality);
+ statusLabel = mContext.getString(
+ com.android.wifitrackerlib.R.string.wifi_connected_low_quality);
return;
}
}
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/PrimarySwitchPreferenceTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/PrimarySwitchPreferenceTest.java
index 74c2fc8cce4c..32a16716d9f9 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/PrimarySwitchPreferenceTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/PrimarySwitchPreferenceTest.java
@@ -54,7 +54,7 @@ public class PrimarySwitchPreferenceTest {
mPreference = new PrimarySwitchPreference(mContext);
LayoutInflater inflater = LayoutInflater.from(mContext);
mHolder = PreferenceViewHolder.createInstanceForTests(inflater.inflate(
- com.android.settingslib.R.layout.preference_two_target, null));
+ com.android.settingslib.widget.R.layout.preference_two_target, null));
mWidgetView = mHolder.itemView.findViewById(android.R.id.widget_frame);
inflater.inflate(R.layout.preference_widget_primary_switch, mWidgetView, true);
}
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/collapsingtoolbar/widget/CollapsingCoordinatorLayoutTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/collapsingtoolbar/widget/CollapsingCoordinatorLayoutTest.java
index 06343f59e2b8..ff84dc92037f 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/collapsingtoolbar/widget/CollapsingCoordinatorLayoutTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/collapsingtoolbar/widget/CollapsingCoordinatorLayoutTest.java
@@ -55,7 +55,8 @@ public class CollapsingCoordinatorLayoutTest {
@Test
public void onCreate_userAddedChildViewsBeMovedToContentFrame() {
CollapsingCoordinatorLayout layout = mActivity.getCollapsingCoordinatorLayout();
- View contentFrameView = layout.findViewById(R.id.content_frame);
+ View contentFrameView =
+ layout.findViewById(com.android.settingslib.widget.R.id.content_frame);
TextView textView = contentFrameView.findViewById(R.id.text_hello_world);
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/core/lifecycle/HideNonSystemOverlayMixinTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/core/lifecycle/HideNonSystemOverlayMixinTest.java
index 471dac05e6b4..8246aff8b18e 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/core/lifecycle/HideNonSystemOverlayMixinTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/core/lifecycle/HideNonSystemOverlayMixinTest.java
@@ -29,8 +29,6 @@ import android.view.WindowManager;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
-import com.android.settingslib.R;
-
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -95,7 +93,7 @@ public class HideNonSystemOverlayMixinTest {
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
- setTheme(R.style.Theme_AppCompat);
+ setTheme(androidx.appcompat.R.style.Theme_AppCompat);
getLifecycle().addObserver(new HideNonSystemOverlayMixin(this));
}
}
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/enterprise/FinancedDeviceActionDisabledByAdminControllerTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/enterprise/FinancedDeviceActionDisabledByAdminControllerTest.java
index 7b08fee9ac91..2f8967e34e79 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/enterprise/FinancedDeviceActionDisabledByAdminControllerTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/enterprise/FinancedDeviceActionDisabledByAdminControllerTest.java
@@ -30,8 +30,6 @@ import android.content.Context;
import androidx.test.core.app.ApplicationProvider;
-import com.android.settingslib.R;
-
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -51,7 +49,7 @@ public class FinancedDeviceActionDisabledByAdminControllerTest {
@Before
public void setUp() {
- mActivity.setTheme(R.style.Theme_AppCompat_DayNight);
+ mActivity.setTheme(androidx.appcompat.R.style.Theme_AppCompat_DayNight);
mController.initialize(mTestUtils.createLearnMoreButtonLauncher());
mController.updateEnforcedAdmin(ENFORCED_ADMIN, ENFORCEMENT_ADMIN_USER_ID);
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/enterprise/ManagedDeviceActionDisabledByAdminControllerTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/enterprise/ManagedDeviceActionDisabledByAdminControllerTest.java
index 7b885660ccea..f168122994c3 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/enterprise/ManagedDeviceActionDisabledByAdminControllerTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/enterprise/ManagedDeviceActionDisabledByAdminControllerTest.java
@@ -33,8 +33,6 @@ import android.os.UserManager;
import androidx.test.core.app.ApplicationProvider;
-import com.android.settingslib.R;
-
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -57,7 +55,7 @@ public class ManagedDeviceActionDisabledByAdminControllerTest {
@Before
public void setUp() {
- mActivity.setTheme(R.style.Theme_AppCompat_DayNight);
+ mActivity.setTheme(androidx.appcompat.R.style.Theme_AppCompat_DayNight);
}
@Test
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/users/CreateUserDialogControllerTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/users/CreateUserDialogControllerTest.java
index 66a2ea69559b..68312223b4b1 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/users/CreateUserDialogControllerTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/users/CreateUserDialogControllerTest.java
@@ -62,7 +62,7 @@ public class CreateUserDialogControllerTest {
public void setup() {
MockitoAnnotations.initMocks(this);
mActivity = spy(ActivityController.of(new FragmentActivity()).get());
- mActivity.setTheme(R.style.Theme_AppCompat_DayNight);
+ mActivity.setTheme(androidx.appcompat.R.style.Theme_AppCompat_DayNight);
mUnderTest = new TestCreateUserDialogController();
mPhotoRestrictedByBase = false;
}
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/users/EditUserInfoControllerTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/users/EditUserInfoControllerTest.java
index f595cd334105..a95257a903e0 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/users/EditUserInfoControllerTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/users/EditUserInfoControllerTest.java
@@ -99,7 +99,7 @@ public class EditUserInfoControllerTest {
public void setup() {
MockitoAnnotations.initMocks(this);
mActivity = spy(ActivityController.of(new FragmentActivity()).get());
- mActivity.setTheme(R.style.Theme_AppCompat_DayNight);
+ mActivity.setTheme(androidx.appcompat.R.style.Theme_AppCompat_DayNight);
mController = new TestEditUserInfoController();
mPhotoRestrictedByBase = false;
}
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/AdaptiveIconTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/AdaptiveIconTest.java
index 6cbae05ce9a5..10862403ae70 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/AdaptiveIconTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/AdaptiveIconTest.java
@@ -105,15 +105,15 @@ public class AdaptiveIconTest {
icon.setBackgroundColor(mContext, tile);
- assertThat(icon.mBackgroundColor)
- .isEqualTo(mContext.getColor(R.color.homepage_generic_icon_background));
+ assertThat(icon.mBackgroundColor).isEqualTo(mContext.getColor(
+ com.android.settingslib.widget.R.color.homepage_generic_icon_background));
}
@Test
public void onBindTile_externalTileWithBackgroundColorHint_shouldUpdateIcon() {
final Tile tile = spy(new ActivityTile(mActivityInfo, CategoryKey.CATEGORY_HOMEPAGE));
mActivityInfo.metaData.putInt(META_DATA_PREFERENCE_ICON_BACKGROUND_HINT,
- R.color.bt_outline_color);
+ com.android.settingslib.widget.R.color.bt_outline_color);
doReturn(Icon.createWithResource(mContext, R.drawable.ic_system_update))
.when(tile).getIcon(mContext);
@@ -121,8 +121,8 @@ public class AdaptiveIconTest {
new AdaptiveIcon(mContext, new ColorDrawable(Color.BLACK));
icon.setBackgroundColor(mContext, tile);
- assertThat(icon.mBackgroundColor)
- .isEqualTo(mContext.getColor(R.color.bt_outline_color));
+ assertThat(icon.mBackgroundColor).isEqualTo(mContext.getColor(
+ com.android.settingslib.widget.R.color.bt_outline_color));
}
@Test
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/AdaptiveOutlineDrawableTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/AdaptiveOutlineDrawableTest.java
index 71d55bc3de2a..b2bc53dda1fa 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/AdaptiveOutlineDrawableTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/AdaptiveOutlineDrawableTest.java
@@ -21,8 +21,6 @@ import static com.google.common.truth.Truth.assertThat;
import android.content.res.Resources;
import android.graphics.Paint;
-import com.android.settingslib.R;
-
import org.junit.Test;
import org.junit.runner.RunWith;
import org.robolectric.RobolectricTestRunner;
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/FooterPreferenceTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/FooterPreferenceTest.java
index 049c90e971a9..a26f200ec603 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/FooterPreferenceTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/FooterPreferenceTest.java
@@ -58,14 +58,15 @@ public class FooterPreferenceTest {
@Test
public void setLearnMoreText_shouldSetAsTextInLearnMore() {
final PreferenceViewHolder holder = PreferenceViewHolder.createInstanceForTests(
- LayoutInflater.from(mContext).inflate(R.layout.preference_footer, null));
+ LayoutInflater.from(mContext)
+ .inflate(com.android.settingslib.widget.R.layout.preference_footer, null));
mFooterPreference.setLearnMoreText("Custom learn more");
mFooterPreference.setLearnMoreAction(view -> { /* do nothing */ } /* listener */);
mFooterPreference.onBindViewHolder(holder);
assertThat(((TextView) holder.findViewById(
- R.id.settingslib_learn_more)).getText().toString())
+ com.android.settingslib.widget.R.id.settingslib_learn_more)).getText().toString())
.isEqualTo("Custom learn more");
}
@@ -94,8 +95,9 @@ public class FooterPreferenceTest {
@Test
public void onBindViewHolder_whenTitleIsNull_shouldNotRaiseNpe() {
PreferenceViewHolder viewHolder = spy(PreferenceViewHolder.createInstanceForTests(
- LayoutInflater.from(mContext).inflate(R.layout.preference_footer, null)));
- when(viewHolder.findViewById(R.id.title)).thenReturn(null);
+ LayoutInflater.from(mContext)
+ .inflate(com.android.settingslib.widget.R.layout.preference_footer, null)));
+ when(viewHolder.findViewById(androidx.core.R.id.title)).thenReturn(null);
Throwable actualThrowable = null;
try {
@@ -110,8 +112,10 @@ public class FooterPreferenceTest {
@Test
public void onBindViewHolder_whenLearnMoreIsNull_shouldNotRaiseNpe() {
PreferenceViewHolder viewHolder = spy(PreferenceViewHolder.createInstanceForTests(
- LayoutInflater.from(mContext).inflate(R.layout.preference_footer, null)));
- when(viewHolder.findViewById(R.id.settingslib_learn_more)).thenReturn(null);
+ LayoutInflater.from(mContext)
+ .inflate(com.android.settingslib.widget.R.layout.preference_footer, null)));
+ when(viewHolder.findViewById(com.android.settingslib.widget.R.id.settingslib_learn_more))
+ .thenReturn(null);
Throwable actualThrowable = null;
try {
@@ -126,7 +130,8 @@ public class FooterPreferenceTest {
@Test
public void onBindViewHolder_whenIconFrameIsNull_shouldNotRaiseNpe() {
PreferenceViewHolder viewHolder = spy(PreferenceViewHolder.createInstanceForTests(
- LayoutInflater.from(mContext).inflate(R.layout.preference_footer, null)));
+ LayoutInflater.from(mContext)
+ .inflate(com.android.settingslib.widget.R.layout.preference_footer, null)));
when(viewHolder.findViewById(R.id.icon_frame)).thenReturn(null);
Throwable actualThrowable = null;
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/TwoTargetPreferenceTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/TwoTargetPreferenceTest.java
index aaec909aa335..23b4c2aec80f 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/TwoTargetPreferenceTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/TwoTargetPreferenceTest.java
@@ -32,8 +32,6 @@ import android.widget.LinearLayout;
import androidx.preference.PreferenceViewHolder;
-import com.android.settingslib.R;
-
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
diff --git a/packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java b/packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java
index 8787c2516f64..94a3173b13a1 100644
--- a/packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java
+++ b/packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java
@@ -165,12 +165,10 @@ public class SecureSettings {
Settings.Secure.CHARGING_VIBRATION_ENABLED,
Settings.Secure.ACCESSIBILITY_NON_INTERACTIVE_UI_TIMEOUT_MS,
Settings.Secure.ACCESSIBILITY_INTERACTIVE_UI_TIMEOUT_MS,
- Settings.Secure.TRUST_AGENTS_EXTEND_UNLOCK,
Settings.Secure.UI_NIGHT_MODE,
Settings.Secure.UI_NIGHT_MODE_CUSTOM_TYPE,
Settings.Secure.DARK_THEME_CUSTOM_START_TIME,
Settings.Secure.DARK_THEME_CUSTOM_END_TIME,
- Settings.Secure.LOCK_SCREEN_WHEN_TRUST_LOST,
Settings.Secure.SKIP_DIRECTION,
Settings.Secure.THEME_CUSTOMIZATION_OVERLAY_PACKAGES,
Settings.Secure.BACK_GESTURE_INSET_SCALE_LEFT,
diff --git a/packages/SettingsProvider/src/android/provider/settings/backup/SystemSettings.java b/packages/SettingsProvider/src/android/provider/settings/backup/SystemSettings.java
index 6b0a9060d782..248c60cb4fe9 100644
--- a/packages/SettingsProvider/src/android/provider/settings/backup/SystemSettings.java
+++ b/packages/SettingsProvider/src/android/provider/settings/backup/SystemSettings.java
@@ -61,7 +61,7 @@ public class SystemSettings {
Settings.System.TTY_MODE,
Settings.System.MASTER_MONO,
Settings.System.MASTER_BALANCE,
- Settings.System.STAY_AWAKE_ON_FOLD,
+ Settings.System.FOLD_LOCK_BEHAVIOR,
Settings.System.SOUND_EFFECTS_ENABLED,
Settings.System.HAPTIC_FEEDBACK_ENABLED,
Settings.System.POWER_SOUNDS_ENABLED, // moved to global
diff --git a/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java b/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java
index dfc3cef48426..817999839c54 100644
--- a/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java
+++ b/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java
@@ -245,9 +245,7 @@ public class SecureSettingsValidators {
Secure.ACCESSIBILITY_INTERACTIVE_UI_TIMEOUT_MS, NON_NEGATIVE_INTEGER_VALIDATOR);
VALIDATORS.put(Secure.USER_SETUP_COMPLETE, BOOLEAN_VALIDATOR);
VALIDATORS.put(Secure.ASSIST_GESTURE_SETUP_COMPLETE, BOOLEAN_VALIDATOR);
- VALIDATORS.put(Secure.TRUST_AGENTS_EXTEND_UNLOCK, BOOLEAN_VALIDATOR);
VALIDATORS.put(Secure.LOCK_SCREEN_CUSTOM_CLOCK_FACE, JSON_OBJECT_VALIDATOR);
- VALIDATORS.put(Secure.LOCK_SCREEN_WHEN_TRUST_LOST, BOOLEAN_VALIDATOR);
VALIDATORS.put(Secure.SKIP_GESTURE, BOOLEAN_VALIDATOR);
/*
* Only used if FeatureFlag "settings_skip_direction_mutable" is enabled.
diff --git a/packages/SettingsProvider/src/android/provider/settings/validators/SystemSettingsValidators.java b/packages/SettingsProvider/src/android/provider/settings/validators/SystemSettingsValidators.java
index 20740dcedf95..17ce7c7cc435 100644
--- a/packages/SettingsProvider/src/android/provider/settings/validators/SystemSettingsValidators.java
+++ b/packages/SettingsProvider/src/android/provider/settings/validators/SystemSettingsValidators.java
@@ -134,6 +134,7 @@ public class SystemSettingsValidators {
VALIDATORS.put(System.HAPTIC_FEEDBACK_ENABLED, BOOLEAN_VALIDATOR);
VALIDATORS.put(System.RINGTONE, URI_VALIDATOR);
VALIDATORS.put(System.NOTIFICATION_SOUND, URI_VALIDATOR);
+ VALIDATORS.put(System.FOLD_LOCK_BEHAVIOR, ANY_STRING_VALIDATOR);
VALIDATORS.put(System.ALARM_ALERT, URI_VALIDATOR);
VALIDATORS.put(System.TEXT_AUTO_REPLACE, BOOLEAN_VALIDATOR);
VALIDATORS.put(System.TEXT_AUTO_CAPS, BOOLEAN_VALIDATOR);
@@ -219,7 +220,6 @@ public class SystemSettingsValidators {
VALIDATORS.put(System.WIFI_STATIC_DNS1, LENIENT_IP_ADDRESS_VALIDATOR);
VALIDATORS.put(System.WIFI_STATIC_DNS2, LENIENT_IP_ADDRESS_VALIDATOR);
VALIDATORS.put(System.SHOW_BATTERY_PERCENT, BOOLEAN_VALIDATOR);
- VALIDATORS.put(System.STAY_AWAKE_ON_FOLD, BOOLEAN_VALIDATOR);
VALIDATORS.put(System.NOTIFICATION_LIGHT_PULSE, BOOLEAN_VALIDATOR);
VALIDATORS.put(System.WEAR_ACCESSIBILITY_GESTURE_ENABLED, BOOLEAN_VALIDATOR);
VALIDATORS.put(System.WEAR_ACCESSIBILITY_GESTURE_ENABLED_DURING_OOBE, BOOLEAN_VALIDATOR);
diff --git a/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java b/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java
index 92f65d6cd21a..c0f62313cb39 100644
--- a/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java
+++ b/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java
@@ -98,7 +98,6 @@ public class SettingsBackupTest {
Settings.System.VOLUME_VOICE, // deprecated since API 2?
Settings.System.WHEN_TO_MAKE_WIFI_CALLS, // bug?
Settings.System.WINDOW_ORIENTATION_LISTENER_LOG, // used for debugging only
- Settings.System.DESKTOP_MODE, // developer setting for internal prototyping
Settings.System.MIN_REFRESH_RATE, // depends on hardware capabilities
Settings.System.PEAK_REFRESH_RATE, // depends on hardware capabilities
Settings.System.SCREEN_BRIGHTNESS_FLOAT,
diff --git a/packages/SharedStorageBackup/Android.bp b/packages/SharedStorageBackup/Android.bp
index 21516fade1ab..225b5b4234b6 100644
--- a/packages/SharedStorageBackup/Android.bp
+++ b/packages/SharedStorageBackup/Android.bp
@@ -27,9 +27,6 @@ android_app {
name: "SharedStorageBackup",
defaults: ["platform_app_defaults"],
srcs: ["src/**/*.java"],
- optimize: {
- proguard_flags_files: ["proguard.flags"],
- },
platform_apis: true,
certificate: "platform",
privileged: true,
diff --git a/packages/SharedStorageBackup/proguard.flags b/packages/SharedStorageBackup/proguard.flags
deleted file mode 100644
index 6a66a47e3050..000000000000
--- a/packages/SharedStorageBackup/proguard.flags
+++ /dev/null
@@ -1,2 +0,0 @@
--keep class com.android.sharedstoragebackup.SharedStorageAgent
--keep class com.android.sharedstoragebackup.ObbBackupService
diff --git a/packages/SystemUI/Android.bp b/packages/SystemUI/Android.bp
index c92fe2251f68..bba79bbcab5b 100644
--- a/packages/SystemUI/Android.bp
+++ b/packages/SystemUI/Android.bp
@@ -132,20 +132,6 @@ android_library {
manifest: "AndroidManifest-res.xml",
}
-aconfig_declarations {
- name: "systemui_aconfig_flags",
- package: "com.android.systemui.aconfig",
- srcs: [
- "src/com/android/systemui/aconfig/systemui.aconfig",
- "src/com/android/systemui/accessibility/aconfig/accessibility.aconfig",
- ],
-}
-
-java_aconfig_library {
- name: "systemui_aconfig_flags_lib",
- aconfig_declarations: "systemui_aconfig_flags",
-}
-
android_library {
name: "SystemUI-core",
defaults: [
@@ -180,7 +166,7 @@ android_library {
"SystemUISharedLib",
"SystemUI-statsd",
"SettingsLib",
- "systemui_aconfig_flags_lib",
+ "com_android_systemui_flags_lib",
"androidx.core_core-ktx",
"androidx.viewpager2_viewpager2",
"androidx.legacy_legacy-support-v4",
@@ -251,6 +237,9 @@ filegroup {
"tests/src/com/android/systemui/statusbar/pipeline/airplane/data/repository/FakeAirplaneModeRepository.kt",
"tests/src/com/android/systemui/statusbar/pipeline/shared/data/repository/FakeConnectivityRepository.kt",
"tests/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/FakeWifiRepository.kt",
+
+ /* Log fakes */
+ "tests/src/com/android/systemui/log/core/FakeLogBuffer.kt",
],
path: "tests/src",
}
@@ -337,6 +326,28 @@ filegroup {
"tests/src/com/android/keyguard/KeyguardSecurityViewFlipperControllerTest.java",
"tests/src/com/android/keyguard/KeyguardSimPinViewControllerTest.kt",
"tests/src/com/android/keyguard/KeyguardSimPukViewControllerTest.kt",
+
+ /* Communal tests */
+ "tests/src/com/android/systemui/communal/data/repository/CommunalWidgetRepositoryImplTest.kt",
+ "tests/src/com/android/systemui/communal/domain/interactor/CommunalInteractorTest.kt",
+ "tests/src/com/android/systemui/communal/ui/view/layout/blueprints/DefaultCommunalBlueprintTest.kt",
+
+ /* Dream tests */
+ "tests/src/com/android/systemui/dreams/complication/HideComplicationTouchHandlerTest.java",
+ "tests/src/com/android/systemui/dreams/conditions/AssistantAttentionConditionTest.java",
+ "tests/src/com/android/systemui/dreams/conditions/DreamConditionTest.java",
+ "tests/src/com/android/systemui/dreams/touch/scrim/BouncerlessScrimControllerTest.java",
+ "tests/src/com/android/systemui/dreams/touch/scrim/ScrimManagerTest.java",
+ "tests/src/com/android/systemui/dreams/touch/BouncerSwipeTouchHandlerTest.java",
+ "tests/src/com/android/systemui/dreams/touch/ShadeTouchHandlerTest.java",
+ "tests/src/com/android/systemui/dreams/DreamOverlayAnimationsControllerTest.kt",
+ "tests/src/com/android/systemui/dreams/DreamOverlayCallbackControllerTest.kt",
+ "tests/src/com/android/systemui/dreams/DreamOverlayContainerViewControllerTest.java",
+ "tests/src/com/android/systemui/dreams/DreamOverlayNotificationCountProviderTest.java",
+ "tests/src/com/android/systemui/dreams/DreamOverlayServiceTest.java",
+ "tests/src/com/android/systemui/dreams/DreamOverlayStateControllerTest.java",
+ "tests/src/com/android/systemui/dreams/DreamOverlayStatusBarItemsProviderTest.java",
+ "tests/src/com/android/systemui/dreams/DreamOverlayStatusBarViewControllerTest.java",
],
path: "tests/src",
}
@@ -369,7 +380,7 @@ android_library {
"SystemUICustomizationLib",
"SystemUI-statsd",
"SettingsLib",
- "systemui_aconfig_flags_lib",
+ "com_android_systemui_flags_lib",
"androidx.viewpager2_viewpager2",
"androidx.legacy_legacy-support-v4",
"androidx.recyclerview_recyclerview",
@@ -541,10 +552,12 @@ systemui_optimized_java_defaults {
optimize: true,
shrink: true,
shrink_resources: true,
+ ignore_warnings: false,
proguard_compatibility: false,
},
conditions_default: {
optimize: {
+ ignore_warnings: false,
proguard_compatibility: false,
},
},
diff --git a/packages/SystemUI/aconfig/Android.bp b/packages/SystemUI/aconfig/Android.bp
new file mode 100644
index 000000000000..c1390b252418
--- /dev/null
+++ b/packages/SystemUI/aconfig/Android.bp
@@ -0,0 +1,13 @@
+aconfig_declarations {
+ name: "com_android_systemui_flags",
+ package: "com.android.systemui",
+ srcs: [
+ "systemui.aconfig",
+ "accessibility.aconfig",
+ ],
+}
+
+java_aconfig_library {
+ name: "com_android_systemui_flags_lib",
+ aconfig_declarations: "com_android_systemui_flags",
+}
diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/aconfig/accessibility.aconfig b/packages/SystemUI/aconfig/accessibility.aconfig
index 91c55510608a..8841967b1535 100644
--- a/packages/SystemUI/src/com/android/systemui/accessibility/aconfig/accessibility.aconfig
+++ b/packages/SystemUI/aconfig/accessibility.aconfig
@@ -1,7 +1,8 @@
-package: "com.android.systemui.aconfig"
+package: "com.android.systemui"
+
flag {
name: "floating_menu_overlaps_nav_bars_flag"
namespace: "accessibility"
description: "Adjusts bounds to allow the floating menu to render on top of navigation bars."
bug: "283768342"
-} \ No newline at end of file
+}
diff --git a/packages/SystemUI/src/com/android/systemui/aconfig/systemui.aconfig b/packages/SystemUI/aconfig/systemui.aconfig
index 2d6e25776134..70832f594941 100644
--- a/packages/SystemUI/src/com/android/systemui/aconfig/systemui.aconfig
+++ b/packages/SystemUI/aconfig/systemui.aconfig
@@ -1,8 +1,8 @@
-package: "com.android.systemui.aconfig"
+package: "com.android.systemui"
flag {
name: "example_flag"
namespace: "systemui"
description: "An Example Flag"
bug: "292511372"
-}
+} \ No newline at end of file
diff --git a/packages/SystemUI/animation/Android.bp b/packages/SystemUI/animation/Android.bp
index 8eb012d2e41c..6f53b42371c6 100644
--- a/packages/SystemUI/animation/Android.bp
+++ b/packages/SystemUI/animation/Android.bp
@@ -68,5 +68,6 @@ android_library {
kotlincflags: ["-Xjvm-default=all"],
// sdk_version must be specified, otherwise it compiles against private APIs.
+ min_sdk_version: "33",
sdk_version: "current",
}
diff --git a/tests/ApkVerityTest/ApkVerityTestApp/src/com/android/apkverity/DummyActivity.java b/packages/SystemUI/compose/facade/disabled/src/com/android/systemui/scene/BouncerSceneModule.kt
index a7bd771400c0..1a5e22b2c5ee 100644
--- a/tests/ApkVerityTest/ApkVerityTestApp/src/com/android/apkverity/DummyActivity.java
+++ b/packages/SystemUI/compose/facade/disabled/src/com/android/systemui/scene/BouncerSceneModule.kt
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2019 The Android Open Source Project
+ * Copyright 2023 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -14,9 +14,8 @@
* limitations under the License.
*/
-package com.android.apkverity;
+package com.android.systemui.scene
-import android.app.Activity;
+import dagger.Module
-/** Placeholder class just to generate some dex */
-public class DummyActivity extends Activity {}
+@Module interface BouncerSceneModule
diff --git a/tests/ApkVerityTest/ApkVerityTestApp/feature_split/src/com/android/apkverity/feature_x/DummyActivity.java b/packages/SystemUI/compose/facade/disabled/src/com/android/systemui/scene/GoneSceneModule.kt
index fe9126003967..5cc3b75df787 100644
--- a/tests/ApkVerityTest/ApkVerityTestApp/feature_split/src/com/android/apkverity/feature_x/DummyActivity.java
+++ b/packages/SystemUI/compose/facade/disabled/src/com/android/systemui/scene/GoneSceneModule.kt
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2019 The Android Open Source Project
+ * Copyright 2023 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -14,9 +14,8 @@
* limitations under the License.
*/
-package com.android.apkverity.feature_x;
+package com.android.systemui.scene
-import android.app.Activity;
+import dagger.Module
-/** Placeholder class just to generate some dex */
-public class DummyActivity extends Activity {}
+@Module interface GoneSceneModule
diff --git a/packages/SystemUI/compose/facade/disabled/src/com/android/systemui/scene/LockscreenSceneModule.kt b/packages/SystemUI/compose/facade/disabled/src/com/android/systemui/scene/LockscreenSceneModule.kt
new file mode 100644
index 000000000000..725aef26cb86
--- /dev/null
+++ b/packages/SystemUI/compose/facade/disabled/src/com/android/systemui/scene/LockscreenSceneModule.kt
@@ -0,0 +1,21 @@
+/*
+ * Copyright 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.scene
+
+import dagger.Module
+
+@Module interface LockscreenSceneModule
diff --git a/packages/SystemUI/compose/facade/disabled/src/com/android/systemui/scene/QuickSettingsSceneModule.kt b/packages/SystemUI/compose/facade/disabled/src/com/android/systemui/scene/QuickSettingsSceneModule.kt
new file mode 100644
index 000000000000..387b05644f14
--- /dev/null
+++ b/packages/SystemUI/compose/facade/disabled/src/com/android/systemui/scene/QuickSettingsSceneModule.kt
@@ -0,0 +1,21 @@
+/*
+ * Copyright 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.scene
+
+import dagger.Module
+
+@Module interface QuickSettingsSceneModule
diff --git a/packages/SystemUI/compose/facade/disabled/src/com/android/systemui/scene/ShadeSceneModule.kt b/packages/SystemUI/compose/facade/disabled/src/com/android/systemui/scene/ShadeSceneModule.kt
new file mode 100644
index 000000000000..232c4211c7c1
--- /dev/null
+++ b/packages/SystemUI/compose/facade/disabled/src/com/android/systemui/scene/ShadeSceneModule.kt
@@ -0,0 +1,21 @@
+/*
+ * Copyright 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.scene
+
+import dagger.Module
+
+@Module interface ShadeSceneModule
diff --git a/packages/SystemUI/compose/facade/enabled/src/com/android/systemui/scene/ui/composable/SceneModule.kt b/packages/SystemUI/compose/facade/enabled/src/com/android/systemui/scene/BouncerSceneModule.kt
index 3e9b3975eef4..ddc3d3a31e94 100644
--- a/packages/SystemUI/compose/facade/enabled/src/com/android/systemui/scene/ui/composable/SceneModule.kt
+++ b/packages/SystemUI/compose/facade/enabled/src/com/android/systemui/scene/BouncerSceneModule.kt
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2023 The Android Open Source Project
+ * Copyright 2023 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.systemui.scene.ui.composable
+package com.android.systemui.scene
import android.app.AlertDialog
import android.content.Context
@@ -22,39 +22,27 @@ import com.android.systemui.bouncer.ui.composable.BouncerScene
import com.android.systemui.bouncer.ui.composable.BouncerSceneDialogFactory
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Application
-import com.android.systemui.keyguard.ui.composable.LockscreenScene
-import com.android.systemui.qs.ui.composable.QuickSettingsScene
import com.android.systemui.scene.shared.model.Scene
-import com.android.systemui.shade.ui.composable.ShadeScene
import com.android.systemui.statusbar.phone.SystemUIDialog
+import dagger.Binds
import dagger.Module
import dagger.Provides
+import dagger.multibindings.IntoSet
@Module
-object SceneModule {
- @Provides
- fun scenes(
- bouncer: BouncerScene,
- gone: GoneScene,
- lockScreen: LockscreenScene,
- qs: QuickSettingsScene,
- shade: ShadeScene,
- ): Set<Scene> {
- return setOf(
- bouncer,
- gone,
- lockScreen,
- qs,
- shade,
- )
- }
+interface BouncerSceneModule {
+
+ @Binds @IntoSet fun bouncerScene(scene: BouncerScene): Scene
+
+ companion object {
- @Provides
- @SysUISingleton
- fun bouncerSceneDialogFactory(@Application context: Context): BouncerSceneDialogFactory {
- return object : BouncerSceneDialogFactory {
- override fun invoke(): AlertDialog {
- return SystemUIDialog(context)
+ @Provides
+ @SysUISingleton
+ fun bouncerSceneDialogFactory(@Application context: Context): BouncerSceneDialogFactory {
+ return object : BouncerSceneDialogFactory {
+ override fun invoke(): AlertDialog {
+ return SystemUIDialog(context)
+ }
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/scene/domain/startable/SceneContainerStartableModule.kt b/packages/SystemUI/compose/facade/enabled/src/com/android/systemui/scene/GoneSceneModule.kt
index fcfdcebba2ea..bc3fef15e577 100644
--- a/packages/SystemUI/src/com/android/systemui/scene/domain/startable/SceneContainerStartableModule.kt
+++ b/packages/SystemUI/compose/facade/enabled/src/com/android/systemui/scene/GoneSceneModule.kt
@@ -14,27 +14,16 @@
* limitations under the License.
*/
-package com.android.systemui.scene.domain.startable
+package com.android.systemui.scene
-import com.android.systemui.CoreStartable
-import com.android.systemui.scene.domain.interactor.WindowRootViewVisibilityInteractor
+import com.android.systemui.scene.shared.model.Scene
+import com.android.systemui.scene.ui.composable.GoneScene
import dagger.Binds
import dagger.Module
-import dagger.multibindings.ClassKey
-import dagger.multibindings.IntoMap
+import dagger.multibindings.IntoSet
@Module
-interface SceneContainerStartableModule {
+interface GoneSceneModule {
- @Binds
- @IntoMap
- @ClassKey(SceneContainerStartable::class)
- fun bind(impl: SceneContainerStartable): CoreStartable
-
- @Binds
- @IntoMap
- @ClassKey(WindowRootViewVisibilityInteractor::class)
- fun bindWindowRootViewVisibilityInteractor(
- impl: WindowRootViewVisibilityInteractor
- ): CoreStartable
+ @Binds @IntoSet fun goneScene(scene: GoneScene): Scene
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/LockscreenSceneModule.kt b/packages/SystemUI/compose/facade/enabled/src/com/android/systemui/scene/LockscreenSceneModule.kt
index c88737e6bd70..4d53cca66e5b 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/LockscreenSceneModule.kt
+++ b/packages/SystemUI/compose/facade/enabled/src/com/android/systemui/scene/LockscreenSceneModule.kt
@@ -14,28 +14,36 @@
* limitations under the License.
*/
-@file:OptIn(ExperimentalCoroutinesApi::class)
-
-package com.android.systemui.keyguard.ui.view
+package com.android.systemui.scene
import android.view.View
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.keyguard.KeyguardViewConfigurator
import com.android.systemui.keyguard.qualifiers.KeyguardRootView
+import com.android.systemui.keyguard.ui.composable.LockscreenScene
+import com.android.systemui.scene.shared.model.Scene
+import dagger.Binds
import dagger.Module
import dagger.Provides
+import dagger.multibindings.IntoSet
import javax.inject.Provider
import kotlinx.coroutines.ExperimentalCoroutinesApi
@Module
-object LockscreenSceneModule {
+interface LockscreenSceneModule {
+
+ @Binds @IntoSet fun lockscreenScene(scene: LockscreenScene): Scene
+
+ companion object {
- @Provides
- @SysUISingleton
- @KeyguardRootView
- fun viewProvider(
- configurator: Provider<KeyguardViewConfigurator>,
- ): () -> View {
- return { configurator.get().getKeyguardRootView() }
+ @OptIn(ExperimentalCoroutinesApi::class)
+ @Provides
+ @SysUISingleton
+ @KeyguardRootView
+ fun viewProvider(
+ configurator: Provider<KeyguardViewConfigurator>,
+ ): () -> View {
+ return { configurator.get().getKeyguardRootView() }
+ }
}
}
diff --git a/packages/SystemUI/compose/facade/enabled/src/com/android/systemui/scene/QuickSettingsSceneModule.kt b/packages/SystemUI/compose/facade/enabled/src/com/android/systemui/scene/QuickSettingsSceneModule.kt
new file mode 100644
index 000000000000..ee1f5259ec69
--- /dev/null
+++ b/packages/SystemUI/compose/facade/enabled/src/com/android/systemui/scene/QuickSettingsSceneModule.kt
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.scene
+
+import com.android.systemui.qs.ui.composable.QuickSettingsScene
+import com.android.systemui.scene.shared.model.Scene
+import dagger.Binds
+import dagger.Module
+import dagger.multibindings.IntoSet
+
+@Module
+interface QuickSettingsSceneModule {
+
+ @Binds @IntoSet fun quickSettingsScene(scene: QuickSettingsScene): Scene
+}
diff --git a/packages/SystemUI/compose/facade/enabled/src/com/android/systemui/scene/ShadeSceneModule.kt b/packages/SystemUI/compose/facade/enabled/src/com/android/systemui/scene/ShadeSceneModule.kt
new file mode 100644
index 000000000000..c655d6ba3f2f
--- /dev/null
+++ b/packages/SystemUI/compose/facade/enabled/src/com/android/systemui/scene/ShadeSceneModule.kt
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.scene
+
+import com.android.systemui.scene.shared.model.Scene
+import com.android.systemui.shade.ui.composable.ShadeScene
+import dagger.Binds
+import dagger.Module
+import dagger.multibindings.IntoSet
+
+@Module
+interface ShadeSceneModule {
+
+ @Binds @IntoSet fun shadeScene(scene: ShadeScene): Scene
+}
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/dialog/ui/composable/AlertDialogContent.kt b/packages/SystemUI/compose/features/src/com/android/systemui/dialog/ui/composable/AlertDialogContent.kt
index 48f40e7f8927..418df5c7778d 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/dialog/ui/composable/AlertDialogContent.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/dialog/ui/composable/AlertDialogContent.kt
@@ -19,13 +19,11 @@ package com.android.systemui.dialog.ui.composable
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.PaddingValues
-import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.defaultMinSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
-import androidx.compose.foundation.layout.width
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll
import androidx.compose.material3.LocalContentColor
@@ -35,9 +33,13 @@ import androidx.compose.runtime.Composable
import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
+import androidx.compose.ui.layout.Layout
+import androidx.compose.ui.layout.Placeable
+import androidx.compose.ui.layout.layoutId
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp
import com.android.compose.theme.LocalAndroidColorScheme
+import kotlin.math.roundToInt
/**
* The content of an AlertDialog which can be used together with
@@ -99,28 +101,101 @@ fun AlertDialogContent(
Spacer(Modifier.height(32.dp))
// Buttons.
- // TODO(b/283817398): If there is not enough space, the buttons should automatically stack
- // as shown in go/sysui-dialog-styling.
if (positiveButton != null || negativeButton != null || neutralButton != null) {
- Row(Modifier.fillMaxWidth()) {
- if (neutralButton != null) {
- neutralButton()
- Spacer(Modifier.width(8.dp))
- }
+ AlertDialogButtons(
+ positiveButton = positiveButton,
+ negativeButton = negativeButton,
+ neutralButton = neutralButton,
+ )
+ }
+ }
+}
- Spacer(Modifier.weight(1f))
+@Composable
+private fun AlertDialogButtons(
+ positiveButton: (@Composable () -> Unit)?,
+ negativeButton: (@Composable () -> Unit)?,
+ neutralButton: (@Composable () -> Unit)?,
+ modifier: Modifier = Modifier,
+) {
+ Layout(
+ content = {
+ positiveButton?.let { Box(Modifier.layoutId("positive")) { it() } }
+ negativeButton?.let { Box(Modifier.layoutId("negative")) { it() } }
+ neutralButton?.let { Box(Modifier.layoutId("neutral")) { it() } }
+ },
+ modifier,
+ ) { measurables, constraints ->
+ check(constraints.hasBoundedWidth) {
+ "AlertDialogButtons should not be composed in an horizontally scrollable layout"
+ }
+ val maxWidth = constraints.maxWidth
- if (negativeButton != null) {
- negativeButton()
- }
+ // Measure the buttons.
+ var positive: Placeable? = null
+ var negative: Placeable? = null
+ var neutral: Placeable? = null
+ for (i in measurables.indices) {
+ val measurable = measurables[i]
+ when (val layoutId = measurable.layoutId) {
+ "positive" -> positive = measurable.measure(constraints)
+ "negative" -> negative = measurable.measure(constraints)
+ "neutral" -> neutral = measurable.measure(constraints)
+ else -> error("Unexpected layoutId=$layoutId")
+ }
+ }
+
+ fun Placeable?.width() = this?.width ?: 0
+ fun Placeable?.height() = this?.height ?: 0
+
+ // The min horizontal spacing between buttons.
+ val horizontalSpacing = 8.dp.toPx()
+ val totalHorizontalSpacing = (measurables.size - 1) * horizontalSpacing
+ val requiredWidth =
+ positive.width() + negative.width() + neutral.width() + totalHorizontalSpacing
- if (positiveButton != null) {
- if (negativeButton != null) {
- Spacer(Modifier.width(8.dp))
+ if (requiredWidth <= maxWidth) {
+ // Stack horizontally: [neutral][flexSpace][negative][positive].
+ val height = maxOf(positive.height(), negative.height(), neutral.height())
+ layout(maxWidth, height) {
+ positive?.let { it.placeRelative(maxWidth - it.width, 0) }
+
+ negative?.let { negative ->
+ if (positive == null) {
+ negative.placeRelative(maxWidth - negative.width, 0)
+ } else {
+ negative.placeRelative(
+ maxWidth -
+ negative.width -
+ positive.width -
+ horizontalSpacing.roundToInt(),
+ 0
+ )
}
+ }
- positiveButton()
+ neutral?.placeRelative(0, 0)
+ }
+ } else {
+ // Stack vertically, aligned on the right (in LTR layouts):
+ // [positive]
+ // [negative]
+ // [neutral]
+ //
+ // TODO(b/283817398): Introduce a ResponsiveDialogButtons composable to create buttons
+ // that have different styles when stacked horizontally, as shown in
+ // go/sysui-dialog-styling.
+ val height = positive.height() + negative.height() + neutral.height()
+ layout(maxWidth, height) {
+ var y = 0
+ fun Placeable.place() {
+ placeRelative(maxWidth - width, y)
+ y += this.height
}
+
+ positive?.place()
+ negative?.place()
+ neutral?.place()
}
}
}
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/LockscreenScene.kt b/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/LockscreenScene.kt
index b3b44cba832b..463253b9fb41 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/LockscreenScene.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/LockscreenScene.kt
@@ -102,17 +102,19 @@ private fun LockscreenScene(
longPressViewModel: KeyguardLongPressViewModel,
modifier: Modifier = Modifier,
) {
- var settingsMenu: View? = null
+ fun findSettingsMenu(): View {
+ return viewProvider().requireViewById(R.id.keyguard_settings_button)
+ }
Box(
modifier = modifier,
) {
LongPressSurface(
viewModel = longPressViewModel,
- isSettingsMenuVisible = { settingsMenu?.isVisible == true },
+ isSettingsMenuVisible = { findSettingsMenu().isVisible },
settingsMenuBounds = {
val bounds = android.graphics.Rect()
- settingsMenu?.getHitRect(bounds)
+ findSettingsMenu().getHitRect(bounds)
bounds.toComposeRect()
},
modifier = Modifier.fillMaxSize(),
@@ -124,12 +126,8 @@ private fun LockscreenScene(
// Remove the KeyguardRootView from any parent it might already have in legacy code
// just in case (a view can't have two parents).
(keyguardRootView.parent as? ViewGroup)?.removeView(keyguardRootView)
- settingsMenu = keyguardRootView.requireViewById(R.id.keyguard_settings_button)
keyguardRootView
},
- update = { keyguardRootView ->
- keyguardRootView.requireViewById<View>(R.id.lock_icon_view)
- },
modifier = Modifier.fillMaxSize(),
)
}
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/qs/footer/ui/compose/FooterActions.kt b/packages/SystemUI/compose/features/src/com/android/systemui/qs/footer/ui/compose/FooterActions.kt
index 13acde206247..482220013e32 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/qs/footer/ui/compose/FooterActions.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/qs/footer/ui/compose/FooterActions.kt
@@ -137,6 +137,7 @@ fun FooterActions(
)
}
+ val horizontalPadding = dimensionResource(R.dimen.qs_content_horizontal_padding)
Row(
modifier
.fillMaxWidth()
@@ -150,6 +151,8 @@ fun FooterActions(
.padding(
top = dimensionResource(R.dimen.qs_footer_actions_top_padding),
bottom = dimensionResource(R.dimen.qs_footer_actions_bottom_padding),
+ start = horizontalPadding,
+ end = horizontalPadding,
)
.layout { measurable, constraints ->
// All buttons have a 4dp padding to increase their touch size. To be consistent
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/SceneContainer.kt b/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/SceneContainer.kt
index 31cbcb90769a..019287d8d500 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/SceneContainer.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/SceneContainer.kt
@@ -26,7 +26,6 @@ import androidx.compose.runtime.getValue
import androidx.compose.runtime.remember
import androidx.compose.ui.ExperimentalComposeUiApi
import androidx.compose.ui.Modifier
-import androidx.compose.ui.input.pointer.motionEventSpy
import androidx.compose.ui.input.pointer.PointerEventPass
import androidx.compose.ui.input.pointer.motionEventSpy
import androidx.compose.ui.input.pointer.pointerInput
diff --git a/packages/SystemUI/proguard_common.flags b/packages/SystemUI/proguard_common.flags
index 319481523cdf..75de94321bfe 100644
--- a/packages/SystemUI/proguard_common.flags
+++ b/packages/SystemUI/proguard_common.flags
@@ -70,9 +70,6 @@
-keep class com.android.systemui.log.core.** {
*;
}
--keep class com.android.systemui.fragments.FragmentService$FragmentCreator {
- *;
-}
-keep class androidx.core.app.CoreComponentFactory
# Keep the wm shell lib
diff --git a/packages/SystemUI/res-keyguard/layout-land/keyguard_pin_view.xml b/packages/SystemUI/res-keyguard/layout-land/keyguard_pin_view.xml
deleted file mode 100644
index cd7ab986844c..000000000000
--- a/packages/SystemUI/res-keyguard/layout-land/keyguard_pin_view.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?><!--
-**
-** Copyright 2023, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License")
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
--->
-
-<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="match_parent">
-
- <include layout="@layout/keyguard_pin_view_landscape" />
-
-</FrameLayout>
diff --git a/packages/SystemUI/res-keyguard/layout-sw600dp-land/keyguard_pin_view.xml b/packages/SystemUI/res-keyguard/layout-sw600dp-land/keyguard_pin_view.xml
deleted file mode 100644
index 80cc8c06680a..000000000000
--- a/packages/SystemUI/res-keyguard/layout-sw600dp-land/keyguard_pin_view.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?><!--
-**
-** Copyright 2023, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License")
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
--->
-
-<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="match_parent">
-
- <include layout="@layout/keyguard_pin_view_portrait" />
-
-</FrameLayout>
diff --git a/packages/SystemUI/res-keyguard/layout/keyguard_pin_view.xml b/packages/SystemUI/res-keyguard/layout/keyguard_pin_view.xml
index 29e14c57a047..f3cd9e49b49c 100644
--- a/packages/SystemUI/res-keyguard/layout/keyguard_pin_view.xml
+++ b/packages/SystemUI/res-keyguard/layout/keyguard_pin_view.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
**
-** Copyright 2012, The Android Open Source Project
+** Copyright 2023, The Android Open Source Project
**
** Licensed under the Apache License, Version 2.0 (the "License")
** you may not use this file except in compliance with the License.
@@ -16,10 +16,203 @@
** limitations under the License.
*/
-->
-<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+
+<com.android.keyguard.KeyguardPINView xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:androidprv="http://schemas.android.com/apk/res-auto"
+ android:id="@+id/keyguard_pin_view"
android:layout_width="match_parent"
- android:layout_height="match_parent">
+ android:layout_height="match_parent"
+ android:layout_gravity="center_horizontal|bottom"
+ android:clipChildren="false"
+ android:clipToPadding="false"
+ android:orientation="vertical"
+ androidprv:layout_maxWidth="@dimen/keyguard_security_width">
+
+ <include layout="@layout/keyguard_bouncer_message_area"/>
+
+ <com.android.systemui.bouncer.ui.BouncerMessageView
+ android:id="@+id/bouncer_message_view"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="vertical" />
+
+ <androidx.constraintlayout.widget.ConstraintLayout
+ android:id="@+id/pin_container"
+ android:layout_width="match_parent"
+ android:layout_height="0dp"
+ android:layout_marginBottom="8dp"
+ android:clipChildren="false"
+ android:clipToPadding="false"
+ android:layout_weight="1"
+ android:layoutDirection="ltr"
+ android:orientation="vertical">
+
+ <!-- Set this to be just above key1. It would be better to introduce a barrier above
+ key1/key2/key3, then place this View above that. Sadly, that doesn't work (the Barrier
+ drops to the bottom of the page, and key1/2/3 all shoot up to the top-left). In any
+ case, the Flow should ensure that key1/2/3 all have the same top, so this should be
+ fine. -->
+ <com.android.keyguard.AlphaOptimizedRelativeLayout
+ android:id="@+id/row0"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:paddingBottom="@dimen/num_pad_entry_row_margin_bottom"
+ androidprv:layout_constraintTop_toTopOf="parent"
+ androidprv:layout_constraintEnd_toEndOf="parent"
+ androidprv:layout_constraintStart_toStartOf="parent"
+ androidprv:layout_constraintBottom_toTopOf="@id/key1"
+ androidprv:layout_constraintVertical_bias="0.5">
+
+ <com.android.keyguard.PasswordTextView
+ android:id="@+id/pinEntry"
+ style="@style/Widget.TextView.Password"
+ android:layout_width="@dimen/keyguard_security_width"
+ android:layout_height="@dimen/keyguard_password_height"
+ android:layout_centerHorizontal="true"
+ android:layout_marginRight="72dp"
+ android:contentDescription="@string/keyguard_accessibility_pin_area"
+ androidprv:scaledTextSize="@integer/scaled_password_text_size" />
+ </com.android.keyguard.AlphaOptimizedRelativeLayout>
+
+ <!-- Guideline used to place the top row of keys relative to the screen height. This will be
+ updated in KeyguardPINView to reduce the height of the PIN pad. -->
+ <androidx.constraintlayout.widget.Guideline
+ android:id="@+id/pin_pad_top_guideline"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ androidprv:layout_constraintGuide_percent="0"
+ android:orientation="horizontal" />
+
+ <com.android.keyguard.KeyguardPinFlowView
+ android:id="@+id/flow1"
+ android:layout_width="0dp"
+ android:layout_height="0dp"
+ android:orientation="horizontal"
+ android:clipChildren="false"
+ android:clipToPadding="false"
+
+ androidprv:constraint_referenced_ids="key1,key2,key3,key4,key5,key6,key7,key8,key9,delete_button,key0,key_enter"
+
+ androidprv:flow_horizontalGap="@dimen/num_pad_key_margin_end"
+
+ androidprv:flow_horizontalStyle="packed"
+ androidprv:flow_maxElementsWrap="3"
+
+ androidprv:flow_verticalBias="1.0"
+ androidprv:flow_verticalGap="@dimen/num_pad_entry_row_margin_bottom"
+ androidprv:flow_verticalStyle="packed"
+
+ androidprv:flow_wrapMode="aligned"
+ androidprv:layout_constraintBottom_toBottomOf="parent"
+ androidprv:layout_constraintEnd_toEndOf="parent"
+ androidprv:layout_constraintStart_toStartOf="parent"
+ androidprv:layout_constraintTop_toBottomOf="@id/pin_pad_top_guideline" />
+
+ <com.android.keyguard.NumPadKey
+ android:id="@+id/key1"
+ android:layout_width="0dp"
+ android:layout_height="0dp"
+ android:accessibilityTraversalBefore="@id/key2"
+ androidprv:digit="1"
+ androidprv:textView="@+id/pinEntry" />
+
+ <com.android.keyguard.NumPadKey
+ android:id="@+id/key2"
+ android:layout_width="0dp"
+ android:layout_height="0dp"
+ android:accessibilityTraversalBefore="@id/key3"
+ androidprv:digit="2"
+ androidprv:textView="@+id/pinEntry" />
+
+ <com.android.keyguard.NumPadKey
+ android:id="@+id/key3"
+ android:layout_width="0dp"
+ android:layout_height="0dp"
+ android:accessibilityTraversalBefore="@id/key4"
+ androidprv:digit="3"
+ androidprv:textView="@+id/pinEntry" />
+
+ <com.android.keyguard.NumPadKey
+ android:id="@+id/key4"
+ android:layout_width="0dp"
+ android:layout_height="0dp"
+ android:accessibilityTraversalBefore="@id/key5"
+ androidprv:digit="4"
+ androidprv:textView="@+id/pinEntry" />
+
+ <com.android.keyguard.NumPadKey
+ android:id="@+id/key5"
+ android:layout_width="0dp"
+ android:layout_height="0dp"
+ android:accessibilityTraversalBefore="@id/key6"
+ androidprv:digit="5"
+ androidprv:textView="@+id/pinEntry" />
+
+ <com.android.keyguard.NumPadKey
+ android:id="@+id/key6"
+ android:layout_width="0dp"
+ android:layout_height="0dp"
+ android:accessibilityTraversalBefore="@id/key7"
+ androidprv:digit="6"
+ androidprv:textView="@+id/pinEntry" />
+
+ <com.android.keyguard.NumPadKey
+ android:id="@+id/key7"
+ android:layout_width="0dp"
+ android:layout_height="0dp"
+ android:accessibilityTraversalBefore="@id/key8"
+ androidprv:digit="7"
+ androidprv:textView="@+id/pinEntry" />
+
+
+ <com.android.keyguard.NumPadKey
+ android:id="@+id/key8"
+ android:layout_width="0dp"
+ android:layout_height="0dp"
+ android:accessibilityTraversalBefore="@id/key9"
+ androidprv:digit="8"
+ androidprv:textView="@+id/pinEntry" />
+
+ <com.android.keyguard.NumPadKey
+ android:id="@+id/key9"
+ android:layout_width="0dp"
+ android:layout_height="0dp"
+ android:accessibilityTraversalBefore="@id/delete_button"
+ androidprv:digit="9"
+ androidprv:textView="@+id/pinEntry" />
+
+ <com.android.keyguard.NumPadButton
+ android:id="@+id/delete_button"
+ style="@style/NumPadKey.Delete"
+ android:layout_width="0dp"
+ android:layout_height="0dp"
+ android:accessibilityTraversalBefore="@id/key0"
+ android:contentDescription="@string/keyboardview_keycode_delete" />
+
+ <com.android.keyguard.NumPadKey
+ android:id="@+id/key0"
+ android:layout_width="0dp"
+ android:layout_height="0dp"
+ android:accessibilityTraversalBefore="@id/key_enter"
+ androidprv:digit="0"
+ androidprv:textView="@+id/pinEntry" />
+
+ <com.android.keyguard.NumPadButton
+ android:id="@+id/key_enter"
+ style="@style/NumPadKey.Enter"
+ android:layout_width="0dp"
+ android:layout_height="0dp"
+ android:contentDescription="@string/keyboardview_keycode_enter" />
+ </androidx.constraintlayout.widget.ConstraintLayout>
- <include layout="@layout/keyguard_pin_view_portrait" />
+ <include layout="@layout/keyguard_eca"
+ android:id="@+id/keyguard_selector_fade_container"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="vertical"
+ android:layout_gravity="bottom|center_horizontal"
+ android:layout_marginTop="@dimen/keyguard_eca_top_margin"
+ android:layout_marginBottom="@dimen/keyguard_eca_bottom_margin"
+ android:gravity="center_horizontal"/>
-</FrameLayout>
+</com.android.keyguard.KeyguardPINView>
diff --git a/packages/SystemUI/res-keyguard/layout/keyguard_pin_view_landscape.xml b/packages/SystemUI/res-keyguard/layout/keyguard_pin_view_landscape.xml
deleted file mode 100644
index e00742d80017..000000000000
--- a/packages/SystemUI/res-keyguard/layout/keyguard_pin_view_landscape.xml
+++ /dev/null
@@ -1,231 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?><!--
-**
-** Copyright 2023, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License")
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
--->
-
-<com.android.keyguard.KeyguardPINView xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:androidprv="http://schemas.android.com/apk/res-auto"
- xmlns:tools="http://schemas.android.com/tools"
- android:id="@+id/keyguard_pin_view"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:layout_gravity="center_horizontal|bottom"
- android:clipChildren="false"
- android:clipToPadding="false"
- android:orientation="horizontal">
-
- <androidx.constraintlayout.widget.ConstraintLayout
- android:layout_width="0dp"
- android:layout_height="match_parent"
- android:layout_weight="2"
- android:clipChildren="false"
- android:clipToPadding="false"
- android:layoutDirection="ltr"
- android:orientation="vertical">
-
- <include layout="@layout/keyguard_bouncer_message_area" />
-
- <com.android.systemui.bouncer.ui.BouncerMessageView
- android:id="@+id/bouncer_message_view"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:orientation="vertical"
- androidprv:layout_constraintBottom_toTopOf="@+id/row0"
- androidprv:layout_constraintTop_toTopOf="parent"
- androidprv:layout_constraintVertical_chainStyle="packed" />
-
- <!-- Set this to be just above key1. It would be better to introduce a barrier above
- key1/key2/key3, then place this View above that. Sadly, that doesn't work (the Barrier
- drops to the bottom of the page, and key1/2/3 all shoot up to the top-left). In any
- case, the Flow should ensure that key1/2/3 all have the same top, so this should be
- fine. -->
- <com.android.keyguard.AlphaOptimizedRelativeLayout
- android:id="@+id/row0"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:paddingBottom="@dimen/num_pad_entry_row_margin_bottom"
- androidprv:layout_constraintBottom_toTopOf="@+id/keyguard_selector_fade_container"
- androidprv:layout_constraintTop_toBottomOf="@+id/bouncer_message_view"
- tools:layout_editor_absoluteX="-16dp">
-
- <com.android.keyguard.PasswordTextView
- android:id="@+id/pinEntry"
- style="@style/Widget.TextView.Password"
- android:layout_width="@dimen/keyguard_security_width"
- android:layout_height="@dimen/keyguard_password_height"
- android:layout_centerHorizontal="true"
- android:layout_marginRight="72dp"
- android:contentDescription="@string/keyguard_accessibility_pin_area"
- androidprv:scaledTextSize="@integer/scaled_password_text_size" />
- </com.android.keyguard.AlphaOptimizedRelativeLayout>
-
- <include
- android:id="@+id/keyguard_selector_fade_container"
- layout="@layout/keyguard_eca"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_gravity="bottom|center_horizontal"
- android:layout_marginBottom="@dimen/keyguard_eca_bottom_margin"
- android:layout_marginTop="@dimen/keyguard_eca_top_margin"
- android:gravity="center_horizontal"
- android:orientation="vertical"
- androidprv:layout_constraintBottom_toBottomOf="parent" />
-
- </androidx.constraintlayout.widget.ConstraintLayout>
-
- <androidx.constraintlayout.widget.ConstraintLayout
- android:id="@+id/pin_container"
- android:layout_width="0dp"
- android:layout_height="match_parent"
- android:layout_weight="3"
- android:clipChildren="false"
- android:clipToPadding="false"
- android:layoutDirection="ltr"
- android:orientation="vertical">
-
- <!-- Guideline used to place the top row of keys relative to the screen height. This will be
- updated in KeyguardPINView to reduce the height of the PIN pad. -->
- <androidx.constraintlayout.widget.Guideline
- android:id="@+id/pin_pad_top_guideline"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:orientation="horizontal"
- androidprv:layout_constraintGuide_percent="0" />
-
- <com.android.keyguard.KeyguardPinFlowView
- android:id="@+id/flow1"
- android:layout_width="0dp"
- android:layout_height="0dp"
- android:clipChildren="false"
- android:clipToPadding="false"
- android:orientation="horizontal"
-
- androidprv:constraint_referenced_ids="key1,key2,key3,key4,key5,key6,key7,key8,key9,delete_button,key0,key_enter"
-
- androidprv:flow_horizontalGap="@dimen/num_pad_key_margin_end"
-
- androidprv:flow_horizontalStyle="packed"
- androidprv:flow_maxElementsWrap="3"
-
- androidprv:flow_verticalBias="0.5"
- androidprv:flow_verticalGap="@dimen/num_pad_entry_row_margin_bottom"
- androidprv:flow_verticalStyle="packed"
-
- androidprv:flow_wrapMode="aligned"
- androidprv:layout_constraintBottom_toBottomOf="parent"
- androidprv:layout_constraintEnd_toEndOf="parent"
- androidprv:layout_constraintStart_toStartOf="parent"
- androidprv:layout_constraintTop_toBottomOf="@id/pin_pad_top_guideline" />
-
- <com.android.keyguard.NumPadButton
- android:id="@+id/delete_button"
- style="@style/NumPadKey.Delete"
- android:layout_width="0dp"
- android:layout_height="0dp"
- android:accessibilityTraversalBefore="@id/key0"
- android:contentDescription="@string/keyboardview_keycode_delete" />
-
- <com.android.keyguard.NumPadButton
- android:id="@+id/key_enter"
- style="@style/NumPadKey.Enter"
- android:layout_width="0dp"
- android:layout_height="0dp"
- android:contentDescription="@string/keyboardview_keycode_enter" />
-
- <com.android.keyguard.NumPadKey
- android:id="@+id/key1"
- android:layout_width="0dp"
- android:layout_height="0dp"
- android:accessibilityTraversalBefore="@id/key2"
- androidprv:digit="1"
- androidprv:textView="@+id/pinEntry" />
-
- <com.android.keyguard.NumPadKey
- android:id="@+id/key2"
- android:layout_width="0dp"
- android:layout_height="0dp"
- android:accessibilityTraversalBefore="@id/key3"
- androidprv:digit="2"
- androidprv:textView="@+id/pinEntry" />
-
- <com.android.keyguard.NumPadKey
- android:id="@+id/key3"
- android:layout_width="0dp"
- android:layout_height="0dp"
- android:accessibilityTraversalBefore="@id/key4"
- androidprv:digit="3"
- androidprv:textView="@+id/pinEntry" />
-
- <com.android.keyguard.NumPadKey
- android:id="@+id/key4"
- android:layout_width="0dp"
- android:layout_height="0dp"
- android:accessibilityTraversalBefore="@id/key5"
- androidprv:digit="4"
- androidprv:textView="@+id/pinEntry" />
-
- <com.android.keyguard.NumPadKey
- android:id="@+id/key5"
- android:layout_width="0dp"
- android:layout_height="0dp"
- android:accessibilityTraversalBefore="@id/key6"
- androidprv:digit="5"
- androidprv:textView="@+id/pinEntry" />
-
-
- <com.android.keyguard.NumPadKey
- android:id="@+id/key6"
- android:layout_width="0dp"
- android:layout_height="0dp"
- android:accessibilityTraversalBefore="@id/key7"
- androidprv:digit="6"
- androidprv:textView="@+id/pinEntry" />
-
- <com.android.keyguard.NumPadKey
- android:id="@+id/key7"
- android:layout_width="0dp"
- android:layout_height="0dp"
- android:accessibilityTraversalBefore="@id/key8"
- androidprv:digit="7"
- androidprv:textView="@+id/pinEntry" />
-
- <com.android.keyguard.NumPadKey
- android:id="@+id/key8"
- android:layout_width="0dp"
- android:layout_height="0dp"
- android:accessibilityTraversalBefore="@id/key9"
- androidprv:digit="8"
- androidprv:textView="@+id/pinEntry" />
-
- <com.android.keyguard.NumPadKey
- android:id="@+id/key9"
- android:layout_width="0dp"
- android:layout_height="0dp"
- android:accessibilityTraversalBefore="@id/delete_button"
- androidprv:digit="9"
- androidprv:textView="@+id/pinEntry" />
-
- <com.android.keyguard.NumPadKey
- android:id="@+id/key0"
- android:layout_width="0dp"
- android:layout_height="0dp"
- android:accessibilityTraversalBefore="@id/key_enter"
- androidprv:digit="0"
- androidprv:textView="@+id/pinEntry" />
-
- </androidx.constraintlayout.widget.ConstraintLayout>
-
-</com.android.keyguard.KeyguardPINView>
diff --git a/packages/SystemUI/res-keyguard/layout/keyguard_pin_view_portrait.xml b/packages/SystemUI/res-keyguard/layout/keyguard_pin_view_portrait.xml
deleted file mode 100644
index f3cd9e49b49c..000000000000
--- a/packages/SystemUI/res-keyguard/layout/keyguard_pin_view_portrait.xml
+++ /dev/null
@@ -1,218 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-**
-** Copyright 2023, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License")
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
--->
-
-<com.android.keyguard.KeyguardPINView xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:androidprv="http://schemas.android.com/apk/res-auto"
- android:id="@+id/keyguard_pin_view"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:layout_gravity="center_horizontal|bottom"
- android:clipChildren="false"
- android:clipToPadding="false"
- android:orientation="vertical"
- androidprv:layout_maxWidth="@dimen/keyguard_security_width">
-
- <include layout="@layout/keyguard_bouncer_message_area"/>
-
- <com.android.systemui.bouncer.ui.BouncerMessageView
- android:id="@+id/bouncer_message_view"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:orientation="vertical" />
-
- <androidx.constraintlayout.widget.ConstraintLayout
- android:id="@+id/pin_container"
- android:layout_width="match_parent"
- android:layout_height="0dp"
- android:layout_marginBottom="8dp"
- android:clipChildren="false"
- android:clipToPadding="false"
- android:layout_weight="1"
- android:layoutDirection="ltr"
- android:orientation="vertical">
-
- <!-- Set this to be just above key1. It would be better to introduce a barrier above
- key1/key2/key3, then place this View above that. Sadly, that doesn't work (the Barrier
- drops to the bottom of the page, and key1/2/3 all shoot up to the top-left). In any
- case, the Flow should ensure that key1/2/3 all have the same top, so this should be
- fine. -->
- <com.android.keyguard.AlphaOptimizedRelativeLayout
- android:id="@+id/row0"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:paddingBottom="@dimen/num_pad_entry_row_margin_bottom"
- androidprv:layout_constraintTop_toTopOf="parent"
- androidprv:layout_constraintEnd_toEndOf="parent"
- androidprv:layout_constraintStart_toStartOf="parent"
- androidprv:layout_constraintBottom_toTopOf="@id/key1"
- androidprv:layout_constraintVertical_bias="0.5">
-
- <com.android.keyguard.PasswordTextView
- android:id="@+id/pinEntry"
- style="@style/Widget.TextView.Password"
- android:layout_width="@dimen/keyguard_security_width"
- android:layout_height="@dimen/keyguard_password_height"
- android:layout_centerHorizontal="true"
- android:layout_marginRight="72dp"
- android:contentDescription="@string/keyguard_accessibility_pin_area"
- androidprv:scaledTextSize="@integer/scaled_password_text_size" />
- </com.android.keyguard.AlphaOptimizedRelativeLayout>
-
- <!-- Guideline used to place the top row of keys relative to the screen height. This will be
- updated in KeyguardPINView to reduce the height of the PIN pad. -->
- <androidx.constraintlayout.widget.Guideline
- android:id="@+id/pin_pad_top_guideline"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- androidprv:layout_constraintGuide_percent="0"
- android:orientation="horizontal" />
-
- <com.android.keyguard.KeyguardPinFlowView
- android:id="@+id/flow1"
- android:layout_width="0dp"
- android:layout_height="0dp"
- android:orientation="horizontal"
- android:clipChildren="false"
- android:clipToPadding="false"
-
- androidprv:constraint_referenced_ids="key1,key2,key3,key4,key5,key6,key7,key8,key9,delete_button,key0,key_enter"
-
- androidprv:flow_horizontalGap="@dimen/num_pad_key_margin_end"
-
- androidprv:flow_horizontalStyle="packed"
- androidprv:flow_maxElementsWrap="3"
-
- androidprv:flow_verticalBias="1.0"
- androidprv:flow_verticalGap="@dimen/num_pad_entry_row_margin_bottom"
- androidprv:flow_verticalStyle="packed"
-
- androidprv:flow_wrapMode="aligned"
- androidprv:layout_constraintBottom_toBottomOf="parent"
- androidprv:layout_constraintEnd_toEndOf="parent"
- androidprv:layout_constraintStart_toStartOf="parent"
- androidprv:layout_constraintTop_toBottomOf="@id/pin_pad_top_guideline" />
-
- <com.android.keyguard.NumPadKey
- android:id="@+id/key1"
- android:layout_width="0dp"
- android:layout_height="0dp"
- android:accessibilityTraversalBefore="@id/key2"
- androidprv:digit="1"
- androidprv:textView="@+id/pinEntry" />
-
- <com.android.keyguard.NumPadKey
- android:id="@+id/key2"
- android:layout_width="0dp"
- android:layout_height="0dp"
- android:accessibilityTraversalBefore="@id/key3"
- androidprv:digit="2"
- androidprv:textView="@+id/pinEntry" />
-
- <com.android.keyguard.NumPadKey
- android:id="@+id/key3"
- android:layout_width="0dp"
- android:layout_height="0dp"
- android:accessibilityTraversalBefore="@id/key4"
- androidprv:digit="3"
- androidprv:textView="@+id/pinEntry" />
-
- <com.android.keyguard.NumPadKey
- android:id="@+id/key4"
- android:layout_width="0dp"
- android:layout_height="0dp"
- android:accessibilityTraversalBefore="@id/key5"
- androidprv:digit="4"
- androidprv:textView="@+id/pinEntry" />
-
- <com.android.keyguard.NumPadKey
- android:id="@+id/key5"
- android:layout_width="0dp"
- android:layout_height="0dp"
- android:accessibilityTraversalBefore="@id/key6"
- androidprv:digit="5"
- androidprv:textView="@+id/pinEntry" />
-
- <com.android.keyguard.NumPadKey
- android:id="@+id/key6"
- android:layout_width="0dp"
- android:layout_height="0dp"
- android:accessibilityTraversalBefore="@id/key7"
- androidprv:digit="6"
- androidprv:textView="@+id/pinEntry" />
-
- <com.android.keyguard.NumPadKey
- android:id="@+id/key7"
- android:layout_width="0dp"
- android:layout_height="0dp"
- android:accessibilityTraversalBefore="@id/key8"
- androidprv:digit="7"
- androidprv:textView="@+id/pinEntry" />
-
-
- <com.android.keyguard.NumPadKey
- android:id="@+id/key8"
- android:layout_width="0dp"
- android:layout_height="0dp"
- android:accessibilityTraversalBefore="@id/key9"
- androidprv:digit="8"
- androidprv:textView="@+id/pinEntry" />
-
- <com.android.keyguard.NumPadKey
- android:id="@+id/key9"
- android:layout_width="0dp"
- android:layout_height="0dp"
- android:accessibilityTraversalBefore="@id/delete_button"
- androidprv:digit="9"
- androidprv:textView="@+id/pinEntry" />
-
- <com.android.keyguard.NumPadButton
- android:id="@+id/delete_button"
- style="@style/NumPadKey.Delete"
- android:layout_width="0dp"
- android:layout_height="0dp"
- android:accessibilityTraversalBefore="@id/key0"
- android:contentDescription="@string/keyboardview_keycode_delete" />
-
- <com.android.keyguard.NumPadKey
- android:id="@+id/key0"
- android:layout_width="0dp"
- android:layout_height="0dp"
- android:accessibilityTraversalBefore="@id/key_enter"
- androidprv:digit="0"
- androidprv:textView="@+id/pinEntry" />
-
- <com.android.keyguard.NumPadButton
- android:id="@+id/key_enter"
- style="@style/NumPadKey.Enter"
- android:layout_width="0dp"
- android:layout_height="0dp"
- android:contentDescription="@string/keyboardview_keycode_enter" />
- </androidx.constraintlayout.widget.ConstraintLayout>
-
- <include layout="@layout/keyguard_eca"
- android:id="@+id/keyguard_selector_fade_container"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:orientation="vertical"
- android:layout_gravity="bottom|center_horizontal"
- android:layout_marginTop="@dimen/keyguard_eca_top_margin"
- android:layout_marginBottom="@dimen/keyguard_eca_bottom_margin"
- android:gravity="center_horizontal"/>
-
-</com.android.keyguard.KeyguardPINView>
diff --git a/packages/SystemUI/res-keyguard/values-da/strings.xml b/packages/SystemUI/res-keyguard/values-da/strings.xml
index 027166ff72c0..c7c863b70336 100644
--- a/packages/SystemUI/res-keyguard/values-da/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-da/strings.xml
@@ -118,7 +118,7 @@
<string name="kg_prompt_reason_device_admin" msgid="6961159596224055685">"Enheden er blevet låst af administratoren"</string>
<string name="kg_prompt_reason_user_request" msgid="6015774877733717904">"Enheden blev låst manuelt"</string>
<string name="kg_face_not_recognized" msgid="7903950626744419160">"Ikke genkendt"</string>
- <string name="kg_face_sensor_privacy_enabled" msgid="939511161763558512">"Aktivér kameraadgang i Indstillinger for at bruge ansigtslås"</string>
+ <string name="kg_face_sensor_privacy_enabled" msgid="939511161763558512">"Aktivér kameraadgang i Indstillinger for at bruge ansigtsoplåsning"</string>
<string name="kg_password_default_pin_message" msgid="1434544655827987873">"{count,plural, =1{Angiv pinkoden til SIM-kortet. Du har # forsøg tilbage, før du skal kontakte dit mobilselskab for at låse din enhed op.}one{Angiv pinkoden til SIM-kortet. Du har # forsøg tilbage.}other{Angiv pinkoden til SIM-kortet. Du har # forsøg tilbage.}}"</string>
<string name="kg_password_default_puk_message" msgid="1025139786449741950">"{count,plural, =1{SIM-kortet er nu deaktiveret. Angiv PUK-koden for at fortsætte. Du har # forsøg tilbage, før SIM-kortet bliver permanent ubrugeligt. Kontakt dit mobilselskab for at få flere oplysninger.}one{SIM-kortet er nu deaktiveret. Angiv PUK-koden for at fortsætte. Du har # forsøg tilbage, før SIM-kortet bliver permanent ubrugeligt. Kontakt dit mobilselskab for at få flere oplysninger.}other{SIM-kortet er nu deaktiveret. Angiv PUK-koden for at fortsætte. Du har # forsøg tilbage, før SIM-kortet bliver permanent ubrugeligt. Kontakt dit mobilselskab for at få flere oplysninger.}}"</string>
<string name="clock_title_default" msgid="6342735240617459864">"Standard"</string>
diff --git a/packages/SystemUI/res/layout/zen_mode_condition.xml b/packages/SystemUI/res/layout/zen_mode_condition.xml
deleted file mode 100644
index 3baae3376bd0..000000000000
--- a/packages/SystemUI/res/layout/zen_mode_condition.xml
+++ /dev/null
@@ -1,85 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- Copyright (C) 2014 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:theme="@style/Theme.SystemUI.QuickSettings"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:clipChildren="false"
- android:layout_marginStart="1dp"
- android:layout_marginEnd="0dp"
- android:layout_weight="1"
- android:gravity="center_vertical" >
-
- <LinearLayout
- android:id="@android:id/content"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:minHeight="48dp"
- android:gravity="center_vertical"
- android:layout_centerVertical="true"
- android:orientation="vertical"
- android:layout_toEndOf="@android:id/checkbox"
- android:layout_toStartOf="@android:id/button1">
-
- <TextView
- android:id="@android:id/text1"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:ellipsize="end"
- android:textAlignment="viewStart"
- android:maxLines="1"
- android:textAppearance="@style/TextAppearance.QS.DetailItemPrimary" />
-
- <TextView
- android:id="@android:id/text2"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_marginTop="@dimen/zen_mode_condition_detail_item_interline_spacing"
- android:ellipsize="end"
- android:textAlignment="viewStart"
- android:maxLines="1"
- android:textAppearance="@style/TextAppearance.QS.DetailItemSecondary" />
-
- </LinearLayout>
-
- <ImageView
- android:id="@android:id/button1"
- style="@style/QSBorderlessButton"
- android:background="@drawable/ripple_drawable_20dp"
- android:layout_width="48dp"
- android:layout_height="48dp"
- android:layout_centerVertical="true"
- android:scaleType="center"
- android:layout_toStartOf="@android:id/button2"
- android:contentDescription="@string/accessibility_quick_settings_less_time"
- android:tint="?android:attr/textColorPrimary"
- android:src="@drawable/ic_qs_minus" />
-
- <ImageView
- android:id="@android:id/button2"
- style="@style/QSBorderlessButton"
- android:background="@drawable/ripple_drawable_20dp"
- android:layout_width="48dp"
- android:layout_height="48dp"
- android:layout_alignParentEnd="true"
- android:scaleType="center"
- android:layout_centerVertical="true"
- android:contentDescription="@string/accessibility_quick_settings_more_time"
- android:tint="?android:attr/textColorPrimary"
- android:src="@drawable/ic_qs_plus" />
-
-</RelativeLayout>
diff --git a/packages/SystemUI/res/values-af/strings.xml b/packages/SystemUI/res/values-af/strings.xml
index a1db50d10197..206a7eeda5c1 100644
--- a/packages/SystemUI/res/values-af/strings.xml
+++ b/packages/SystemUI/res/values-af/strings.xml
@@ -57,8 +57,7 @@
<string name="hdmi_cec_set_menu_language_description" msgid="8176716678074126619">"\'n Ander toestel het versoek om die stelseltaal te verander"</string>
<string name="hdmi_cec_set_menu_language_accept" msgid="2513689457281009578">"Verander taal"</string>
<string name="hdmi_cec_set_menu_language_decline" msgid="7650721096558646011">"Hou huidige taal"</string>
- <!-- no translation found for share_wifi_button_text (1285273973812029240) -->
- <skip />
+ <string name="share_wifi_button_text" msgid="1285273973812029240">"Deel wi-fi"</string>
<string name="wifi_debugging_title" msgid="7300007687492186076">"Laat draadlose ontfouting op hierdie netwerk toe?"</string>
<string name="wifi_debugging_message" msgid="5461204211731802995">"Netwerknaam (SSID)\n<xliff:g id="SSID_0">%1$s</xliff:g>\n\nWi‑Fi-adres (BSSID)\n<xliff:g id="BSSID_1">%2$s</xliff:g>"</string>
<string name="wifi_debugging_always" msgid="2968383799517975155">"Laat altyd toe op hierdie netwerk"</string>
@@ -160,8 +159,7 @@
<string name="biometric_dialog_wrong_pattern" msgid="8954812279840889029">"Verkeerde patroon"</string>
<string name="biometric_dialog_wrong_password" msgid="69477929306843790">"Verkeerde wagwoord"</string>
<string name="biometric_dialog_credential_too_many_attempts" msgid="3083141271737748716">"Te veel verkeerde pogings.\nProbeer oor <xliff:g id="NUMBER">%d</xliff:g> sekondes weer."</string>
- <!-- no translation found for work_challenge_emergency_button_text (8946588434515599288) -->
- <skip />
+ <string name="work_challenge_emergency_button_text" msgid="8946588434515599288">"Noodgeval"</string>
<string name="biometric_dialog_credential_attempts_before_wipe" msgid="6751859711975516999">"Probeer weer. Poging <xliff:g id="ATTEMPTS_0">%1$d</xliff:g> van <xliff:g id="MAX_ATTEMPTS">%2$d</xliff:g>."</string>
<string name="biometric_dialog_last_attempt_before_wipe_dialog_title" msgid="2874250099278693477">"Jou data sal uitgevee word"</string>
<string name="biometric_dialog_last_pattern_attempt_before_wipe_device" msgid="6562299244825817598">"As jy met jou volgende poging \'n verkeerde patroon invoer, sal hierdie toestel se data uitgevee word."</string>
@@ -415,8 +413,7 @@
<string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="8736391633234144237">"Wanneer jy deel, opneem of uitsaai, het <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> toegang tot enigiets wat op jou skerm sigbaar is of op jou toestel gespeel word. Wees dus versigtig met dinge soos wagwoorde, betalingbesonderhede, boodskappe, foto’s, en oudio en video."</string>
<string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="5211695779082563959">"Wanneer jy ’n app deel, opneem of uitsaai, het <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> toegang tot enigiets wat in daardie app gewys of gespeel word. Wees dus versigtig met dinge soos wagwoorde, betalingbesonderhede, boodskappe, foto’s, en oudio en video."</string>
<string name="media_projection_entry_app_permission_dialog_continue" msgid="295463518195075840">"Begin"</string>
- <!-- no translation found for media_projection_entry_app_permission_dialog_single_app_disabled (8999903044874669995) -->
- <skip />
+ <string name="media_projection_entry_app_permission_dialog_single_app_disabled" msgid="8999903044874669995">"<xliff:g id="APP_NAME">%1$s</xliff:g> het hierdie opsie gedeaktiveer"</string>
<string name="media_projection_entry_cast_permission_dialog_title" msgid="8860150223172993547">"Begin uitsaai?"</string>
<string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="1986212276016817231">"Wanneer jy uitsaai, het Android toegang tot enigiets wat op jou skerm sigbaar is of op jou toestel gespeel word. Wees dus versigtig met dinge soos wagwoorde, betalingbesonderhede, boodskappe, foto’s, en oudio en video."</string>
<string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="9900961380294292">"Wanneer jy ’n app uitsaai, het Android toegang tot enigiets wat in daardie app gewys of gespeel word. Wees dus versigtig met dinge soos wagwoorde, betalingbesonderhede, boodskappe, foto’s, en oudio en video."</string>
@@ -1173,6 +1170,10 @@
<string name="assistant_attention_content_description" msgid="6830215897604642875">"Assistent-aandag is aan"</string>
<string name="set_default_notes_app_toast_content" msgid="2812374329662610753">"Stel versteknotasapp in Instellings"</string>
<string name="install_app" msgid="5066668100199613936">"Installeer app"</string>
+ <!-- no translation found for connected_display_dialog_start_mirroring (6237895789920854982) -->
+ <skip />
+ <!-- no translation found for enable_display (8308309634883321977) -->
+ <skip />
<string name="privacy_dialog_title" msgid="7839968133469098311">"Mikrofoon en kamera"</string>
<string name="privacy_dialog_summary" msgid="2458769652125995409">"Onlangse appgebruik"</string>
<string name="privacy_dialog_more_button" msgid="7610604080293562345">"Sien onlangse toegang"</string>
diff --git a/packages/SystemUI/res/values-am/strings.xml b/packages/SystemUI/res/values-am/strings.xml
index bc7273d1e08d..09157f8a7b6d 100644
--- a/packages/SystemUI/res/values-am/strings.xml
+++ b/packages/SystemUI/res/values-am/strings.xml
@@ -57,8 +57,7 @@
<string name="hdmi_cec_set_menu_language_description" msgid="8176716678074126619">"በሌላ መሣሪያ የተጠየቀ የስርዓት ቋንቋ ለውጥ"</string>
<string name="hdmi_cec_set_menu_language_accept" msgid="2513689457281009578">"ቋንቋ ቀይር"</string>
<string name="hdmi_cec_set_menu_language_decline" msgid="7650721096558646011">"አሁን ያለውን ቋንቋ አቆይ"</string>
- <!-- no translation found for share_wifi_button_text (1285273973812029240) -->
- <skip />
+ <string name="share_wifi_button_text" msgid="1285273973812029240">"Wi‑Fiን አጋራ"</string>
<string name="wifi_debugging_title" msgid="7300007687492186076">"በዚህ አውታረ መረብ ላይ ገመድ-አልባ debugging ይፈቀድ?"</string>
<string name="wifi_debugging_message" msgid="5461204211731802995">"የአውታረ መረብ ስም (SSID)\n<xliff:g id="SSID_0">%1$s</xliff:g>\n\nየWi‑Fi አድራሻ (BSSID)\n<xliff:g id="BSSID_1">%2$s</xliff:g>"</string>
<string name="wifi_debugging_always" msgid="2968383799517975155">"ሁልጊዜ በዚህ አውታረ መረብ ላይ ፍቀድ"</string>
@@ -160,8 +159,7 @@
<string name="biometric_dialog_wrong_pattern" msgid="8954812279840889029">"የተሳሳተ ሥርዓተ ጥለት"</string>
<string name="biometric_dialog_wrong_password" msgid="69477929306843790">"የተሳሳተ የይለፍ ቃል"</string>
<string name="biometric_dialog_credential_too_many_attempts" msgid="3083141271737748716">"ከልክ በላይ ብዙ የተሳሳቱ ሙከራዎች።\nበ<xliff:g id="NUMBER">%d</xliff:g> ሰከንዶች ውስጥ እንደገና ይሞክሩ።"</string>
- <!-- no translation found for work_challenge_emergency_button_text (8946588434515599288) -->
- <skip />
+ <string name="work_challenge_emergency_button_text" msgid="8946588434515599288">"ድንገተኛ አደጋ"</string>
<string name="biometric_dialog_credential_attempts_before_wipe" msgid="6751859711975516999">"እንደገና ይሞክሩ። ሙከራ <xliff:g id="ATTEMPTS_0">%1$d</xliff:g> ከ<xliff:g id="MAX_ATTEMPTS">%2$d</xliff:g>።"</string>
<string name="biometric_dialog_last_attempt_before_wipe_dialog_title" msgid="2874250099278693477">"የእርስዎ ውሂብ ይሰረዛል"</string>
<string name="biometric_dialog_last_pattern_attempt_before_wipe_device" msgid="6562299244825817598">"በሚቀጥለው ሙከራ ላይ ትክክል ያልሆነ ሥርዓተ ጥለት ካስገቡ የዚህ መሣሪያ ውሂብ ይሰረዛል።"</string>
@@ -415,8 +413,7 @@
<string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="8736391633234144237">"እርስዎ ሲያጋሩ፣ ሲቀርጹ ወይም cast ሲያደርጉ <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> በማያ ገጽዎ ላይ ለሚታይ ወይም በመሣሪያዎ ላይ ለሚጫወት ማንኛውም ነገር መዳረሻ አለው። ስለዚህ እንደ የይለፍ ቃላት፣ የክፍያ ዝርዝሮች፣ መልዕክቶች፣ ፎቶዎች እና ኦዲዮ እና ቪድዮ ላሉ ነገሮች ጥንቃቄ ያድርጉ።"</string>
<string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="5211695779082563959">"አንድን መተግበሪያ ሲያጋሩ፣ ሲቀርጹ ወይም cast ሲያደርጉ <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> በዚያ መተግበሪያ ላይ ለሚታይ ወይም ለሚጫወት ማንኛውም ነገር መዳረሻ አለው። ስለዚህ እንደ የይለፍ ቃላት፣ የክፍያ ዝርዝሮች፣ መልዕክቶች፣ ፎቶዎች እና ኦዲዮ እና ቪድዮ ላሉ ነገሮች ጥንቃቄ ያድርጉ።"</string>
<string name="media_projection_entry_app_permission_dialog_continue" msgid="295463518195075840">"ጀምር"</string>
- <!-- no translation found for media_projection_entry_app_permission_dialog_single_app_disabled (8999903044874669995) -->
- <skip />
+ <string name="media_projection_entry_app_permission_dialog_single_app_disabled" msgid="8999903044874669995">"<xliff:g id="APP_NAME">%1$s</xliff:g> ይህን አማራጭ አሰናክሏል"</string>
<string name="media_projection_entry_cast_permission_dialog_title" msgid="8860150223172993547">"cast ማድረግ ይጀምር?"</string>
<string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="1986212276016817231">"እርስዎ cast በሚያደርጉበት ጊዜ Android በማያ ገጽዎ ላይ ለሚታይ ወይም በመሣሪያዎ ላይ ለሚጫወት ማንኛውም ነገር መዳረሻ አለው። ስለዚህ እንደ የይለፍ ቃላት፣ የክፍያ ዝርዝሮች፣ መልዕክቶች፣ ፎቶዎች እና ኦዲዮ እና ቪድዮ ላሉ ነገሮች ጥንቃቄ ያድርጉ።"</string>
<string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="9900961380294292">"አንድን መተግበሪያ cast ሲያደርጉ Android በዚያ መተግበሪያ ላይ ለሚታይ ወይም ለሚጫወት ማንኛውም ነገር መዳረሻ አለው። ስለዚህ እንደ ይለፍ ቃላት፣ የክፍያ ዝርዝሮች፣ መልዕክቶች፣ ፎቶዎች እና ኦዲዮ እና ቪድዮ ላሉ ነገሮች ጥንቃቄ ያድርጉ"</string>
@@ -1173,6 +1170,10 @@
<string name="assistant_attention_content_description" msgid="6830215897604642875">"የረዳት ትኩረት በርቷል"</string>
<string name="set_default_notes_app_toast_content" msgid="2812374329662610753">"በቅንብሮች ውስጥ ነባሪ የማስታወሻዎች መተግበሪያን ያቀናብሩ"</string>
<string name="install_app" msgid="5066668100199613936">"መተግበሪያን ጫን"</string>
+ <!-- no translation found for connected_display_dialog_start_mirroring (6237895789920854982) -->
+ <skip />
+ <!-- no translation found for enable_display (8308309634883321977) -->
+ <skip />
<string name="privacy_dialog_title" msgid="7839968133469098311">"ማይክሮፎን እና ካሜራ"</string>
<string name="privacy_dialog_summary" msgid="2458769652125995409">"የቅርብ ጊዜ የመተግበሪያ አጠቃቀም"</string>
<string name="privacy_dialog_more_button" msgid="7610604080293562345">"የቅርብ ጊዜ መዳረሻን አሳይ"</string>
diff --git a/packages/SystemUI/res/values-ar/strings.xml b/packages/SystemUI/res/values-ar/strings.xml
index 7b8f23a5e222..31b7cbe31cc2 100644
--- a/packages/SystemUI/res/values-ar/strings.xml
+++ b/packages/SystemUI/res/values-ar/strings.xml
@@ -57,8 +57,7 @@
<string name="hdmi_cec_set_menu_language_description" msgid="8176716678074126619">"طلب جهاز آخر تغيير لغة النظام."</string>
<string name="hdmi_cec_set_menu_language_accept" msgid="2513689457281009578">"تغيير اللغة"</string>
<string name="hdmi_cec_set_menu_language_decline" msgid="7650721096558646011">"الإبقاء على اللغة الحالية"</string>
- <!-- no translation found for share_wifi_button_text (1285273973812029240) -->
- <skip />
+ <string name="share_wifi_button_text" msgid="1285273973812029240">"‏مشاركة اتصال Wi‑Fi"</string>
<string name="wifi_debugging_title" msgid="7300007687492186076">"هل تريد السماح باستخدام ميزة \"تصحيح الأخطاء اللاسلكي\" على هذه الشبكة؟"</string>
<string name="wifi_debugging_message" msgid="5461204211731802995">"‏اسم الشبكة (SSID)\n<xliff:g id="SSID_0">%1$s</xliff:g>\n\nعنوان شبكة Wi‑Fi‏ (BSSID)\n<xliff:g id="BSSID_1">%2$s</xliff:g>"</string>
<string name="wifi_debugging_always" msgid="2968383799517975155">"السماح باستخدام هذه الميزة على هذه الشبكة دائمًا"</string>
@@ -160,8 +159,7 @@
<string name="biometric_dialog_wrong_pattern" msgid="8954812279840889029">"النقش غير صحيح."</string>
<string name="biometric_dialog_wrong_password" msgid="69477929306843790">"كلمة مرور غير صحيحة"</string>
<string name="biometric_dialog_credential_too_many_attempts" msgid="3083141271737748716">"تم إجراء عدد كبير جدًا من المحاولات غير الصحيحة.\nأعد المحاولة خلال <xliff:g id="NUMBER">%d</xliff:g> ثانية."</string>
- <!-- no translation found for work_challenge_emergency_button_text (8946588434515599288) -->
- <skip />
+ <string name="work_challenge_emergency_button_text" msgid="8946588434515599288">"الطوارئ"</string>
<string name="biometric_dialog_credential_attempts_before_wipe" msgid="6751859711975516999">"يُرجى إعادة المحاولة. المحاولة <xliff:g id="ATTEMPTS_0">%1$d</xliff:g> من <xliff:g id="MAX_ATTEMPTS">%2$d</xliff:g>"</string>
<string name="biometric_dialog_last_attempt_before_wipe_dialog_title" msgid="2874250099278693477">"سيتم حذف بياناتك"</string>
<string name="biometric_dialog_last_pattern_attempt_before_wipe_device" msgid="6562299244825817598">"عند إدخال نقش غير صحيح في المحاولة التالية، سيتم حذف بيانات هذا الجهاز."</string>
@@ -415,8 +413,7 @@
<string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="8736391633234144237">"أثناء المشاركة أو التسجيل أو البثّ، يمكن لتطبيق \"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>\" الوصول إلى كل المحتوى المعروض على شاشتك أو الذي يتم تشغيله على جهاز، لذا يُرجى توخي الحذر بشأن المعلومات، مثل كلمات المرور وتفاصيل الدفع والرسائل والصور وملفات الصوت والفيديو."</string>
<string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="5211695779082563959">"أثناء مشاركة محتوى تطبيق أو تسجيله أو بثّه، يمكن لتطبيق \"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>\" الوصول إلى كل المحتوى المعروض أو الذي يتم تشغيله في ذلك التطبيق، لذا يُرجى توخي الحذر بشأن المعلومات، مثل كلمات المرور وتفاصيل الدفع والرسائل والصور وملفات الصوت والفيديو."</string>
<string name="media_projection_entry_app_permission_dialog_continue" msgid="295463518195075840">"بدء"</string>
- <!-- no translation found for media_projection_entry_app_permission_dialog_single_app_disabled (8999903044874669995) -->
- <skip />
+ <string name="media_projection_entry_app_permission_dialog_single_app_disabled" msgid="8999903044874669995">"تم إيقاف هذا الخيار من خلال تطبيق <xliff:g id="APP_NAME">%1$s</xliff:g>."</string>
<string name="media_projection_entry_cast_permission_dialog_title" msgid="8860150223172993547">"هل تريد بدء البثّ؟"</string>
<string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="1986212276016817231">"‏أثناء البثّ، يمكن لنظام Android الوصول إلى كل المحتوى المعروض على شاشتك أو الذي يتم تشغيله على جهازك، لذا يُرجى توخي الحذر بشأن المعلومات، مثل كلمات المرور وتفاصيل الدفع والرسائل والصور وملفات الصوت والفيديو."</string>
<string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="9900961380294292">"‏أثناء بثّ محتوى تطبيق، يمكن لنظام Android الوصول إلى كل المحتوى المعروض أو الذي يتم تشغيله في ذلك التطبيق، لذا يُرجى توخي الحذر بشأن المعلومات، مثل كلمات المرور وتفاصيل الدفع والرسائل والصور وملفات الصوت والفيديو."</string>
@@ -1173,6 +1170,10 @@
<string name="assistant_attention_content_description" msgid="6830215897604642875">"‏ميزة لفت انتباه \"مساعد Google\" مفعّلة."</string>
<string name="set_default_notes_app_toast_content" msgid="2812374329662610753">"يمكنك ضبط تطبيق تدوين الملاحظات التلقائي في \"الإعدادات\"."</string>
<string name="install_app" msgid="5066668100199613936">"تثبيت التطبيق"</string>
+ <!-- no translation found for connected_display_dialog_start_mirroring (6237895789920854982) -->
+ <skip />
+ <!-- no translation found for enable_display (8308309634883321977) -->
+ <skip />
<string name="privacy_dialog_title" msgid="7839968133469098311">"الميكروفون والكاميرا"</string>
<string name="privacy_dialog_summary" msgid="2458769652125995409">"آخر استخدام في التطبيقات"</string>
<string name="privacy_dialog_more_button" msgid="7610604080293562345">"عرض آخر استخدام في التطبيقات"</string>
diff --git a/packages/SystemUI/res/values-as/strings.xml b/packages/SystemUI/res/values-as/strings.xml
index 9b3be3c2ee1c..732d19d09283 100644
--- a/packages/SystemUI/res/values-as/strings.xml
+++ b/packages/SystemUI/res/values-as/strings.xml
@@ -57,8 +57,7 @@
<string name="hdmi_cec_set_menu_language_description" msgid="8176716678074126619">"অন্য এটা ডিভাইচে ছিষ্টেমৰ ভাষা সলনি কৰাৰ অনুৰোধ কৰিছে"</string>
<string name="hdmi_cec_set_menu_language_accept" msgid="2513689457281009578">"ভাষা সলনি কৰক"</string>
<string name="hdmi_cec_set_menu_language_decline" msgid="7650721096558646011">"বৰ্তমানৰ ভাষাটো ৰাখক"</string>
- <!-- no translation found for share_wifi_button_text (1285273973812029240) -->
- <skip />
+ <string name="share_wifi_button_text" msgid="1285273973812029240">"ৱাই-ফাই শ্বেয়াৰ কৰক"</string>
<string name="wifi_debugging_title" msgid="7300007687492186076">"এই নেটৱৰ্কত ৱায়াৰলেচ ডি\'বাগিংৰ অনুমতি দিবনে?"</string>
<string name="wifi_debugging_message" msgid="5461204211731802995">"নেটৱৰ্কৰ নাম (SSID)\n<xliff:g id="SSID_0">%1$s</xliff:g>\n\nৱাই-ফাইৰ ঠিকনা (BSSID)\n<xliff:g id="BSSID_1">%2$s</xliff:g>"</string>
<string name="wifi_debugging_always" msgid="2968383799517975155">"এই নেটৱৰ্কত সদায় অনুমতি দিয়ক"</string>
@@ -160,8 +159,7 @@
<string name="biometric_dialog_wrong_pattern" msgid="8954812279840889029">"ভুল আৰ্হি"</string>
<string name="biometric_dialog_wrong_password" msgid="69477929306843790">"ভুল পাছৱৰ্ড"</string>
<string name="biometric_dialog_credential_too_many_attempts" msgid="3083141271737748716">"বহুসংখ্যক ভুল প্ৰয়াস।\n<xliff:g id="NUMBER">%d</xliff:g>ছেকেণ্ডত পুনৰ চেষ্টা কৰক।"</string>
- <!-- no translation found for work_challenge_emergency_button_text (8946588434515599288) -->
- <skip />
+ <string name="work_challenge_emergency_button_text" msgid="8946588434515599288">"জৰুৰীকালীন"</string>
<string name="biometric_dialog_credential_attempts_before_wipe" msgid="6751859711975516999">"আকৌ চেষ্টা কৰক। <xliff:g id="MAX_ATTEMPTS">%2$d</xliff:g> টাৰ প্ৰয়াসৰ ভিতৰত <xliff:g id="ATTEMPTS_0">%1$d</xliff:g> টা প্ৰয়াস।"</string>
<string name="biometric_dialog_last_attempt_before_wipe_dialog_title" msgid="2874250099278693477">"আপোনাৰ ডেটা মচি পেলোৱা হ’ব"</string>
<string name="biometric_dialog_last_pattern_attempt_before_wipe_device" msgid="6562299244825817598">"আপুনি পৰৱৰ্তী প্ৰয়াসত এটা ভুল আৰ্হি দিলে, এই ডিভাইচটোৰ ডেটা মচি পেলোৱা হ’ব।"</string>
@@ -415,8 +413,7 @@
<string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="8736391633234144237">"আপুনি শ্বেয়াৰ কৰা, ৰেকৰ্ড কৰা অথবা কাষ্ট কৰাৰ সময়ত, আপোনাৰ স্ক্ৰীনখনত দৃশ্যমান হোৱা যিকোনো বস্তু অথবা আপোনাৰ ডিভাইচত প্লে’ কৰা যিকোনো সমললৈ <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>ৰ এক্সেছ থাকে। গতিকে, পাছৱৰ্ড, পৰিশোধৰ সবিশেষ, বাৰ্তা, ফট’ আৰু অডিঅ’ আৰু ভিডিঅ’ৰ ক্ষেত্ৰত সাৱধান হওক।"</string>
<string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="5211695779082563959">"আপুনি শ্বেয়াৰ কৰা, ৰেকৰ্ড কৰা অথবা কাষ্ট কৰাৰ সময়ত, সেইটো এপত দৃশ্যমান যিকোনো বস্তু অথবা আপোনাৰ ডিভাইচত প্লে’ কৰা যিকোনো সমললৈ <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>ৰ এক্সেছ থাকে। গতিকে, পাছৱৰ্ড, পৰিশোধৰ সবিশেষ, বাৰ্তা, ফট’ আৰু অডিঅ’ আৰু ভিডিঅ’ৰ ক্ষেত্ৰত সাৱধান হওক।"</string>
<string name="media_projection_entry_app_permission_dialog_continue" msgid="295463518195075840">"আৰম্ভ কৰক"</string>
- <!-- no translation found for media_projection_entry_app_permission_dialog_single_app_disabled (8999903044874669995) -->
- <skip />
+ <string name="media_projection_entry_app_permission_dialog_single_app_disabled" msgid="8999903044874669995">"<xliff:g id="APP_NAME">%1$s</xliff:g>এ এই বিকল্পটো অক্ষম কৰিছে"</string>
<string name="media_projection_entry_cast_permission_dialog_title" msgid="8860150223172993547">"কাষ্ট কৰিবলৈ আৰম্ভ কৰিবনে?"</string>
<string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="1986212276016817231">"আপুনি কাষ্ট কৰাৰ সময়ত, আপোনাৰ স্ক্ৰীনখনত দৃশ্যমান যিকোনো বস্তু অথবা আপোনাৰ ডিভাইচত প্লে’ কৰা যিকোনো সমললৈ Androidৰ এক্সেছ থাকে। গতিকে, পাছৱৰ্ড, পৰিশোধৰ সবিশেষ, বাৰ্তা, ফট’ আৰু অডিঅ’ আৰু ভিডিঅ’ৰ ক্ষেত্ৰত সাৱধান হওক।"</string>
<string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="9900961380294292">"আপুনি এটা এপ্ কাষ্ট কৰাৰ সময়ত সেইটো এপত দৃশ্যমান হোৱা যিকোনো বস্তু অথবা আপোনাৰ ডিভাইচত প্লে’ কৰা যিকোনো সমললৈ Androidৰ এক্সেছ থাকে। গতিকে, পাছৱৰ্ড, পৰিশোধৰ সবিশেষ, বাৰ্তা, ফট’ আৰু অডিঅ’ আৰু ভিডিঅ’ৰ ক্ষেত্ৰত সাৱধান হওক।"</string>
@@ -1173,6 +1170,10 @@
<string name="assistant_attention_content_description" msgid="6830215897604642875">"Assistantএ আপোনাৰ কথা শুনি আছে"</string>
<string name="set_default_notes_app_toast_content" msgid="2812374329662610753">"ছেটিঙত টোকাৰ ডিফ’ল্ট এপ্ ছেট কৰক"</string>
<string name="install_app" msgid="5066668100199613936">"এপ্‌টো ইনষ্টল কৰক"</string>
+ <!-- no translation found for connected_display_dialog_start_mirroring (6237895789920854982) -->
+ <skip />
+ <!-- no translation found for enable_display (8308309634883321977) -->
+ <skip />
<string name="privacy_dialog_title" msgid="7839968133469098311">"মাইক্ৰ’ফ’ন আৰু কেমেৰা"</string>
<string name="privacy_dialog_summary" msgid="2458769652125995409">"শেহতীয়া এপৰ ব্যৱহাৰ"</string>
<string name="privacy_dialog_more_button" msgid="7610604080293562345">"শেহতীয়া এক্সেছ চাওক"</string>
diff --git a/packages/SystemUI/res/values-az/strings.xml b/packages/SystemUI/res/values-az/strings.xml
index af63640676eb..080f450432fc 100644
--- a/packages/SystemUI/res/values-az/strings.xml
+++ b/packages/SystemUI/res/values-az/strings.xml
@@ -57,8 +57,7 @@
<string name="hdmi_cec_set_menu_language_description" msgid="8176716678074126619">"Sistem dilinin dəyişdirilməsi başqa cihaz tərəfindən tələb olunur"</string>
<string name="hdmi_cec_set_menu_language_accept" msgid="2513689457281009578">"Dili dəyişin"</string>
<string name="hdmi_cec_set_menu_language_decline" msgid="7650721096558646011">"Cari dili saxlayın"</string>
- <!-- no translation found for share_wifi_button_text (1285273973812029240) -->
- <skip />
+ <string name="share_wifi_button_text" msgid="1285273973812029240">"Wi‑Fi-ı paylaşın"</string>
<string name="wifi_debugging_title" msgid="7300007687492186076">"Bu şəbəkədə WiFi sazlamasına icazə verilsin?"</string>
<string name="wifi_debugging_message" msgid="5461204211731802995">"Şəbəkə Adı (SSID)\n<xliff:g id="SSID_0">%1$s</xliff:g>\n\nWi‑Fi Ünvanı (BSSID)\n<xliff:g id="BSSID_1">%2$s</xliff:g>"</string>
<string name="wifi_debugging_always" msgid="2968383799517975155">"Bu şəbəkədə həmişə icazə verilsin"</string>
@@ -160,8 +159,7 @@
<string name="biometric_dialog_wrong_pattern" msgid="8954812279840889029">"Yanlış model"</string>
<string name="biometric_dialog_wrong_password" msgid="69477929306843790">"Yanlış parol"</string>
<string name="biometric_dialog_credential_too_many_attempts" msgid="3083141271737748716">"Həddindən çox yanlış cəhd.\n<xliff:g id="NUMBER">%d</xliff:g> saniyəyə yenidən cəhd edin."</string>
- <!-- no translation found for work_challenge_emergency_button_text (8946588434515599288) -->
- <skip />
+ <string name="work_challenge_emergency_button_text" msgid="8946588434515599288">"Fövqəladə hal"</string>
<string name="biometric_dialog_credential_attempts_before_wipe" msgid="6751859711975516999">"Yenidən cəhd edin. Cəhd: <xliff:g id="ATTEMPTS_0">%1$d</xliff:g>/<xliff:g id="MAX_ATTEMPTS">%2$d</xliff:g>."</string>
<string name="biometric_dialog_last_attempt_before_wipe_dialog_title" msgid="2874250099278693477">"Data silinəcək"</string>
<string name="biometric_dialog_last_pattern_attempt_before_wipe_device" msgid="6562299244825817598">"Növbəti cəhddə yanlış model daxil etsəniz, bu cihazın datası silinəcək."</string>
@@ -415,8 +413,7 @@
<string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="8736391633234144237">"Paylaşım, qeydəalma və ya yayım zamanı <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> ekranda görünən, yaxud cihazda oxudulan məlumatlara giriş edə bilir. Parol, ödəniş detalları, mesaj, foto, habelə audio və video kimi məlumatlarla bağlı diqqətli olun."</string>
<string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="5211695779082563959">"Tətbiq paylaşdıqda, qeydə aldıqda və ya yayımladıqda <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> həmin tətbiqdə göstərilən, yaxud oxudulan məlumatlara giriş edə bilir. Parol, ödəniş detalları, mesaj, foto, habelə audio və video kimi məlumatlarla bağlı diqqətli olun."</string>
<string name="media_projection_entry_app_permission_dialog_continue" msgid="295463518195075840">"Başlayın"</string>
- <!-- no translation found for media_projection_entry_app_permission_dialog_single_app_disabled (8999903044874669995) -->
- <skip />
+ <string name="media_projection_entry_app_permission_dialog_single_app_disabled" msgid="8999903044874669995">"<xliff:g id="APP_NAME">%1$s</xliff:g> bu seçimi deaktiv edib"</string>
<string name="media_projection_entry_cast_permission_dialog_title" msgid="8860150223172993547">"Yayım başladılsın?"</string>
<string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="1986212276016817231">"Yayım zamanı Android-in ekranda görünən, yaxud cihazda oxudulan məlumatlara girişi olur. Parol, ödəniş detalları, mesaj, foto, habelə audio və video kimi məlumatlarla bağlı diqqətli olun."</string>
<string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="9900961380294292">"Tətbiq yayımladıqda Android-in həmin tətbiqdə göstərilən və ya oxudulan məlumatlara girişi olur. Parol, ödəniş detalları, mesaj, foto, habelə audio və video kimi məlumatlarla bağlı diqqətli olun."</string>
@@ -1173,6 +1170,10 @@
<string name="assistant_attention_content_description" msgid="6830215897604642875">"Assistent aktivdir"</string>
<string name="set_default_notes_app_toast_content" msgid="2812374329662610753">"Ayarlarda defolt qeydlər tətbiqi ayarlayın"</string>
<string name="install_app" msgid="5066668100199613936">"Tətbiqi quraşdırın"</string>
+ <!-- no translation found for connected_display_dialog_start_mirroring (6237895789920854982) -->
+ <skip />
+ <!-- no translation found for enable_display (8308309634883321977) -->
+ <skip />
<string name="privacy_dialog_title" msgid="7839968133469098311">"Mikrofon və kamera"</string>
<string name="privacy_dialog_summary" msgid="2458769652125995409">"Son tətbiq istifadəsi"</string>
<string name="privacy_dialog_more_button" msgid="7610604080293562345">"Son girişə baxın"</string>
diff --git a/packages/SystemUI/res/values-b+sr+Latn/strings.xml b/packages/SystemUI/res/values-b+sr+Latn/strings.xml
index 94c526515715..b524c343548f 100644
--- a/packages/SystemUI/res/values-b+sr+Latn/strings.xml
+++ b/packages/SystemUI/res/values-b+sr+Latn/strings.xml
@@ -57,8 +57,7 @@
<string name="hdmi_cec_set_menu_language_description" msgid="8176716678074126619">"Drugi uređaj je zatražio promenu jezika sistema"</string>
<string name="hdmi_cec_set_menu_language_accept" msgid="2513689457281009578">"Promeni jezik"</string>
<string name="hdmi_cec_set_menu_language_decline" msgid="7650721096558646011">"Zadrži aktuelni jezik"</string>
- <!-- no translation found for share_wifi_button_text (1285273973812029240) -->
- <skip />
+ <string name="share_wifi_button_text" msgid="1285273973812029240">"Deli WiFi"</string>
<string name="wifi_debugging_title" msgid="7300007687492186076">"Želite da dozvolite bežično otklanjanje grešaka na ovoj mreži?"</string>
<string name="wifi_debugging_message" msgid="5461204211731802995">"Naziv mreže (SSID)\n<xliff:g id="SSID_0">%1$s</xliff:g>\n\nWi‑Fi adresa (BSSID)\n<xliff:g id="BSSID_1">%2$s</xliff:g>"</string>
<string name="wifi_debugging_always" msgid="2968383799517975155">"Uvek dozvoli na ovoj mreži"</string>
@@ -160,8 +159,7 @@
<string name="biometric_dialog_wrong_pattern" msgid="8954812279840889029">"Pogrešan šablon"</string>
<string name="biometric_dialog_wrong_password" msgid="69477929306843790">"Pogrešna lozinka"</string>
<string name="biometric_dialog_credential_too_many_attempts" msgid="3083141271737748716">"Previše netačnih pokušaja.\n Probajte ponovo za <xliff:g id="NUMBER">%d</xliff:g> sek."</string>
- <!-- no translation found for work_challenge_emergency_button_text (8946588434515599288) -->
- <skip />
+ <string name="work_challenge_emergency_button_text" msgid="8946588434515599288">"Hitan slučaj"</string>
<string name="biometric_dialog_credential_attempts_before_wipe" msgid="6751859711975516999">"Probajte ponovo. <xliff:g id="ATTEMPTS_0">%1$d</xliff:g>. pokušaj od <xliff:g id="MAX_ATTEMPTS">%2$d</xliff:g>."</string>
<string name="biometric_dialog_last_attempt_before_wipe_dialog_title" msgid="2874250099278693477">"Podaci će se izbrisati"</string>
<string name="biometric_dialog_last_pattern_attempt_before_wipe_device" msgid="6562299244825817598">"Ako unesete netačan šablon pri sledećem pokušaju, izbrisaćemo podatke sa ovog uređaja."</string>
@@ -415,8 +413,7 @@
<string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="8736391633234144237">"Kada delite, snimate ili prebacujete, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> ima pristup kompletnom sadržaju koji je vidljiv na ekranu ili se pušta na uređaju. Zato budite pažljivi sa lozinkama, informacijama o plaćanju, porukama, slikama i audio i video snimcima."</string>
<string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="5211695779082563959">"Kada delite, snimate ili prebacujete aplikaciju, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> ima pristup kompletnom sadržaju koji je vidljiv ili se pušta u toj aplikaciji. Zato budite pažljivi sa lozinkama, informacijama o plaćanju, porukama, slikama i audio i video snimcima."</string>
<string name="media_projection_entry_app_permission_dialog_continue" msgid="295463518195075840">"Pokreni"</string>
- <!-- no translation found for media_projection_entry_app_permission_dialog_single_app_disabled (8999903044874669995) -->
- <skip />
+ <string name="media_projection_entry_app_permission_dialog_single_app_disabled" msgid="8999903044874669995">"Aplikacija <xliff:g id="APP_NAME">%1$s</xliff:g> je onemogućila ovu opciju"</string>
<string name="media_projection_entry_cast_permission_dialog_title" msgid="8860150223172993547">"Želite da započnete prebacivanje?"</string>
<string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="1986212276016817231">"Kada prebacujete, Android ima pristup kompletnom sadržaju koji je vidljiv na ekranu ili se pušta na uređaju. Zato budite pažljivi sa lozinkama, informacijama o plaćanju, porukama, slikama i audio i video snimcima."</string>
<string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="9900961380294292">"Kada prebacujete aplikaciju, Android ima pristup kompletnom sadržaju koji je vidljiv ili se pušta u toj aplikaciji. Zato budite pažljivi sa lozinkama, informacijama o plaćanju, porukama, slikama i audio i video snimcima."</string>
@@ -1173,6 +1170,10 @@
<string name="assistant_attention_content_description" msgid="6830215897604642875">"Pomoćnik je u aktivnom stanju"</string>
<string name="set_default_notes_app_toast_content" msgid="2812374329662610753">"Podesite podrazumevanu aplikaciju za beleške u Podešavanjima"</string>
<string name="install_app" msgid="5066668100199613936">"Instaliraj aplikaciju"</string>
+ <!-- no translation found for connected_display_dialog_start_mirroring (6237895789920854982) -->
+ <skip />
+ <!-- no translation found for enable_display (8308309634883321977) -->
+ <skip />
<string name="privacy_dialog_title" msgid="7839968133469098311">"Mikrofon i kamera"</string>
<string name="privacy_dialog_summary" msgid="2458769652125995409">"Nedavno koristila aplikacija"</string>
<string name="privacy_dialog_more_button" msgid="7610604080293562345">"Prikaži nedavni pristup"</string>
diff --git a/packages/SystemUI/res/values-be/strings.xml b/packages/SystemUI/res/values-be/strings.xml
index e271408f43b7..dd8199edb123 100644
--- a/packages/SystemUI/res/values-be/strings.xml
+++ b/packages/SystemUI/res/values-be/strings.xml
@@ -57,8 +57,7 @@
<string name="hdmi_cec_set_menu_language_description" msgid="8176716678074126619">"Іншая прылада запытала змяненне мовы сістэмы"</string>
<string name="hdmi_cec_set_menu_language_accept" msgid="2513689457281009578">"Змяніць мову"</string>
<string name="hdmi_cec_set_menu_language_decline" msgid="7650721096558646011">"Захаваць бягучую мову"</string>
- <!-- no translation found for share_wifi_button_text (1285273973812029240) -->
- <skip />
+ <string name="share_wifi_button_text" msgid="1285273973812029240">"Абагуліць Wi‑Fi"</string>
<string name="wifi_debugging_title" msgid="7300007687492186076">"Дазволіць адладку па Wi-Fi у гэтай сетцы?"</string>
<string name="wifi_debugging_message" msgid="5461204211731802995">"Назва сеткі (SSID)\n<xliff:g id="SSID_0">%1$s</xliff:g>\n\nАдрас Wi‑Fi (BSSID)\n<xliff:g id="BSSID_1">%2$s</xliff:g>"</string>
<string name="wifi_debugging_always" msgid="2968383799517975155">"Заўсёды дазваляць у гэтай сетцы"</string>
@@ -160,8 +159,7 @@
<string name="biometric_dialog_wrong_pattern" msgid="8954812279840889029">"Няправільны ўзор разблакіроўкі"</string>
<string name="biometric_dialog_wrong_password" msgid="69477929306843790">"Няправільны пароль"</string>
<string name="biometric_dialog_credential_too_many_attempts" msgid="3083141271737748716">"Занадта шмат няўдалых спроб.\nПаспрабуйце зноў праз <xliff:g id="NUMBER">%d</xliff:g> с."</string>
- <!-- no translation found for work_challenge_emergency_button_text (8946588434515599288) -->
- <skip />
+ <string name="work_challenge_emergency_button_text" msgid="8946588434515599288">"Экстранны выклік"</string>
<string name="biometric_dialog_credential_attempts_before_wipe" msgid="6751859711975516999">"Паўтарыце спробу. Спроба <xliff:g id="ATTEMPTS_0">%1$d</xliff:g> з <xliff:g id="MAX_ATTEMPTS">%2$d</xliff:g>."</string>
<string name="biometric_dialog_last_attempt_before_wipe_dialog_title" msgid="2874250099278693477">"Вашы даныя будуць выдалены"</string>
<string name="biometric_dialog_last_pattern_attempt_before_wipe_device" msgid="6562299244825817598">"Калі вы ўведзяце няправільны ўзор разблакіроўкі яшчэ раз, даныя з гэтай прылады будуць выдалены."</string>
@@ -415,8 +413,7 @@
<string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="8736391633234144237">"Калі пачынаецца абагульванне, запіс ці трансляцыя, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> атрымлівае доступ да ўсяго змесціва, якое паказваецца на экране ці прайграецца на прыладзе. Таму прадухіліце паказ пароляў, плацежных рэквізітаў, паведамленняў, фота, відэа і аўдыя."</string>
<string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="5211695779082563959">"Калі пачынаецца абагульванне, запіс ці трансляцыя змесціва праграмы, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> атрымлівае доступ да ўсяго змесціва, якое паказваецца ці прайграецца ў праграме. Таму прадухіліце паказ пароляў, плацежных рэквізітаў, паведамленняў, фота, відэа і аўдыя."</string>
<string name="media_projection_entry_app_permission_dialog_continue" msgid="295463518195075840">"Пачаць"</string>
- <!-- no translation found for media_projection_entry_app_permission_dialog_single_app_disabled (8999903044874669995) -->
- <skip />
+ <string name="media_projection_entry_app_permission_dialog_single_app_disabled" msgid="8999903044874669995">"Праграма \"<xliff:g id="APP_NAME">%1$s</xliff:g>\" адключыла гэты параметр"</string>
<string name="media_projection_entry_cast_permission_dialog_title" msgid="8860150223172993547">"Пачаць трансляцыю?"</string>
<string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="1986212276016817231">"Калі адбываецца трансляцыя, Android мае доступ да ўсяго змесціва, якое паказваецца на экране ці прайграецца на прыладзе. Таму прадухіліце паказ пароляў, плацежных рэквізітаў, паведамленняў, фота, відэа і аўдыя."</string>
<string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="9900961380294292">"Калі адбываецца трансляцыя змесціва праграмы, Android мае доступ да ўсяго змесціва, якое паказваецца ці прайграецца ў праграме. Таму прадухіліце паказ пароляў, плацежных рэквізітаў, паведамленняў, фота, відэа і аўдыя."</string>
@@ -1173,6 +1170,10 @@
<string name="assistant_attention_content_description" msgid="6830215897604642875">"Памочнік гатовы выконваць каманды"</string>
<string name="set_default_notes_app_toast_content" msgid="2812374329662610753">"Задайце ў Наладах стандартную праграму для нататак"</string>
<string name="install_app" msgid="5066668100199613936">"Усталяваць праграму"</string>
+ <!-- no translation found for connected_display_dialog_start_mirroring (6237895789920854982) -->
+ <skip />
+ <!-- no translation found for enable_display (8308309634883321977) -->
+ <skip />
<string name="privacy_dialog_title" msgid="7839968133469098311">"Мікрафон і камера"</string>
<string name="privacy_dialog_summary" msgid="2458769652125995409">"Нядаўна выкарыстоўваліся праграмамі"</string>
<string name="privacy_dialog_more_button" msgid="7610604080293562345">"Паглядзець нядаўні доступ"</string>
diff --git a/packages/SystemUI/res/values-bg/strings.xml b/packages/SystemUI/res/values-bg/strings.xml
index 38781a4fe64c..896756dc9b37 100644
--- a/packages/SystemUI/res/values-bg/strings.xml
+++ b/packages/SystemUI/res/values-bg/strings.xml
@@ -57,8 +57,7 @@
<string name="hdmi_cec_set_menu_language_description" msgid="8176716678074126619">"Друго устройство е заявило промяна на езика на системата"</string>
<string name="hdmi_cec_set_menu_language_accept" msgid="2513689457281009578">"Промяна на езика"</string>
<string name="hdmi_cec_set_menu_language_decline" msgid="7650721096558646011">"Текущ език: Запазване"</string>
- <!-- no translation found for share_wifi_button_text (1285273973812029240) -->
- <skip />
+ <string name="share_wifi_button_text" msgid="1285273973812029240">"Споделяне на Wi‑Fi"</string>
<string name="wifi_debugging_title" msgid="7300007687492186076">"Разрешаване на безжичното отстраняване на грешки?"</string>
<string name="wifi_debugging_message" msgid="5461204211731802995">"Име на мрежата (SSID)\n<xliff:g id="SSID_0">%1$s</xliff:g>\n\nАдрес на Wi‑Fi мрежата (BSSID)\n<xliff:g id="BSSID_1">%2$s</xliff:g>"</string>
<string name="wifi_debugging_always" msgid="2968383799517975155">"Винаги да се разрешава в тази мрежа"</string>
@@ -160,8 +159,7 @@
<string name="biometric_dialog_wrong_pattern" msgid="8954812279840889029">"Грешна фигура"</string>
<string name="biometric_dialog_wrong_password" msgid="69477929306843790">"Грешна парола"</string>
<string name="biometric_dialog_credential_too_many_attempts" msgid="3083141271737748716">"Твърде много неправилни опити.\nОпитайте отново след <xliff:g id="NUMBER">%d</xliff:g> секунди."</string>
- <!-- no translation found for work_challenge_emergency_button_text (8946588434515599288) -->
- <skip />
+ <string name="work_challenge_emergency_button_text" msgid="8946588434515599288">"Спешен случай"</string>
<string name="biometric_dialog_credential_attempts_before_wipe" msgid="6751859711975516999">"Опитайте отново. Опит <xliff:g id="ATTEMPTS_0">%1$d</xliff:g> от <xliff:g id="MAX_ATTEMPTS">%2$d</xliff:g>."</string>
<string name="biometric_dialog_last_attempt_before_wipe_dialog_title" msgid="2874250099278693477">"Данните ви ще бъдат изтрити"</string>
<string name="biometric_dialog_last_pattern_attempt_before_wipe_device" msgid="6562299244825817598">"Ако въведете неправилна фигура при следващия опит, данните от това устройство ще бъдат изтрити."</string>
@@ -415,8 +413,7 @@
<string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="8736391633234144237">"Когато споделяте, записвате или предавате, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> има достъп до всичко, което се вижда на екрана ви или се възпроизвежда на устройството ви. Затова бъдете внимателни с неща като пароли, подробности за начини на плащане, съобщения, снимки, аудио и видео."</string>
<string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="5211695779082563959">"Когато споделяте, записвате или предавате дадено приложение, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> има достъп до всичко, което се показва или възпроизвежда в него. Затова бъдете внимателни с неща като пароли, подробности за начини на плащане, съобщения, снимки, аудио и видео."</string>
<string name="media_projection_entry_app_permission_dialog_continue" msgid="295463518195075840">"Стартиране"</string>
- <!-- no translation found for media_projection_entry_app_permission_dialog_single_app_disabled (8999903044874669995) -->
- <skip />
+ <string name="media_projection_entry_app_permission_dialog_single_app_disabled" msgid="8999903044874669995">"<xliff:g id="APP_NAME">%1$s</xliff:g> деактивира тази опция"</string>
<string name="media_projection_entry_cast_permission_dialog_title" msgid="8860150223172993547">"Искате ли да стартирате предаване?"</string>
<string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="1986212276016817231">"Когато предавате, Android има достъп до всичко, което се вижда на екрана ви или се възпроизвежда на устройството ви. Затова бъдете внимателни с неща като пароли, подробности за начини на плащане, съобщения, снимки, аудио и видео."</string>
<string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="9900961380294292">"Когато предавате дадено приложение, Android има достъп до всичко, което се показва или възпроизвежда в него. Затова бъдете внимателни с неща като пароли, подробности за начини на плащане, съобщения, снимки, аудио и видео."</string>
@@ -1173,6 +1170,10 @@
<string name="assistant_attention_content_description" msgid="6830215897604642875">"Функцията за активиране на Асистент е включена"</string>
<string name="set_default_notes_app_toast_content" msgid="2812374329662610753">"Задайте стандартно приложение за бележки от настройките"</string>
<string name="install_app" msgid="5066668100199613936">"Инсталиране на приложението"</string>
+ <!-- no translation found for connected_display_dialog_start_mirroring (6237895789920854982) -->
+ <skip />
+ <!-- no translation found for enable_display (8308309634883321977) -->
+ <skip />
<string name="privacy_dialog_title" msgid="7839968133469098311">"Микрофон и камера"</string>
<string name="privacy_dialog_summary" msgid="2458769652125995409">"Скорошно използване на приложението"</string>
<string name="privacy_dialog_more_button" msgid="7610604080293562345">"Вижте скорошния достъп"</string>
diff --git a/packages/SystemUI/res/values-bn/strings.xml b/packages/SystemUI/res/values-bn/strings.xml
index b6b539cea93e..5c1b445fc1d9 100644
--- a/packages/SystemUI/res/values-bn/strings.xml
+++ b/packages/SystemUI/res/values-bn/strings.xml
@@ -57,8 +57,7 @@
<string name="hdmi_cec_set_menu_language_description" msgid="8176716678074126619">"অন্য ডিভাইসের দ্বারা সিস্টেমের ভাষা পরিবর্তনের অনুরোধ করা হয়েছে"</string>
<string name="hdmi_cec_set_menu_language_accept" msgid="2513689457281009578">"ভাষা পরিবর্তন করুন"</string>
<string name="hdmi_cec_set_menu_language_decline" msgid="7650721096558646011">"বর্তমান ভাষা রাখুন"</string>
- <!-- no translation found for share_wifi_button_text (1285273973812029240) -->
- <skip />
+ <string name="share_wifi_button_text" msgid="1285273973812029240">"ওয়াই-ফাই শেয়ার করুন"</string>
<string name="wifi_debugging_title" msgid="7300007687492186076">"এই নেটওয়ার্কে ওয়্যারলেস ডিবাগিংয়ের অনুমতি দেবেন?"</string>
<string name="wifi_debugging_message" msgid="5461204211731802995">"নেটওয়ার্কের নাম (SSID)\n<xliff:g id="SSID_0">%1$s</xliff:g>\n\nওয়াই-ফাই অ্যাড্রেস (BSSID)\n<xliff:g id="BSSID_1">%2$s</xliff:g>"</string>
<string name="wifi_debugging_always" msgid="2968383799517975155">"এই নেটওয়ার্কে সবসময় অনুমতি দিন"</string>
@@ -160,8 +159,7 @@
<string name="biometric_dialog_wrong_pattern" msgid="8954812279840889029">"ভুল প্যাটার্ন"</string>
<string name="biometric_dialog_wrong_password" msgid="69477929306843790">"ভুল পাসওয়ার্ড"</string>
<string name="biometric_dialog_credential_too_many_attempts" msgid="3083141271737748716">"অনেকবার ভুল চেষ্টা করা হয়েছে। \n<xliff:g id="NUMBER">%d</xliff:g> সেকেন্ডের মধ্যে আবার চেষ্টা করুন।"</string>
- <!-- no translation found for work_challenge_emergency_button_text (8946588434515599288) -->
- <skip />
+ <string name="work_challenge_emergency_button_text" msgid="8946588434515599288">"জরুরি"</string>
<string name="biometric_dialog_credential_attempts_before_wipe" msgid="6751859711975516999">"আবার চেষ্টা করুন। <xliff:g id="MAX_ATTEMPTS">%2$d</xliff:g> বারের মধ্যে <xliff:g id="ATTEMPTS_0">%1$d</xliff:g> বার চেষ্টা করা হয়েছে।"</string>
<string name="biometric_dialog_last_attempt_before_wipe_dialog_title" msgid="2874250099278693477">"আপনার ডেটা মুছে দেওয়া হবে"</string>
<string name="biometric_dialog_last_pattern_attempt_before_wipe_device" msgid="6562299244825817598">"আপনি পরের বারও ভুল প্যাটার্ন আঁকলে এই ডিভাইসের ডেটা মুছে দেওয়া হবে।"</string>
@@ -415,8 +413,7 @@
<string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="8736391633234144237">"আপনি শেয়ার, রেকর্ড বা কাস্ট করার সময়, স্ক্রিনে দৃশ্যমান বা ডিভাইসে চালানো সব কিছুই <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> অ্যাক্সেস করতে পারবে। তাই পাসওয়ার্ড, পেমেন্টের বিবরণ, মেসেজ, ফটো এবং অডিও ও ভিডিওর মতো বিষয়ে সতর্ক থাকুন।"</string>
<string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="5211695779082563959">"আপনি কোনও অ্যাপ শেয়ার, রেকর্ড বা কাস্ট করার সময়, সেই অ্যাপে দেখা যায় বা চালানো হয় এমন সব কিছু <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> অ্যাক্সেস করতে পারবে। তাই পাসওয়ার্ড, পেমেন্টের বিবরণ, মেসেজ, ফটো এবং অডিও ও ভিডিওর মতো বিষয়ে সতর্ক থাকুন।"</string>
<string name="media_projection_entry_app_permission_dialog_continue" msgid="295463518195075840">"শুরু করুন"</string>
- <!-- no translation found for media_projection_entry_app_permission_dialog_single_app_disabled (8999903044874669995) -->
- <skip />
+ <string name="media_projection_entry_app_permission_dialog_single_app_disabled" msgid="8999903044874669995">"<xliff:g id="APP_NAME">%1$s</xliff:g> এই বিকল্পটি বন্ধ করে দিয়েছে"</string>
<string name="media_projection_entry_cast_permission_dialog_title" msgid="8860150223172993547">"কাস্ট করা শুরু করবেন?"</string>
<string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="1986212276016817231">"আপনি কাস্ট করার সময়, স্ক্রিনে দৃশ্যমান বা ডিভাইসে চালানো সবকিছুই Android অ্যাক্সেস করতে পারবে। তাই পাসওয়ার্ড, পেমেন্টের বিবরণ, মেসেজ, ফটো এবং অডিও ও ভিডিওর মতো বিষয়ে সতর্ক থাকুন।"</string>
<string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="9900961380294292">"আপনি কোনও অ্যাপ কাস্ট করার সময়, ওই অ্যাপে দেখানো বা চালানো হয় এমন সবকিছুই Android অ্যাক্সেস করতে পারবে। তাই পাসওয়ার্ড, পেমেন্টের বিবরণ, মেসেজ, ফটো এবং অডিও ও ভিডিওর মতো বিষয়ে সতর্ক থাকুন।"</string>
@@ -1173,6 +1170,10 @@
<string name="assistant_attention_content_description" msgid="6830215897604642875">"অ্যাসিস্ট্যান্ট আপনার কথা শোনার জন্য চালু করা আছে"</string>
<string name="set_default_notes_app_toast_content" msgid="2812374329662610753">"\'সেটিংস\' থেকে ডিফল্ট নোট নেওয়ার অ্যাপ সেট করুন"</string>
<string name="install_app" msgid="5066668100199613936">"অ্যাপ ইনস্টল করুন"</string>
+ <!-- no translation found for connected_display_dialog_start_mirroring (6237895789920854982) -->
+ <skip />
+ <!-- no translation found for enable_display (8308309634883321977) -->
+ <skip />
<string name="privacy_dialog_title" msgid="7839968133469098311">"মাইক্রোফোন ও ক্যামেরা"</string>
<string name="privacy_dialog_summary" msgid="2458769652125995409">"সম্প্রতি ব্যবহার করা অ্যাপ"</string>
<string name="privacy_dialog_more_button" msgid="7610604080293562345">"সাম্প্রতিক অ্যাক্সেস দেখুন"</string>
diff --git a/packages/SystemUI/res/values-bs/strings.xml b/packages/SystemUI/res/values-bs/strings.xml
index b5fa00eec995..63f62f173ec5 100644
--- a/packages/SystemUI/res/values-bs/strings.xml
+++ b/packages/SystemUI/res/values-bs/strings.xml
@@ -57,8 +57,7 @@
<string name="hdmi_cec_set_menu_language_description" msgid="8176716678074126619">"Promjenu jezika sistema je zatražio drugi uređaj"</string>
<string name="hdmi_cec_set_menu_language_accept" msgid="2513689457281009578">"Promijeni jezik"</string>
<string name="hdmi_cec_set_menu_language_decline" msgid="7650721096558646011">"Zadrži trenutni jezik"</string>
- <!-- no translation found for share_wifi_button_text (1285273973812029240) -->
- <skip />
+ <string name="share_wifi_button_text" msgid="1285273973812029240">"Dijeli WiFi"</string>
<string name="wifi_debugging_title" msgid="7300007687492186076">"Dozvoliti bežično otklanjanje grešaka na ovoj mreži?"</string>
<string name="wifi_debugging_message" msgid="5461204211731802995">"Naziv mreže (SSID)\n<xliff:g id="SSID_0">%1$s</xliff:g>\n\nAdresa WiFi mreže (BSSID)\n<xliff:g id="BSSID_1">%2$s</xliff:g>"</string>
<string name="wifi_debugging_always" msgid="2968383799517975155">"Uvijek dozvoli na ovoj mreži"</string>
@@ -160,8 +159,7 @@
<string name="biometric_dialog_wrong_pattern" msgid="8954812279840889029">"Pogrešan uzorak"</string>
<string name="biometric_dialog_wrong_password" msgid="69477929306843790">"Pogrešna lozinka"</string>
<string name="biometric_dialog_credential_too_many_attempts" msgid="3083141271737748716">"Previše pogrešnih pokušaja.\n Pokušajte ponovo za <xliff:g id="NUMBER">%d</xliff:g> s."</string>
- <!-- no translation found for work_challenge_emergency_button_text (8946588434515599288) -->
- <skip />
+ <string name="work_challenge_emergency_button_text" msgid="8946588434515599288">"Hitan slučaj"</string>
<string name="biometric_dialog_credential_attempts_before_wipe" msgid="6751859711975516999">"Pokušajte ponovo. <xliff:g id="ATTEMPTS_0">%1$d</xliff:g>. pokušaj od <xliff:g id="MAX_ATTEMPTS">%2$d</xliff:g>."</string>
<string name="biometric_dialog_last_attempt_before_wipe_dialog_title" msgid="2874250099278693477">"Vaši podaci će se izbrisati"</string>
<string name="biometric_dialog_last_pattern_attempt_before_wipe_device" msgid="6562299244825817598">"Ako u sljedećem pokušaju unesete neispravan uzorak, podaci ovog uređaja će se izbrisati."</string>
@@ -415,8 +413,7 @@
<string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="8736391633234144237">"Kada dijelite, snimate ili emitirate, aplikacija <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> ima pristup svemu što je vidljivo na ekranu ili što se reproducira na uređaju. Stoga budite oprezni s informacijama kao što su lozinke, podaci o plaćanju, poruke, fotografije, zvukovi i videozapisi."</string>
<string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="5211695779082563959">"Kada dijelite, snimate ili emitirate aplikaciju, aplikacija <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> ima pristup svemu što se prikazuje ili reproducira u toj aplikaciji. Stoga budite oprezni s informacijama kao što su lozinke, podaci o plaćanju, poruke, fotografije, zvukovi i videozapisi."</string>
<string name="media_projection_entry_app_permission_dialog_continue" msgid="295463518195075840">"Pokreni"</string>
- <!-- no translation found for media_projection_entry_app_permission_dialog_single_app_disabled (8999903044874669995) -->
- <skip />
+ <string name="media_projection_entry_app_permission_dialog_single_app_disabled" msgid="8999903044874669995">"Aplikacija <xliff:g id="APP_NAME">%1$s</xliff:g> je onemogućila tu opciju"</string>
<string name="media_projection_entry_cast_permission_dialog_title" msgid="8860150223172993547">"Pokrenuti emitiranje?"</string>
<string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="1986212276016817231">"Kada emitirate, Android ima pristup svemu što je vidljivo na ekranu ili što se reproducira na uređaju. Stoga budite oprezni s informacijama kao što su lozinke, podaci o plaćanju, poruke, fotografije, zvukovi i videozapisi."</string>
<string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="9900961380294292">"Kada emitirate aplikaciju, Android ima pristup svemu što se prikazuje ili reproducira u toj aplikaciji. Stoga budite oprezni s informacijama kao što su lozinke, podaci o plaćanju, poruke, fotografije, zvukovi i videozapisi."</string>
@@ -1173,6 +1170,10 @@
<string name="assistant_attention_content_description" msgid="6830215897604642875">"Pažnja Asistenta je uključena"</string>
<string name="set_default_notes_app_toast_content" msgid="2812374329662610753">"Postavite zadanu aplikaciju za bilješke u Postavkama"</string>
<string name="install_app" msgid="5066668100199613936">"Instaliraj aplikaciju"</string>
+ <!-- no translation found for connected_display_dialog_start_mirroring (6237895789920854982) -->
+ <skip />
+ <!-- no translation found for enable_display (8308309634883321977) -->
+ <skip />
<string name="privacy_dialog_title" msgid="7839968133469098311">"Mikrofon i kamera"</string>
<string name="privacy_dialog_summary" msgid="2458769652125995409">"Nedavno korištenje aplikacije"</string>
<string name="privacy_dialog_more_button" msgid="7610604080293562345">"Prikaži nedavni pristup"</string>
diff --git a/packages/SystemUI/res/values-ca/strings.xml b/packages/SystemUI/res/values-ca/strings.xml
index fea2ee67e3a9..f54a0acca100 100644
--- a/packages/SystemUI/res/values-ca/strings.xml
+++ b/packages/SystemUI/res/values-ca/strings.xml
@@ -57,8 +57,7 @@
<string name="hdmi_cec_set_menu_language_description" msgid="8176716678074126619">"Un altre dispositiu ha sol·licitat canviar l\'idioma del sistema"</string>
<string name="hdmi_cec_set_menu_language_accept" msgid="2513689457281009578">"Canvia l\'idioma"</string>
<string name="hdmi_cec_set_menu_language_decline" msgid="7650721096558646011">"Mantén l\'idioma actual"</string>
- <!-- no translation found for share_wifi_button_text (1285273973812029240) -->
- <skip />
+ <string name="share_wifi_button_text" msgid="1285273973812029240">"Comparteix la Wi‑Fi"</string>
<string name="wifi_debugging_title" msgid="7300007687492186076">"Vols permetre la depuració sense fil en aquesta xarxa?"</string>
<string name="wifi_debugging_message" msgid="5461204211731802995">"Nom de la xarxa (SSID)\n<xliff:g id="SSID_0">%1$s</xliff:g>\n\nAdreça Wi‑Fi (BSSID)\n<xliff:g id="BSSID_1">%2$s</xliff:g>"</string>
<string name="wifi_debugging_always" msgid="2968383799517975155">"Permet sempre en aquesta xarxa"</string>
@@ -160,8 +159,7 @@
<string name="biometric_dialog_wrong_pattern" msgid="8954812279840889029">"Patró incorrecte"</string>
<string name="biometric_dialog_wrong_password" msgid="69477929306843790">"Contrasenya incorrecta"</string>
<string name="biometric_dialog_credential_too_many_attempts" msgid="3083141271737748716">"Has superat el nombre d\'intents incorrectes permesos.\nTorna-ho a provar d\'aquí a <xliff:g id="NUMBER">%d</xliff:g> segons."</string>
- <!-- no translation found for work_challenge_emergency_button_text (8946588434515599288) -->
- <skip />
+ <string name="work_challenge_emergency_button_text" msgid="8946588434515599288">"Emergència"</string>
<string name="biometric_dialog_credential_attempts_before_wipe" msgid="6751859711975516999">"Torna-ho a provar. Intent <xliff:g id="ATTEMPTS_0">%1$d</xliff:g> de <xliff:g id="MAX_ATTEMPTS">%2$d</xliff:g>."</string>
<string name="biometric_dialog_last_attempt_before_wipe_dialog_title" msgid="2874250099278693477">"Se suprimiran les teves dades"</string>
<string name="biometric_dialog_last_pattern_attempt_before_wipe_device" msgid="6562299244825817598">"Si tornes a introduir un patró incorrecte, se suprimiran les dades del dispositiu."</string>
@@ -415,8 +413,7 @@
<string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="8736391633234144237">"Quan comparteixes, graves o emets contingut, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> té accés a qualsevol cosa que es vegi a la pantalla o que es reprodueixi al dispositiu. Per aquest motiu, ves amb compte amb les contrasenyes, les dades de pagament, els missatges, les fotos i l\'àudio i el vídeo."</string>
<string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="5211695779082563959">"Quan comparteixes, graves o emets contingut, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> té accés a qualsevol cosa que es vegi a la pantalla o que es reprodueixi a l\'aplicació. Per aquest motiu, ves amb compte amb les contrasenyes, les dades de pagament, els missatges, les fotos i l\'àudio i el vídeo."</string>
<string name="media_projection_entry_app_permission_dialog_continue" msgid="295463518195075840">"Inicia"</string>
- <!-- no translation found for media_projection_entry_app_permission_dialog_single_app_disabled (8999903044874669995) -->
- <skip />
+ <string name="media_projection_entry_app_permission_dialog_single_app_disabled" msgid="8999903044874669995">"<xliff:g id="APP_NAME">%1$s</xliff:g> ha desactivat aquesta opció"</string>
<string name="media_projection_entry_cast_permission_dialog_title" msgid="8860150223172993547">"Vols iniciar una emissió?"</string>
<string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="1986212276016817231">"Quan emets contingut, Android té accés a qualsevol cosa que es vegi a la pantalla o que es reprodueixi al dispositiu. Per aquest motiu, ves amb compte amb les contrasenyes, les dades de pagament, els missatges, les fotos i l\'àudio i el vídeo."</string>
<string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="9900961380294292">"Quan emets una aplicació, Android té accés a qualsevol cosa que es mostri o que es reprodueixi en aquella aplicació. Per aquest motiu, ves amb compte amb les contrasenyes, les dades de pagament, els missatges, les fotos i l\'àudio i el vídeo."</string>
@@ -1173,6 +1170,10 @@
<string name="assistant_attention_content_description" msgid="6830215897604642875">"L\'Assistent està activat"</string>
<string name="set_default_notes_app_toast_content" msgid="2812374329662610753">"Defineix l\'aplicació de notes predeterminada a Configuració"</string>
<string name="install_app" msgid="5066668100199613936">"Instal·la l\'aplicació"</string>
+ <!-- no translation found for connected_display_dialog_start_mirroring (6237895789920854982) -->
+ <skip />
+ <!-- no translation found for enable_display (8308309634883321977) -->
+ <skip />
<string name="privacy_dialog_title" msgid="7839968133469098311">"Micròfon i càmera"</string>
<string name="privacy_dialog_summary" msgid="2458769652125995409">"Ús recent de l\'aplicació"</string>
<string name="privacy_dialog_more_button" msgid="7610604080293562345">"Mostra l\'accés recent"</string>
diff --git a/packages/SystemUI/res/values-cs/strings.xml b/packages/SystemUI/res/values-cs/strings.xml
index 339ba71a0b82..1bfe1f4ecdad 100644
--- a/packages/SystemUI/res/values-cs/strings.xml
+++ b/packages/SystemUI/res/values-cs/strings.xml
@@ -57,8 +57,7 @@
<string name="hdmi_cec_set_menu_language_description" msgid="8176716678074126619">"Jiné zařízení požádalo o změnu systémového jazyka"</string>
<string name="hdmi_cec_set_menu_language_accept" msgid="2513689457281009578">"Změnit jazyk"</string>
<string name="hdmi_cec_set_menu_language_decline" msgid="7650721096558646011">"Zachovat stávající jazyk"</string>
- <!-- no translation found for share_wifi_button_text (1285273973812029240) -->
- <skip />
+ <string name="share_wifi_button_text" msgid="1285273973812029240">"Sdílení sítě Wi-Fi"</string>
<string name="wifi_debugging_title" msgid="7300007687492186076">"Povolit v této síti bezdrátové ladění?"</string>
<string name="wifi_debugging_message" msgid="5461204211731802995">"Název sítě (SSID)\n<xliff:g id="SSID_0">%1$s</xliff:g>\n\nAdresa Wi‑Fi (BSSID)\n<xliff:g id="BSSID_1">%2$s</xliff:g>"</string>
<string name="wifi_debugging_always" msgid="2968383799517975155">"V této síti vždy povolit"</string>
@@ -160,8 +159,7 @@
<string name="biometric_dialog_wrong_pattern" msgid="8954812279840889029">"Nesprávné gesto"</string>
<string name="biometric_dialog_wrong_password" msgid="69477929306843790">"Nesprávné heslo"</string>
<string name="biometric_dialog_credential_too_many_attempts" msgid="3083141271737748716">"Příliš mnoho neplatných pokusů.\nZkuste to znovu za <xliff:g id="NUMBER">%d</xliff:g> s."</string>
- <!-- no translation found for work_challenge_emergency_button_text (8946588434515599288) -->
- <skip />
+ <string name="work_challenge_emergency_button_text" msgid="8946588434515599288">"Stav nouze"</string>
<string name="biometric_dialog_credential_attempts_before_wipe" msgid="6751859711975516999">"Zkuste to znovu. Pokus <xliff:g id="ATTEMPTS_0">%1$d</xliff:g> z <xliff:g id="MAX_ATTEMPTS">%2$d</xliff:g>."</string>
<string name="biometric_dialog_last_attempt_before_wipe_dialog_title" msgid="2874250099278693477">"Vaše data budou smazána"</string>
<string name="biometric_dialog_last_pattern_attempt_before_wipe_device" msgid="6562299244825817598">"Pokud při příštím pokusu zadáte nesprávné gesto, data v tomto zařízení budou smazána."</string>
@@ -415,8 +413,7 @@
<string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="8736391633234144237">"Během sdílení, nahrávání nebo odesílání má <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> přístup k veškerému obsahu, který je viditelný na obrazovce nebo se přehrává v zařízení. Buďte proto opatrní s věcmi, jako jsou hesla, platební údaje, zprávy, fotografie, zvuk a video."</string>
<string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="5211695779082563959">"Během sdílení, nahrávání nebo odesílání aplikace má <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> přístup k veškerému obsahu, který je v dané aplikaci zobrazen nebo přehráván. Buďte proto opatrní s věcmi, jako jsou hesla, platební údaje, zprávy, fotografie, zvuk a video."</string>
<string name="media_projection_entry_app_permission_dialog_continue" msgid="295463518195075840">"Začít"</string>
- <!-- no translation found for media_projection_entry_app_permission_dialog_single_app_disabled (8999903044874669995) -->
- <skip />
+ <string name="media_projection_entry_app_permission_dialog_single_app_disabled" msgid="8999903044874669995">"Aplikace <xliff:g id="APP_NAME">%1$s</xliff:g> tuto možnost zakázala"</string>
<string name="media_projection_entry_cast_permission_dialog_title" msgid="8860150223172993547">"Začít odesílat?"</string>
<string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="1986212276016817231">"Během odesílání má Android přístup ke všemu, co je viditelné na obrazovce nebo se přehrává v zařízení. Buďte proto opatrní s věcmi, jako jsou hesla, platební údaje, zprávy, fotografie, zvuk a video."</string>
<string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="9900961380294292">"Během odesílání aplikace má Android přístup k veškerému obsahu, který je v dané aplikaci zobrazen nebo přehráván. Buďte proto opatrní s věcmi, jako jsou hesla, platební údaje, zprávy, fotografie, zvuk a video."</string>
@@ -1173,6 +1170,10 @@
<string name="assistant_attention_content_description" msgid="6830215897604642875">"Pozornost Asistenta je zapnutá"</string>
<string name="set_default_notes_app_toast_content" msgid="2812374329662610753">"Výchozí aplikaci pro poznámky nastavíte v Nastavení"</string>
<string name="install_app" msgid="5066668100199613936">"Nainstalovat aplikaci"</string>
+ <!-- no translation found for connected_display_dialog_start_mirroring (6237895789920854982) -->
+ <skip />
+ <!-- no translation found for enable_display (8308309634883321977) -->
+ <skip />
<string name="privacy_dialog_title" msgid="7839968133469098311">"Mikrofon a fotoaparát"</string>
<string name="privacy_dialog_summary" msgid="2458769652125995409">"Nedávné použití aplikacemi"</string>
<string name="privacy_dialog_more_button" msgid="7610604080293562345">"Zobrazit nedávný přístup"</string>
diff --git a/packages/SystemUI/res/values-da/strings.xml b/packages/SystemUI/res/values-da/strings.xml
index 79ba451c4aae..17853e7228d3 100644
--- a/packages/SystemUI/res/values-da/strings.xml
+++ b/packages/SystemUI/res/values-da/strings.xml
@@ -57,8 +57,7 @@
<string name="hdmi_cec_set_menu_language_description" msgid="8176716678074126619">"En anden enhed har anmodet om en ændring af systemsproget"</string>
<string name="hdmi_cec_set_menu_language_accept" msgid="2513689457281009578">"Skift sprog"</string>
<string name="hdmi_cec_set_menu_language_decline" msgid="7650721096558646011">"Behold nuværende sprog"</string>
- <!-- no translation found for share_wifi_button_text (1285273973812029240) -->
- <skip />
+ <string name="share_wifi_button_text" msgid="1285273973812029240">"Del Wi‑Fi"</string>
<string name="wifi_debugging_title" msgid="7300007687492186076">"Vil du tillade trådløs fejlretning på dette netværk?"</string>
<string name="wifi_debugging_message" msgid="5461204211731802995">"Netværksnavn (SSID)\n<xliff:g id="SSID_0">%1$s</xliff:g>\n\nWi‑Fi-adresse (BSSID)\n<xliff:g id="BSSID_1">%2$s</xliff:g>"</string>
<string name="wifi_debugging_always" msgid="2968383799517975155">"Tillad altid på dette netværk"</string>
@@ -160,8 +159,7 @@
<string name="biometric_dialog_wrong_pattern" msgid="8954812279840889029">"Forkert mønster"</string>
<string name="biometric_dialog_wrong_password" msgid="69477929306843790">"Forkert adgangskode"</string>
<string name="biometric_dialog_credential_too_many_attempts" msgid="3083141271737748716">"For mange mislykkede forsøg. \nPrøv igen om <xliff:g id="NUMBER">%d</xliff:g> sekunder."</string>
- <!-- no translation found for work_challenge_emergency_button_text (8946588434515599288) -->
- <skip />
+ <string name="work_challenge_emergency_button_text" msgid="8946588434515599288">"Nødsituation"</string>
<string name="biometric_dialog_credential_attempts_before_wipe" msgid="6751859711975516999">"Prøv igen. <xliff:g id="ATTEMPTS_0">%1$d</xliff:g>. forsøg ud af <xliff:g id="MAX_ATTEMPTS">%2$d</xliff:g>."</string>
<string name="biometric_dialog_last_attempt_before_wipe_dialog_title" msgid="2874250099278693477">"Dine data bliver slettet"</string>
<string name="biometric_dialog_last_pattern_attempt_before_wipe_device" msgid="6562299244825817598">"Hvis du angiver et forkert mønster i næste forsøg, slettes dataene på denne enhed."</string>
@@ -182,11 +180,11 @@
<string name="fingerprint_re_enroll_dialog_content" msgid="4866561176695984879">"Hvis du vil konfigurere oplåsning med fingeraftryk igen, bliver dine nuværende fingeraftryksbilleder og -modeller slettet.\n\nNår de er slettet, skal du konfigurere oplåsning med fingeraftryk igen for at bruge dit fingeraftryk til at låse din telefon op eller verificere din identitet."</string>
<string name="fingerprint_re_enroll_dialog_content_singular" msgid="3083663339787381218">"Hvis du vil konfigurere oplåsning med fingeraftryk igen, bliver dine nuværende fingeraftryksbilleder og -modeller slettet.\n\nNår de er slettet, skal du konfigurere oplåsning med fingeraftryk igen for at bruge dit fingeraftryk til at låse din telefon op eller verificere din identitet."</string>
<string name="fingerprint_reenroll_failure_dialog_content" msgid="4733768492747300666">"Oplåsning med fingeraftryk kunne ikke konfigureres. Gå til Indstillinger for at prøve igen."</string>
- <string name="face_re_enroll_notification_title" msgid="1850838867718410520">"Konfigurer ansigtslås igen"</string>
- <string name="face_re_enroll_notification_name" msgid="7384545252206120659">"Ansigtslås"</string>
- <string name="face_re_enroll_dialog_title" msgid="6392173708176069994">"Konfigurer ansigtslås"</string>
- <string name="face_re_enroll_dialog_content" msgid="7353502359464038511">"Hvis du vil konfigurere ansigtslås igen, bliver din nuværende ansigtsmodel slettet.\n\nDu skal konfigurere funktionen igen for at bruge ansigtsgenkendelse til at låse din telefon op."</string>
- <string name="face_reenroll_failure_dialog_content" msgid="7073947334397236935">"Ansigtslås kunne ikke konfigureres. Gå til Indstillinger for at prøve igen."</string>
+ <string name="face_re_enroll_notification_title" msgid="1850838867718410520">"Konfigurer ansigtsoplåsning igen"</string>
+ <string name="face_re_enroll_notification_name" msgid="7384545252206120659">"Ansigtsoplåsning"</string>
+ <string name="face_re_enroll_dialog_title" msgid="6392173708176069994">"Konfigurer ansigtsoplåsning"</string>
+ <string name="face_re_enroll_dialog_content" msgid="7353502359464038511">"Hvis du vil konfigurere ansigtsoplåsning igen, bliver din nuværende ansigtsmodel slettet.\n\nDu skal konfigurere funktionen igen for at bruge ansigtsgenkendelse til at låse din telefon op."</string>
+ <string name="face_reenroll_failure_dialog_content" msgid="7073947334397236935">"Ansigtsoplåsning kunne ikke konfigureres. Gå til Indstillinger for at prøve igen."</string>
<string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"Sæt fingeren på fingeraftrykssensoren"</string>
<string name="fingerprint_dialog_authenticated_confirmation" msgid="1603899612957562862">"Tryk på oplåsningsikonet for at fortsætte"</string>
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Ansigtet kan ikke genkendes. Brug fingeraftryk i stedet."</string>
@@ -194,7 +192,7 @@
<skip />
<string name="keyguard_face_failed" msgid="9044619102286917151">"Ansigt kan ikke genkendes"</string>
<string name="keyguard_suggest_fingerprint" msgid="8742015961962702960">"Brug fingeraftryk i stedet"</string>
- <string name="keyguard_face_unlock_unavailable" msgid="1581949044193418736">"Ansigtslås er utilgængelig"</string>
+ <string name="keyguard_face_unlock_unavailable" msgid="1581949044193418736">"Ansigtsoplåsning er utilgængelig"</string>
<string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"Bluetooth tilsluttet."</string>
<string name="accessibility_battery_unknown" msgid="1807789554617976440">"Batteriniveauet er ukendt."</string>
<string name="accessibility_bluetooth_name" msgid="7300973230214067678">"Tilsluttet <xliff:g id="BLUETOOTH">%s</xliff:g>."</string>
@@ -369,7 +367,7 @@
<string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"Låst op via ansigtsgenkendelse"</string>
<string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"Ansigtet er genkendt"</string>
<string name="keyguard_retry" msgid="886802522584053523">"Stryg opad for at prøve igen"</string>
- <string name="accesssibility_keyguard_retry" msgid="8880238862712870676">"Stryg opad for at prøve ansigtslåsen igen"</string>
+ <string name="accesssibility_keyguard_retry" msgid="8880238862712870676">"Stryg opad for at prøve ansigtsoplåsning igen"</string>
<string name="require_unlock_for_nfc" msgid="1305686454823018831">"Lås op for at bruge NFC"</string>
<string name="do_disclosure_generic" msgid="4896482821974707167">"Denne enhed tilhører din organisation"</string>
<string name="do_disclosure_with_name" msgid="2091641464065004091">"Denne enhed tilhører <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string>
@@ -415,8 +413,7 @@
<string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="8736391633234144237">"Når du deler, optager eller caster, har <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> adgang til alt, der er synligt på din skærm eller afspilles på din enhed. Vær derfor forsigtig med ting såsom adgangskoder, betalingsoplysninger, beskeder, billeder, lyd og video."</string>
<string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="5211695779082563959">"Når du deler, optager eller caster en app, har <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> adgang til alt, der vises eller afspilles i den pågældende app. Vær derfor forsigtig med ting såsom adgangskoder, betalingsoplysninger, beskeder, billeder, lyd og video."</string>
<string name="media_projection_entry_app_permission_dialog_continue" msgid="295463518195075840">"Start"</string>
- <!-- no translation found for media_projection_entry_app_permission_dialog_single_app_disabled (8999903044874669995) -->
- <skip />
+ <string name="media_projection_entry_app_permission_dialog_single_app_disabled" msgid="8999903044874669995">"<xliff:g id="APP_NAME">%1$s</xliff:g> har deaktiveret denne valgmulighed"</string>
<string name="media_projection_entry_cast_permission_dialog_title" msgid="8860150223172993547">"Vil du begynde at caste?"</string>
<string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="1986212276016817231">"Når du caster, har Android adgang til alt, der vises på din skærm eller afspilles på din enhed. Vær derfor forsigtig med ting såsom adgangskoder, betalingsoplysninger, beskeder, billeder, lyd og video."</string>
<string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="9900961380294292">"Når du caster en app, har Android adgang til alt, der vises eller afspilles i den pågældende app. Vær derfor forsigtig med ting såsom adgangskoder, betalingsoplysninger, beskeder, billeder, lyd og video."</string>
@@ -1173,6 +1170,10 @@
<string name="assistant_attention_content_description" msgid="6830215897604642875">"Assistent lytter"</string>
<string name="set_default_notes_app_toast_content" msgid="2812374329662610753">"Angiv standardapp til noter i Indstillinger"</string>
<string name="install_app" msgid="5066668100199613936">"Installer app"</string>
+ <!-- no translation found for connected_display_dialog_start_mirroring (6237895789920854982) -->
+ <skip />
+ <!-- no translation found for enable_display (8308309634883321977) -->
+ <skip />
<string name="privacy_dialog_title" msgid="7839968133469098311">"Mikrofon og kamera"</string>
<string name="privacy_dialog_summary" msgid="2458769652125995409">"Seneste brug af apps"</string>
<string name="privacy_dialog_more_button" msgid="7610604080293562345">"Se seneste adgang"</string>
diff --git a/packages/SystemUI/res/values-de/strings.xml b/packages/SystemUI/res/values-de/strings.xml
index 4f08805ebdfe..822ab277ba85 100644
--- a/packages/SystemUI/res/values-de/strings.xml
+++ b/packages/SystemUI/res/values-de/strings.xml
@@ -57,8 +57,7 @@
<string name="hdmi_cec_set_menu_language_description" msgid="8176716678074126619">"Von einem anderen Gerät wurde eine Änderung der Systemsprache angefordert"</string>
<string name="hdmi_cec_set_menu_language_accept" msgid="2513689457281009578">"Sprache ändern"</string>
<string name="hdmi_cec_set_menu_language_decline" msgid="7650721096558646011">"Aktuelle Sprache nutzen"</string>
- <!-- no translation found for share_wifi_button_text (1285273973812029240) -->
- <skip />
+ <string name="share_wifi_button_text" msgid="1285273973812029240">"WLAN teilen"</string>
<string name="wifi_debugging_title" msgid="7300007687492186076">"Debugging über WLAN in diesem Netzwerk zulassen?"</string>
<string name="wifi_debugging_message" msgid="5461204211731802995">"Netzwerkname (SSID)\n<xliff:g id="SSID_0">%1$s</xliff:g>\n\nWLAN-Adresse (BSSID)\n<xliff:g id="BSSID_1">%2$s</xliff:g>"</string>
<string name="wifi_debugging_always" msgid="2968383799517975155">"Immer in diesem Netzwerk zulassen"</string>
@@ -160,8 +159,7 @@
<string name="biometric_dialog_wrong_pattern" msgid="8954812279840889029">"Falsches Muster"</string>
<string name="biometric_dialog_wrong_password" msgid="69477929306843790">"Falsches Passwort"</string>
<string name="biometric_dialog_credential_too_many_attempts" msgid="3083141271737748716">"Zu viele Fehlversuche.\nBitte probiere es in <xliff:g id="NUMBER">%d</xliff:g> Sekunden noch einmal."</string>
- <!-- no translation found for work_challenge_emergency_button_text (8946588434515599288) -->
- <skip />
+ <string name="work_challenge_emergency_button_text" msgid="8946588434515599288">"Notfall"</string>
<string name="biometric_dialog_credential_attempts_before_wipe" msgid="6751859711975516999">"Bitte probier es noch einmal. Versuch <xliff:g id="ATTEMPTS_0">%1$d</xliff:g> von <xliff:g id="MAX_ATTEMPTS">%2$d</xliff:g>."</string>
<string name="biometric_dialog_last_attempt_before_wipe_dialog_title" msgid="2874250099278693477">"Deine Daten werden gelöscht"</string>
<string name="biometric_dialog_last_pattern_attempt_before_wipe_device" msgid="6562299244825817598">"Wenn du beim nächsten Versuch ein falsches Muster eingibst, werden die Daten auf diesem Gerät gelöscht."</string>
@@ -415,8 +413,7 @@
<string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="8736391633234144237">"Beim Teilen, Aufnehmen oder Streamen hat <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> Zugriff auf alle Inhalte, die auf deinem Bildschirm sichtbar sind oder von deinem Gerät wiedergegeben werden. Sei also vorsichtig mit Informationen wie Passwörtern, Zahlungsdetails, Nachrichten, Fotos sowie Audio- und Videoinhalten."</string>
<string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="5211695779082563959">"Beim Teilen, Aufnehmen oder Streamen einer App hat <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> Zugriff auf alle Inhalte, die in dieser App sichtbar sind oder von ihr wiedergegeben werden. Sei also vorsichtig mit Informationen wie Passwörtern, Zahlungsdetails, Nachrichten, Fotos sowie Audio- und Videoinhalten."</string>
<string name="media_projection_entry_app_permission_dialog_continue" msgid="295463518195075840">"Starten"</string>
- <!-- no translation found for media_projection_entry_app_permission_dialog_single_app_disabled (8999903044874669995) -->
- <skip />
+ <string name="media_projection_entry_app_permission_dialog_single_app_disabled" msgid="8999903044874669995">"<xliff:g id="APP_NAME">%1$s</xliff:g> hat diese Option deaktiviert"</string>
<string name="media_projection_entry_cast_permission_dialog_title" msgid="8860150223172993547">"Stream starten?"</string>
<string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="1986212276016817231">"Beim Streamen hat Android Zugriff auf alle Inhalte, die auf deinem Bildschirm sichtbar sind oder von deinem Gerät wiedergegeben werden. Sei also vorsichtig mit Informationen wie Passwörtern, Zahlungsdetails, Nachrichten, Fotos sowie Audio- und Videoinhalten."</string>
<string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="9900961380294292">"Beim Streamen einer App hat Android Zugriff auf alle Inhalte, die in dieser App sichtbar sind oder von ihr wiedergegeben werden. Sei also vorsichtig mit Informationen wie Passwörtern, Zahlungsdetails, Nachrichten, Fotos sowie Audio- und Videoinhalten."</string>
@@ -1173,6 +1170,10 @@
<string name="assistant_attention_content_description" msgid="6830215897604642875">"Assistant-Aktivierung an"</string>
<string name="set_default_notes_app_toast_content" msgid="2812374329662610753">"Standard-Notizen-App in den Einstellungen einrichten"</string>
<string name="install_app" msgid="5066668100199613936">"App installieren"</string>
+ <!-- no translation found for connected_display_dialog_start_mirroring (6237895789920854982) -->
+ <skip />
+ <!-- no translation found for enable_display (8308309634883321977) -->
+ <skip />
<string name="privacy_dialog_title" msgid="7839968133469098311">"Mikrofon &amp; Kamera"</string>
<string name="privacy_dialog_summary" msgid="2458769652125995409">"Kürzliche App-Nutzung"</string>
<string name="privacy_dialog_more_button" msgid="7610604080293562345">"Kürzliche Zugriffe ansehen"</string>
diff --git a/packages/SystemUI/res/values-el/strings.xml b/packages/SystemUI/res/values-el/strings.xml
index 63337fd90c15..c33b7534198c 100644
--- a/packages/SystemUI/res/values-el/strings.xml
+++ b/packages/SystemUI/res/values-el/strings.xml
@@ -57,8 +57,7 @@
<string name="hdmi_cec_set_menu_language_description" msgid="8176716678074126619">"Ζητήθηκε αλλαγή της γλώσσας συστήματος από άλλη συσκευή"</string>
<string name="hdmi_cec_set_menu_language_accept" msgid="2513689457281009578">"Αλλαγή γλώσσας"</string>
<string name="hdmi_cec_set_menu_language_decline" msgid="7650721096558646011">"Διατήρ. τρέχουσας γλώσσας"</string>
- <!-- no translation found for share_wifi_button_text (1285273973812029240) -->
- <skip />
+ <string name="share_wifi_button_text" msgid="1285273973812029240">"Κοινοποίηση Wi‑Fi"</string>
<string name="wifi_debugging_title" msgid="7300007687492186076">"Να επιτρέπεται ασύρματος εντοπ. σφαλ. στο δίκτυο;"</string>
<string name="wifi_debugging_message" msgid="5461204211731802995">"Όνομα δικτύου (SSID)\n<xliff:g id="SSID_0">%1$s</xliff:g>\n\nΔιεύθυνση Wi‑Fi (BSSID)\n<xliff:g id="BSSID_1">%2$s</xliff:g>"</string>
<string name="wifi_debugging_always" msgid="2968383799517975155">"Να επιτρέπεται πάντα σε αυτό το δίκτυο"</string>
@@ -160,8 +159,7 @@
<string name="biometric_dialog_wrong_pattern" msgid="8954812279840889029">"Εσφαλμένο μοτίβο"</string>
<string name="biometric_dialog_wrong_password" msgid="69477929306843790">"Εσφαλμένος κωδικός πρόσβασης"</string>
<string name="biometric_dialog_credential_too_many_attempts" msgid="3083141271737748716">"Πάρα πολλές αποτυχημένες προσπάθειες.\nΔοκιμάστε ξανά σε <xliff:g id="NUMBER">%d</xliff:g> δευτερόλεπτα."</string>
- <!-- no translation found for work_challenge_emergency_button_text (8946588434515599288) -->
- <skip />
+ <string name="work_challenge_emergency_button_text" msgid="8946588434515599288">"Έκτακτη ανάγκη"</string>
<string name="biometric_dialog_credential_attempts_before_wipe" msgid="6751859711975516999">"Προσπαθήστε ξανά. Προσπάθεια <xliff:g id="ATTEMPTS_0">%1$d</xliff:g> από <xliff:g id="MAX_ATTEMPTS">%2$d</xliff:g>."</string>
<string name="biometric_dialog_last_attempt_before_wipe_dialog_title" msgid="2874250099278693477">"Τα δεδομένα σας θα διαγραφούν"</string>
<string name="biometric_dialog_last_pattern_attempt_before_wipe_device" msgid="6562299244825817598">"Εάν εισαγάγετε εσφαλμένο μοτίβο στην επόμενη προσπάθεια, τα δεδομένα αυτής της συσκευής θα διαγραφούν."</string>
@@ -415,8 +413,7 @@
<string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="8736391633234144237">"Όταν κάνετε κοινή χρήση, εγγραφή ή μετάδοση, η εφαρμογή <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> έχει πρόσβαση σε οτιδήποτε είναι ορατό στην οθόνη σας ή αναπαράγεται στη συσκευή σας. Επομένως, να είστε προσεκτικοί με τους κωδικούς πρόσβασης, τα στοιχεία πληρωμής, τα μηνύματα, τις φωτογραφίες, τον ήχο και το βίντεο."</string>
<string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="5211695779082563959">"Όταν κάνετε κοινή χρήση, εγγραφή ή μετάδοση μιας εφαρμογής, η εφαρμογή <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> έχει πρόσβαση σε οτιδήποτε είναι ορατό ή αναπαράγεται στη συγκεκριμένη εφαρμογή. Επομένως, να είστε προσεκτικοί με τους κωδικούς πρόσβασης, τα στοιχεία πληρωμής, τα μηνύματα, τις φωτογραφίες, τον ήχο και το βίντεο."</string>
<string name="media_projection_entry_app_permission_dialog_continue" msgid="295463518195075840">"Έναρξη"</string>
- <!-- no translation found for media_projection_entry_app_permission_dialog_single_app_disabled (8999903044874669995) -->
- <skip />
+ <string name="media_projection_entry_app_permission_dialog_single_app_disabled" msgid="8999903044874669995">"Η εφαρμογή <xliff:g id="APP_NAME">%1$s</xliff:g> απενεργοποίησε αυτήν την επιλογή"</string>
<string name="media_projection_entry_cast_permission_dialog_title" msgid="8860150223172993547">"Έναρξη μετάδοσης;"</string>
<string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="1986212276016817231">"Όταν κάνετε μετάδοση, το Android έχει πρόσβαση σε οτιδήποτε είναι ορατό στην οθόνη σας ή αναπαράγεται στη συσκευή σας. Επομένως, να είστε προσεκτικοί με τους κωδικούς πρόσβασης, τα στοιχεία πληρωμής, τα μηνύματα, τις φωτογραφίες, τον ήχο και το βίντεο."</string>
<string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="9900961380294292">"Όταν κάνετε μετάδοση μιας εφαρμογής, το Android έχει πρόσβαση σε οτιδήποτε είναι ορατό ή αναπαράγεται στη συγκεκριμένη εφαρμογή. Επομένως, να είστε προσεκτικοί με τους κωδικούς πρόσβασης, τα στοιχεία πληρωμής, τα μηνύματα, τις φωτογραφίες, τον ήχο και το βίντεο."</string>
@@ -1173,6 +1170,10 @@
<string name="assistant_attention_content_description" msgid="6830215897604642875">"Ο Βοηθός βρίσκεται σε αναμονή"</string>
<string name="set_default_notes_app_toast_content" msgid="2812374329662610753">"Ορίστε την προεπιλεγμένη εφαρμογή σημειώσεων στις Ρυθμίσεις"</string>
<string name="install_app" msgid="5066668100199613936">"Εγκατάσταση εφαρμογής"</string>
+ <!-- no translation found for connected_display_dialog_start_mirroring (6237895789920854982) -->
+ <skip />
+ <!-- no translation found for enable_display (8308309634883321977) -->
+ <skip />
<string name="privacy_dialog_title" msgid="7839968133469098311">"Μικρόφωνο και Κάμερα"</string>
<string name="privacy_dialog_summary" msgid="2458769652125995409">"Πρόσφατη χρήση εφαρμογής"</string>
<string name="privacy_dialog_more_button" msgid="7610604080293562345">"Εμφάνιση πρόσφατης πρόσβασης"</string>
diff --git a/packages/SystemUI/res/values-en-rAU/strings.xml b/packages/SystemUI/res/values-en-rAU/strings.xml
index 7fbd4bf66aba..901459dea907 100644
--- a/packages/SystemUI/res/values-en-rAU/strings.xml
+++ b/packages/SystemUI/res/values-en-rAU/strings.xml
@@ -57,8 +57,7 @@
<string name="hdmi_cec_set_menu_language_description" msgid="8176716678074126619">"System language change requested by another device"</string>
<string name="hdmi_cec_set_menu_language_accept" msgid="2513689457281009578">"Change language"</string>
<string name="hdmi_cec_set_menu_language_decline" msgid="7650721096558646011">"Keep current language"</string>
- <!-- no translation found for share_wifi_button_text (1285273973812029240) -->
- <skip />
+ <string name="share_wifi_button_text" msgid="1285273973812029240">"Share Wi‑Fi"</string>
<string name="wifi_debugging_title" msgid="7300007687492186076">"Allow wireless debugging on this network?"</string>
<string name="wifi_debugging_message" msgid="5461204211731802995">"Network Name (SSID)\n<xliff:g id="SSID_0">%1$s</xliff:g>\n\nWi‑Fi Address (BSSID)\n<xliff:g id="BSSID_1">%2$s</xliff:g>"</string>
<string name="wifi_debugging_always" msgid="2968383799517975155">"Always allow on this network"</string>
@@ -160,8 +159,7 @@
<string name="biometric_dialog_wrong_pattern" msgid="8954812279840889029">"Wrong pattern"</string>
<string name="biometric_dialog_wrong_password" msgid="69477929306843790">"Wrong password"</string>
<string name="biometric_dialog_credential_too_many_attempts" msgid="3083141271737748716">"Too many incorrect attempts.\nTry again in <xliff:g id="NUMBER">%d</xliff:g> seconds."</string>
- <!-- no translation found for work_challenge_emergency_button_text (8946588434515599288) -->
- <skip />
+ <string name="work_challenge_emergency_button_text" msgid="8946588434515599288">"Emergency"</string>
<string name="biometric_dialog_credential_attempts_before_wipe" msgid="6751859711975516999">"Try again. Attempt <xliff:g id="ATTEMPTS_0">%1$d</xliff:g> of <xliff:g id="MAX_ATTEMPTS">%2$d</xliff:g>."</string>
<string name="biometric_dialog_last_attempt_before_wipe_dialog_title" msgid="2874250099278693477">"Your data will be deleted"</string>
<string name="biometric_dialog_last_pattern_attempt_before_wipe_device" msgid="6562299244825817598">"If you enter an incorrect pattern on the next attempt, this device’s data will be deleted."</string>
@@ -415,8 +413,7 @@
<string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="8736391633234144237">"When you’re sharing, recording or casting, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> has access to anything visible on your screen or played on your device. So be careful with things like passwords, payment details, messages, photos, audio and video."</string>
<string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="5211695779082563959">"When you’re sharing, recording or casting an app, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> has access to anything shown or played on that app. So be careful with things like passwords, payment details, messages, photos, audio and video."</string>
<string name="media_projection_entry_app_permission_dialog_continue" msgid="295463518195075840">"Start"</string>
- <!-- no translation found for media_projection_entry_app_permission_dialog_single_app_disabled (8999903044874669995) -->
- <skip />
+ <string name="media_projection_entry_app_permission_dialog_single_app_disabled" msgid="8999903044874669995">"<xliff:g id="APP_NAME">%1$s</xliff:g> has disabled this option"</string>
<string name="media_projection_entry_cast_permission_dialog_title" msgid="8860150223172993547">"Start casting?"</string>
<string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="1986212276016817231">"When you’re casting, Android has access to anything visible on your screen or played on your device. So be careful with things like passwords, payment details, messages, photos, audio and video."</string>
<string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="9900961380294292">"When you’re casting an app, Android has access to anything shown or played on that app. So be careful with things like passwords, payment details, messages, photos, audio and video."</string>
@@ -1173,6 +1170,8 @@
<string name="assistant_attention_content_description" msgid="6830215897604642875">"Assistant attention on"</string>
<string name="set_default_notes_app_toast_content" msgid="2812374329662610753">"Set default notes app in Settings"</string>
<string name="install_app" msgid="5066668100199613936">"Install app"</string>
+ <string name="connected_display_dialog_start_mirroring" msgid="6237895789920854982">"Mirror to external display?"</string>
+ <string name="enable_display" msgid="8308309634883321977">"Enable display"</string>
<string name="privacy_dialog_title" msgid="7839968133469098311">"Microphone and Camera"</string>
<string name="privacy_dialog_summary" msgid="2458769652125995409">"Recent app use"</string>
<string name="privacy_dialog_more_button" msgid="7610604080293562345">"See recent access"</string>
diff --git a/packages/SystemUI/res/values-en-rCA/strings.xml b/packages/SystemUI/res/values-en-rCA/strings.xml
index 0e50776c3308..01aa63784bbd 100644
--- a/packages/SystemUI/res/values-en-rCA/strings.xml
+++ b/packages/SystemUI/res/values-en-rCA/strings.xml
@@ -57,8 +57,7 @@
<string name="hdmi_cec_set_menu_language_description" msgid="8176716678074126619">"System language change requested by another device"</string>
<string name="hdmi_cec_set_menu_language_accept" msgid="2513689457281009578">"Change language"</string>
<string name="hdmi_cec_set_menu_language_decline" msgid="7650721096558646011">"Keep current language"</string>
- <!-- no translation found for share_wifi_button_text (1285273973812029240) -->
- <skip />
+ <string name="share_wifi_button_text" msgid="1285273973812029240">"Share Wi‑Fi"</string>
<string name="wifi_debugging_title" msgid="7300007687492186076">"Allow wireless debugging on this network?"</string>
<string name="wifi_debugging_message" msgid="5461204211731802995">"Network Name (SSID)\n<xliff:g id="SSID_0">%1$s</xliff:g>\n\nWi‑Fi Address (BSSID)\n<xliff:g id="BSSID_1">%2$s</xliff:g>"</string>
<string name="wifi_debugging_always" msgid="2968383799517975155">"Always allow on this network"</string>
@@ -160,8 +159,7 @@
<string name="biometric_dialog_wrong_pattern" msgid="8954812279840889029">"Wrong pattern"</string>
<string name="biometric_dialog_wrong_password" msgid="69477929306843790">"Wrong password"</string>
<string name="biometric_dialog_credential_too_many_attempts" msgid="3083141271737748716">"Too many incorrect attempts.\nTry again in <xliff:g id="NUMBER">%d</xliff:g> seconds."</string>
- <!-- no translation found for work_challenge_emergency_button_text (8946588434515599288) -->
- <skip />
+ <string name="work_challenge_emergency_button_text" msgid="8946588434515599288">"Emergency"</string>
<string name="biometric_dialog_credential_attempts_before_wipe" msgid="6751859711975516999">"Try again. Attempt <xliff:g id="ATTEMPTS_0">%1$d</xliff:g> of <xliff:g id="MAX_ATTEMPTS">%2$d</xliff:g>."</string>
<string name="biometric_dialog_last_attempt_before_wipe_dialog_title" msgid="2874250099278693477">"Your data will be deleted"</string>
<string name="biometric_dialog_last_pattern_attempt_before_wipe_device" msgid="6562299244825817598">"If you enter an incorrect pattern on the next attempt, this device’s data will be deleted."</string>
@@ -415,8 +413,7 @@
<string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="8736391633234144237">"When you’re sharing, recording, or casting, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> has access to anything visible on your screen or played on your device. So be careful with things like passwords, payment details, messages, photos, and audio and video."</string>
<string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="5211695779082563959">"When you’re sharing, recording, or casting an app, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> has access to anything shown or played on that app. So be careful with things like passwords, payment details, messages, photos, and audio and video."</string>
<string name="media_projection_entry_app_permission_dialog_continue" msgid="295463518195075840">"Start"</string>
- <!-- no translation found for media_projection_entry_app_permission_dialog_single_app_disabled (8999903044874669995) -->
- <skip />
+ <string name="media_projection_entry_app_permission_dialog_single_app_disabled" msgid="8999903044874669995">"<xliff:g id="APP_NAME">%1$s</xliff:g> has disabled this option"</string>
<string name="media_projection_entry_cast_permission_dialog_title" msgid="8860150223172993547">"Start casting?"</string>
<string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="1986212276016817231">"When you’re casting, Android has access to anything visible on your screen or played on your device. So be careful with things like passwords, payment details, messages, photos, and audio and video."</string>
<string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="9900961380294292">"When you’re casting an app, Android has access to anything shown or played on that app. So be careful with things like passwords, payment details, messages, photos, and audio and video."</string>
@@ -1173,6 +1170,8 @@
<string name="assistant_attention_content_description" msgid="6830215897604642875">"Assistant attention on"</string>
<string name="set_default_notes_app_toast_content" msgid="2812374329662610753">"Set default notes app in Settings"</string>
<string name="install_app" msgid="5066668100199613936">"Install app"</string>
+ <string name="connected_display_dialog_start_mirroring" msgid="6237895789920854982">"Mirror to external display?"</string>
+ <string name="enable_display" msgid="8308309634883321977">"Enable display"</string>
<string name="privacy_dialog_title" msgid="7839968133469098311">"Microphone &amp; Camera"</string>
<string name="privacy_dialog_summary" msgid="2458769652125995409">"Recent app use"</string>
<string name="privacy_dialog_more_button" msgid="7610604080293562345">"See recent access"</string>
diff --git a/packages/SystemUI/res/values-en-rGB/strings.xml b/packages/SystemUI/res/values-en-rGB/strings.xml
index 7fbd4bf66aba..901459dea907 100644
--- a/packages/SystemUI/res/values-en-rGB/strings.xml
+++ b/packages/SystemUI/res/values-en-rGB/strings.xml
@@ -57,8 +57,7 @@
<string name="hdmi_cec_set_menu_language_description" msgid="8176716678074126619">"System language change requested by another device"</string>
<string name="hdmi_cec_set_menu_language_accept" msgid="2513689457281009578">"Change language"</string>
<string name="hdmi_cec_set_menu_language_decline" msgid="7650721096558646011">"Keep current language"</string>
- <!-- no translation found for share_wifi_button_text (1285273973812029240) -->
- <skip />
+ <string name="share_wifi_button_text" msgid="1285273973812029240">"Share Wi‑Fi"</string>
<string name="wifi_debugging_title" msgid="7300007687492186076">"Allow wireless debugging on this network?"</string>
<string name="wifi_debugging_message" msgid="5461204211731802995">"Network Name (SSID)\n<xliff:g id="SSID_0">%1$s</xliff:g>\n\nWi‑Fi Address (BSSID)\n<xliff:g id="BSSID_1">%2$s</xliff:g>"</string>
<string name="wifi_debugging_always" msgid="2968383799517975155">"Always allow on this network"</string>
@@ -160,8 +159,7 @@
<string name="biometric_dialog_wrong_pattern" msgid="8954812279840889029">"Wrong pattern"</string>
<string name="biometric_dialog_wrong_password" msgid="69477929306843790">"Wrong password"</string>
<string name="biometric_dialog_credential_too_many_attempts" msgid="3083141271737748716">"Too many incorrect attempts.\nTry again in <xliff:g id="NUMBER">%d</xliff:g> seconds."</string>
- <!-- no translation found for work_challenge_emergency_button_text (8946588434515599288) -->
- <skip />
+ <string name="work_challenge_emergency_button_text" msgid="8946588434515599288">"Emergency"</string>
<string name="biometric_dialog_credential_attempts_before_wipe" msgid="6751859711975516999">"Try again. Attempt <xliff:g id="ATTEMPTS_0">%1$d</xliff:g> of <xliff:g id="MAX_ATTEMPTS">%2$d</xliff:g>."</string>
<string name="biometric_dialog_last_attempt_before_wipe_dialog_title" msgid="2874250099278693477">"Your data will be deleted"</string>
<string name="biometric_dialog_last_pattern_attempt_before_wipe_device" msgid="6562299244825817598">"If you enter an incorrect pattern on the next attempt, this device’s data will be deleted."</string>
@@ -415,8 +413,7 @@
<string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="8736391633234144237">"When you’re sharing, recording or casting, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> has access to anything visible on your screen or played on your device. So be careful with things like passwords, payment details, messages, photos, audio and video."</string>
<string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="5211695779082563959">"When you’re sharing, recording or casting an app, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> has access to anything shown or played on that app. So be careful with things like passwords, payment details, messages, photos, audio and video."</string>
<string name="media_projection_entry_app_permission_dialog_continue" msgid="295463518195075840">"Start"</string>
- <!-- no translation found for media_projection_entry_app_permission_dialog_single_app_disabled (8999903044874669995) -->
- <skip />
+ <string name="media_projection_entry_app_permission_dialog_single_app_disabled" msgid="8999903044874669995">"<xliff:g id="APP_NAME">%1$s</xliff:g> has disabled this option"</string>
<string name="media_projection_entry_cast_permission_dialog_title" msgid="8860150223172993547">"Start casting?"</string>
<string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="1986212276016817231">"When you’re casting, Android has access to anything visible on your screen or played on your device. So be careful with things like passwords, payment details, messages, photos, audio and video."</string>
<string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="9900961380294292">"When you’re casting an app, Android has access to anything shown or played on that app. So be careful with things like passwords, payment details, messages, photos, audio and video."</string>
@@ -1173,6 +1170,8 @@
<string name="assistant_attention_content_description" msgid="6830215897604642875">"Assistant attention on"</string>
<string name="set_default_notes_app_toast_content" msgid="2812374329662610753">"Set default notes app in Settings"</string>
<string name="install_app" msgid="5066668100199613936">"Install app"</string>
+ <string name="connected_display_dialog_start_mirroring" msgid="6237895789920854982">"Mirror to external display?"</string>
+ <string name="enable_display" msgid="8308309634883321977">"Enable display"</string>
<string name="privacy_dialog_title" msgid="7839968133469098311">"Microphone and Camera"</string>
<string name="privacy_dialog_summary" msgid="2458769652125995409">"Recent app use"</string>
<string name="privacy_dialog_more_button" msgid="7610604080293562345">"See recent access"</string>
diff --git a/packages/SystemUI/res/values-en-rIN/strings.xml b/packages/SystemUI/res/values-en-rIN/strings.xml
index 7fbd4bf66aba..901459dea907 100644
--- a/packages/SystemUI/res/values-en-rIN/strings.xml
+++ b/packages/SystemUI/res/values-en-rIN/strings.xml
@@ -57,8 +57,7 @@
<string name="hdmi_cec_set_menu_language_description" msgid="8176716678074126619">"System language change requested by another device"</string>
<string name="hdmi_cec_set_menu_language_accept" msgid="2513689457281009578">"Change language"</string>
<string name="hdmi_cec_set_menu_language_decline" msgid="7650721096558646011">"Keep current language"</string>
- <!-- no translation found for share_wifi_button_text (1285273973812029240) -->
- <skip />
+ <string name="share_wifi_button_text" msgid="1285273973812029240">"Share Wi‑Fi"</string>
<string name="wifi_debugging_title" msgid="7300007687492186076">"Allow wireless debugging on this network?"</string>
<string name="wifi_debugging_message" msgid="5461204211731802995">"Network Name (SSID)\n<xliff:g id="SSID_0">%1$s</xliff:g>\n\nWi‑Fi Address (BSSID)\n<xliff:g id="BSSID_1">%2$s</xliff:g>"</string>
<string name="wifi_debugging_always" msgid="2968383799517975155">"Always allow on this network"</string>
@@ -160,8 +159,7 @@
<string name="biometric_dialog_wrong_pattern" msgid="8954812279840889029">"Wrong pattern"</string>
<string name="biometric_dialog_wrong_password" msgid="69477929306843790">"Wrong password"</string>
<string name="biometric_dialog_credential_too_many_attempts" msgid="3083141271737748716">"Too many incorrect attempts.\nTry again in <xliff:g id="NUMBER">%d</xliff:g> seconds."</string>
- <!-- no translation found for work_challenge_emergency_button_text (8946588434515599288) -->
- <skip />
+ <string name="work_challenge_emergency_button_text" msgid="8946588434515599288">"Emergency"</string>
<string name="biometric_dialog_credential_attempts_before_wipe" msgid="6751859711975516999">"Try again. Attempt <xliff:g id="ATTEMPTS_0">%1$d</xliff:g> of <xliff:g id="MAX_ATTEMPTS">%2$d</xliff:g>."</string>
<string name="biometric_dialog_last_attempt_before_wipe_dialog_title" msgid="2874250099278693477">"Your data will be deleted"</string>
<string name="biometric_dialog_last_pattern_attempt_before_wipe_device" msgid="6562299244825817598">"If you enter an incorrect pattern on the next attempt, this device’s data will be deleted."</string>
@@ -415,8 +413,7 @@
<string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="8736391633234144237">"When you’re sharing, recording or casting, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> has access to anything visible on your screen or played on your device. So be careful with things like passwords, payment details, messages, photos, audio and video."</string>
<string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="5211695779082563959">"When you’re sharing, recording or casting an app, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> has access to anything shown or played on that app. So be careful with things like passwords, payment details, messages, photos, audio and video."</string>
<string name="media_projection_entry_app_permission_dialog_continue" msgid="295463518195075840">"Start"</string>
- <!-- no translation found for media_projection_entry_app_permission_dialog_single_app_disabled (8999903044874669995) -->
- <skip />
+ <string name="media_projection_entry_app_permission_dialog_single_app_disabled" msgid="8999903044874669995">"<xliff:g id="APP_NAME">%1$s</xliff:g> has disabled this option"</string>
<string name="media_projection_entry_cast_permission_dialog_title" msgid="8860150223172993547">"Start casting?"</string>
<string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="1986212276016817231">"When you’re casting, Android has access to anything visible on your screen or played on your device. So be careful with things like passwords, payment details, messages, photos, audio and video."</string>
<string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="9900961380294292">"When you’re casting an app, Android has access to anything shown or played on that app. So be careful with things like passwords, payment details, messages, photos, audio and video."</string>
@@ -1173,6 +1170,8 @@
<string name="assistant_attention_content_description" msgid="6830215897604642875">"Assistant attention on"</string>
<string name="set_default_notes_app_toast_content" msgid="2812374329662610753">"Set default notes app in Settings"</string>
<string name="install_app" msgid="5066668100199613936">"Install app"</string>
+ <string name="connected_display_dialog_start_mirroring" msgid="6237895789920854982">"Mirror to external display?"</string>
+ <string name="enable_display" msgid="8308309634883321977">"Enable display"</string>
<string name="privacy_dialog_title" msgid="7839968133469098311">"Microphone and Camera"</string>
<string name="privacy_dialog_summary" msgid="2458769652125995409">"Recent app use"</string>
<string name="privacy_dialog_more_button" msgid="7610604080293562345">"See recent access"</string>
diff --git a/packages/SystemUI/res/values-en-rXC/strings.xml b/packages/SystemUI/res/values-en-rXC/strings.xml
index 876bb0e9678e..c496aeea9325 100644
--- a/packages/SystemUI/res/values-en-rXC/strings.xml
+++ b/packages/SystemUI/res/values-en-rXC/strings.xml
@@ -57,8 +57,7 @@
<string name="hdmi_cec_set_menu_language_description" msgid="8176716678074126619">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‎‎‏‎‏‏‏‏‎‎‏‏‎‎‎‏‎‎‎‎‏‏‏‏‏‏‏‎‎‏‎‎‎‎‏‏‎‎‏‏‏‏‎‏‏‎‏‎‎‎‏‎‎‎‏‏‎‏‏‎System language change requested by another device‎‏‎‎‏‎"</string>
<string name="hdmi_cec_set_menu_language_accept" msgid="2513689457281009578">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‎‎‏‎‏‏‏‎‎‎‏‎‎‏‏‎‏‎‏‏‎‎‏‏‏‏‏‎‎‏‎‎‏‎‎‎‏‏‏‎‎‎‎‏‎‎‎‎‎‏‏‏‏‎‏‎‏‎‏‎‎Change language‎‏‎‎‏‎"</string>
<string name="hdmi_cec_set_menu_language_decline" msgid="7650721096558646011">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‎‏‎‎‎‏‎‏‏‎‎‏‏‎‏‎‎‏‎‎‏‎‎‏‏‎‏‎‏‎‏‎‎‏‏‏‏‏‏‎‏‏‏‎‎‎‏‎‎‏‎‏‏‏‏‏‎‏‏‎Keep current language‎‏‎‎‏‎"</string>
- <!-- no translation found for share_wifi_button_text (1285273973812029240) -->
- <skip />
+ <string name="share_wifi_button_text" msgid="1285273973812029240">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‎‎‎‏‏‏‎‏‎‏‏‎‎‎‏‏‎‏‎‏‏‏‎‏‏‏‏‎‏‎‎‏‏‎‎‎‎‎‎‏‏‏‏‎‏‏‏‎‎‏‏‏‎‎‏‏‏‎‎‎‎Share Wi‑Fi‎‏‎‎‏‎"</string>
<string name="wifi_debugging_title" msgid="7300007687492186076">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‎‏‎‏‎‏‎‎‏‏‏‎‏‏‎‏‎‏‏‎‎‏‎‏‎‎‎‎‏‎‎‎‏‏‏‎‏‎‎‏‎‏‏‏‏‎‏‎‏‏‏‏‏‏‎‏‏‏‎‎‎Allow wireless debugging on this network?‎‏‎‎‏‎"</string>
<string name="wifi_debugging_message" msgid="5461204211731802995">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‎‏‏‏‏‎‎‏‎‏‎‎‎‎‏‏‎‎‎‎‏‎‎‏‎‏‏‏‎‏‏‏‏‏‎‎‎‏‎‎‏‎‎‎‎‏‎‏‎‏‏‎‏‏‏‎‎‏‏‎Network Name (SSID)‎‏‎‎‏‏‎\n‎‏‎‎‏‏‏‎‎‏‎‎‏‏‎<xliff:g id="SSID_0">%1$s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‏‎\n‎‏‎‎‏‏‏‎‎‏‎‎‏‏‎\n‎‏‎‎‏‏‏‎Wi‑Fi Address (BSSID)‎‏‎‎‏‏‎\n‎‏‎‎‏‏‏‎‎‏‎‎‏‏‎<xliff:g id="BSSID_1">%2$s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
<string name="wifi_debugging_always" msgid="2968383799517975155">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‏‎‎‏‎‎‏‏‎‎‎‏‏‏‎‏‎‎‎‏‎‏‎‏‎‏‏‎‏‎‏‎‎‏‏‏‎‏‎‎‏‎‏‏‎‎‎‏‎‎‏‎‎‏‏‏‎‎‏‏‎Always allow on this network‎‏‎‎‏‎"</string>
@@ -160,8 +159,7 @@
<string name="biometric_dialog_wrong_pattern" msgid="8954812279840889029">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‏‏‎‎‎‏‎‎‎‏‎‏‏‏‏‎‎‎‏‎‎‏‎‏‎‎‏‎‏‏‏‎‏‎‏‎‎‎‏‏‏‎‎‎‏‏‎‏‏‎‎‎‏‏‎‎‎‏‎‏‎Wrong pattern‎‏‎‎‏‎"</string>
<string name="biometric_dialog_wrong_password" msgid="69477929306843790">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‎‎‎‏‏‏‏‎‏‏‎‏‏‎‏‎‏‎‏‏‏‎‎‏‏‏‏‎‎‎‎‎‎‎‎‎‎‎‏‎‎‎‎‎‏‏‎‏‎‏‎‏‎‎‎‏‏‏‎‎Wrong password‎‏‎‎‏‎"</string>
<string name="biometric_dialog_credential_too_many_attempts" msgid="3083141271737748716">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‏‎‏‎‏‏‎‎‏‎‎‏‏‎‎‎‎‏‎‎‏‎‏‎‎‏‏‎‏‏‎‎‎‏‏‎‎‏‎‎‎‏‏‎‎‏‎‎‏‏‎‎‏‏‏‎‏‏‎‎‎Too many incorrect attempts.‎‏‎‎‏‏‎\n‎‏‎‎‏‏‏‎Try again in ‎‏‎‎‏‏‎<xliff:g id="NUMBER">%d</xliff:g>‎‏‎‎‏‏‏‎ seconds.‎‏‎‎‏‎"</string>
- <!-- no translation found for work_challenge_emergency_button_text (8946588434515599288) -->
- <skip />
+ <string name="work_challenge_emergency_button_text" msgid="8946588434515599288">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‏‏‎‎‎‎‏‎‏‎‎‎‏‎‏‎‏‎‏‎‏‏‎‎‎‏‏‏‏‎‏‏‎‏‏‎‏‏‏‎‏‎‏‏‏‎‎‏‏‏‏‏‏‎‏‏‏‎‎‎‎Emergency‎‏‎‎‏‎"</string>
<string name="biometric_dialog_credential_attempts_before_wipe" msgid="6751859711975516999">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‏‏‎‏‏‎‏‏‎‎‏‏‎‏‏‎‏‏‎‎‏‎‏‎‎‎‏‎‏‎‎‏‏‎‎‏‏‎‎‏‎‎‏‎‎‏‏‎‏‎‏‏‎‏‎‎‎‏‏‏‎Try again. Attempt ‎‏‎‎‏‏‎<xliff:g id="ATTEMPTS_0">%1$d</xliff:g>‎‏‎‎‏‏‏‎ of ‎‏‎‎‏‏‎<xliff:g id="MAX_ATTEMPTS">%2$d</xliff:g>‎‏‎‎‏‏‏‎.‎‏‎‎‏‎"</string>
<string name="biometric_dialog_last_attempt_before_wipe_dialog_title" msgid="2874250099278693477">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‎‏‏‏‏‏‏‎‎‎‏‏‎‏‏‎‎‎‏‏‎‎‏‏‏‏‎‎‏‎‏‎‎‎‏‏‎‎‏‎‎‎‏‏‎‏‎‎‎‏‎‎‎‏‏‎‎‏‎‏‎Your data will be deleted‎‏‎‎‏‎"</string>
<string name="biometric_dialog_last_pattern_attempt_before_wipe_device" msgid="6562299244825817598">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‏‎‏‏‎‎‎‏‎‎‎‏‏‏‏‏‏‎‎‎‎‏‏‎‎‏‎‏‎‎‎‎‎‏‎‏‏‎‏‎‏‎‎‎‎‎‏‏‎‎‎‏‏‏‏‏‏‏‏‎‎If you enter an incorrect pattern on the next attempt, this device’s data will be deleted.‎‏‎‎‏‎"</string>
@@ -415,8 +413,7 @@
<string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="8736391633234144237">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‏‎‎‏‎‎‏‏‏‏‎‏‏‏‏‎‎‏‎‏‏‏‏‎‎‏‏‏‎‎‏‎‏‏‎‏‏‎‎‏‏‏‎‏‏‎‏‎‏‎‏‏‏‏‏‎‏‏‎‏‎When you’re sharing, recording, or casting, ‎‏‎‎‏‏‎<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>‎‏‎‎‏‏‏‎ has access to anything visible on your screen or played on your device. So be careful with things like passwords, payment details, messages, photos, and audio and video.‎‏‎‎‏‎"</string>
<string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="5211695779082563959">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‎‎‎‎‏‎‏‎‎‏‏‏‎‏‎‏‎‎‏‏‎‏‏‎‎‏‎‏‏‎‎‎‏‎‏‏‎‎‏‏‏‏‎‎‏‏‏‎‎‎‏‎‏‏‏‎‏‏‏‎When you’re sharing, recording, or casting an app, ‎‏‎‎‏‏‎<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>‎‏‎‎‏‏‏‎ has access to anything shown or played on that app. So be careful with things like passwords, payment details, messages, photos, and audio and video.‎‏‎‎‏‎"</string>
<string name="media_projection_entry_app_permission_dialog_continue" msgid="295463518195075840">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‎‏‏‏‎‎‎‎‎‏‏‎‎‏‏‎‏‏‎‎‏‎‏‎‎‎‎‎‎‏‎‎‎‏‏‏‏‎‎‎‎‏‏‎‏‎‏‏‎‎‏‎‏‏‎‎‎‎‎‎‎‎‎Start‎‏‎‎‏‎"</string>
- <!-- no translation found for media_projection_entry_app_permission_dialog_single_app_disabled (8999903044874669995) -->
- <skip />
+ <string name="media_projection_entry_app_permission_dialog_single_app_disabled" msgid="8999903044874669995">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‏‏‎‎‏‏‏‎‎‏‏‎‎‎‎‏‎‏‎‎‎‎‏‎‎‎‏‎‏‏‎‎‎‎‏‎‏‎‏‏‎‏‏‎‎‎‎‎‏‏‏‏‏‎‏‎‏‎‏‏‎‎‏‎‎‏‏‎<xliff:g id="APP_NAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎ has disabled this option‎‏‎‎‏‎"</string>
<string name="media_projection_entry_cast_permission_dialog_title" msgid="8860150223172993547">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‏‎‏‎‏‏‏‏‎‏‎‏‏‎‎‏‎‎‏‏‏‎‏‎‏‏‏‏‎‏‎‏‎‏‎‎‏‏‎‏‎‎‏‏‎‎‎‎‎‎‏‎‎‎‎‎‏‎‏‏‎Start casting?‎‏‎‎‏‎"</string>
<string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="1986212276016817231">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‎‏‏‏‎‎‏‎‎‎‎‎‏‏‏‎‎‎‏‏‎‎‎‏‎‏‎‏‎‏‎‏‎‎‎‏‎‎‎‎‎‎‎‏‎‏‎‎‏‎‎‎‏‎‎‏‏‏‏‎When you’re casting, Android has access to anything visible on your screen or played on your device. So be careful with things like passwords, payment details, messages, photos, and audio and video.‎‏‎‎‏‎"</string>
<string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="9900961380294292">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‎‏‏‎‏‎‎‎‏‏‎‎‏‎‏‏‎‎‏‏‎‏‏‏‏‏‎‎‏‏‎‏‏‎‎‎‎‎‎‎‎‏‏‏‎‏‏‏‏‎‏‎‎‏‎‏‎‎‎When you’re casting an app, Android has access to anything shown or played on that app. So be careful with things like passwords, payment details, messages, photos, and audio and video.‎‏‎‎‏‎"</string>
@@ -1173,6 +1170,8 @@
<string name="assistant_attention_content_description" msgid="6830215897604642875">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‏‏‏‎‏‏‎‎‏‎‎‏‏‏‎‎‏‏‎‏‎‎‏‎‏‎‏‏‏‎‏‏‏‎‏‏‏‏‏‏‎‎‏‏‎‏‎‏‏‎‎‎‎‎‏‏‏‎‏‏‎Assistant attention on‎‏‎‎‏‎"</string>
<string name="set_default_notes_app_toast_content" msgid="2812374329662610753">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‎‏‏‏‎‎‎‎‎‏‏‏‏‎‎‎‏‏‏‏‏‎‎‎‏‏‎‏‎‏‎‏‏‏‏‎‏‏‏‏‎‏‏‏‏‎‎‏‏‏‎‏‎‏‎‎‎‎‎‏‎Set default notes app in Settings‎‏‎‎‏‎"</string>
<string name="install_app" msgid="5066668100199613936">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‏‏‎‎‏‎‏‎‎‎‎‎‏‏‎‏‎‏‏‏‏‎‎‏‎‏‎‏‏‏‏‎‎‏‏‎‎‏‏‎‎‏‏‏‎‎‎‎‏‎‏‏‏‏‏‎‎‎‎‎Install app‎‏‎‎‏‎"</string>
+ <string name="connected_display_dialog_start_mirroring" msgid="6237895789920854982">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‎‏‏‎‏‎‎‏‎‎‎‏‎‏‏‏‎‏‎‏‎‎‏‎‏‎‏‏‏‏‎‏‎‎‎‎‎‎‏‎‎‎‏‏‎‎‏‎‎‎‏‏‏‏‎‎‎‏‏‎‎Mirror to external display?‎‏‎‎‏‎"</string>
+ <string name="enable_display" msgid="8308309634883321977">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‎‏‏‎‏‎‎‏‏‎‏‎‎‎‎‏‎‏‏‏‎‎‏‎‏‏‏‏‏‏‏‎‏‏‏‎‎‏‎‏‏‎‏‎‎‎‎‎‎‎‎‎‏‏‏‏‎‎‏‎Enable display‎‏‎‎‏‎"</string>
<string name="privacy_dialog_title" msgid="7839968133469098311">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‏‎‎‏‏‎‎‏‏‎‏‎‎‏‎‏‎‎‏‎‏‏‏‏‎‏‎‏‎‏‏‏‏‎‏‏‏‎‎‏‏‏‎‏‏‎‏‎‎‎‏‎‏‎‎‎‏‏‏‎Microphone &amp; Camera‎‏‎‎‏‎"</string>
<string name="privacy_dialog_summary" msgid="2458769652125995409">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‎‎‏‎‎‎‎‏‏‏‏‏‎‏‎‎‏‏‎‏‏‏‏‏‏‎‎‎‏‎‏‏‎‎‏‏‎‏‏‏‏‎‏‏‎‎‎‏‎‎‎‏‏‎‎‏‎‎‎‏‎Recent app use‎‏‎‎‏‎"</string>
<string name="privacy_dialog_more_button" msgid="7610604080293562345">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‎‎‏‏‎‎‏‏‏‏‎‎‏‎‎‏‏‎‎‎‎‎‏‎‏‏‎‏‎‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‏‎‎‎‏‏‏‏‏‏‎‏‎‎‏‎See recent access‎‏‎‎‏‎"</string>
diff --git a/packages/SystemUI/res/values-es-rUS/strings.xml b/packages/SystemUI/res/values-es-rUS/strings.xml
index e5d197d18017..3653839f5a00 100644
--- a/packages/SystemUI/res/values-es-rUS/strings.xml
+++ b/packages/SystemUI/res/values-es-rUS/strings.xml
@@ -57,8 +57,7 @@
<string name="hdmi_cec_set_menu_language_description" msgid="8176716678074126619">"Cambio de idioma del sistema solicitado por otro dispositivo"</string>
<string name="hdmi_cec_set_menu_language_accept" msgid="2513689457281009578">"Cambiar idioma"</string>
<string name="hdmi_cec_set_menu_language_decline" msgid="7650721096558646011">"Mantener el idioma actual"</string>
- <!-- no translation found for share_wifi_button_text (1285273973812029240) -->
- <skip />
+ <string name="share_wifi_button_text" msgid="1285273973812029240">"Compartir Wi‑Fi"</string>
<string name="wifi_debugging_title" msgid="7300007687492186076">"¿Quieres permitir la depuración inalámbrica en esta red?"</string>
<string name="wifi_debugging_message" msgid="5461204211731802995">"Nombre de red (SSID)\n<xliff:g id="SSID_0">%1$s</xliff:g>\n\nDirección Wi‑Fi (BSSID)\n<xliff:g id="BSSID_1">%2$s</xliff:g>"</string>
<string name="wifi_debugging_always" msgid="2968383799517975155">"Permitir siempre en esta red"</string>
@@ -160,8 +159,7 @@
<string name="biometric_dialog_wrong_pattern" msgid="8954812279840889029">"Patrón incorrecto"</string>
<string name="biometric_dialog_wrong_password" msgid="69477929306843790">"Contraseña incorrecta"</string>
<string name="biometric_dialog_credential_too_many_attempts" msgid="3083141271737748716">"Demasiados intentos incorrectos.\nVuelve a intentarlo en <xliff:g id="NUMBER">%d</xliff:g> segundos."</string>
- <!-- no translation found for work_challenge_emergency_button_text (8946588434515599288) -->
- <skip />
+ <string name="work_challenge_emergency_button_text" msgid="8946588434515599288">"Emergencia"</string>
<string name="biometric_dialog_credential_attempts_before_wipe" msgid="6751859711975516999">"Vuelve a intentarlo. Intento <xliff:g id="ATTEMPTS_0">%1$d</xliff:g> de <xliff:g id="MAX_ATTEMPTS">%2$d</xliff:g>."</string>
<string name="biometric_dialog_last_attempt_before_wipe_dialog_title" msgid="2874250099278693477">"Se borrarán tus datos"</string>
<string name="biometric_dialog_last_pattern_attempt_before_wipe_device" msgid="6562299244825817598">"Si ingresas un patrón incorrecto en el próximo intento, se borrarán los datos de este dispositivo."</string>
@@ -415,8 +413,7 @@
<string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="8736391633234144237">"Cuando compartas, grabes o transmitas contenido, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> podrá acceder a todo lo que sea visible en la pantalla o que reproduzcas en el dispositivo. Por lo tanto, debes tener cuidado con contraseñas, detalles de pagos, mensajes, fotos, audios y videos."</string>
<string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="5211695779082563959">"Cuando compartas, grabes o transmitas una app, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> podrá acceder a todo el contenido que se muestre o que reproduzcas en ella. Por lo tanto, debes tener cuidado con contraseñas, detalles de pagos, mensajes, fotos, audios y videos."</string>
<string name="media_projection_entry_app_permission_dialog_continue" msgid="295463518195075840">"Iniciar"</string>
- <!-- no translation found for media_projection_entry_app_permission_dialog_single_app_disabled (8999903044874669995) -->
- <skip />
+ <string name="media_projection_entry_app_permission_dialog_single_app_disabled" msgid="8999903044874669995">"<xliff:g id="APP_NAME">%1$s</xliff:g> inhabilitó esta opción"</string>
<string name="media_projection_entry_cast_permission_dialog_title" msgid="8860150223172993547">"¿Quieres comenzar a transmitir contenido?"</string>
<string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="1986212276016817231">"Cuando transmitas contenido, Android podrá acceder a todo lo que sea visible en la pantalla o que reproduzcas en el dispositivo. Por lo tanto, debes tener cuidado con contraseñas, detalles de pagos, mensajes, fotos, audios y videos."</string>
<string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="9900961380294292">"Cuando transmitas una app, Android podrá acceder a todo el contenido que se muestre o que reproduzcas en ella. Por lo tanto, debes tener cuidado con contraseñas, detalles de pagos, mensajes, fotos, audios y videos."</string>
@@ -1173,6 +1170,10 @@
<string name="assistant_attention_content_description" msgid="6830215897604642875">"Asistente está prestando atención"</string>
<string name="set_default_notes_app_toast_content" msgid="2812374329662610753">"Configura la app de notas predeterminada en Configuración"</string>
<string name="install_app" msgid="5066668100199613936">"Instalar app"</string>
+ <!-- no translation found for connected_display_dialog_start_mirroring (6237895789920854982) -->
+ <skip />
+ <!-- no translation found for enable_display (8308309634883321977) -->
+ <skip />
<string name="privacy_dialog_title" msgid="7839968133469098311">"Micrófono y cámara"</string>
<string name="privacy_dialog_summary" msgid="2458769652125995409">"Uso reciente en apps"</string>
<string name="privacy_dialog_more_button" msgid="7610604080293562345">"Ver accesos recientes"</string>
diff --git a/packages/SystemUI/res/values-es/strings.xml b/packages/SystemUI/res/values-es/strings.xml
index c2a6b7122d0f..0680821c1729 100644
--- a/packages/SystemUI/res/values-es/strings.xml
+++ b/packages/SystemUI/res/values-es/strings.xml
@@ -57,8 +57,7 @@
<string name="hdmi_cec_set_menu_language_description" msgid="8176716678074126619">"Otro dispositivo ha solicitado un cambio en el idioma del sistema"</string>
<string name="hdmi_cec_set_menu_language_accept" msgid="2513689457281009578">"Cambiar idioma"</string>
<string name="hdmi_cec_set_menu_language_decline" msgid="7650721096558646011">"Seguir en este idioma"</string>
- <!-- no translation found for share_wifi_button_text (1285273973812029240) -->
- <skip />
+ <string name="share_wifi_button_text" msgid="1285273973812029240">"Compartir Wi-Fi"</string>
<string name="wifi_debugging_title" msgid="7300007687492186076">"¿Permitir la depuración inalámbrica en esta red?"</string>
<string name="wifi_debugging_message" msgid="5461204211731802995">"Nombre de la red (SSID)\n<xliff:g id="SSID_0">%1$s</xliff:g>\n\nDirección Wi‑Fi (BSSID)\n<xliff:g id="BSSID_1">%2$s</xliff:g>"</string>
<string name="wifi_debugging_always" msgid="2968383799517975155">"Permitir siempre en esta red"</string>
@@ -160,8 +159,7 @@
<string name="biometric_dialog_wrong_pattern" msgid="8954812279840889029">"Patrón incorrecto"</string>
<string name="biometric_dialog_wrong_password" msgid="69477929306843790">"Contraseña incorrecta"</string>
<string name="biometric_dialog_credential_too_many_attempts" msgid="3083141271737748716">"Demasiados intentos fallidos.\n Vuelve a intentarlo en <xliff:g id="NUMBER">%d</xliff:g> segundos."</string>
- <!-- no translation found for work_challenge_emergency_button_text (8946588434515599288) -->
- <skip />
+ <string name="work_challenge_emergency_button_text" msgid="8946588434515599288">"Emergencia"</string>
<string name="biometric_dialog_credential_attempts_before_wipe" msgid="6751859711975516999">"Vuelve a intentarlo. Intento <xliff:g id="ATTEMPTS_0">%1$d</xliff:g> de <xliff:g id="MAX_ATTEMPTS">%2$d</xliff:g>."</string>
<string name="biometric_dialog_last_attempt_before_wipe_dialog_title" msgid="2874250099278693477">"Tus datos se eliminarán"</string>
<string name="biometric_dialog_last_pattern_attempt_before_wipe_device" msgid="6562299244825817598">"Si vuelves a introducir un patrón incorrecto, los datos de este dispositivo se eliminarán."</string>
@@ -415,8 +413,7 @@
<string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="8736391633234144237">"Cuando compartes, grabas o envías contenido, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> puede acceder a todo lo que se muestre en la pantalla o se reproduzca en tu dispositivo. Debes tener cuidado con elementos como contraseñas, detalles de pagos, mensajes, fotos, audio y vídeo."</string>
<string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="5211695779082563959">"Cuando compartes, grabas o envías una aplicación, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> puede acceder a todo lo que se muestre o se reproduzca en ella. Debes tener cuidado con elementos como contraseñas, detalles de pagos, mensajes, fotos, audio y vídeo."</string>
<string name="media_projection_entry_app_permission_dialog_continue" msgid="295463518195075840">"Empezar"</string>
- <!-- no translation found for media_projection_entry_app_permission_dialog_single_app_disabled (8999903044874669995) -->
- <skip />
+ <string name="media_projection_entry_app_permission_dialog_single_app_disabled" msgid="8999903044874669995">"<xliff:g id="APP_NAME">%1$s</xliff:g> ha inhabilitado esta opción"</string>
<string name="media_projection_entry_cast_permission_dialog_title" msgid="8860150223172993547">"¿Empezar a enviar contenido?"</string>
<string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="1986212276016817231">"Cuando envías contenido, Android puede acceder a todo lo que se muestre en la pantalla o se reproduzca en tu dispositivo. Debes tener cuidado con elementos como contraseñas, detalles de pagos, mensajes, fotos, audio y vídeo."</string>
<string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="9900961380294292">"Cuando envías una aplicación, Android puede acceder a todo lo que se muestre o se reproduzca en ella. Debes tener cuidado con elementos como contraseñas, detalles de pagos, mensajes, fotos, audio y vídeo."</string>
@@ -1173,6 +1170,10 @@
<string name="assistant_attention_content_description" msgid="6830215897604642875">"El Asistente está activado"</string>
<string name="set_default_notes_app_toast_content" msgid="2812374329662610753">"Configura la aplicación de notas predeterminada en Ajustes"</string>
<string name="install_app" msgid="5066668100199613936">"Instalar aplicación"</string>
+ <!-- no translation found for connected_display_dialog_start_mirroring (6237895789920854982) -->
+ <skip />
+ <!-- no translation found for enable_display (8308309634883321977) -->
+ <skip />
<string name="privacy_dialog_title" msgid="7839968133469098311">"Micrófono y cámara"</string>
<string name="privacy_dialog_summary" msgid="2458769652125995409">"Uso reciente en aplicaciones"</string>
<string name="privacy_dialog_more_button" msgid="7610604080293562345">"Ver acceso reciente"</string>
diff --git a/packages/SystemUI/res/values-et/strings.xml b/packages/SystemUI/res/values-et/strings.xml
index 3817e78fa686..988d4d745494 100644
--- a/packages/SystemUI/res/values-et/strings.xml
+++ b/packages/SystemUI/res/values-et/strings.xml
@@ -57,8 +57,7 @@
<string name="hdmi_cec_set_menu_language_description" msgid="8176716678074126619">"Teine seade taotles süsteemi keele muutmist"</string>
<string name="hdmi_cec_set_menu_language_accept" msgid="2513689457281009578">"Muuda keelt"</string>
<string name="hdmi_cec_set_menu_language_decline" msgid="7650721096558646011">"Kasuta praegust keelt"</string>
- <!-- no translation found for share_wifi_button_text (1285273973812029240) -->
- <skip />
+ <string name="share_wifi_button_text" msgid="1285273973812029240">"WiFi jagamine"</string>
<string name="wifi_debugging_title" msgid="7300007687492186076">"Kas lubada selles võrgus juhtmevaba silumine?"</string>
<string name="wifi_debugging_message" msgid="5461204211731802995">"Võrgu nimi (SSID)\n<xliff:g id="SSID_0">%1$s</xliff:g>\n\nWiFi-võrgu aadress (BSSID)\n<xliff:g id="BSSID_1">%2$s</xliff:g>"</string>
<string name="wifi_debugging_always" msgid="2968383799517975155">"Luba selles võrgus alati"</string>
@@ -160,8 +159,7 @@
<string name="biometric_dialog_wrong_pattern" msgid="8954812279840889029">"Vale muster"</string>
<string name="biometric_dialog_wrong_password" msgid="69477929306843790">"Vale parool"</string>
<string name="biometric_dialog_credential_too_many_attempts" msgid="3083141271737748716">"Liiga palju valesid katseid.\nProovige <xliff:g id="NUMBER">%d</xliff:g> sekundi pärast uuesti."</string>
- <!-- no translation found for work_challenge_emergency_button_text (8946588434515599288) -->
- <skip />
+ <string name="work_challenge_emergency_button_text" msgid="8946588434515599288">"Hädaabi"</string>
<string name="biometric_dialog_credential_attempts_before_wipe" msgid="6751859711975516999">"Proovige uuesti. Katse <xliff:g id="ATTEMPTS_0">%1$d</xliff:g>/<xliff:g id="MAX_ATTEMPTS">%2$d</xliff:g>."</string>
<string name="biometric_dialog_last_attempt_before_wipe_dialog_title" msgid="2874250099278693477">"Teie andmed kustutatakse"</string>
<string name="biometric_dialog_last_pattern_attempt_before_wipe_device" msgid="6562299244825817598">"Kui sisestate järgmisel katsel vale mustri, kustutatakse selle seadme andmed."</string>
@@ -415,8 +413,7 @@
<string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="8736391633234144237">"Kui jagate, salvestate või kannate üle, on rakendusel <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> juurdepääs kõigele, mis on teie ekraanikuval nähtaval või mida teie seadmes esitatakse. Seega olge ettevaatlik selliste andmetega nagu paroolid, makseteave, sõnumid, fotod ning heli ja video."</string>
<string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="5211695779082563959">"Kui jagate, salvestate või kannate rakendust üle, on rakendusel <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> juurdepääs kõigele, mida selles rakenduses kuvatakse või esitatakse. Seega olge paroolide, makseteabe, sõnumite, fotode, heli ja videoga ettevaatlik."</string>
<string name="media_projection_entry_app_permission_dialog_continue" msgid="295463518195075840">"Alusta"</string>
- <!-- no translation found for media_projection_entry_app_permission_dialog_single_app_disabled (8999903044874669995) -->
- <skip />
+ <string name="media_projection_entry_app_permission_dialog_single_app_disabled" msgid="8999903044874669995">"<xliff:g id="APP_NAME">%1$s</xliff:g> on selle valiku keelanud"</string>
<string name="media_projection_entry_cast_permission_dialog_title" msgid="8860150223172993547">"Kas alustada ülekandmist?"</string>
<string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="1986212276016817231">"Kui kannate üle, on Androidil juurdepääs kõigele, mis on teie ekraanikuval nähtaval või mida teie seadmes esitatakse. Seega olge ettevaatlik selliste andmetega nagu paroolid, makseteave, sõnumid, fotod ning heli ja video."</string>
<string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="9900961380294292">"Rakenduse ülekandmise ajal on Androidil juurdepääs kõigele, mis on selles rakenduses nähtaval või mida selles esitatakse. Seega olge paroolide, makseteabe, sõnumite, fotode, heli ja videoga ettevaatlik."</string>
@@ -1173,6 +1170,10 @@
<string name="assistant_attention_content_description" msgid="6830215897604642875">"Assistent on aktiveeritud"</string>
<string name="set_default_notes_app_toast_content" msgid="2812374329662610753">"Määrake seadetes märkmete vaikerakendus."</string>
<string name="install_app" msgid="5066668100199613936">"Installi rakendus"</string>
+ <!-- no translation found for connected_display_dialog_start_mirroring (6237895789920854982) -->
+ <skip />
+ <!-- no translation found for enable_display (8308309634883321977) -->
+ <skip />
<string name="privacy_dialog_title" msgid="7839968133469098311">"Mikrofon ja kaamera"</string>
<string name="privacy_dialog_summary" msgid="2458769652125995409">"Rakenduste hiljutine kasutamine"</string>
<string name="privacy_dialog_more_button" msgid="7610604080293562345">"Kuva hiljutine juurdepääs"</string>
diff --git a/packages/SystemUI/res/values-eu/strings.xml b/packages/SystemUI/res/values-eu/strings.xml
index 2ad43cc86ddd..71cb074dc599 100644
--- a/packages/SystemUI/res/values-eu/strings.xml
+++ b/packages/SystemUI/res/values-eu/strings.xml
@@ -57,8 +57,7 @@
<string name="hdmi_cec_set_menu_language_description" msgid="8176716678074126619">"Beste gailu batek sistemaren hizkuntza aldatzeko eskatu du"</string>
<string name="hdmi_cec_set_menu_language_accept" msgid="2513689457281009578">"Aldatu hizkuntza"</string>
<string name="hdmi_cec_set_menu_language_decline" msgid="7650721096558646011">"Mantendu oraingo hizkuntza"</string>
- <!-- no translation found for share_wifi_button_text (1285273973812029240) -->
- <skip />
+ <string name="share_wifi_button_text" msgid="1285273973812029240">"Partekatu wifia"</string>
<string name="wifi_debugging_title" msgid="7300007687492186076">"Hari gabeko arazketa sare honetan erabiltzeko baimena eman nahi duzu?"</string>
<string name="wifi_debugging_message" msgid="5461204211731802995">"Sarearen izena (SSID)\n<xliff:g id="SSID_0">%1$s</xliff:g>\n\nWifi-helbidea (BSSID)\n<xliff:g id="BSSID_1">%2$s</xliff:g>"</string>
<string name="wifi_debugging_always" msgid="2968383799517975155">"Eman baimena beti sare honetan"</string>
@@ -160,8 +159,7 @@
<string name="biometric_dialog_wrong_pattern" msgid="8954812279840889029">"Eredua ez da zuzena"</string>
<string name="biometric_dialog_wrong_password" msgid="69477929306843790">"Pasahitza ez da zuzena"</string>
<string name="biometric_dialog_credential_too_many_attempts" msgid="3083141271737748716">"Saiakera oker gehiegi egin dituzu.\nSaiatu berriro <xliff:g id="NUMBER">%d</xliff:g> segundo barru."</string>
- <!-- no translation found for work_challenge_emergency_button_text (8946588434515599288) -->
- <skip />
+ <string name="work_challenge_emergency_button_text" msgid="8946588434515599288">"Larrialdi-deia"</string>
<string name="biometric_dialog_credential_attempts_before_wipe" msgid="6751859711975516999">"Saiatu berriro. <xliff:g id="ATTEMPTS_0">%1$d</xliff:g>/<xliff:g id="MAX_ATTEMPTS">%2$d</xliff:g> saiakera."</string>
<string name="biometric_dialog_last_attempt_before_wipe_dialog_title" msgid="2874250099278693477">"Datuak ezabatuko dira"</string>
<string name="biometric_dialog_last_pattern_attempt_before_wipe_device" msgid="6562299244825817598">"Hurrengo saiakeran eredua oker marrazten baduzu, gailuko datuak ezabatuko dira."</string>
@@ -415,8 +413,7 @@
<string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="8736391633234144237">"Edukia partekatzen, grabatzen edo igortzen ari zarenean, pantailan ikusgai dagoen edo gailuan erreproduzitzen ari den guztia atzi dezake <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> aplikazioak. Beraz, kontuz ibili pasahitzekin, ordainketen xehetasunekin, mezuekin, argazkiekin, audioekin eta bideoekin, besteak beste."</string>
<string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="5211695779082563959">"Aplikazio bat partekatzen, grabatzen edo igortzen ari zarenean, aplikazio horretan ikusgai dagoen edo bertan erreproduzitzen ari den guztia atzi dezake <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> aplikazioak. Beraz, kontuz ibili pasahitzekin, ordainketen xehetasunekin, mezuekin, argazkiekin, audioekin eta bideoekin, besteak beste."</string>
<string name="media_projection_entry_app_permission_dialog_continue" msgid="295463518195075840">"Hasi"</string>
- <!-- no translation found for media_projection_entry_app_permission_dialog_single_app_disabled (8999903044874669995) -->
- <skip />
+ <string name="media_projection_entry_app_permission_dialog_single_app_disabled" msgid="8999903044874669995">"<xliff:g id="APP_NAME">%1$s</xliff:g> aplikazioak aukera desgaitu du"</string>
<string name="media_projection_entry_cast_permission_dialog_title" msgid="8860150223172993547">"Igortzen hasi nahi duzu?"</string>
<string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="1986212276016817231">"Edukia igortzen ari zarenean, pantailan ikusgai dagoen edo gailuan erreproduzitzen ari den guztia atzi dezake Android-ek. Beraz, kontuz ibili pasahitzekin, ordainketen xehetasunekin, mezuekin, argazkiekin, audioekin eta bideoekin, besteak beste."</string>
<string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="9900961380294292">"Aplikazio bat igortzen ari zarenean, aplikazio horretan ikusgai dagoen edo bertan erreproduzitzen ari den guztia atzi dezake Android-ek. Beraz, kontuz ibili pasahitzekin, ordainketen xehetasunekin, mezuekin, argazkiekin, audioekin eta bideoekin, besteak beste."</string>
@@ -1173,6 +1170,10 @@
<string name="assistant_attention_content_description" msgid="6830215897604642875">"Laguntzailea zerbitzuak arreta jarrita dauka"</string>
<string name="set_default_notes_app_toast_content" msgid="2812374329662610753">"Ezarri oharren aplikazio lehenetsia ezarpenetan"</string>
<string name="install_app" msgid="5066668100199613936">"Instalatu aplikazioa"</string>
+ <!-- no translation found for connected_display_dialog_start_mirroring (6237895789920854982) -->
+ <skip />
+ <!-- no translation found for enable_display (8308309634883321977) -->
+ <skip />
<string name="privacy_dialog_title" msgid="7839968133469098311">"Mikrofonoa eta kamera"</string>
<string name="privacy_dialog_summary" msgid="2458769652125995409">"Aplikazioen azken erabilera"</string>
<string name="privacy_dialog_more_button" msgid="7610604080293562345">"Ikusi azkenaldiko sarbidea"</string>
diff --git a/packages/SystemUI/res/values-fa/strings.xml b/packages/SystemUI/res/values-fa/strings.xml
index 8263639a4fc1..8902103c4399 100644
--- a/packages/SystemUI/res/values-fa/strings.xml
+++ b/packages/SystemUI/res/values-fa/strings.xml
@@ -57,8 +57,7 @@
<string name="hdmi_cec_set_menu_language_description" msgid="8176716678074126619">"دستگاه دیگری درخواست کرده است زبان سیستم تغییر کند"</string>
<string name="hdmi_cec_set_menu_language_accept" msgid="2513689457281009578">"تغییر زبان"</string>
<string name="hdmi_cec_set_menu_language_decline" msgid="7650721096558646011">"حفظ زبان فعلی"</string>
- <!-- no translation found for share_wifi_button_text (1285273973812029240) -->
- <skip />
+ <string name="share_wifi_button_text" msgid="1285273973812029240">"‏اشتراک‌گذاری Wi‑Fi"</string>
<string name="wifi_debugging_title" msgid="7300007687492186076">"اشکال‌زدایی بی‌سیم در این شبکه مجاز شود؟"</string>
<string name="wifi_debugging_message" msgid="5461204211731802995">"‏نام شبکه (SSID)\n<xliff:g id="SSID_0">%1$s</xliff:g>\n\nنشانی Wi‑Fi (BSSID)‎\n<xliff:g id="BSSID_1">%2$s</xliff:g>"</string>
<string name="wifi_debugging_always" msgid="2968383799517975155">"همیشه در این شبکه مجاز شود"</string>
@@ -160,8 +159,7 @@
<string name="biometric_dialog_wrong_pattern" msgid="8954812279840889029">"الگو اشتباه است"</string>
<string name="biometric_dialog_wrong_password" msgid="69477929306843790">"گذرواژه اشتباه است"</string>
<string name="biometric_dialog_credential_too_many_attempts" msgid="3083141271737748716">"تلاش‌های نادرست بسیاری انجام شده است.\nپس از <xliff:g id="NUMBER">%d</xliff:g> ثانیه دوباره امتحان کنید."</string>
- <!-- no translation found for work_challenge_emergency_button_text (8946588434515599288) -->
- <skip />
+ <string name="work_challenge_emergency_button_text" msgid="8946588434515599288">"اضطراری"</string>
<string name="biometric_dialog_credential_attempts_before_wipe" msgid="6751859711975516999">"دوباره امتحان کنید. تلاش <xliff:g id="ATTEMPTS_0">%1$d</xliff:g> از <xliff:g id="MAX_ATTEMPTS">%2$d</xliff:g>."</string>
<string name="biometric_dialog_last_attempt_before_wipe_dialog_title" msgid="2874250099278693477">"داده‌هایتان حذف خواهد شد"</string>
<string name="biometric_dialog_last_pattern_attempt_before_wipe_device" msgid="6562299244825817598">"اگر در تلاش بعدی الگوی نادرستی وارد کنید، داده‌های این دستگاه حذف خواهد شد."</string>
@@ -415,8 +413,7 @@
<string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="8736391633234144237">"وقتی درحال هم‌رسانی، ضبط، یا پخش محتوا هستید، <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> به همه محتوایی که در صفحه‌تان نمایان است یا در دستگاهتان پخش می‌شود دسترسی دارد. درنتیجه مراقب چیزهایی مثل گذرواژه‌ها، جزئیات پرداخت، پیام‌ها، عکس‌ها، و صدا و تصویر باشید."</string>
<string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="5211695779082563959">"وقتی درحال هم‌رسانی، ضبط، یا پخش محتوای برنامه‌ای هستید، <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> به همه محتوایی که در آن برنامه نمایان است یا پخش می‌شود دسترسی دارد. درنتیجه مراقب چیزهایی مثل گذرواژه‌ها، جزئیات پرداخت، پیام‌ها، عکس‌ها، و صدا و تصویر باشید."</string>
<string name="media_projection_entry_app_permission_dialog_continue" msgid="295463518195075840">"شروع"</string>
- <!-- no translation found for media_projection_entry_app_permission_dialog_single_app_disabled (8999903044874669995) -->
- <skip />
+ <string name="media_projection_entry_app_permission_dialog_single_app_disabled" msgid="8999903044874669995">"<xliff:g id="APP_NAME">%1$s</xliff:g>این گزینه را غیرفعال کرده است"</string>
<string name="media_projection_entry_cast_permission_dialog_title" msgid="8860150223172993547">"پخش محتوا شروع شود؟"</string>
<string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="1986212276016817231">"‏وقتی محتوا پخش می‌کنید، Android به همه محتوایی که در صفحه‌تان نمایان است یا در دستگاهتان پخش می‌شود دسترسی دارد. درنتیجه مراقب چیزهایی مثل گذرواژه‌ها، جزئیات پرداخت، پیام‌ها، عکس‌ها، و صدا و تصویر باشید."</string>
<string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="9900961380294292">"‏وقتی محتوای برنامه‌ای را پخش می‌کنید، Android به همه محتوایی که در آن برنامه نمایان است یا پخش می‌شود دسترسی دارد. درنتیجه مراقب چیزهایی مثل گذرواژه‌ها، جزئیات پرداخت، پیام‌ها، عکس‌ها، و صدا و تصویر باشید."</string>
@@ -1173,6 +1170,10 @@
<string name="assistant_attention_content_description" msgid="6830215897604642875">"توجه «دستیار» روشن است"</string>
<string name="set_default_notes_app_toast_content" msgid="2812374329662610753">"برنامه پیش‌فرض یادداشت را در «تنظیمات» تنظیم کنید"</string>
<string name="install_app" msgid="5066668100199613936">"نصب برنامه"</string>
+ <!-- no translation found for connected_display_dialog_start_mirroring (6237895789920854982) -->
+ <skip />
+ <!-- no translation found for enable_display (8308309634883321977) -->
+ <skip />
<string name="privacy_dialog_title" msgid="7839968133469098311">"میکروفون و دوربین"</string>
<string name="privacy_dialog_summary" msgid="2458769652125995409">"استفاده اخیر از برنامه"</string>
<string name="privacy_dialog_more_button" msgid="7610604080293562345">"دیدن دسترسی اخیر"</string>
diff --git a/packages/SystemUI/res/values-fi/strings.xml b/packages/SystemUI/res/values-fi/strings.xml
index dc0e52de6217..7e2ab650f037 100644
--- a/packages/SystemUI/res/values-fi/strings.xml
+++ b/packages/SystemUI/res/values-fi/strings.xml
@@ -57,8 +57,7 @@
<string name="hdmi_cec_set_menu_language_description" msgid="8176716678074126619">"Toiselta laitteelta pyydetty järjestelmän kielen vaihtamista"</string>
<string name="hdmi_cec_set_menu_language_accept" msgid="2513689457281009578">"Vaihda kieltä"</string>
<string name="hdmi_cec_set_menu_language_decline" msgid="7650721096558646011">"Pidä nykyinen kieli"</string>
- <!-- no translation found for share_wifi_button_text (1285273973812029240) -->
- <skip />
+ <string name="share_wifi_button_text" msgid="1285273973812029240">"Jaa Wi‑Fi"</string>
<string name="wifi_debugging_title" msgid="7300007687492186076">"Sallitaanko langaton virheenkorjaus tässä verkossa?"</string>
<string name="wifi_debugging_message" msgid="5461204211731802995">"Verkon nimi (SSID)\n<xliff:g id="SSID_0">%1$s</xliff:g>\n\nWi-Fin osoite (BSSID)\n<xliff:g id="BSSID_1">%2$s</xliff:g>"</string>
<string name="wifi_debugging_always" msgid="2968383799517975155">"Salli aina tässä verkossa"</string>
@@ -160,8 +159,7 @@
<string name="biometric_dialog_wrong_pattern" msgid="8954812279840889029">"Väärä kuvio"</string>
<string name="biometric_dialog_wrong_password" msgid="69477929306843790">"Väärä salasana"</string>
<string name="biometric_dialog_credential_too_many_attempts" msgid="3083141271737748716">"Liian monta virheellistä yritystä.\nYritä uudelleen <xliff:g id="NUMBER">%d</xliff:g> sekunnin kuluttua."</string>
- <!-- no translation found for work_challenge_emergency_button_text (8946588434515599288) -->
- <skip />
+ <string name="work_challenge_emergency_button_text" msgid="8946588434515599288">"Hätätilanne"</string>
<string name="biometric_dialog_credential_attempts_before_wipe" msgid="6751859711975516999">"Yritä uudelleen. Yritys <xliff:g id="ATTEMPTS_0">%1$d</xliff:g>/<xliff:g id="MAX_ATTEMPTS">%2$d</xliff:g>."</string>
<string name="biometric_dialog_last_attempt_before_wipe_dialog_title" msgid="2874250099278693477">"Datasi poistetaan"</string>
<string name="biometric_dialog_last_pattern_attempt_before_wipe_device" msgid="6562299244825817598">"Jos annat väärän kuvion seuraavalla yrityskerralla, tämän laitteen data poistetaan."</string>
@@ -415,8 +413,7 @@
<string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="8736391633234144237">"Kun jaat, tallennat tai striimaat, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> saa pääsyn kaikkeen näytölläsi näkyvään tai laitteellasi toistettuun sisältöön. Ole siis varovainen, kun lisäät salasanoja, maksutietoja, viestejä, kuvia, audiota tai videoita."</string>
<string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="5211695779082563959">"Kun jaat, tallennat tai striimaat sovellusta, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> saa pääsyn kaikkeen sovelluksessa näkyvään tai toistettuun sisältöön. Ole siis varovainen, kun lisäät salasanoja, maksutietoja, viestejä, kuvia, audiota tai videoita."</string>
<string name="media_projection_entry_app_permission_dialog_continue" msgid="295463518195075840">"Aloita"</string>
- <!-- no translation found for media_projection_entry_app_permission_dialog_single_app_disabled (8999903044874669995) -->
- <skip />
+ <string name="media_projection_entry_app_permission_dialog_single_app_disabled" msgid="8999903044874669995">"<xliff:g id="APP_NAME">%1$s</xliff:g> on poistanut vaihtoehdon käytöstä"</string>
<string name="media_projection_entry_cast_permission_dialog_title" msgid="8860150223172993547">"Aloitetaanko striimaus?"</string>
<string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="1986212276016817231">"Kun striimaat, Android saa pääsyn kaikkeen näytölläsi näkyvään tai laitteellasi toistettuun sisältöön. Ole siis varovainen, kun lisäät salasanoja, maksutietoja, viestejä, kuvia, audiota tai videoita."</string>
<string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="9900961380294292">"Kun striimaat sovellusta, Android saa pääsyn kaikkeen sovelluksessa näkyvään tai toistettuun sisältöön. Ole siis varovainen, kun lisäät salasanoja, maksutietoja, viestejä, kuvia, audiota tai videoita."</string>
@@ -1173,6 +1170,10 @@
<string name="assistant_attention_content_description" msgid="6830215897604642875">"Assistant on aktiivinen"</string>
<string name="set_default_notes_app_toast_content" msgid="2812374329662610753">"Aseta oletusmuistiinpanosovellus Asetuksista"</string>
<string name="install_app" msgid="5066668100199613936">"Asenna sovellus"</string>
+ <!-- no translation found for connected_display_dialog_start_mirroring (6237895789920854982) -->
+ <skip />
+ <!-- no translation found for enable_display (8308309634883321977) -->
+ <skip />
<string name="privacy_dialog_title" msgid="7839968133469098311">"Mikrofoni ja kamera"</string>
<string name="privacy_dialog_summary" msgid="2458769652125995409">"Sovellusten viimeaikainen käyttö"</string>
<string name="privacy_dialog_more_button" msgid="7610604080293562345">"Katso viimeaikainen käyttö"</string>
diff --git a/packages/SystemUI/res/values-fr-rCA/strings.xml b/packages/SystemUI/res/values-fr-rCA/strings.xml
index dcaaef0c5b53..a863623df8d1 100644
--- a/packages/SystemUI/res/values-fr-rCA/strings.xml
+++ b/packages/SystemUI/res/values-fr-rCA/strings.xml
@@ -57,8 +57,7 @@
<string name="hdmi_cec_set_menu_language_description" msgid="8176716678074126619">"Un autre appareil demande de changer la langue du système"</string>
<string name="hdmi_cec_set_menu_language_accept" msgid="2513689457281009578">"Changer la langue"</string>
<string name="hdmi_cec_set_menu_language_decline" msgid="7650721096558646011">"Garder la langue actuelle"</string>
- <!-- no translation found for share_wifi_button_text (1285273973812029240) -->
- <skip />
+ <string name="share_wifi_button_text" msgid="1285273973812029240">"Partager le Wi‑Fi"</string>
<string name="wifi_debugging_title" msgid="7300007687492186076">"Autoriser le débogage sans fil sur ce réseau?"</string>
<string name="wifi_debugging_message" msgid="5461204211731802995">"Nom du réseau (SSID)\n<xliff:g id="SSID_0">%1$s</xliff:g>\n\nAdresse Wi‑Fi (BSSID)\n<xliff:g id="BSSID_1">%2$s</xliff:g>"</string>
<string name="wifi_debugging_always" msgid="2968383799517975155">"Toujours autoriser sur ce réseau"</string>
@@ -160,8 +159,7 @@
<string name="biometric_dialog_wrong_pattern" msgid="8954812279840889029">"Schéma incorrect"</string>
<string name="biometric_dialog_wrong_password" msgid="69477929306843790">"Mot de passe incorrect"</string>
<string name="biometric_dialog_credential_too_many_attempts" msgid="3083141271737748716">"Trop de tentatives incorrectes. \nRéessayez dans <xliff:g id="NUMBER">%d</xliff:g> secondes."</string>
- <!-- no translation found for work_challenge_emergency_button_text (8946588434515599288) -->
- <skip />
+ <string name="work_challenge_emergency_button_text" msgid="8946588434515599288">"Appel d\'urgence"</string>
<string name="biometric_dialog_credential_attempts_before_wipe" msgid="6751859711975516999">"Réessayez. Tentative <xliff:g id="ATTEMPTS_0">%1$d</xliff:g> sur <xliff:g id="MAX_ATTEMPTS">%2$d</xliff:g>."</string>
<string name="biometric_dialog_last_attempt_before_wipe_dialog_title" msgid="2874250099278693477">"Vos données seront supprimées"</string>
<string name="biometric_dialog_last_pattern_attempt_before_wipe_device" msgid="6562299244825817598">"Si vous entrez un schéma incorrect à la prochaine tentative, les données de cet appareil seront supprimées."</string>
@@ -415,8 +413,7 @@
<string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="8736391633234144237">"Lorsque vous partagez, enregistrez ou diffusez, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> a accès à tout ce qui est visible sur votre écran ou lu sur votre appareil. Par conséquent, soyez prudent avec les mots de passe, les détails du paiement, les messages, les photos et les contenus audio et vidéo."</string>
<string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="5211695779082563959">"Lorsque vous partagez, enregistrez ou diffusez une application, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> a accès à tout ce qui est visible sur votre écran ou lu sur cette application. Par conséquent, soyez prudent avec les mots de passe, les détails du paiement, les messages, les photos et les contenus audio et vidéo."</string>
<string name="media_projection_entry_app_permission_dialog_continue" msgid="295463518195075840">"Commencer"</string>
- <!-- no translation found for media_projection_entry_app_permission_dialog_single_app_disabled (8999903044874669995) -->
- <skip />
+ <string name="media_projection_entry_app_permission_dialog_single_app_disabled" msgid="8999903044874669995">"<xliff:g id="APP_NAME">%1$s</xliff:g> a désactivé cette option"</string>
<string name="media_projection_entry_cast_permission_dialog_title" msgid="8860150223172993547">"Commencer la diffusion?"</string>
<string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="1986212276016817231">"Lorsque vous diffusez, Android a accès à tout ce qui est visible sur votre écran ou lu sur votre appareil. Par conséquent, soyez prudent avec les mots de passe, les détails du paiement, les messages, les photos et les contenus audio et vidéo."</string>
<string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="9900961380294292">"Lorsque vous diffusez une application, Android a accès à tout ce qui est visible sur votre écran ou lu sur cette application. Par conséquent, soyez prudent avec les mots de passe, les détails du paiement, les messages, les photos et les contenus audio et vidéo."</string>
@@ -1173,6 +1170,10 @@
<string name="assistant_attention_content_description" msgid="6830215897604642875">"Assistant à l\'écoute"</string>
<string name="set_default_notes_app_toast_content" msgid="2812374329662610753">"Définir l\'application de prise de notes par défaut dans les Paramètres"</string>
<string name="install_app" msgid="5066668100199613936">"Installer l\'application"</string>
+ <!-- no translation found for connected_display_dialog_start_mirroring (6237895789920854982) -->
+ <skip />
+ <!-- no translation found for enable_display (8308309634883321977) -->
+ <skip />
<string name="privacy_dialog_title" msgid="7839968133469098311">"Microphone et appareil photo"</string>
<string name="privacy_dialog_summary" msgid="2458769652125995409">"Utilisation récente par les applications"</string>
<string name="privacy_dialog_more_button" msgid="7610604080293562345">"Afficher l\'accès récent"</string>
diff --git a/packages/SystemUI/res/values-fr/strings.xml b/packages/SystemUI/res/values-fr/strings.xml
index 0fbf014e57c3..a3920de7bf9e 100644
--- a/packages/SystemUI/res/values-fr/strings.xml
+++ b/packages/SystemUI/res/values-fr/strings.xml
@@ -57,8 +57,7 @@
<string name="hdmi_cec_set_menu_language_description" msgid="8176716678074126619">"Changement de langue système demandé par un autre appareil"</string>
<string name="hdmi_cec_set_menu_language_accept" msgid="2513689457281009578">"Changer de langue"</string>
<string name="hdmi_cec_set_menu_language_decline" msgid="7650721096558646011">"Garder la langue actuelle"</string>
- <!-- no translation found for share_wifi_button_text (1285273973812029240) -->
- <skip />
+ <string name="share_wifi_button_text" msgid="1285273973812029240">"Partager le Wi‑Fi"</string>
<string name="wifi_debugging_title" msgid="7300007687492186076">"Autoriser le débogage sans fil sur ce réseau ?"</string>
<string name="wifi_debugging_message" msgid="5461204211731802995">"Nom du réseau (SSID)\n<xliff:g id="SSID_0">%1$s</xliff:g>\n\nAdresse Wi‑Fi (BSSID)\n<xliff:g id="BSSID_1">%2$s</xliff:g>"</string>
<string name="wifi_debugging_always" msgid="2968383799517975155">"Toujours autoriser sur ce réseau"</string>
@@ -160,8 +159,7 @@
<string name="biometric_dialog_wrong_pattern" msgid="8954812279840889029">"Schéma incorrect"</string>
<string name="biometric_dialog_wrong_password" msgid="69477929306843790">"Mot de passe incorrect"</string>
<string name="biometric_dialog_credential_too_many_attempts" msgid="3083141271737748716">"Trop de tentatives incorrectes.\nVeuillez réessayer dans <xliff:g id="NUMBER">%d</xliff:g> secondes."</string>
- <!-- no translation found for work_challenge_emergency_button_text (8946588434515599288) -->
- <skip />
+ <string name="work_challenge_emergency_button_text" msgid="8946588434515599288">"Urgence"</string>
<string name="biometric_dialog_credential_attempts_before_wipe" msgid="6751859711975516999">"Réessayez. Tentative <xliff:g id="ATTEMPTS_0">%1$d</xliff:g> sur <xliff:g id="MAX_ATTEMPTS">%2$d</xliff:g>."</string>
<string name="biometric_dialog_last_attempt_before_wipe_dialog_title" msgid="2874250099278693477">"Risque de perte des données"</string>
<string name="biometric_dialog_last_pattern_attempt_before_wipe_device" msgid="6562299244825817598">"Si vous dessinez un schéma incorrect lors de la prochaine tentative, les données de cet appareil seront supprimées."</string>
@@ -415,8 +413,7 @@
<string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="8736391633234144237">"Lorsque vous partagez, enregistrez ou castez, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> a accès à tout ce qui est visible sur votre écran ou lu sur votre appareil. Faites donc attention aux éléments tels que les mots de passe, détails de mode de paiement, messages, photos et contenus audio et vidéo."</string>
<string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="5211695779082563959">"Lorsque vous partagez, enregistrez ou castez une appli, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> a accès à tout ce qui est visible sur votre écran ou lu sur votre appareil. Faites donc attention aux éléments tels que les mots de passe, détails de mode de paiement, messages et contenus audio et vidéo."</string>
<string name="media_projection_entry_app_permission_dialog_continue" msgid="295463518195075840">"Commencer"</string>
- <!-- no translation found for media_projection_entry_app_permission_dialog_single_app_disabled (8999903044874669995) -->
- <skip />
+ <string name="media_projection_entry_app_permission_dialog_single_app_disabled" msgid="8999903044874669995">"<xliff:g id="APP_NAME">%1$s</xliff:g> a désactivé cette option"</string>
<string name="media_projection_entry_cast_permission_dialog_title" msgid="8860150223172993547">"Commencer à caster ?"</string>
<string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="1986212276016817231">"Lorsque vous castez, Android a accès à tout ce qui est visible sur votre écran ou lu sur votre appareil. Faites donc attention aux éléments tels que les mots de passe, détails de mode de paiement, messages, photos et contenus audio et vidéo."</string>
<string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="9900961380294292">"Lorsque vous castez une appli, Android a accès à tout ce qui est visible sur votre écran ou lu sur votre appareil. Faites donc attention aux éléments tels que les mots de passe, détails de mode de paiement, messages et contenus audio et vidéo."</string>
@@ -1173,6 +1170,10 @@
<string name="assistant_attention_content_description" msgid="6830215897604642875">"Assistant à l\'écoute"</string>
<string name="set_default_notes_app_toast_content" msgid="2812374329662610753">"Définir une appli de notes par défaut dans les paramètres"</string>
<string name="install_app" msgid="5066668100199613936">"Installer l\'appli"</string>
+ <!-- no translation found for connected_display_dialog_start_mirroring (6237895789920854982) -->
+ <skip />
+ <!-- no translation found for enable_display (8308309634883321977) -->
+ <skip />
<string name="privacy_dialog_title" msgid="7839968133469098311">"Micro et caméra"</string>
<string name="privacy_dialog_summary" msgid="2458769652125995409">"Utilisation récente par les applis"</string>
<string name="privacy_dialog_more_button" msgid="7610604080293562345">"Consulter les accès récents"</string>
diff --git a/packages/SystemUI/res/values-gl/strings.xml b/packages/SystemUI/res/values-gl/strings.xml
index 27b57e419aa8..344c0d4191f6 100644
--- a/packages/SystemUI/res/values-gl/strings.xml
+++ b/packages/SystemUI/res/values-gl/strings.xml
@@ -57,8 +57,7 @@
<string name="hdmi_cec_set_menu_language_description" msgid="8176716678074126619">"Outro dispositivo solicitou un cambio do idioma do sistema"</string>
<string name="hdmi_cec_set_menu_language_accept" msgid="2513689457281009578">"Cambiar idioma"</string>
<string name="hdmi_cec_set_menu_language_decline" msgid="7650721096558646011">"Manter idioma actual"</string>
- <!-- no translation found for share_wifi_button_text (1285273973812029240) -->
- <skip />
+ <string name="share_wifi_button_text" msgid="1285273973812029240">"Compartir wifi"</string>
<string name="wifi_debugging_title" msgid="7300007687492186076">"Queres permitir a depuración sen fíos nesta rede?"</string>
<string name="wifi_debugging_message" msgid="5461204211731802995">"Nome de rede (SSID)\n<xliff:g id="SSID_0">%1$s</xliff:g>\n\nEnderezo wifi (BSSID)\n<xliff:g id="BSSID_1">%2$s</xliff:g>"</string>
<string name="wifi_debugging_always" msgid="2968383799517975155">"Permitir sempre nesta rede"</string>
@@ -160,8 +159,7 @@
<string name="biometric_dialog_wrong_pattern" msgid="8954812279840889029">"O padrón é incorrecto"</string>
<string name="biometric_dialog_wrong_password" msgid="69477929306843790">"O contrasinal é incorrecto"</string>
<string name="biometric_dialog_credential_too_many_attempts" msgid="3083141271737748716">"Realizáronse demasiados intentos incorrectos.\nTéntao de novo en <xliff:g id="NUMBER">%d</xliff:g> segundos."</string>
- <!-- no translation found for work_challenge_emergency_button_text (8946588434515599288) -->
- <skip />
+ <string name="work_challenge_emergency_button_text" msgid="8946588434515599288">"Emerxencia"</string>
<string name="biometric_dialog_credential_attempts_before_wipe" msgid="6751859711975516999">"Téntao de novo. Intento <xliff:g id="ATTEMPTS_0">%1$d</xliff:g> de <xliff:g id="MAX_ATTEMPTS">%2$d</xliff:g>."</string>
<string name="biometric_dialog_last_attempt_before_wipe_dialog_title" msgid="2874250099278693477">"Eliminaranse os teus datos"</string>
<string name="biometric_dialog_last_pattern_attempt_before_wipe_device" msgid="6562299244825817598">"Se indicas un padrón incorrecto no seguinte intento, eliminaranse os datos deste dispositivo."</string>
@@ -415,8 +413,7 @@
<string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="8736391633234144237">"Cando compartes, gravas ou emites contido, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> ten acceso a todo o que se vexa na pantalla ou se reproduza no teu dispositivo. Polo tanto, debes ter coidado con determinada información, como os contrasinais, os detalles de pago, as mensaxes e as fotos, así como o contido de audio e de vídeo."</string>
<string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="5211695779082563959">"Cando compartes, gravas ou emites unha aplicación, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> ten acceso a todo o que se vexa ou se reproduza nela. Polo tanto, debes ter coidado con determinada información, como os contrasinais, os detalles de pago, as mensaxes e as fotos, así como o contido de audio e de vídeo."</string>
<string name="media_projection_entry_app_permission_dialog_continue" msgid="295463518195075840">"Iniciar"</string>
- <!-- no translation found for media_projection_entry_app_permission_dialog_single_app_disabled (8999903044874669995) -->
- <skip />
+ <string name="media_projection_entry_app_permission_dialog_single_app_disabled" msgid="8999903044874669995">"<xliff:g id="APP_NAME">%1$s</xliff:g> desactivou esta opción"</string>
<string name="media_projection_entry_cast_permission_dialog_title" msgid="8860150223172993547">"Queres comezar a emitir contido?"</string>
<string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="1986212276016817231">"Cando emites contido, Android ten acceso a todo o que se vexa na pantalla ou se reproduza no teu dispositivo. Polo tanto, debes ter coidado con determinada información, como os contrasinais, os detalles de pago, as mensaxes e as fotos, así como o contido de audio e de vídeo."</string>
<string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="9900961380294292">"Cando emites unha aplicación, Android ten acceso a todo o que se vexa ou se reproduza nela. Polo tanto, debes ter coidado con determinada información, como os contrasinais, os detalles de pago, as mensaxes e as fotos, así como o contido de audio e de vídeo."</string>
@@ -1173,6 +1170,10 @@
<string name="assistant_attention_content_description" msgid="6830215897604642875">"A atención do Asistente está activada"</string>
<string name="set_default_notes_app_toast_content" msgid="2812374329662610753">"Establece a aplicación de notas predeterminada en Configuración"</string>
<string name="install_app" msgid="5066668100199613936">"Instalar aplicación"</string>
+ <!-- no translation found for connected_display_dialog_start_mirroring (6237895789920854982) -->
+ <skip />
+ <!-- no translation found for enable_display (8308309634883321977) -->
+ <skip />
<string name="privacy_dialog_title" msgid="7839968133469098311">"Micrófono e cámara"</string>
<string name="privacy_dialog_summary" msgid="2458769652125995409">"Uso recente por parte de aplicacións"</string>
<string name="privacy_dialog_more_button" msgid="7610604080293562345">"Ver acceso recente"</string>
diff --git a/packages/SystemUI/res/values-gu/strings.xml b/packages/SystemUI/res/values-gu/strings.xml
index d62fd9986575..a32c78fce8bb 100644
--- a/packages/SystemUI/res/values-gu/strings.xml
+++ b/packages/SystemUI/res/values-gu/strings.xml
@@ -57,8 +57,7 @@
<string name="hdmi_cec_set_menu_language_description" msgid="8176716678074126619">"બીજા ડિવાઇસ દ્વારા સિસ્ટમની ભાષા બદલવાની વિનંતી કરવામાં આવી છે"</string>
<string name="hdmi_cec_set_menu_language_accept" msgid="2513689457281009578">"ભાષા બદલો"</string>
<string name="hdmi_cec_set_menu_language_decline" msgid="7650721096558646011">"વર્તમાન ભાષા રાખો"</string>
- <!-- no translation found for share_wifi_button_text (1285273973812029240) -->
- <skip />
+ <string name="share_wifi_button_text" msgid="1285273973812029240">"વાઇ-ફાઇ શેર કરો"</string>
<string name="wifi_debugging_title" msgid="7300007687492186076">"આ નેટવર્ક પર વાયરલેસ ડિબગીંગની મંજૂરી આપીએ?"</string>
<string name="wifi_debugging_message" msgid="5461204211731802995">"નેટવર્કનું નામ (SSID)\n<xliff:g id="SSID_0">%1$s</xliff:g>\n\nવાઇ-ફાઇ ઍડ્રેસ (BSSID)\n<xliff:g id="BSSID_1">%2$s</xliff:g>"</string>
<string name="wifi_debugging_always" msgid="2968383799517975155">"આ નેટવર્ક પર હંમેશા મંજૂરી આપો"</string>
@@ -160,8 +159,7 @@
<string name="biometric_dialog_wrong_pattern" msgid="8954812279840889029">"ખોટી પૅટર્ન"</string>
<string name="biometric_dialog_wrong_password" msgid="69477929306843790">"ખોટો પાસવર્ડ"</string>
<string name="biometric_dialog_credential_too_many_attempts" msgid="3083141271737748716">"ઘણા વધારે ખોટા પ્રયત્નો. \n <xliff:g id="NUMBER">%d</xliff:g> સેકંડમાં ફરી પ્રયાસ કરો."</string>
- <!-- no translation found for work_challenge_emergency_button_text (8946588434515599288) -->
- <skip />
+ <string name="work_challenge_emergency_button_text" msgid="8946588434515599288">"ઇમર્જન્સી"</string>
<string name="biometric_dialog_credential_attempts_before_wipe" msgid="6751859711975516999">"ફરી પ્રયાસ કરો. <xliff:g id="MAX_ATTEMPTS">%2$d</xliff:g> માંથી <xliff:g id="ATTEMPTS_0">%1$d</xliff:g> પ્રયત્ન."</string>
<string name="biometric_dialog_last_attempt_before_wipe_dialog_title" msgid="2874250099278693477">"તમારો ડેટા ડિલીટ કરવામાં આવશે"</string>
<string name="biometric_dialog_last_pattern_attempt_before_wipe_device" msgid="6562299244825817598">"જો તમે આગલા પ્રયત્નમાં ખોટી પૅટર્ન દાખલ કરશો, તો આ ડિવાઇસનો ડેટા ડિલીટ કરવામાં આવશે."</string>
@@ -415,8 +413,7 @@
<string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="8736391633234144237">"જ્યારે તમે શેર, રેકોર્ડ અથવા કાસ્ટ કરી રહ્યાં હો, ત્યારે તમારી સ્ક્રીન પર દેખાતી હોય કે તમારા ડિવાઇસ પર ચલાવવામાં આવતી હોય તેવી બધી વસ્તુનો ઍક્સેસ <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> પાસે હોય છે. તેથી પાસવર્ડ, ચુકવણીની વિગતો, મેસેજ, ફોટા અને ડિવાઇસ પર વાગી રહેલા ઑડિયો તથા વીડિયો જેવી બાબતોને લઈને સાવચેત રહો."</string>
<string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="5211695779082563959">"જ્યારે તમે કોઈ ઍપ શેર, રેકોર્ડ અથવા કાસ્ટ કરી રહ્યાં હો, ત્યારે તે ઍપ પર બતાવવામાં કે ચલાવવામાં આવતી હોય તેવી બધી વસ્તુનો ઍક્સેસ <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> પાસે હોય છે. તેથી પાસવર્ડ, ચુકવણીની વિગતો, મેસેજ, ફોટા અને ડિવાઇસ પર વાગી રહેલા ઑડિયો તથા વીડિયો જેવી બાબતોને લઈને સાવચેત રહો."</string>
<string name="media_projection_entry_app_permission_dialog_continue" msgid="295463518195075840">"શરૂ કરો"</string>
- <!-- no translation found for media_projection_entry_app_permission_dialog_single_app_disabled (8999903044874669995) -->
- <skip />
+ <string name="media_projection_entry_app_permission_dialog_single_app_disabled" msgid="8999903044874669995">"<xliff:g id="APP_NAME">%1$s</xliff:g> દ્વારા આ વિકલ્પ બંધ કરવામાં આવ્યો છે"</string>
<string name="media_projection_entry_cast_permission_dialog_title" msgid="8860150223172993547">"કાસ્ટ કરવાનું શરૂ કરીએ?"</string>
<string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="1986212276016817231">"જ્યારે તમે કાસ્ટ કરી રહ્યાં હો, ત્યારે તમારી સ્ક્રીન પર દેખાતી કે તમારા ડિવાઇસ પર ચલાવવામાં આવતી બધી વસ્તુઓનો ઍક્સેસ Android પાસે હોય છે. તેથી પાસવર્ડ, ચુકવણીની વિગતો, મેસેજ, ફોટા અને ડિવાઇસ પર વાગી રહેલા ઑડિયો તથા વીડિયો જેવી બાબતોને લઈને સાવચેત રહો."</string>
<string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="9900961380294292">"જ્યારે તમે ઍપને કાસ્ટ કરી રહ્યાં હો, ત્યારે તે ઍપ પર બતાવવામાં કે ચલાવવામાં આવતી હોય તેવી બધી વસ્તુનો ઍક્સેસ Android પાસે હોય છે. તેથી પાસવર્ડ, ચુકવણીની વિગતો, મેસેજ, ફોટા અને ડિવાઇસ પર વાગી રહેલા ઑડિયો તથા વીડિયો જેવી બાબતોને લઈને સાવચેત રહો."</string>
@@ -1173,6 +1170,10 @@
<string name="assistant_attention_content_description" msgid="6830215897604642875">"Assistant સક્રિય છે"</string>
<string name="set_default_notes_app_toast_content" msgid="2812374329662610753">"સેટિંગમાં નોંધની ડિફૉલ્ટ ઍપ સેટ કરો"</string>
<string name="install_app" msgid="5066668100199613936">"ઍપ ઇન્સ્ટૉલ કરો"</string>
+ <!-- no translation found for connected_display_dialog_start_mirroring (6237895789920854982) -->
+ <skip />
+ <!-- no translation found for enable_display (8308309634883321977) -->
+ <skip />
<string name="privacy_dialog_title" msgid="7839968133469098311">"માઇક્રોફોન અને કૅમેરા"</string>
<string name="privacy_dialog_summary" msgid="2458769652125995409">"તાજેતરનો ઍપનો વપરાશ"</string>
<string name="privacy_dialog_more_button" msgid="7610604080293562345">"તાજેતરનો ઍક્સેસ મેનેજ કરો"</string>
diff --git a/packages/SystemUI/res/values-hi/strings.xml b/packages/SystemUI/res/values-hi/strings.xml
index 18774aeddef6..c73b8f79c873 100644
--- a/packages/SystemUI/res/values-hi/strings.xml
+++ b/packages/SystemUI/res/values-hi/strings.xml
@@ -57,8 +57,7 @@
<string name="hdmi_cec_set_menu_language_description" msgid="8176716678074126619">"किसी दूसरे डिवाइस से, सिस्टम की भाषा बदलने का अनुरोध किया गया"</string>
<string name="hdmi_cec_set_menu_language_accept" msgid="2513689457281009578">"भाषा बदलें"</string>
<string name="hdmi_cec_set_menu_language_decline" msgid="7650721096558646011">"मौजूदा भाषा रखें"</string>
- <!-- no translation found for share_wifi_button_text (1285273973812029240) -->
- <skip />
+ <string name="share_wifi_button_text" msgid="1285273973812029240">"वाई-फ़ाई शेयर करें"</string>
<string name="wifi_debugging_title" msgid="7300007687492186076">"क्या आप इस नेटवर्क पर वॉयरलेस डीबगिंग के इस्तेमाल की अनुमति देना चाहते हैं?"</string>
<string name="wifi_debugging_message" msgid="5461204211731802995">"नेटवर्क का नाम (SSID)\n<xliff:g id="SSID_0">%1$s</xliff:g>\n\nवाई-फ़ाई का पता (BSSID)\n<xliff:g id="BSSID_1">%2$s</xliff:g>"</string>
<string name="wifi_debugging_always" msgid="2968383799517975155">"इस नेटवर्क पर हमेशा अनुमति दें"</string>
@@ -160,8 +159,7 @@
<string name="biometric_dialog_wrong_pattern" msgid="8954812279840889029">"गलत पैटर्न"</string>
<string name="biometric_dialog_wrong_password" msgid="69477929306843790">"गलत पासवर्ड"</string>
<string name="biometric_dialog_credential_too_many_attempts" msgid="3083141271737748716">"आपकी कोशिशें बहुत बार गलत हुई हैं.\nआप <xliff:g id="NUMBER">%d</xliff:g> सेकंड में फिर से कोशिश कर सकते हैं."</string>
- <!-- no translation found for work_challenge_emergency_button_text (8946588434515599288) -->
- <skip />
+ <string name="work_challenge_emergency_button_text" msgid="8946588434515599288">"आपातकालीन कॉल"</string>
<string name="biometric_dialog_credential_attempts_before_wipe" msgid="6751859711975516999">"फिर से कोशिश करें. आप <xliff:g id="MAX_ATTEMPTS">%2$d</xliff:g> में से <xliff:g id="ATTEMPTS_0">%1$d</xliff:g> बार कोशिश कर चुके हैं."</string>
<string name="biometric_dialog_last_attempt_before_wipe_dialog_title" msgid="2874250099278693477">"आपका डेटा मिटा दिया जाएगा"</string>
<string name="biometric_dialog_last_pattern_attempt_before_wipe_device" msgid="6562299244825817598">"अगर आप फिर से गलत पैटर्न डालते हैं, तो इस डिवाइस का डेटा मिटा दिया जाएगा."</string>
@@ -415,8 +413,7 @@
<string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="8736391633234144237">"शेयर, रिकॉर्ड या कास्ट करते समय, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> के पास स्क्रीन पर दिख रहे कॉन्टेंट या डिवाइस पर चल रहे हर मीडिया का ऐक्सेस होता है. इसलिए, पासवर्ड, पेमेंट के तरीके की जानकारी, मैसेज, फ़ोटो, और डिवाइस पर चल रहे ऑडियो और वीडियो को लेकर सावधानी बरतें."</string>
<string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="5211695779082563959">"किसी ऐप्लिकेशन को शेयर, रिकॉर्ड या कास्ट करते समय, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> के पास उस ऐप्लिकेशन पर दिख रहे कॉन्टेंट या उस पर चल रहे हर मीडिया का ऐक्सेस होता है. इसलिए, पासवर्ड, पेमेंट के तरीके की जानकारी, मैसेज, फ़ोटो, और डिवाइस पर चल रहे ऑडियो और वीडियो को लेकर सावधानी बरतें."</string>
<string name="media_projection_entry_app_permission_dialog_continue" msgid="295463518195075840">"शुरू करें"</string>
- <!-- no translation found for media_projection_entry_app_permission_dialog_single_app_disabled (8999903044874669995) -->
- <skip />
+ <string name="media_projection_entry_app_permission_dialog_single_app_disabled" msgid="8999903044874669995">"<xliff:g id="APP_NAME">%1$s</xliff:g> ने इस विकल्प को बंद कर दिया है"</string>
<string name="media_projection_entry_cast_permission_dialog_title" msgid="8860150223172993547">"क्या मीडिया कास्ट करना है?"</string>
<string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="1986212276016817231">"कास्ट करते समय, Android के पास स्क्रीन पर दिख रहे कॉन्टेंट या डिवाइस पर चल रहे हर मीडिया का ऐक्सेस होता है. इसलिए, पासवर्ड, पेमेंट के तरीके की जानकारी, मैसेज, फ़ोटो, और डिवाइस पर चल रहे ऑडियो और वीडियो को लेकर सावधानी बरतें."</string>
<string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="9900961380294292">"किसी ऐप्लिकेशन को कास्ट करते समय, Android के पास उस ऐप्लिकेशन पर दिख रहे कॉन्टेंट या उस पर चल रहे हर मीडिया का ऐक्सेस होता है. इसलिए, पासवर्ड, पेमेंट के तरीके की जानकारी, मैसेज, फ़ोटो, और डिवाइस पर चल रहे ऑडियो और वीडियो को लेकर सावधानी बरतें."</string>
@@ -1173,6 +1170,10 @@
<string name="assistant_attention_content_description" msgid="6830215897604642875">"Assistant आपकी बातें सुन रही है"</string>
<string name="set_default_notes_app_toast_content" msgid="2812374329662610753">"सेटिंग में जाकर, नोट लेने की सुविधा देने वाले ऐप्लिकेशन को डिफ़ॉल्ट के तौर पर सेट करें"</string>
<string name="install_app" msgid="5066668100199613936">"ऐप्लिकेशन इंस्टॉल करें"</string>
+ <!-- no translation found for connected_display_dialog_start_mirroring (6237895789920854982) -->
+ <skip />
+ <!-- no translation found for enable_display (8308309634883321977) -->
+ <skip />
<string name="privacy_dialog_title" msgid="7839968133469098311">"माइक्रोफ़ोन और कैमरा"</string>
<string name="privacy_dialog_summary" msgid="2458769652125995409">"हाल ही में इस्तेमाल करने वाला ऐप्लिकेशन"</string>
<string name="privacy_dialog_more_button" msgid="7610604080293562345">"हाल में ऐक्सेस करने वाले ऐप"</string>
diff --git a/packages/SystemUI/res/values-hr/strings.xml b/packages/SystemUI/res/values-hr/strings.xml
index b6840383da38..f9b220ddb9f1 100644
--- a/packages/SystemUI/res/values-hr/strings.xml
+++ b/packages/SystemUI/res/values-hr/strings.xml
@@ -57,8 +57,7 @@
<string name="hdmi_cec_set_menu_language_description" msgid="8176716678074126619">"Drugi uređaj zatražio je promjenu jezika sustava"</string>
<string name="hdmi_cec_set_menu_language_accept" msgid="2513689457281009578">"Promijeni jezik"</string>
<string name="hdmi_cec_set_menu_language_decline" msgid="7650721096558646011">"Zadrži trenutačni jezik"</string>
- <!-- no translation found for share_wifi_button_text (1285273973812029240) -->
- <skip />
+ <string name="share_wifi_button_text" msgid="1285273973812029240">"Dijeli Wi‑Fi"</string>
<string name="wifi_debugging_title" msgid="7300007687492186076">"Dopustiti bežično otklanjanje pogrešaka na ovoj mreži?"</string>
<string name="wifi_debugging_message" msgid="5461204211731802995">"Naziv mreže (SSID)\n<xliff:g id="SSID_0">%1$s</xliff:g>\n\nAdresa Wi‑Fija (BSSID)\n<xliff:g id="BSSID_1">%2$s</xliff:g>"</string>
<string name="wifi_debugging_always" msgid="2968383799517975155">"Uvijek dopusti na ovoj mreži"</string>
@@ -160,8 +159,7 @@
<string name="biometric_dialog_wrong_pattern" msgid="8954812279840889029">"Pogrešan uzorak"</string>
<string name="biometric_dialog_wrong_password" msgid="69477929306843790">"Pogrešna zaporka"</string>
<string name="biometric_dialog_credential_too_many_attempts" msgid="3083141271737748716">"Previše netočnih pokušaja.\nPokušajte ponovo za <xliff:g id="NUMBER">%d</xliff:g> s."</string>
- <!-- no translation found for work_challenge_emergency_button_text (8946588434515599288) -->
- <skip />
+ <string name="work_challenge_emergency_button_text" msgid="8946588434515599288">"Hitni slučaj"</string>
<string name="biometric_dialog_credential_attempts_before_wipe" msgid="6751859711975516999">"Pokušajte ponovo. <xliff:g id="ATTEMPTS_0">%1$d</xliff:g>. pokušaj od <xliff:g id="MAX_ATTEMPTS">%2$d</xliff:g>."</string>
<string name="biometric_dialog_last_attempt_before_wipe_dialog_title" msgid="2874250099278693477">"Vaši će se podaci izbrisati"</string>
<string name="biometric_dialog_last_pattern_attempt_before_wipe_device" msgid="6562299244825817598">"Ako pri sljedećem pokušaju unesete netočan uzorak, izbrisat će se podaci s ovog uređaja."</string>
@@ -415,8 +413,7 @@
<string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="8736391633234144237">"Kad dijelite, snimate ili emitirate, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> ima pristup svemu što je vidljivo na vašem zaslonu ili se reproducira na vašem uređaju. Stoga pazite na stvari kao što su zaporke, podaci o plaćanju, poruke, fotografije te audio i videozapisi."</string>
<string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="5211695779082563959">"Kad dijelite, snimate ili emitirate aplikaciju, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> ima pristup svemu što se prikazuje ili reproducira u toj aplikaciji. Stoga pazite na stvari kao što su zaporke, podaci o plaćanju, poruke, fotografije te audio i videozapisi."</string>
<string name="media_projection_entry_app_permission_dialog_continue" msgid="295463518195075840">"Pokreni"</string>
- <!-- no translation found for media_projection_entry_app_permission_dialog_single_app_disabled (8999903044874669995) -->
- <skip />
+ <string name="media_projection_entry_app_permission_dialog_single_app_disabled" msgid="8999903044874669995">"Aplikacija <xliff:g id="APP_NAME">%1$s</xliff:g> onemogućila je ovu opciju"</string>
<string name="media_projection_entry_cast_permission_dialog_title" msgid="8860150223172993547">"Želite li pokrenuti emitiranje?"</string>
<string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="1986212276016817231">"Kad emitirate, Android ima pristup svemu što je vidljivo na vašem zaslonu ili se reproducira na vašem uređaju. Stoga pazite na stvari kao što su zaporke, podaci o plaćanju, poruke, fotografije te audio i videozapisi."</string>
<string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="9900961380294292">"Kad emitirate aplikaciju, Android ima pristup svemu što se prikazuje ili reproducira u toj aplikaciji. Stoga pazite na stvari kao što su zaporke, podaci o plaćanju, poruke, fotografije te audio i videozapisi."</string>
@@ -1173,6 +1170,10 @@
<string name="assistant_attention_content_description" msgid="6830215897604642875">"Pažnja Asistenta je aktivirana"</string>
<string name="set_default_notes_app_toast_content" msgid="2812374329662610753">"Postavite zadanu aplikaciju za bilješke u postavkama"</string>
<string name="install_app" msgid="5066668100199613936">"Instalacija"</string>
+ <!-- no translation found for connected_display_dialog_start_mirroring (6237895789920854982) -->
+ <skip />
+ <!-- no translation found for enable_display (8308309634883321977) -->
+ <skip />
<string name="privacy_dialog_title" msgid="7839968133469098311">"Mikrofon i kamera"</string>
<string name="privacy_dialog_summary" msgid="2458769652125995409">"Nedavna upotreba aplikacije"</string>
<string name="privacy_dialog_more_button" msgid="7610604080293562345">"Pogledajte nedavni pristup"</string>
diff --git a/packages/SystemUI/res/values-hu/strings.xml b/packages/SystemUI/res/values-hu/strings.xml
index 26f60f9ac69b..0d40770bb939 100644
--- a/packages/SystemUI/res/values-hu/strings.xml
+++ b/packages/SystemUI/res/values-hu/strings.xml
@@ -57,8 +57,7 @@
<string name="hdmi_cec_set_menu_language_description" msgid="8176716678074126619">"Egy másik eszköz a rendszer nyelvének módosítását kéri"</string>
<string name="hdmi_cec_set_menu_language_accept" msgid="2513689457281009578">"Nyelvmódosítás"</string>
<string name="hdmi_cec_set_menu_language_decline" msgid="7650721096558646011">"Aktuális nyelv megtartása"</string>
- <!-- no translation found for share_wifi_button_text (1285273973812029240) -->
- <skip />
+ <string name="share_wifi_button_text" msgid="1285273973812029240">"Wi‑Fi megosztása"</string>
<string name="wifi_debugging_title" msgid="7300007687492186076">"Engedélyezi a vezeték nélküli hibakeresést ezen a hálózaton?"</string>
<string name="wifi_debugging_message" msgid="5461204211731802995">"Hálózat neve (SSID):\n<xliff:g id="SSID_0">%1$s</xliff:g>\n\nWi‑Fi-cím (BSSID):\n<xliff:g id="BSSID_1">%2$s</xliff:g>"</string>
<string name="wifi_debugging_always" msgid="2968383799517975155">"Mindig engedélyezze ezen a hálózaton"</string>
@@ -160,8 +159,7 @@
<string name="biometric_dialog_wrong_pattern" msgid="8954812279840889029">"Helytelen minta"</string>
<string name="biometric_dialog_wrong_password" msgid="69477929306843790">"Helytelen jelszó"</string>
<string name="biometric_dialog_credential_too_many_attempts" msgid="3083141271737748716">"Túl sok helytelen próbálkozás.\nPróbálja újra <xliff:g id="NUMBER">%d</xliff:g> másodperc múlva."</string>
- <!-- no translation found for work_challenge_emergency_button_text (8946588434515599288) -->
- <skip />
+ <string name="work_challenge_emergency_button_text" msgid="8946588434515599288">"Vészhelyzet"</string>
<string name="biometric_dialog_credential_attempts_before_wipe" msgid="6751859711975516999">"Próbálja újra. <xliff:g id="ATTEMPTS_0">%1$d</xliff:g>. kísérlet, összesen: <xliff:g id="MAX_ATTEMPTS">%2$d</xliff:g>."</string>
<string name="biometric_dialog_last_attempt_before_wipe_dialog_title" msgid="2874250099278693477">"Adatai törlődni fognak"</string>
<string name="biometric_dialog_last_pattern_attempt_before_wipe_device" msgid="6562299244825817598">"Amennyiben helytelen mintát ad meg a következő kísérletnél, a rendszer törli az adatokat erről az eszközről."</string>
@@ -415,8 +413,7 @@
<string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="8736391633234144237">"Amikor Ön megosztást, rögzítést vagy átküldést végez, a(z) <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> a képernyőn látható vagy az eszközön lejátszott minden tartalomhoz hozzáfér. Ezért legyen elővigyázatos a jelszavakkal, a fizetési adatokkal, az üzenetekkel, a fotókkal, valamint a hang- és videófelvételekkel."</string>
<string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="5211695779082563959">"Amikor Ön megoszt, rögzít vagy átküld egy alkalmazást, a(z) <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> az adott appban látható vagy lejátszott minden tartalomhoz hozzáfér. Ezért legyen elővigyázatos a jelszavakkal, a fizetési adatokkal, az üzenetekkel, a fotókkal, valamint a hang- és videófelvételekkel."</string>
<string name="media_projection_entry_app_permission_dialog_continue" msgid="295463518195075840">"Indítás"</string>
- <!-- no translation found for media_projection_entry_app_permission_dialog_single_app_disabled (8999903044874669995) -->
- <skip />
+ <string name="media_projection_entry_app_permission_dialog_single_app_disabled" msgid="8999903044874669995">"<xliff:g id="APP_NAME">%1$s</xliff:g> letiltotta ezt a beállítást"</string>
<string name="media_projection_entry_cast_permission_dialog_title" msgid="8860150223172993547">"Elindítja az átküldést?"</string>
<string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="1986212276016817231">"Amikor Ön átküldést végez, az Android a képernyőn látható vagy az eszközön lejátszott minden tartalomhoz hozzáfér. Ezért legyen elővigyázatos a jelszavakkal, a fizetési adatokkal, az üzenetekkel, a fotókkal, valamint a hang- és videófelvételekkel."</string>
<string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="9900961380294292">"Alkalmazás átküldése közben az Android az adott appban látható vagy lejátszott minden tartalomhoz hozzáfér. Ezért legyen elővigyázatos a jelszavakkal, a fizetési adatokkal, az üzenetekkel, a fotókkal, valamint a hang- és videófelvételekkel."</string>
@@ -1173,6 +1170,10 @@
<string name="assistant_attention_content_description" msgid="6830215897604642875">"A Segéd figyel"</string>
<string name="set_default_notes_app_toast_content" msgid="2812374329662610753">"Állítson be alapértelmezett jegyzetkészítő alkalmazást a Beállításokban"</string>
<string name="install_app" msgid="5066668100199613936">"Alkalmazás telepítése"</string>
+ <!-- no translation found for connected_display_dialog_start_mirroring (6237895789920854982) -->
+ <skip />
+ <!-- no translation found for enable_display (8308309634883321977) -->
+ <skip />
<string name="privacy_dialog_title" msgid="7839968133469098311">"Mikrofon és kamera"</string>
<string name="privacy_dialog_summary" msgid="2458769652125995409">"Legutóbbi alkalmazáshasználat"</string>
<string name="privacy_dialog_more_button" msgid="7610604080293562345">"Legutóbbi hozzáférés"</string>
diff --git a/packages/SystemUI/res/values-hy/strings.xml b/packages/SystemUI/res/values-hy/strings.xml
index da38ae11a457..e64a8de3b638 100644
--- a/packages/SystemUI/res/values-hy/strings.xml
+++ b/packages/SystemUI/res/values-hy/strings.xml
@@ -57,8 +57,7 @@
<string name="hdmi_cec_set_menu_language_description" msgid="8176716678074126619">"Մեկ այլ սարք համակարգի լեզվի փոփոխության հարցում է ուղարկել"</string>
<string name="hdmi_cec_set_menu_language_accept" msgid="2513689457281009578">"Փոխել լեզուն"</string>
<string name="hdmi_cec_set_menu_language_decline" msgid="7650721096558646011">"Թողնել ընթացիկ լեզուն"</string>
- <!-- no translation found for share_wifi_button_text (1285273973812029240) -->
- <skip />
+ <string name="share_wifi_button_text" msgid="1285273973812029240">"Կիսվել Wi‑Fi-ով"</string>
<string name="wifi_debugging_title" msgid="7300007687492186076">"Թույլատրե՞լ անլար վրիպազերծումն այս ցանցում"</string>
<string name="wifi_debugging_message" msgid="5461204211731802995">"Ցանցի անվանումը (SSID)\n<xliff:g id="SSID_0">%1$s</xliff:g>\n\nWi‑Fi-ի հասցեն (BSSID)\n<xliff:g id="BSSID_1">%2$s</xliff:g>"</string>
<string name="wifi_debugging_always" msgid="2968383799517975155">"Միշտ թույլատրել այս ցանցում"</string>
@@ -160,8 +159,7 @@
<string name="biometric_dialog_wrong_pattern" msgid="8954812279840889029">"Նախշը սխալ է"</string>
<string name="biometric_dialog_wrong_password" msgid="69477929306843790">"Գաղտնաբառը սխալ է"</string>
<string name="biometric_dialog_credential_too_many_attempts" msgid="3083141271737748716">"Չափից շատ սխալ փորձ է կատարվել:\nՆորից փորձեք <xliff:g id="NUMBER">%d</xliff:g> վայրկյանից:"</string>
- <!-- no translation found for work_challenge_emergency_button_text (8946588434515599288) -->
- <skip />
+ <string name="work_challenge_emergency_button_text" msgid="8946588434515599288">"Արտակարգ իրավիճակ"</string>
<string name="biometric_dialog_credential_attempts_before_wipe" msgid="6751859711975516999">"Փորձեք նորից։ Փորձ <xliff:g id="ATTEMPTS_0">%1$d</xliff:g>՝ <xliff:g id="MAX_ATTEMPTS">%2$d</xliff:g>-ից։"</string>
<string name="biometric_dialog_last_attempt_before_wipe_dialog_title" msgid="2874250099278693477">"Ձեր տվյալները կջնջվեն"</string>
<string name="biometric_dialog_last_pattern_attempt_before_wipe_device" msgid="6562299244825817598">"Հաջորդ փորձի ժամանակ սխալ նախշ մուտքագրելու դեպքում սարքի տվյալները կջնջվեն։"</string>
@@ -415,8 +413,7 @@
<string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="8736391633234144237">"Երբ դուք ցուցադրում, տեսագրում կամ հեռարձակում եք էկրանը, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> հավելվածին հասանելի է լինում այն ամենը, ինչ տեսանելի է ձեր էկրանին և նվագարկվում է ձեր սարքում։ Ուստի ուշադիր եղեք այնպիսի բաների հետ, ինչպիսիք են գաղտնաբառերը, վճարային տվյալները, հաղորդագրությունները, լուսանկարները, աուդիո և վիդեո բովանդակությունը։"</string>
<string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="5211695779082563959">"Երբ դուք ցուցադրում, տեսագրում կամ հեռարձակում եք որևէ հավելվածի էկրանը, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> հավելվածին հասանելի է լինում այն ամենը, ինչ ցուցադրվում կամ նվագարկվում է այդ հավելվածում։ Ուստի ուշադիր եղեք այնպիսի բաների հետ, ինչպիսիք են գաղտնաբառերը, վճարային տվյալները, հաղորդագրությունները, լուսանկարները, աուդիո և վիդեո բովանդակությունը։"</string>
<string name="media_projection_entry_app_permission_dialog_continue" msgid="295463518195075840">"Սկսել"</string>
- <!-- no translation found for media_projection_entry_app_permission_dialog_single_app_disabled (8999903044874669995) -->
- <skip />
+ <string name="media_projection_entry_app_permission_dialog_single_app_disabled" msgid="8999903044874669995">"<xliff:g id="APP_NAME">%1$s</xliff:g>-ն անջատել է այս ընտրանքը"</string>
<string name="media_projection_entry_cast_permission_dialog_title" msgid="8860150223172993547">"Սկսե՞լ հեռարձակումը"</string>
<string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="1986212276016817231">"Երբ դուք հեռարձակում եք էկրանը, Android-ին հասանելի է լինում այն ամենը, ինչ տեսանելի է ձեր էկրանին կամ նվագարկվում է ձեր սարքում։ Ուստի ուշադիր եղեք այնպիսի բաների հետ, ինչպիսիք են գաղտնաբառերը, վճարային տվյալները, հաղորդագրությունները, լուսանկարները, աուդիո և վիդեո բովանդակությունը։"</string>
<string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="9900961380294292">"Երբ դուք տեսագրում եք որևէ հավելվածի էկրանը, Android-ին հասանելի է լինում այն ամենը, ինչ ցուցադրվում կամ նվագարկվում է այդ հավելվածում։ Ուստի ուշադիր եղեք այնպիսի բաների հետ, ինչպիսիք են գաղտնաբառերը, վճարային տվյալները, հաղորդագրությունները, լուսանկարները, աուդիո և վիդեո բովանդակությունը։"</string>
@@ -1173,6 +1170,10 @@
<string name="assistant_attention_content_description" msgid="6830215897604642875">"Օգնականը լսում է"</string>
<string name="set_default_notes_app_toast_content" msgid="2812374329662610753">"Կարգավորեք նշումների կանխադրված հավելված Կարգավորումներում"</string>
<string name="install_app" msgid="5066668100199613936">"Տեղադրել հավելվածը"</string>
+ <!-- no translation found for connected_display_dialog_start_mirroring (6237895789920854982) -->
+ <skip />
+ <!-- no translation found for enable_display (8308309634883321977) -->
+ <skip />
<string name="privacy_dialog_title" msgid="7839968133469098311">"Խոսափող և տեսախցիկ"</string>
<string name="privacy_dialog_summary" msgid="2458769652125995409">"Հավելվածի վերջին օգտագործումը"</string>
<string name="privacy_dialog_more_button" msgid="7610604080293562345">"Տեսնել վերջին օգտագործումը"</string>
diff --git a/packages/SystemUI/res/values-in/strings.xml b/packages/SystemUI/res/values-in/strings.xml
index 320e125a9632..d2a974784026 100644
--- a/packages/SystemUI/res/values-in/strings.xml
+++ b/packages/SystemUI/res/values-in/strings.xml
@@ -57,8 +57,7 @@
<string name="hdmi_cec_set_menu_language_description" msgid="8176716678074126619">"Perubahan bahasa sistem diminta oleh perangkat lain"</string>
<string name="hdmi_cec_set_menu_language_accept" msgid="2513689457281009578">"Ubah bahasa"</string>
<string name="hdmi_cec_set_menu_language_decline" msgid="7650721096558646011">"Pertahankan bahasa"</string>
- <!-- no translation found for share_wifi_button_text (1285273973812029240) -->
- <skip />
+ <string name="share_wifi_button_text" msgid="1285273973812029240">"Bagikan Wi‑Fi"</string>
<string name="wifi_debugging_title" msgid="7300007687492186076">"Izinkan proses debug nirkabel di perangkat ini?"</string>
<string name="wifi_debugging_message" msgid="5461204211731802995">"Nama Jaringan (SSID)\n<xliff:g id="SSID_0">%1$s</xliff:g>\n\nAlamat Wi‑Fi (BSSID)\n<xliff:g id="BSSID_1">%2$s</xliff:g>"</string>
<string name="wifi_debugging_always" msgid="2968383799517975155">"Selalu izinkan di jaringan ini"</string>
@@ -160,8 +159,7 @@
<string name="biometric_dialog_wrong_pattern" msgid="8954812279840889029">"Pola salah"</string>
<string name="biometric_dialog_wrong_password" msgid="69477929306843790">"Sandi salah"</string>
<string name="biometric_dialog_credential_too_many_attempts" msgid="3083141271737748716">"Terlalu banyak kesalahan pola.\nCoba lagi dalam <xliff:g id="NUMBER">%d</xliff:g> detik."</string>
- <!-- no translation found for work_challenge_emergency_button_text (8946588434515599288) -->
- <skip />
+ <string name="work_challenge_emergency_button_text" msgid="8946588434515599288">"Keadaan Darurat"</string>
<string name="biometric_dialog_credential_attempts_before_wipe" msgid="6751859711975516999">"Coba lagi. Percobaan <xliff:g id="ATTEMPTS_0">%1$d</xliff:g> dari <xliff:g id="MAX_ATTEMPTS">%2$d</xliff:g>."</string>
<string name="biometric_dialog_last_attempt_before_wipe_dialog_title" msgid="2874250099278693477">"Data akan dihapus"</string>
<string name="biometric_dialog_last_pattern_attempt_before_wipe_device" msgid="6562299244825817598">"Jika Anda memasukkan pola yang salah saat mencoba lagi, data perangkat ini akan dihapus."</string>
@@ -415,8 +413,7 @@
<string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="8736391633234144237">"Jika Anda membagikan, merekam, atau mentransmisikan, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> akan memiliki akses ke semua hal yang ditampilkan di layar atau yang diputar di perangkat Anda. Jadi, berhati-hatilah saat memasukkan sandi, detail pembayaran, pesan, foto, audio, dan video."</string>
<string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="5211695779082563959">"Jika Anda membagikan, merekam, atau mentransmisikan suatu aplikasi, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> akan memiliki akses ke semua hal yang ditampilkan atau yang diputar di aplikasi tersebut. Jadi, berhati-hatilah saat memasukkan sandi, detail pembayaran, pesan, foto, audio dan video."</string>
<string name="media_projection_entry_app_permission_dialog_continue" msgid="295463518195075840">"Mulai"</string>
- <!-- no translation found for media_projection_entry_app_permission_dialog_single_app_disabled (8999903044874669995) -->
- <skip />
+ <string name="media_projection_entry_app_permission_dialog_single_app_disabled" msgid="8999903044874669995">"<xliff:g id="APP_NAME">%1$s</xliff:g> telah menonaktifkan opsi ini"</string>
<string name="media_projection_entry_cast_permission_dialog_title" msgid="8860150223172993547">"Mulai mentransmisikan?"</string>
<string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="1986212276016817231">"Jika mentransmisikan, Android akan memiliki akses ke semua hal yang ditampilkan di layar atau yang diputar di perangkat Anda. Jadi, berhati-hatilah saat memasukkan sandi, detail pembayaran, pesan, foto, audio, dan video."</string>
<string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="9900961380294292">"Jika Anda mentransmisikan aplikasi, Android akan memiliki akses ke semua hal yang ditampilkan atau yang diputar di aplikasi tersebut. Jadi, berhati-hatilah saat memasukkan sandi, detail pembayaran, pesan, foto, audio, dan video."</string>
@@ -712,7 +709,7 @@
<string name="switch_bar_off" msgid="5669805115416379556">"Nonaktif"</string>
<string name="tile_unavailable" msgid="3095879009136616920">"Tidak tersedia"</string>
<string name="accessibility_tile_disabled_by_policy_action_description" msgid="6958422730461646926">"pelajari lebih lanjut"</string>
- <string name="nav_bar" msgid="4642708685386136807">"Bilah navigasi"</string>
+ <string name="nav_bar" msgid="4642708685386136807">"Menu navigasi"</string>
<string name="nav_bar_layout" msgid="4716392484772899544">"Tata letak"</string>
<string name="left_nav_bar_button_type" msgid="2634852842345192790">"Jenis tombol ekstra kiri"</string>
<string name="right_nav_bar_button_type" msgid="4472566498647364715">"Jenis tombol ekstra kanan"</string>
@@ -1173,6 +1170,10 @@
<string name="assistant_attention_content_description" msgid="6830215897604642875">"Asisten sedang memerhatikan"</string>
<string name="set_default_notes_app_toast_content" msgid="2812374329662610753">"Setel aplikasi catatan default di Setelan"</string>
<string name="install_app" msgid="5066668100199613936">"Instal aplikasi"</string>
+ <!-- no translation found for connected_display_dialog_start_mirroring (6237895789920854982) -->
+ <skip />
+ <!-- no translation found for enable_display (8308309634883321977) -->
+ <skip />
<string name="privacy_dialog_title" msgid="7839968133469098311">"Mikrofon &amp; Kamera"</string>
<string name="privacy_dialog_summary" msgid="2458769652125995409">"Penggunaan aplikasi baru-baru ini"</string>
<string name="privacy_dialog_more_button" msgid="7610604080293562345">"Lihat akses terbaru"</string>
diff --git a/packages/SystemUI/res/values-is/strings.xml b/packages/SystemUI/res/values-is/strings.xml
index 73f17453fe2f..d5bb28a87afd 100644
--- a/packages/SystemUI/res/values-is/strings.xml
+++ b/packages/SystemUI/res/values-is/strings.xml
@@ -57,8 +57,7 @@
<string name="hdmi_cec_set_menu_language_description" msgid="8176716678074126619">"Beiðni frá öðru tæki um að breyta tungumáli kerfis"</string>
<string name="hdmi_cec_set_menu_language_accept" msgid="2513689457281009578">"Breyta tungumáli"</string>
<string name="hdmi_cec_set_menu_language_decline" msgid="7650721096558646011">"Halda núverandi tungumáli"</string>
- <!-- no translation found for share_wifi_button_text (1285273973812029240) -->
- <skip />
+ <string name="share_wifi_button_text" msgid="1285273973812029240">"Deila Wi‑Fi"</string>
<string name="wifi_debugging_title" msgid="7300007687492186076">"Viltu leyfa þráðlausa villuleit á þessu neti?"</string>
<string name="wifi_debugging_message" msgid="5461204211731802995">"Heiti netkerfis (SSID)\n<xliff:g id="SSID_0">%1$s</xliff:g>\n\nWi‑Fi vistfang (BSSID)\n<xliff:g id="BSSID_1">%2$s</xliff:g>"</string>
<string name="wifi_debugging_always" msgid="2968383799517975155">"Leyfa alltaf á þessu neti"</string>
@@ -160,8 +159,7 @@
<string name="biometric_dialog_wrong_pattern" msgid="8954812279840889029">"Rangt mynstur"</string>
<string name="biometric_dialog_wrong_password" msgid="69477929306843790">"Rangt aðgangsorð"</string>
<string name="biometric_dialog_credential_too_many_attempts" msgid="3083141271737748716">"Of margar misheppnaðar tilraunir.\nReyndu aftur eftir <xliff:g id="NUMBER">%d</xliff:g> sekúndur."</string>
- <!-- no translation found for work_challenge_emergency_button_text (8946588434515599288) -->
- <skip />
+ <string name="work_challenge_emergency_button_text" msgid="8946588434515599288">"Neyðartilvik"</string>
<string name="biometric_dialog_credential_attempts_before_wipe" msgid="6751859711975516999">"Reyndu aftur. Tilraun <xliff:g id="ATTEMPTS_0">%1$d</xliff:g> af <xliff:g id="MAX_ATTEMPTS">%2$d</xliff:g>."</string>
<string name="biometric_dialog_last_attempt_before_wipe_dialog_title" msgid="2874250099278693477">"Gögnunum þínum verður eytt"</string>
<string name="biometric_dialog_last_pattern_attempt_before_wipe_device" msgid="6562299244825817598">"Ef þú slærð inn rangt mynstur í næstu tilraun verður gögnum tækisins eytt."</string>
@@ -415,8 +413,7 @@
<string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="8736391633234144237">"Þegar þú deilir, tekur upp eða varpar hefur<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> aðgang að öllu sem sést á skjánum eða spilast í tækinu. Passaðu því upp á aðgangsorð, greiðsluupplýsingar, skilaboð, myndir, hljóð og myndskeið."</string>
<string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="5211695779082563959">"Þegar þú deilir, tekur upp eða varpar forriti hefur <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> aðgang að öllu sem sést eða spilast í viðkomandi forriti. Passaðu því upp á aðgangsorð, greiðsluupplýsingar, skilaboð, myndir, hljóð og myndskeið."</string>
<string name="media_projection_entry_app_permission_dialog_continue" msgid="295463518195075840">"Byrja"</string>
- <!-- no translation found for media_projection_entry_app_permission_dialog_single_app_disabled (8999903044874669995) -->
- <skip />
+ <string name="media_projection_entry_app_permission_dialog_single_app_disabled" msgid="8999903044874669995">"<xliff:g id="APP_NAME">%1$s</xliff:g> slökkti á þessum valkosti"</string>
<string name="media_projection_entry_cast_permission_dialog_title" msgid="8860150223172993547">"Byrja að varpa?"</string>
<string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="1986212276016817231">"Þegar þú varpar hefur Android aðgang að öllu sem er sýnilegt á skjánum hjá þér eða spilast í tækinu þínu. Passaðu því upp á aðgangsorð, greiðsluupplýsingar, skilaboð, myndir, hljóð og myndskeið."</string>
<string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="9900961380294292">"Þegar þú varpar forriti hefur Android aðgang að öllu sem sést eða spilast í viðkomandi forriti. Passaðu því upp á aðgangsorð, greiðsluupplýsingar, skilaboð, myndir, hljóð og myndskeið."</string>
@@ -1173,6 +1170,10 @@
<string name="assistant_attention_content_description" msgid="6830215897604642875">"Hjálparinn er að hlusta"</string>
<string name="set_default_notes_app_toast_content" msgid="2812374329662610753">"Stilltu sjálfgefið glósuforrit í stillingunum"</string>
<string name="install_app" msgid="5066668100199613936">"Setja upp forrit"</string>
+ <!-- no translation found for connected_display_dialog_start_mirroring (6237895789920854982) -->
+ <skip />
+ <!-- no translation found for enable_display (8308309634883321977) -->
+ <skip />
<string name="privacy_dialog_title" msgid="7839968133469098311">"Hljóðnemi og myndavél"</string>
<string name="privacy_dialog_summary" msgid="2458769652125995409">"Nýlega notað af forriti"</string>
<string name="privacy_dialog_more_button" msgid="7610604080293562345">"Sjá nýlegan aðgang"</string>
diff --git a/packages/SystemUI/res/values-it/strings.xml b/packages/SystemUI/res/values-it/strings.xml
index 0db6d7f9a3cf..9f6228d549b7 100644
--- a/packages/SystemUI/res/values-it/strings.xml
+++ b/packages/SystemUI/res/values-it/strings.xml
@@ -57,8 +57,7 @@
<string name="hdmi_cec_set_menu_language_description" msgid="8176716678074126619">"Cambio della lingua di sistema richiesto da un altro dispositivo"</string>
<string name="hdmi_cec_set_menu_language_accept" msgid="2513689457281009578">"Cambia lingua"</string>
<string name="hdmi_cec_set_menu_language_decline" msgid="7650721096558646011">"Mantieni lingua attuale"</string>
- <!-- no translation found for share_wifi_button_text (1285273973812029240) -->
- <skip />
+ <string name="share_wifi_button_text" msgid="1285273973812029240">"Condividi Wi‑Fi"</string>
<string name="wifi_debugging_title" msgid="7300007687492186076">"Consentire il debug wireless su questa rete?"</string>
<string name="wifi_debugging_message" msgid="5461204211731802995">"Nome della rete (SSID)\n<xliff:g id="SSID_0">%1$s</xliff:g>\n\nIndirizzo Wi‑Fi (BSSID)\n<xliff:g id="BSSID_1">%2$s</xliff:g>"</string>
<string name="wifi_debugging_always" msgid="2968383799517975155">"Consenti sempre su questa rete"</string>
@@ -160,8 +159,7 @@
<string name="biometric_dialog_wrong_pattern" msgid="8954812279840889029">"Sequenza errata"</string>
<string name="biometric_dialog_wrong_password" msgid="69477929306843790">"Password errata"</string>
<string name="biometric_dialog_credential_too_many_attempts" msgid="3083141271737748716">"Troppi tentativi errati.\nRiprova tra <xliff:g id="NUMBER">%d</xliff:g> secondi."</string>
- <!-- no translation found for work_challenge_emergency_button_text (8946588434515599288) -->
- <skip />
+ <string name="work_challenge_emergency_button_text" msgid="8946588434515599288">"Emergenza"</string>
<string name="biometric_dialog_credential_attempts_before_wipe" msgid="6751859711975516999">"Riprova. Tentativo <xliff:g id="ATTEMPTS_0">%1$d</xliff:g> di <xliff:g id="MAX_ATTEMPTS">%2$d</xliff:g>."</string>
<string name="biometric_dialog_last_attempt_before_wipe_dialog_title" msgid="2874250099278693477">"I tuoi dati verranno eliminati"</string>
<string name="biometric_dialog_last_pattern_attempt_before_wipe_device" msgid="6562299244825817598">"Se al prossimo tentativo inserirai una sequenza sbagliata, i dati del dispositivo verranno eliminati."</string>
@@ -415,8 +413,7 @@
<string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="8736391633234144237">"Quando condividi, registri o trasmetti, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> ha accesso a qualsiasi elemento visibile sul tuo schermo o in riproduzione sul tuo dispositivo. Presta quindi attenzione a password, dettagli sui pagamenti, messaggi, foto, audio e video."</string>
<string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="5211695779082563959">"Quando condividi, registri o trasmetti un\'app, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> ha accesso a qualsiasi elemento visualizzato o riprodotto sull\'app. Presta quindi attenzione a password, dettagli sui pagamenti, messaggi, foto, audio e video."</string>
<string name="media_projection_entry_app_permission_dialog_continue" msgid="295463518195075840">"Inizia"</string>
- <!-- no translation found for media_projection_entry_app_permission_dialog_single_app_disabled (8999903044874669995) -->
- <skip />
+ <string name="media_projection_entry_app_permission_dialog_single_app_disabled" msgid="8999903044874669995">"<xliff:g id="APP_NAME">%1$s</xliff:g> ha disattivato questa opzione"</string>
<string name="media_projection_entry_cast_permission_dialog_title" msgid="8860150223172993547">"Iniziare a trasmettere?"</string>
<string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="1986212276016817231">"Quando trasmetti, Android ha accesso a qualsiasi elemento visibile sul tuo schermo o in riproduzione sul tuo dispositivo. Presta quindi attenzione a password, dettagli sui pagamenti, messaggi, foto, audio e video."</string>
<string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="9900961380294292">"Quando trasmetti un\'app, Android ha accesso a qualsiasi elemento visualizzato o riprodotto sull\'app. Presta quindi attenzione a password, dettagli sui pagamenti, messaggi, foto, audio e video."</string>
@@ -1173,6 +1170,10 @@
<string name="assistant_attention_content_description" msgid="6830215897604642875">"L\'assistente è attivo"</string>
<string name="set_default_notes_app_toast_content" msgid="2812374329662610753">"Imposta l\'app per le note predefinita nelle Impostazioni"</string>
<string name="install_app" msgid="5066668100199613936">"Installa app"</string>
+ <!-- no translation found for connected_display_dialog_start_mirroring (6237895789920854982) -->
+ <skip />
+ <!-- no translation found for enable_display (8308309634883321977) -->
+ <skip />
<string name="privacy_dialog_title" msgid="7839968133469098311">"Microfono e fotocamera"</string>
<string name="privacy_dialog_summary" msgid="2458769652125995409">"Uso recente da app"</string>
<string name="privacy_dialog_more_button" msgid="7610604080293562345">"Vedi accesso recente"</string>
diff --git a/packages/SystemUI/res/values-iw/strings.xml b/packages/SystemUI/res/values-iw/strings.xml
index 053963543bfc..44ad4452e808 100644
--- a/packages/SystemUI/res/values-iw/strings.xml
+++ b/packages/SystemUI/res/values-iw/strings.xml
@@ -57,8 +57,7 @@
<string name="hdmi_cec_set_menu_language_description" msgid="8176716678074126619">"התקבלה בקשה ממכשיר אחר לשינוי שפת המערכת"</string>
<string name="hdmi_cec_set_menu_language_accept" msgid="2513689457281009578">"שינוי שפה"</string>
<string name="hdmi_cec_set_menu_language_decline" msgid="7650721096558646011">"השארת השפה הנוכחית"</string>
- <!-- no translation found for share_wifi_button_text (1285273973812029240) -->
- <skip />
+ <string name="share_wifi_button_text" msgid="1285273973812029240">"‏שיתוף Wi‑Fi"</string>
<string name="wifi_debugging_title" msgid="7300007687492186076">"לאשר ניפוי באגים אלחוטי ברשת הזו?"</string>
<string name="wifi_debugging_message" msgid="5461204211731802995">"‏שם הרשת (SSID)\n<xliff:g id="SSID_0">%1$s</xliff:g>\n\nכתובת Wi‑Fi‏ (BSSID)\n<xliff:g id="BSSID_1">%2$s</xliff:g>"</string>
<string name="wifi_debugging_always" msgid="2968383799517975155">"לאשר תמיד ברשת הזו"</string>
@@ -160,8 +159,7 @@
<string name="biometric_dialog_wrong_pattern" msgid="8954812279840889029">"קו ביטול נעילה שגוי"</string>
<string name="biometric_dialog_wrong_password" msgid="69477929306843790">"סיסמה שגויה"</string>
<string name="biometric_dialog_credential_too_many_attempts" msgid="3083141271737748716">"יותר מדי ניסיונות שגויים.\nיש לנסות שוב בעוד <xliff:g id="NUMBER">%d</xliff:g> שניות."</string>
- <!-- no translation found for work_challenge_emergency_button_text (8946588434515599288) -->
- <skip />
+ <string name="work_challenge_emergency_button_text" msgid="8946588434515599288">"חירום"</string>
<string name="biometric_dialog_credential_attempts_before_wipe" msgid="6751859711975516999">"יש לנסות שוב. ניסיון <xliff:g id="ATTEMPTS_0">%1$d</xliff:g> מתוך <xliff:g id="MAX_ATTEMPTS">%2$d</xliff:g>."</string>
<string name="biometric_dialog_last_attempt_before_wipe_dialog_title" msgid="2874250099278693477">"הנתונים שלך יימחקו"</string>
<string name="biometric_dialog_last_pattern_attempt_before_wipe_device" msgid="6562299244825817598">"הזנת קו ביטול נעילה שגוי בניסיון הבא תגרום למחיקת הנתונים במכשיר."</string>
@@ -415,8 +413,7 @@
<string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="8736391633234144237">"‏בזמן שיתוף, הקלטה או העברה (cast) תהיה ל-<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> גישה לכל הפרטים שגלויים במסך שלך או מופעלים מהמכשיר שלך. מומלץ להיזהר עם סיסמאות, פרטי תשלום, הודעות, תמונות, אודיו וסרטונים."</string>
<string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="5211695779082563959">"‏בזמן שיתוף, הקלטה או העברה (cast) של אפליקציה, תהיה ל-<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> גישה לכל מה שגלוי באפליקציה או מופעל מהאפליקציה. מומלץ להיזהר עם סיסמאות, פרטי תשלום, הודעות, תמונות, אודיו וסרטונים."</string>
<string name="media_projection_entry_app_permission_dialog_continue" msgid="295463518195075840">"התחלה"</string>
- <!-- no translation found for media_projection_entry_app_permission_dialog_single_app_disabled (8999903044874669995) -->
- <skip />
+ <string name="media_projection_entry_app_permission_dialog_single_app_disabled" msgid="8999903044874669995">"האפליקציה <xliff:g id="APP_NAME">%1$s</xliff:g> השביתה את האפשרות הזו"</string>
<string name="media_projection_entry_cast_permission_dialog_title" msgid="8860150223172993547">"להתחיל את ההעברה?"</string>
<string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="1986212276016817231">"‏בזמן העברה (cast), תהיה ל-Android גישה לכל הפרטים שגלויים במסך שלך או מופעלים מהמכשיר שלך. מומלץ להיזהר עם סיסמאות, פרטי תשלום, הודעות, תמונות, אודיו וסרטונים."</string>
<string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="9900961380294292">"‏בזמן העברה (cast) של אפליקציה, תהיה ל-Android גישה לכל מה שגלוי באפליקציה או מופעל מהאפליקציה. כדאי להיזהר עם סיסמאות, פרטי תשלום, הודעות, תמונות, אודיו וסרטונים."</string>
@@ -1173,6 +1170,10 @@
<string name="assistant_attention_content_description" msgid="6830215897604642875">"‏Assistant מאזינה"</string>
<string name="set_default_notes_app_toast_content" msgid="2812374329662610753">"צריך להגדיר את אפליקציית ברירת המחדל לפתקים ב\'הגדרות\'"</string>
<string name="install_app" msgid="5066668100199613936">"התקנת האפליקציה"</string>
+ <!-- no translation found for connected_display_dialog_start_mirroring (6237895789920854982) -->
+ <skip />
+ <!-- no translation found for enable_display (8308309634883321977) -->
+ <skip />
<string name="privacy_dialog_title" msgid="7839968133469098311">"מיקרופון ומצלמה"</string>
<string name="privacy_dialog_summary" msgid="2458769652125995409">"נעשה שימוש לאחרונה באפליקציות"</string>
<string name="privacy_dialog_more_button" msgid="7610604080293562345">"צפייה בהרשאות הגישה האחרונות"</string>
diff --git a/packages/SystemUI/res/values-ja/strings.xml b/packages/SystemUI/res/values-ja/strings.xml
index 967d2d1818e5..5bd77fc5df48 100644
--- a/packages/SystemUI/res/values-ja/strings.xml
+++ b/packages/SystemUI/res/values-ja/strings.xml
@@ -57,8 +57,7 @@
<string name="hdmi_cec_set_menu_language_description" msgid="8176716678074126619">"他のデバイスからシステム言語の変更が要求されました"</string>
<string name="hdmi_cec_set_menu_language_accept" msgid="2513689457281009578">"言語を変更"</string>
<string name="hdmi_cec_set_menu_language_decline" msgid="7650721096558646011">"現在の言語を変更しない"</string>
- <!-- no translation found for share_wifi_button_text (1285273973812029240) -->
- <skip />
+ <string name="share_wifi_button_text" msgid="1285273973812029240">"Wi-Fi を共有"</string>
<string name="wifi_debugging_title" msgid="7300007687492186076">"このネットワークでワイヤレス デバッグを許可しますか?"</string>
<string name="wifi_debugging_message" msgid="5461204211731802995">"ネットワーク名(SSID)\n<xliff:g id="SSID_0">%1$s</xliff:g>\n\nWi‑Fi アドレス(BSSID)\n<xliff:g id="BSSID_1">%2$s</xliff:g>"</string>
<string name="wifi_debugging_always" msgid="2968383799517975155">"このネットワークで常に許可する"</string>
@@ -160,8 +159,7 @@
<string name="biometric_dialog_wrong_pattern" msgid="8954812279840889029">"パターンが正しくありません"</string>
<string name="biometric_dialog_wrong_password" msgid="69477929306843790">"パスワードが正しくありません"</string>
<string name="biometric_dialog_credential_too_many_attempts" msgid="3083141271737748716">"間違えた回数が上限を超えました。\n<xliff:g id="NUMBER">%d</xliff:g> 秒後にもう一度お試しください。"</string>
- <!-- no translation found for work_challenge_emergency_button_text (8946588434515599288) -->
- <skip />
+ <string name="work_challenge_emergency_button_text" msgid="8946588434515599288">"緊急通報"</string>
<string name="biometric_dialog_credential_attempts_before_wipe" msgid="6751859711975516999">"もう一度お試しください。入力回数: <xliff:g id="ATTEMPTS_0">%1$d</xliff:g>/<xliff:g id="MAX_ATTEMPTS">%2$d</xliff:g> 回"</string>
<string name="biometric_dialog_last_attempt_before_wipe_dialog_title" msgid="2874250099278693477">"データが削除されます"</string>
<string name="biometric_dialog_last_pattern_attempt_before_wipe_device" msgid="6562299244825817598">"パターンをあと 1 回間違えると、このデバイスのデータが削除されます。"</string>
@@ -415,8 +413,7 @@
<string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="8736391633234144237">"共有、録画、キャスト中は、画面に表示される内容やデバイスで再生される内容に <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> がアクセスできるため、パスワード、お支払いの詳細、メッセージ、写真、音声、動画などの情報にご注意ください。"</string>
<string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="5211695779082563959">"アプリの共有、録画、キャスト中は、そのアプリで表示または再生される内容に <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> がアクセスできるため、パスワード、お支払いの詳細、メッセージ、写真、音声、動画などの情報にご注意ください。"</string>
<string name="media_projection_entry_app_permission_dialog_continue" msgid="295463518195075840">"開始"</string>
- <!-- no translation found for media_projection_entry_app_permission_dialog_single_app_disabled (8999903044874669995) -->
- <skip />
+ <string name="media_projection_entry_app_permission_dialog_single_app_disabled" msgid="8999903044874669995">"<xliff:g id="APP_NAME">%1$s</xliff:g> がこのオプションを無効にしています"</string>
<string name="media_projection_entry_cast_permission_dialog_title" msgid="8860150223172993547">"キャスト開始しますか?"</string>
<string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="1986212276016817231">"キャスト中は、画面に表示される内容やデバイスで再生される内容に Android がアクセスできるため、パスワード、お支払いの詳細、メッセージ、写真、音声、動画などの情報にご注意ください。"</string>
<string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="9900961380294292">"アプリのキャスト中は、そのアプリで表示または再生される内容に Android がアクセスできるため、パスワード、お支払いの詳細、メッセージ、写真、音声、動画などの情報にご注意ください。"</string>
@@ -1173,6 +1170,10 @@
<string name="assistant_attention_content_description" msgid="6830215897604642875">"アシスタントは起動済みです"</string>
<string name="set_default_notes_app_toast_content" msgid="2812374329662610753">"[設定] でデフォルトのメモアプリを設定してください"</string>
<string name="install_app" msgid="5066668100199613936">"アプリをインストール"</string>
+ <!-- no translation found for connected_display_dialog_start_mirroring (6237895789920854982) -->
+ <skip />
+ <!-- no translation found for enable_display (8308309634883321977) -->
+ <skip />
<string name="privacy_dialog_title" msgid="7839968133469098311">"マイクとカメラ"</string>
<string name="privacy_dialog_summary" msgid="2458769652125995409">"最近のアプリの使用状況"</string>
<string name="privacy_dialog_more_button" msgid="7610604080293562345">"最近のアクセスを表示"</string>
diff --git a/packages/SystemUI/res/values-ka/strings.xml b/packages/SystemUI/res/values-ka/strings.xml
index 2a30da73c0d7..e0aa8ca955c7 100644
--- a/packages/SystemUI/res/values-ka/strings.xml
+++ b/packages/SystemUI/res/values-ka/strings.xml
@@ -57,8 +57,7 @@
<string name="hdmi_cec_set_menu_language_description" msgid="8176716678074126619">"სისტემის ენის შეცვლა მოითხოვა სხვა მოწყობილობამ"</string>
<string name="hdmi_cec_set_menu_language_accept" msgid="2513689457281009578">"ენის შეცვლა"</string>
<string name="hdmi_cec_set_menu_language_decline" msgid="7650721096558646011">"მიმდინარე ენის დატოვება"</string>
- <!-- no translation found for share_wifi_button_text (1285273973812029240) -->
- <skip />
+ <string name="share_wifi_button_text" msgid="1285273973812029240">"Wi‑Fi-ს გაზიარება"</string>
<string name="wifi_debugging_title" msgid="7300007687492186076">"დაუშვებთ ამ ქსელში შეცდომების უსადენო გამართვას?"</string>
<string name="wifi_debugging_message" msgid="5461204211731802995">"ქსელის სახელი (SSID)\n<xliff:g id="SSID_0">%1$s</xliff:g>\n\nWi‑Fi მისამართი (BSSID)\n<xliff:g id="BSSID_1">%2$s</xliff:g>"</string>
<string name="wifi_debugging_always" msgid="2968383799517975155">"ყოველთვის დაშვება ამ ქსელში"</string>
@@ -160,8 +159,7 @@
<string name="biometric_dialog_wrong_pattern" msgid="8954812279840889029">"ნიმუში არასწორია"</string>
<string name="biometric_dialog_wrong_password" msgid="69477929306843790">"პაროლი არასწორია"</string>
<string name="biometric_dialog_credential_too_many_attempts" msgid="3083141271737748716">"დაფიქსირდა ძალიან ბევრი არასწორი მცდელობა.\nცადეთ ხელახლა <xliff:g id="NUMBER">%d</xliff:g> წამში."</string>
- <!-- no translation found for work_challenge_emergency_button_text (8946588434515599288) -->
- <skip />
+ <string name="work_challenge_emergency_button_text" msgid="8946588434515599288">"საგანგებო სიტუაცია"</string>
<string name="biometric_dialog_credential_attempts_before_wipe" msgid="6751859711975516999">"ცადეთ ხელახლა. მცდელობა <xliff:g id="ATTEMPTS_0">%1$d</xliff:g> / <xliff:g id="MAX_ATTEMPTS">%2$d</xliff:g>-დან."</string>
<string name="biometric_dialog_last_attempt_before_wipe_dialog_title" msgid="2874250099278693477">"თქვენი მონაცემები წაიშლება"</string>
<string name="biometric_dialog_last_pattern_attempt_before_wipe_device" msgid="6562299244825817598">"შემდეგი მცდელობისას განმბლოკავი ნიმუშის არასწორად შეყვანის შემთხვევაში, ამ მოწყობილობის მონაცემები წაიშლება."</string>
@@ -415,8 +413,7 @@
<string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="8736391633234144237">"გაზიარების, ჩაწერის ან ტრანსლირების დროს, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>-ს აქვს წვდომა ყველაფერზე, რაც ჩანს თქვენს ეკრანზე ან უკრავს თქვენს მოწყობილობაზე. ამიტომ იყავით ფრთხილად ისეთ ინფორმაციასთან, როგორიცაა პაროლები, გადახდის დეტალები, შეტყობინებები, ფოტოები, აუდიო და ვიდეო."</string>
<string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="5211695779082563959">"აპის გაზიარებისას, ჩაწერისას ან ტრანსლირებისას, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>-ს წვდომა აქვს ყველაფერზე, რაც ჩანს ან იკვრება აპში. ამიტომ იყავით ფრთხილად ისეთ ინფორმაციასთან, როგორიცაა პაროლები, გადახდის დეტალები, შეტყობინებები, ფოტოები, აუდიო და ვიდეო."</string>
<string name="media_projection_entry_app_permission_dialog_continue" msgid="295463518195075840">"დაწყება"</string>
- <!-- no translation found for media_projection_entry_app_permission_dialog_single_app_disabled (8999903044874669995) -->
- <skip />
+ <string name="media_projection_entry_app_permission_dialog_single_app_disabled" msgid="8999903044874669995">"<xliff:g id="APP_NAME">%1$s</xliff:g>-მა გათიშა ეს ვარიანტი"</string>
<string name="media_projection_entry_cast_permission_dialog_title" msgid="8860150223172993547">"გსურთ ტრანსლირების დაწყება?"</string>
<string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="1986212276016817231">"როდესაც თქვენ ტრანსლირებთ, ამ აპს აქვს წვდომა ყველაფერზე, რაც ჩანს თქვენს ეკრანზე ან უკრავს თქვენს მოწყობილობაზე. ამიტომ იყავით ფრთხილად ისეთ ინფორმაციასთან, როგორიცაა პაროლები, გადახდის დეტალები, შეტყობინებები, ფოტოები, აუდიო და ვიდეო."</string>
<string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="9900961380294292">"როდესაც აპს ტრანსლირებთ, Android-ს წვდომა აქვს ყველაფერზე, რაც ჩანს ან იკვრება აპში. ამიტომ იყავით ფრთხილად ისეთ ინფორმაციასთან, როგორიცაა პაროლები, გადახდის დეტალები, შეტყობინებები, ფოტოები, აუდიო და ვიდეო."</string>
@@ -1173,6 +1170,8 @@
<string name="assistant_attention_content_description" msgid="6830215897604642875">"ასისტენტის ყურადღების ფუნქცია ჩართულია"</string>
<string name="set_default_notes_app_toast_content" msgid="2812374329662610753">"დააყენეთ ნაგულისხმევი შენიშვნების აპი პარამეტრებში"</string>
<string name="install_app" msgid="5066668100199613936">"აპის ინსტალაცია"</string>
+ <string name="connected_display_dialog_start_mirroring" msgid="6237895789920854982">"აირეკლოს გარე ეკრანზე?"</string>
+ <string name="enable_display" msgid="8308309634883321977">"ეკრანის ჩართვა"</string>
<string name="privacy_dialog_title" msgid="7839968133469098311">"მიკროფონი და კამერა"</string>
<string name="privacy_dialog_summary" msgid="2458769652125995409">"აპის ბოლოდროინდელი გამოყენება"</string>
<string name="privacy_dialog_more_button" msgid="7610604080293562345">"ბოლო წვდომის ნახვა"</string>
diff --git a/packages/SystemUI/res/values-kk/strings.xml b/packages/SystemUI/res/values-kk/strings.xml
index 1adda91ee5da..917383bc4979 100644
--- a/packages/SystemUI/res/values-kk/strings.xml
+++ b/packages/SystemUI/res/values-kk/strings.xml
@@ -57,8 +57,7 @@
<string name="hdmi_cec_set_menu_language_description" msgid="8176716678074126619">"Басқа құрылғыдан жүйе тілін өзгерту туралы сұрау жіберілді."</string>
<string name="hdmi_cec_set_menu_language_accept" msgid="2513689457281009578">"Тілді өзгерту"</string>
<string name="hdmi_cec_set_menu_language_decline" msgid="7650721096558646011">"Қазіргі тіл тұра берсін"</string>
- <!-- no translation found for share_wifi_button_text (1285273973812029240) -->
- <skip />
+ <string name="share_wifi_button_text" msgid="1285273973812029240">"Wi‑Fi желісін бөлісу"</string>
<string name="wifi_debugging_title" msgid="7300007687492186076">"Бұл желіде сымсыз түзетуге рұқсат етілсін бе?"</string>
<string name="wifi_debugging_message" msgid="5461204211731802995">"Желі атауы (SSID)\n<xliff:g id="SSID_0">%1$s</xliff:g>\n\nWi‑Fi мекенжайы (BSSID)\n<xliff:g id="BSSID_1">%2$s</xliff:g>"</string>
<string name="wifi_debugging_always" msgid="2968383799517975155">"Осы желіде үнемі рұқсат ету"</string>
@@ -160,8 +159,7 @@
<string name="biometric_dialog_wrong_pattern" msgid="8954812279840889029">"Өрнек қате."</string>
<string name="biometric_dialog_wrong_password" msgid="69477929306843790">"Құпия сөз қате."</string>
<string name="biometric_dialog_credential_too_many_attempts" msgid="3083141271737748716">"Тым көп қате енгізілді.\n<xliff:g id="NUMBER">%d</xliff:g> секундта әрекетті қайталаңыз."</string>
- <!-- no translation found for work_challenge_emergency_button_text (8946588434515599288) -->
- <skip />
+ <string name="work_challenge_emergency_button_text" msgid="8946588434515599288">"Төтенше жағдай"</string>
<string name="biometric_dialog_credential_attempts_before_wipe" msgid="6751859711975516999">"Әрекетті қайталаңыз. <xliff:g id="ATTEMPTS_0">%1$d</xliff:g> мүмкіндік, барлығы – <xliff:g id="MAX_ATTEMPTS">%2$d</xliff:g>."</string>
<string name="biometric_dialog_last_attempt_before_wipe_dialog_title" msgid="2874250099278693477">"Деректеріңіз жойылады"</string>
<string name="biometric_dialog_last_pattern_attempt_before_wipe_device" msgid="6562299244825817598">"Келесі әрекет кезінде қате өрнек енгізсеңіз, бұл құрылғылардың деректері жойылады."</string>
@@ -415,8 +413,7 @@
<string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="8736391633234144237">"Бөлісу, жазу не трансляциялау кезінде <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> экраныңызда көрінетін не құрылғыңызда ойнатылатын барлық нәрсені пайдалана алады. Сондықтан құпия сөздерді, төлем туралы мәліметті, хабарларды немесе басқа құпия ақпаратты енгізген кезде сақ болыңыз."</string>
<string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="5211695779082563959">"Қолданба экранын бөлісу, жазу не трансляциялау кезінде <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> онда көрінетін не ойнатылатын барлық нәрсені пайдалана алады. Сондықтан құпия сөздерді, төлем туралы мәліметті, хабарларды немесе басқа құпия ақпаратты енгізген кезде сақ болыңыз."</string>
<string name="media_projection_entry_app_permission_dialog_continue" msgid="295463518195075840">"Бастау"</string>
- <!-- no translation found for media_projection_entry_app_permission_dialog_single_app_disabled (8999903044874669995) -->
- <skip />
+ <string name="media_projection_entry_app_permission_dialog_single_app_disabled" msgid="8999903044874669995">"<xliff:g id="APP_NAME">%1$s</xliff:g> қолданбасы осы опцияны өшірді."</string>
<string name="media_projection_entry_cast_permission_dialog_title" msgid="8860150223172993547">"Трансляциялау басталсын ба?"</string>
<string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="1986212276016817231">"Трансляциялау кезінде Android жүйесі экраныңызда көрінетін не құрылғыңызда ойнатылатын барлық нәрсені пайдалана алады. Сондықтан құпия сөздерді, төлем туралы мәліметті, хабарларды немесе басқа құпия ақпаратты енгізген кезде сақ болыңыз."</string>
<string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="9900961380294292">"Қолданба экранын трансляциялау кезінде Android жүйесі қолданбада көрінетін не ойнатылатын барлық нәрсені пайдалана алады. Сондықтан құпия сөздерді, төлем туралы мәліметті, хабарларды немесе басқа құпия ақпаратты енгізген кезде сақ болыңыз."</string>
@@ -1173,6 +1170,10 @@
<string name="assistant_attention_content_description" msgid="6830215897604642875">"Assistant қосулы."</string>
<string name="set_default_notes_app_toast_content" msgid="2812374329662610753">"Параметрлерден әдепкі жазба қолданбасын орнатыңыз."</string>
<string name="install_app" msgid="5066668100199613936">"Қолданбаны орнату"</string>
+ <!-- no translation found for connected_display_dialog_start_mirroring (6237895789920854982) -->
+ <skip />
+ <!-- no translation found for enable_display (8308309634883321977) -->
+ <skip />
<string name="privacy_dialog_title" msgid="7839968133469098311">"Микрофон және камера"</string>
<string name="privacy_dialog_summary" msgid="2458769652125995409">"Соңғы рет қолданбаның датчикті пайдалануы"</string>
<string name="privacy_dialog_more_button" msgid="7610604080293562345">"Соңғы рет пайдаланғандар"</string>
diff --git a/packages/SystemUI/res/values-km/strings.xml b/packages/SystemUI/res/values-km/strings.xml
index af1e3b500e54..92c2c1b35c73 100644
--- a/packages/SystemUI/res/values-km/strings.xml
+++ b/packages/SystemUI/res/values-km/strings.xml
@@ -57,8 +57,7 @@
<string name="hdmi_cec_set_menu_language_description" msgid="8176716678074126619">"ការប្ដូរភាសា​ប្រព័ន្ធដែលបានស្នើសុំ​ដោយ​ឧបករណ៍ផ្សេងទៀត"</string>
<string name="hdmi_cec_set_menu_language_accept" msgid="2513689457281009578">"​ប្ដូរ​ភាសា"</string>
<string name="hdmi_cec_set_menu_language_decline" msgid="7650721096558646011">"រក្សាភាសាបច្ចុប្បន្ន"</string>
- <!-- no translation found for share_wifi_button_text (1285273973812029240) -->
- <skip />
+ <string name="share_wifi_button_text" msgid="1285273973812029240">"ចែករំលែក Wi‑Fi"</string>
<string name="wifi_debugging_title" msgid="7300007687492186076">"អនុញ្ញាត​ការជួសជុល​ដោយឥតខ្សែ​នៅលើ​បណ្ដាញ​នេះ​ឬ?"</string>
<string name="wifi_debugging_message" msgid="5461204211731802995">"ឈ្មោះបណ្ដាញ (SSID)\n<xliff:g id="SSID_0">%1$s</xliff:g>\n\nអាសយដ្ឋាន Wi‑Fi (BSSID)\n<xliff:g id="BSSID_1">%2$s</xliff:g>"</string>
<string name="wifi_debugging_always" msgid="2968383799517975155">"អនុញ្ញាត​នៅលើ​បណ្ដាញ​នេះ​ជានិច្ច"</string>
@@ -160,8 +159,7 @@
<string name="biometric_dialog_wrong_pattern" msgid="8954812279840889029">"លំនាំមិនត្រឹមត្រូវ"</string>
<string name="biometric_dialog_wrong_password" msgid="69477929306843790">"ពាក្យសម្ងាត់មិនត្រឹមត្រូវ"</string>
<string name="biometric_dialog_credential_too_many_attempts" msgid="3083141271737748716">"ការព្យាយាម​ចូលខុស​ច្រើនដងពេក។\nសូមព្យាយាម​ម្តងទៀត​ក្នុងរយៈពេល <xliff:g id="NUMBER">%d</xliff:g> វិនាទី។"</string>
- <!-- no translation found for work_challenge_emergency_button_text (8946588434515599288) -->
- <skip />
+ <string name="work_challenge_emergency_button_text" msgid="8946588434515599288">"ពេលមានអាសន្ន"</string>
<string name="biometric_dialog_credential_attempts_before_wipe" msgid="6751859711975516999">"សូមព្យាយាម​ម្តងទៀត។ ការព្យាយាម <xliff:g id="ATTEMPTS_0">%1$d</xliff:g> នៃ <xliff:g id="MAX_ATTEMPTS">%2$d</xliff:g> ដង។"</string>
<string name="biometric_dialog_last_attempt_before_wipe_dialog_title" msgid="2874250099278693477">"ទិន្នន័យរបស់អ្នកនឹងត្រូវបានលុប"</string>
<string name="biometric_dialog_last_pattern_attempt_before_wipe_device" msgid="6562299244825817598">"ប្រសិនបើអ្នក​បញ្ចូលលំនាំ​មិនត្រឹមត្រូវ នៅពេលព្យាយាមបញ្ចូល​លើកក្រោយ ទិន្នន័យរបស់​ឧបករណ៍នេះ​នឹងត្រូវបានលុប។"</string>
@@ -415,8 +413,7 @@
<string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="8736391633234144237">"នៅពេលអ្នកកំពុងចែករំលែក ថត ឬភ្ជាប់, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> មានសិទ្ធិចូលប្រើអ្វីៗដែលអាចមើលឃើញនៅលើអេក្រង់របស់អ្នក ឬចាក់នៅលើឧបករណ៍របស់អ្នក។ ដូច្នេះ សូមប្រុងប្រយ័ត្នចំពោះអ្វីៗដូចជា ពាក្យសម្ងាត់ ព័ត៌មានលម្អិតអំពីការទូទាត់ប្រាក់ សារ រូបថត ព្រមទាំងសំឡេង និងវីដេអូ។"</string>
<string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="5211695779082563959">"នៅពេលអ្នកកំពុងចែករំលែក ថត ឬភ្ជាប់កម្មវិធី, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> មានសិទ្ធិចូលប្រើអ្វីៗដែលបង្ហាញ ឬចាក់នៅលើកម្មវិធីនោះ។ ដូច្នេះ សូមប្រុងប្រយ័ត្នចំពោះអ្វីៗដូចជា ពាក្យសម្ងាត់ ព័ត៌មានលម្អិតអំពីការទូទាត់ប្រាក់ សារ រូបថត ព្រមទាំងសំឡេង និងវីដេអូ។"</string>
<string name="media_projection_entry_app_permission_dialog_continue" msgid="295463518195075840">"ចាប់ផ្ដើម"</string>
- <!-- no translation found for media_projection_entry_app_permission_dialog_single_app_disabled (8999903044874669995) -->
- <skip />
+ <string name="media_projection_entry_app_permission_dialog_single_app_disabled" msgid="8999903044874669995">"<xliff:g id="APP_NAME">%1$s</xliff:g> បានបិទជម្រើសនេះ"</string>
<string name="media_projection_entry_cast_permission_dialog_title" msgid="8860150223172993547">"ចាប់ផ្តើមភ្ជាប់ឬ?"</string>
<string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="1986212276016817231">"នៅពេលអ្នក​កំពុងភ្ជាប់, Android មានសិទ្ធិចូលប្រើអ្វីៗដែលអាចមើលឃើញនៅលើ​អេក្រង់របស់អ្នក ឬចាក់នៅលើឧបករណ៍របស់អ្នក។ ដូច្នេះ សូមប្រុងប្រយ័ត្នចំពោះអ្វីៗដូចជា ពាក្យសម្ងាត់ ព័ត៌មានលម្អិតអំពីការទូទាត់ប្រាក់ សារ រូបថត ព្រមទាំងសំឡេង និងវីដេអូ។"</string>
<string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="9900961380294292">"នៅពេលអ្នក​កំពុងភ្ជាប់កម្មវិធី, Android មានសិទ្ធិចូលប្រើអ្វីៗដែលបង្ហាញ ឬចាក់នៅលើកម្មវិធីនោះ។ ដូច្នេះ សូមប្រុងប្រយ័ត្នចំពោះអ្វីៗដូចជា ពាក្យសម្ងាត់ ព័ត៌មានលម្អិតអំពីការទូទាត់ប្រាក់ សារ រូបថត ព្រមទាំងសំឡេង និងវីដេអូ។"</string>
@@ -1173,6 +1170,10 @@
<string name="assistant_attention_content_description" msgid="6830215897604642875">"ភាពប្រុងប្រៀប​របស់ Google Assistant ត្រូវបានបើក"</string>
<string name="set_default_notes_app_toast_content" msgid="2812374329662610753">"កំណត់កម្មវិធីកំណត់ចំណាំលំនាំដើមនៅក្នុងការកំណត់"</string>
<string name="install_app" msgid="5066668100199613936">"ដំឡើង​កម្មវិធី"</string>
+ <!-- no translation found for connected_display_dialog_start_mirroring (6237895789920854982) -->
+ <skip />
+ <!-- no translation found for enable_display (8308309634883321977) -->
+ <skip />
<string name="privacy_dialog_title" msgid="7839968133469098311">"មីក្រូហ្វូន និងកាមេរ៉ា"</string>
<string name="privacy_dialog_summary" msgid="2458769652125995409">"ការប្រើប្រាស់កម្មវិធីថ្មីៗនេះ"</string>
<string name="privacy_dialog_more_button" msgid="7610604080293562345">"មើលការចូលប្រើនាពេលថ្មីៗនេះ"</string>
diff --git a/packages/SystemUI/res/values-kn/strings.xml b/packages/SystemUI/res/values-kn/strings.xml
index db1b35dfaf43..6c0f833b563b 100644
--- a/packages/SystemUI/res/values-kn/strings.xml
+++ b/packages/SystemUI/res/values-kn/strings.xml
@@ -57,8 +57,7 @@
<string name="hdmi_cec_set_menu_language_description" msgid="8176716678074126619">"ಬೇರೊಂದು ಸಾಧನದಿಂದ ಸಿಸ್ಟಮ್ ಭಾಷೆಯ ಬದಲಾವಣೆಯನ್ನು ವಿನಂತಿಸಲಾಗಿದೆ"</string>
<string name="hdmi_cec_set_menu_language_accept" msgid="2513689457281009578">"ಭಾಷೆಯನ್ನು ಬದಲಾಯಿಸಿ"</string>
<string name="hdmi_cec_set_menu_language_decline" msgid="7650721096558646011">"ಪ್ರಸ್ತುತ ಭಾಷೆಯನ್ನೇ ಇರಿಸಿ"</string>
- <!-- no translation found for share_wifi_button_text (1285273973812029240) -->
- <skip />
+ <string name="share_wifi_button_text" msgid="1285273973812029240">"ವೈ-ಫೈ ಹಂಚಿಕೊಳ್ಳಿ"</string>
<string name="wifi_debugging_title" msgid="7300007687492186076">"ಈ ನೆಟ್‌ವರ್ಕ್‌ನಲ್ಲಿ ವೈರ್‌ಲೆಸ್ ಡೀಬಗ್ ಮಾಡುವಿಕೆಯನ್ನು ಅನುಮತಿಸಬೇಕೆ?"</string>
<string name="wifi_debugging_message" msgid="5461204211731802995">"ನೆಟ್‌ವರ್ಕ್ ಹೆಸರು (SSID)\n<xliff:g id="SSID_0">%1$s</xliff:g>\n\nವೈ-ಫೈ ವಿಳಾಸ (BSSID)\n<xliff:g id="BSSID_1">%2$s</xliff:g>"</string>
<string name="wifi_debugging_always" msgid="2968383799517975155">"ಈ ನೆಟ್‌ವರ್ಕ್‌ನಲ್ಲಿ ಅನುಮತಿಸಿ"</string>
@@ -160,8 +159,7 @@
<string name="biometric_dialog_wrong_pattern" msgid="8954812279840889029">"ಪ್ಯಾಟರ್ನ್ ತಪ್ಪಾಗಿದೆ"</string>
<string name="biometric_dialog_wrong_password" msgid="69477929306843790">"ಪಾಸ್‌ವರ್ಡ್ ತಪ್ಪಾಗಿದೆ"</string>
<string name="biometric_dialog_credential_too_many_attempts" msgid="3083141271737748716">"ಹಲವಾರು ತಪ್ಪು ಪ್ರಯತ್ನಗಳು.\nಮತ್ತೆ <xliff:g id="NUMBER">%d</xliff:g> ಸೆಕೆಂಡುಗಳಲ್ಲಿ ಪ್ರಯತ್ನಿಸಿ."</string>
- <!-- no translation found for work_challenge_emergency_button_text (8946588434515599288) -->
- <skip />
+ <string name="work_challenge_emergency_button_text" msgid="8946588434515599288">"ತುರ್ತು"</string>
<string name="biometric_dialog_credential_attempts_before_wipe" msgid="6751859711975516999">"ಮತ್ತೆ ಪ್ರಯತ್ನಿಸಿ. <xliff:g id="ATTEMPTS_0">%1$d</xliff:g>/<xliff:g id="MAX_ATTEMPTS">%2$d</xliff:g> ಪ್ರಯತ್ನಗಳು."</string>
<string name="biometric_dialog_last_attempt_before_wipe_dialog_title" msgid="2874250099278693477">"ನಿಮ್ಮ ಡೇಟಾವನ್ನು ಅಳಿಸಲಾಗುತ್ತದೆ"</string>
<string name="biometric_dialog_last_pattern_attempt_before_wipe_device" msgid="6562299244825817598">"ಮುಂದಿನ ಪ್ರಯತ್ನದಲ್ಲಿ ನೀವು ತಪ್ಪಾದ ಪ್ಯಾಟರ್ನ್‌ ನಮೂದಿಸಿದರೆ, ಈ ಸಾಧನದ ಡೇಟಾವನ್ನು ಅಳಿಸಲಾಗುತ್ತದೆ."</string>
@@ -415,8 +413,7 @@
<string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="8736391633234144237">"ನೀವು ಹಂಚಿಕೊಳ್ಳುತ್ತಿರುವಾಗ, ರೆಕಾರ್ಡಿಂಗ್ ಮಾಡುತ್ತಿರುವಾಗ ಅಥವಾ ಕ್ಯಾಸ್ಟ್ ಮಾಡುತ್ತಿರುವಾಗ, ನಿಮ್ಮ ಸ್ಕ್ರೀನ್ ಮೇಲೆ ಕಾಣಿಸುವ ಅಥವಾ ನಿಮ್ಮ ಸಾಧನದಲ್ಲಿ ಪ್ಲೇ ಮಾಡುವ ಯಾವುದೇ ವಿಷಯಕ್ಕೆ <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> ಆ್ಯಕ್ಸೆಸ್ ಅನ್ನು ಹೊಂದಿರುತ್ತದೆ. ಆದ್ದರಿಂದ ಪಾಸ್‌ವರ್ಡ್‌ಗಳು, ಪಾವತಿ ವಿವರಗಳು, ಸಂದೇಶಗಳು, ಫೋಟೋಗಳು ಹಾಗೂ ಆಡಿಯೊ ಮತ್ತು ವೀಡಿಯೊದಂತಹ ವಿಷಯಗಳ ಕುರಿತು ಜಾಗರೂಕರಾಗಿರಿ."</string>
<string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="5211695779082563959">"ನೀವು ಆ್ಯಪ್ ಅನ್ನು ಹಂಚಿಕೊಳ್ಳುತ್ತಿರುವಾಗ, ರೆಕಾರ್ಡಿಂಗ್ ಮಾಡುತ್ತಿರುವಾಗ ಅಥವಾ ಕ್ಯಾಸ್ಟ್ ಮಾಡುತ್ತಿರುವಾಗ, ಆ ಆ್ಯಪ್‌ನಲ್ಲಿ ತೋರಿಸುವ ಅಥವಾ ಪ್ಲೇ ಮಾಡುವ ಯಾವುದೇ ವಿಷಯಕ್ಕೆ <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> ಆ್ಯಕ್ಸೆಸ್ ಅನ್ನು ಹೊಂದಿರುತ್ತದೆ. ಆದ್ದರಿಂದ ಪಾಸ್‌ವರ್ಡ್‌ಗಳು, ಪಾವತಿ ವಿವರಗಳು, ಸಂದೇಶಗಳು, ಫೋಟೋಗಳು ಹಾಗೂ ಆಡಿಯೊ ಮತ್ತು ವೀಡಿಯೊದಂತಹ ವಿಷಯಗಳ ಕುರಿತು ಜಾಗರೂಕರಾಗಿರಿ."</string>
<string name="media_projection_entry_app_permission_dialog_continue" msgid="295463518195075840">"ಪ್ರಾರಂಭಿಸಿ"</string>
- <!-- no translation found for media_projection_entry_app_permission_dialog_single_app_disabled (8999903044874669995) -->
- <skip />
+ <string name="media_projection_entry_app_permission_dialog_single_app_disabled" msgid="8999903044874669995">"<xliff:g id="APP_NAME">%1$s</xliff:g> ಈ ಆಯ್ಕೆಯನ್ನು ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಿದೆ"</string>
<string name="media_projection_entry_cast_permission_dialog_title" msgid="8860150223172993547">"ಕ್ಯಾಸ್ಟ್ ಮಾಡಲು ಪ್ರಾರಂಭಿಸಬೇಕೇ?"</string>
<string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="1986212276016817231">"ನೀವು ಕ್ಯಾಸ್ಟ್ ಮಾಡುವಾಗ, ನಿಮ್ಮ ಸ್ಕ್ರೀನ್ ಮೇಲೆ ಕಾಣಿಸುವ ಅಥವಾ ನಿಮ್ಮ ಸಾಧನದಲ್ಲಿ ಪ್ಲೇ ಮಾಡುವ ಯಾವುದೇ ವಿಷಯಕ್ಕೆ Android ಆ್ಯಕ್ಸೆಸ್ ಅನ್ನು ಹೊಂದಿರುತ್ತದೆ. ಆದ್ದರಿಂದ ಪಾಸ್‌ವರ್ಡ್‌ಗಳು, ಪಾವತಿ ವಿವರಗಳು, ಸಂದೇಶಗಳು, ಫೋಟೋಗಳು ಹಾಗೂ ಆಡಿಯೊ ಮತ್ತು ವೀಡಿಯೊದಂತಹ ವಿಷಯಗಳ ಕುರಿತು ಜಾಗರೂಕರಾಗಿರಿ."</string>
<string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="9900961380294292">"ನೀವು ಆ್ಯಪ್ ಅನ್ನು ಕ್ಯಾಸ್ಟ್ ಮಾಡುತ್ತಿರುವಾಗ, ಆ ಆ್ಯಪ್‌ನಲ್ಲಿ ತೋರಿಸುವ ಅಥವಾ ಪ್ಲೇ ಮಾಡುವ ಯಾವುದೇ ವಿಷಯಕ್ಕೆ Android ಆ್ಯಕ್ಸೆಸ್ ಅನ್ನು ಹೊಂದಿರುತ್ತದೆ. ಆದ್ದರಿಂದ ಪಾಸ್‌ವರ್ಡ್‌ಗಳು, ಪಾವತಿ ವಿವರಗಳು, ಸಂದೇಶಗಳು, ಫೋಟೋಗಳು ಹಾಗೂ ಆಡಿಯೊ ಮತ್ತು ವೀಡಿಯೊದಂತಹ ವಿಷಯಗಳ ಕುರಿತು ಜಾಗರೂಕರಾಗಿರಿ."</string>
@@ -1173,6 +1170,10 @@
<string name="assistant_attention_content_description" msgid="6830215897604642875">"Assistant ನಿಮ್ಮ ಮಾತನ್ನು ಆಲಿಸುತ್ತಿದೆ"</string>
<string name="set_default_notes_app_toast_content" msgid="2812374329662610753">"ಸೆಟ್ಟಿಂಗ್‌ಗಳಲ್ಲಿ ಡೀಫಾಲ್ಟ್ ಟಿಪ್ಪಣಿಗಳ ಆ್ಯಪ್ ಅನ್ನು ಸೆಟ್ ಮಾಡಿ"</string>
<string name="install_app" msgid="5066668100199613936">"ಆ್ಯಪ್ ಇನ್‌ಸ್ಟಾಲ್ ಮಾಡಿ"</string>
+ <!-- no translation found for connected_display_dialog_start_mirroring (6237895789920854982) -->
+ <skip />
+ <!-- no translation found for enable_display (8308309634883321977) -->
+ <skip />
<string name="privacy_dialog_title" msgid="7839968133469098311">"ಮೈಕ್ರೊಫೋನ್ ಮತ್ತು ಕ್ಯಾಮರಾ"</string>
<string name="privacy_dialog_summary" msgid="2458769652125995409">"ಇತ್ತೀಚಿನ ಆ್ಯಪ್ ಬಳಕೆ"</string>
<string name="privacy_dialog_more_button" msgid="7610604080293562345">"ಇತ್ತೀಚಿನ ಆ್ಯಕ್ಸೆಸ್ ಅನ್ನು ನೋಡಿ"</string>
diff --git a/packages/SystemUI/res/values-ko/strings.xml b/packages/SystemUI/res/values-ko/strings.xml
index 97271c580103..491c4e47073f 100644
--- a/packages/SystemUI/res/values-ko/strings.xml
+++ b/packages/SystemUI/res/values-ko/strings.xml
@@ -57,8 +57,7 @@
<string name="hdmi_cec_set_menu_language_description" msgid="8176716678074126619">"다른 기기에서 시스템 언어 변경을 요청함"</string>
<string name="hdmi_cec_set_menu_language_accept" msgid="2513689457281009578">"언어 변경"</string>
<string name="hdmi_cec_set_menu_language_decline" msgid="7650721096558646011">"현재 언어 유지"</string>
- <!-- no translation found for share_wifi_button_text (1285273973812029240) -->
- <skip />
+ <string name="share_wifi_button_text" msgid="1285273973812029240">"Wi‑Fi 공유"</string>
<string name="wifi_debugging_title" msgid="7300007687492186076">"이 네트워크에서 무선 디버깅을 허용하시겠습니까?"</string>
<string name="wifi_debugging_message" msgid="5461204211731802995">"네트워크 이름(SSID)\n<xliff:g id="SSID_0">%1$s</xliff:g>\n\nWi‑Fi 주소(BSSID)\n<xliff:g id="BSSID_1">%2$s</xliff:g>"</string>
<string name="wifi_debugging_always" msgid="2968383799517975155">"이 네트워크에서 항상 허용"</string>
@@ -160,8 +159,7 @@
<string name="biometric_dialog_wrong_pattern" msgid="8954812279840889029">"잘못된 패턴"</string>
<string name="biometric_dialog_wrong_password" msgid="69477929306843790">"잘못된 비밀번호"</string>
<string name="biometric_dialog_credential_too_many_attempts" msgid="3083141271737748716">"잘못된 시도 횟수가 너무 많습니다.\n<xliff:g id="NUMBER">%d</xliff:g>초 후에 다시 시도하세요."</string>
- <!-- no translation found for work_challenge_emergency_button_text (8946588434515599288) -->
- <skip />
+ <string name="work_challenge_emergency_button_text" msgid="8946588434515599288">"긴급"</string>
<string name="biometric_dialog_credential_attempts_before_wipe" msgid="6751859711975516999">"다시 시도하세요. <xliff:g id="MAX_ATTEMPTS">%2$d</xliff:g>회 중 <xliff:g id="ATTEMPTS_0">%1$d</xliff:g>번째 시도입니다."</string>
<string name="biometric_dialog_last_attempt_before_wipe_dialog_title" msgid="2874250099278693477">"데이터가 삭제됨"</string>
<string name="biometric_dialog_last_pattern_attempt_before_wipe_device" msgid="6562299244825817598">"다음번 시도에서 잘못된 패턴을 입력하면 이 기기의 데이터가 삭제됩니다."</string>
@@ -415,8 +413,7 @@
<string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="8736391633234144237">"공유, 녹화 또는 전송 중에 <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> 앱이 화면에 표시되거나 기기에서 재생되는 모든 항목에 액세스할 수 있습니다. 따라서 비밀번호, 결제 세부정보, 메시지, 사진, 오디오 및 동영상 등이 노출되지 않도록 주의하세요."</string>
<string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="5211695779082563959">"앱을 공유, 녹화 또는 전송할 때는 <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> 앱이 해당 앱에 표시되거나 재생되는 모든 항목에 액세스할 수 있으므로 비밀번호, 결제 세부정보, 메시지, 사진, 오디오 및 동영상 등이 노출되지 않도록 주의하세요."</string>
<string name="media_projection_entry_app_permission_dialog_continue" msgid="295463518195075840">"시작"</string>
- <!-- no translation found for media_projection_entry_app_permission_dialog_single_app_disabled (8999903044874669995) -->
- <skip />
+ <string name="media_projection_entry_app_permission_dialog_single_app_disabled" msgid="8999903044874669995">"<xliff:g id="APP_NAME">%1$s</xliff:g>에서 이 옵션을 사용 중지했습니다."</string>
<string name="media_projection_entry_cast_permission_dialog_title" msgid="8860150223172993547">"전송을 시작하시겠습니까?"</string>
<string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="1986212276016817231">"전송 중에는 Android가 화면에 표시되거나 기기에서 재생되는 모든 항목에 액세스할 수 있습니다. 따라서 비밀번호, 결제 세부정보, 메시지, 사진, 오디오 및 동영상 등이 노출되지 않도록 주의하세요."</string>
<string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="9900961380294292">"앱을 전송할 때 Android가 해당 앱에 표시되거나 재생되는 모든 항목에 액세스할 수 있으므로 비밀번호, 결제 세부정보, 메시지, 사진, 오디오 및 동영상 등이 노출되지 않도록 주의하세요."</string>
@@ -1173,6 +1170,10 @@
<string name="assistant_attention_content_description" msgid="6830215897604642875">"어시스턴트가 대기 중임"</string>
<string name="set_default_notes_app_toast_content" msgid="2812374329662610753">"설정에서 기본 메모 앱 설정"</string>
<string name="install_app" msgid="5066668100199613936">"앱 설치"</string>
+ <!-- no translation found for connected_display_dialog_start_mirroring (6237895789920854982) -->
+ <skip />
+ <!-- no translation found for enable_display (8308309634883321977) -->
+ <skip />
<string name="privacy_dialog_title" msgid="7839968133469098311">"마이크 및 카메라"</string>
<string name="privacy_dialog_summary" msgid="2458769652125995409">"최근 앱 사용"</string>
<string name="privacy_dialog_more_button" msgid="7610604080293562345">"최근 액세스 보기"</string>
diff --git a/packages/SystemUI/res/values-ky/strings.xml b/packages/SystemUI/res/values-ky/strings.xml
index db47e39a5de1..77e4e9c7c844 100644
--- a/packages/SystemUI/res/values-ky/strings.xml
+++ b/packages/SystemUI/res/values-ky/strings.xml
@@ -57,8 +57,7 @@
<string name="hdmi_cec_set_menu_language_description" msgid="8176716678074126619">"Система тилин өзгөртүү сурамы башка түзмөктөн жөнөтүлдү"</string>
<string name="hdmi_cec_set_menu_language_accept" msgid="2513689457281009578">"Тилди өзгөртүү"</string>
<string name="hdmi_cec_set_menu_language_decline" msgid="7650721096558646011">"Учурдагы тилди калтыруу"</string>
- <!-- no translation found for share_wifi_button_text (1285273973812029240) -->
- <skip />
+ <string name="share_wifi_button_text" msgid="1285273973812029240">"Wi‑Fi\'ды бөлүшүү"</string>
<string name="wifi_debugging_title" msgid="7300007687492186076">"Ушул тармакта мүчүлүштүктөрдү Wi-Fi аркылуу аныктоого уруксат бересизби?"</string>
<string name="wifi_debugging_message" msgid="5461204211731802995">"Тармактын аталышы (SSID)\n<xliff:g id="SSID_0">%1$s</xliff:g>\n\nWi‑Fi дареги (BSSID)\n<xliff:g id="BSSID_1">%2$s</xliff:g>"</string>
<string name="wifi_debugging_always" msgid="2968383799517975155">"Бул тармакта ар дайым уруксат берилсин"</string>
@@ -160,8 +159,7 @@
<string name="biometric_dialog_wrong_pattern" msgid="8954812279840889029">"Графикалык ачкыч туура эмес"</string>
<string name="biometric_dialog_wrong_password" msgid="69477929306843790">"Сырсөз туура эмес"</string>
<string name="biometric_dialog_credential_too_many_attempts" msgid="3083141271737748716">"Өтө көп жолу жаңылдыңыз.\n<xliff:g id="NUMBER">%d</xliff:g> секунддан кийин кайра кайталаңыз."</string>
- <!-- no translation found for work_challenge_emergency_button_text (8946588434515599288) -->
- <skip />
+ <string name="work_challenge_emergency_button_text" msgid="8946588434515599288">"Шашылыш чалуу"</string>
<string name="biometric_dialog_credential_attempts_before_wipe" msgid="6751859711975516999">"Кайра кайталаңыз. <xliff:g id="MAX_ATTEMPTS">%2$d</xliff:g> аракеттен <xliff:g id="ATTEMPTS_0">%1$d</xliff:g> аракет калды."</string>
<string name="biometric_dialog_last_attempt_before_wipe_dialog_title" msgid="2874250099278693477">"Акыркы аракет калды"</string>
<string name="biometric_dialog_last_pattern_attempt_before_wipe_device" msgid="6562299244825817598">"Эгер графикалык ачкычты кийинки жолу туура эмес киргизсеңиз, бул түзмөктүн маалыматы өчүрүлөт."</string>
@@ -415,8 +413,7 @@
<string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="8736391633234144237">"Бөлүшүп, жаздырып же тышкы экранга чыгарып жатканда <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> колдонмосу экраныңыздагы бардык маалыматты же түзмөктө ойнотулуп жаткан нерселерди көрө алат. Андыктан сырсөздөрдү, төлөмдүн чоо-жайын, билдирүүлөрдү, сүрөттөрдү, аудио жана видеону көрсөтүп албаңыз."</string>
<string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="5211695779082563959">"Колдонмону бөлүшүп, жаздырып же тышкы экранга чыгарганда <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> колдонмосу ал колдонмодо көрсөтүлүп жана ойнотулуп жаткан нерселерди көрө алат. Андыктан сырсөздөрдү, төлөмдүн чоо-жайын, билдирүүлөрдү, сүрөттөрдү, аудио жана видеону көрсөтүп албаңыз."</string>
<string name="media_projection_entry_app_permission_dialog_continue" msgid="295463518195075840">"Баштоо"</string>
- <!-- no translation found for media_projection_entry_app_permission_dialog_single_app_disabled (8999903044874669995) -->
- <skip />
+ <string name="media_projection_entry_app_permission_dialog_single_app_disabled" msgid="8999903044874669995">"<xliff:g id="APP_NAME">%1$s</xliff:g> бул параметрди өчүрүп койду"</string>
<string name="media_projection_entry_cast_permission_dialog_title" msgid="8860150223172993547">"Тышкы экранга чыгаруу башталсынбы?"</string>
<string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="1986212276016817231">"Тышкы экранга чыгарганда Android экраныңызда көрүнүп жана түзмөктө ойнотулуп жаткан нерселерди көрө алат. Андыктан сырсөздөрдү, төлөмдүн чоо-жайын, билдирүүлөрдү, сүрөттөрдү, аудио жана видеону көрсөтүп албаңыз."</string>
<string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="9900961380294292">"Колдонмону тышкы экранга чыгарганда Android ал колдонмодо көрсөтүлүп жана ойнотулуп жаткан нерселерди көрө алат. Андыктан сырсөздөрдү, төлөмдүн чоо-жайын, билдирүүлөрдү, сүрөттөрдү, аудио жана видеону көрсөтүп албаңыз."</string>
@@ -1173,6 +1170,10 @@
<string name="assistant_attention_content_description" msgid="6830215897604642875">"Жардамчы иштетилди"</string>
<string name="set_default_notes_app_toast_content" msgid="2812374329662610753">"Параметрлерден демейки кыска жазуулар колдонмосун тууралаңыз"</string>
<string name="install_app" msgid="5066668100199613936">"Колдонмону орнотуу"</string>
+ <!-- no translation found for connected_display_dialog_start_mirroring (6237895789920854982) -->
+ <skip />
+ <!-- no translation found for enable_display (8308309634883321977) -->
+ <skip />
<string name="privacy_dialog_title" msgid="7839968133469098311">"Микрофон жана камера"</string>
<string name="privacy_dialog_summary" msgid="2458769652125995409">"Жакында колдонмолордо иштетилген"</string>
<string name="privacy_dialog_more_button" msgid="7610604080293562345">"Акыркы пайдалануусун көрүү"</string>
diff --git a/packages/SystemUI/res/values-lo/strings.xml b/packages/SystemUI/res/values-lo/strings.xml
index ff08be17aa31..ec1744168592 100644
--- a/packages/SystemUI/res/values-lo/strings.xml
+++ b/packages/SystemUI/res/values-lo/strings.xml
@@ -57,8 +57,7 @@
<string name="hdmi_cec_set_menu_language_description" msgid="8176716678074126619">"ມີການຮ້ອງຂໍໃຫ້ປ່ຽນພາສາລະບົບໂດຍອຸປະກອນອື່ນ"</string>
<string name="hdmi_cec_set_menu_language_accept" msgid="2513689457281009578">"ປ່ຽນພາສາ"</string>
<string name="hdmi_cec_set_menu_language_decline" msgid="7650721096558646011">"ໃຊ້ພາສາປັດຈຸບັນ"</string>
- <!-- no translation found for share_wifi_button_text (1285273973812029240) -->
- <skip />
+ <string name="share_wifi_button_text" msgid="1285273973812029240">"ແບ່ງປັນ Wi‑Fi"</string>
<string name="wifi_debugging_title" msgid="7300007687492186076">"ອະນຸຍາດການດີບັກໄຮ້ສາຍຢູ່ເຄືອຂ່າຍນີ້ບໍ?"</string>
<string name="wifi_debugging_message" msgid="5461204211731802995">"ຊື່ເຄືອຂ່າຍ (SSID)\n<xliff:g id="SSID_0">%1$s</xliff:g>\n\nທີ່ຢູ່ Wi‑Fi (BSSID)\n<xliff:g id="BSSID_1">%2$s</xliff:g>"</string>
<string name="wifi_debugging_always" msgid="2968383799517975155">"ອະນຸຍາດຕະຫຼອດຢູ່ເຄືອຂ່າຍນີ້"</string>
@@ -160,8 +159,7 @@
<string name="biometric_dialog_wrong_pattern" msgid="8954812279840889029">"ຮູບແບບບໍ່ຖືກຕ້ອງ"</string>
<string name="biometric_dialog_wrong_password" msgid="69477929306843790">"ລະຫັດຜ່ານບໍ່ຖືກຕ້ອງ"</string>
<string name="biometric_dialog_credential_too_many_attempts" msgid="3083141271737748716">"ມີ​ຄວາມ​ພະ​ຍາ​ຍາມ​ບໍ່​ຖືກ​ຕ້ອງ​ຫຼາຍ​ເທື່ອ​ເກີນ​ໄປ.\nກະລຸນາລອງ​ໃໝ່​ອີກ​ໃນ <xliff:g id="NUMBER">%d</xliff:g> ​ວິ​ນາ​ທີ."</string>
- <!-- no translation found for work_challenge_emergency_button_text (8946588434515599288) -->
- <skip />
+ <string name="work_challenge_emergency_button_text" msgid="8946588434515599288">"ສຸກເສີນ"</string>
<string name="biometric_dialog_credential_attempts_before_wipe" msgid="6751859711975516999">"ກະລຸນາລອງໃໝ່. ຄວາມພະຍາຍາມເທື່ອທີ <xliff:g id="ATTEMPTS_0">%1$d</xliff:g> ຈາກທັງໝົດ <xliff:g id="MAX_ATTEMPTS">%2$d</xliff:g>."</string>
<string name="biometric_dialog_last_attempt_before_wipe_dialog_title" msgid="2874250099278693477">"ຂໍ້ມູນຂອງທ່ານຈະຖືກລຶບອອກ"</string>
<string name="biometric_dialog_last_pattern_attempt_before_wipe_device" msgid="6562299244825817598">"ຫາກທ່ານໃສ່ຣູບແບບຜິດໃນຄວາມພະຍາຍາມເທື່ອຕໍ່ໄປ, ອຸປະກອນນີ້ຈະຖືກລຶບຂໍ້ມູນອອກ."</string>
@@ -415,8 +413,7 @@
<string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="8736391633234144237">"ເມື່ອທ່ານກຳລັງແບ່ງປັນ, ບັນທຶກ ຫຼື ສົ່ງສັນຍານ, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> ຈະມີສິດເຂົ້າເຖິງທຸກສິ່ງທີ່ປາກົດຢູ່ໜ້າຈໍຂອງທ່ານ ຫຼື ຫຼິ້ນຢູ່ອຸປະກອນຂອງທ່ານ. ດັ່ງນັ້ນ, ໃຫ້ລະມັດລະວັງສິ່ງຕ່າງໆ ເຊັ່ນ: ລະຫັດຜ່ານ, ລາຍລະອຽດການຈ່າຍເງິນ, ຂໍ້ຄວາມ, ຮູບພາບ ພ້ອມທັງສຽງ ແລະ ວິດີໂອ."</string>
<string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="5211695779082563959">"ເມື່ອທ່ານກຳລັງແບ່ງປັນ, ບັນທຶກ ຫຼື ສົ່ງສັນຍານແອັບ, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> ຈະມີສິດເຂົ້າເຖິງທຸກສິ່ງທີ່ສະແດງ ຫຼື ຫຼິ້ນຢູ່ແອັບດັ່ງກ່າວ. ດັ່ງນັ້ນ, ໃຫ້ລະມັດລະວັງສິ່ງຕ່າງໆ ເຊັ່ນ: ລະຫັດຜ່ານ, ລາຍລະອຽດການຈ່າຍເງິນ, ຂໍ້ຄວາມ, ຮູບພາບ ພ້ອມທັງສຽງ ແລະ ວິດີໂອ."</string>
<string name="media_projection_entry_app_permission_dialog_continue" msgid="295463518195075840">"ເລີ່ມ"</string>
- <!-- no translation found for media_projection_entry_app_permission_dialog_single_app_disabled (8999903044874669995) -->
- <skip />
+ <string name="media_projection_entry_app_permission_dialog_single_app_disabled" msgid="8999903044874669995">"<xliff:g id="APP_NAME">%1$s</xliff:g> ປິດການນຳໃຊ້ຕົວເລືອກນີ້ແລ້ວ"</string>
<string name="media_projection_entry_cast_permission_dialog_title" msgid="8860150223172993547">"ເລີ່ມການສົ່ງສັນຍານບໍ?"</string>
<string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="1986212276016817231">"ເມື່ອທ່ານກຳລັງສົ່ງສັນຍານ, Android ຈະມີສິດເຂົ້າເຖິງທຸກສິ່ງທີ່ປາກົດຢູ່ໜ້າຈໍຂອງທ່ານ ຫຼື ຫຼິ້ນຢູ່ອຸປະກອນຂອງທ່ານ. ດັ່ງນັ້ນ, ໃຫ້ລະມັດລະວັງສິ່ງຕ່າງໆ ເຊັ່ນ: ລະຫັດຜ່ານ, ລາຍລະອຽດການຈ່າຍເງິນ, ຂໍ້ຄວາມ, ຮູບພາບ ພ້ອມທັງສຽງ ແລະ ວິດີໂອ."</string>
<string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="9900961380294292">"ເມື່ອທ່ານກຳລັງສົ່ງສັນຍານແອັບ, Android ຈະມີສິດເຂົ້າເຖິງທຸກສິ່ງທີ່ສະແດງ ຫຼື ຫຼິ້ນຢູ່ແອັບດັ່ງກ່າວ. ດັ່ງນັ້ນ, ໃຫ້ລະມັດລະວັງສິ່ງຕ່າງໆ ເຊັ່ນ: ລະຫັດຜ່ານ, ລາຍລະອຽດການຈ່າຍເງິນ, ຂໍ້ຄວາມ, ຮູບພາບ ພ້ອມທັງສຽງ ແລະ ວິດີໂອ."</string>
@@ -1173,6 +1170,10 @@
<string name="assistant_attention_content_description" msgid="6830215897604642875">"ການເອີ້ນໃຊ້ຜູ້ຊ່ວຍເປີດຢູ່"</string>
<string name="set_default_notes_app_toast_content" msgid="2812374329662610753">"ຕັ້ງຄ່າແອັບຈົດບັນທຶກເລີ່ມຕົ້ນໃນການຕັ້ງຄ່າ"</string>
<string name="install_app" msgid="5066668100199613936">"ຕິດຕັ້ງແອັບ"</string>
+ <!-- no translation found for connected_display_dialog_start_mirroring (6237895789920854982) -->
+ <skip />
+ <!-- no translation found for enable_display (8308309634883321977) -->
+ <skip />
<string name="privacy_dialog_title" msgid="7839968133469098311">"ໄມໂຄຣໂຟນ ແລະ ກ້ອງຖ່າຍຮູບ"</string>
<string name="privacy_dialog_summary" msgid="2458769652125995409">"ການໃຊ້ແອັບຫຼ້າສຸດ"</string>
<string name="privacy_dialog_more_button" msgid="7610604080293562345">"ເບິ່ງສິດເຂົ້າເຖິງຫຼ້າສຸດ"</string>
diff --git a/packages/SystemUI/res/values-lt/strings.xml b/packages/SystemUI/res/values-lt/strings.xml
index d3fc0633550c..e418e1828bfa 100644
--- a/packages/SystemUI/res/values-lt/strings.xml
+++ b/packages/SystemUI/res/values-lt/strings.xml
@@ -57,8 +57,7 @@
<string name="hdmi_cec_set_menu_language_description" msgid="8176716678074126619">"Užklausą dėl sistemos kalbos pakeitimo pateikė kitas įrenginys"</string>
<string name="hdmi_cec_set_menu_language_accept" msgid="2513689457281009578">"Keisti kalbą"</string>
<string name="hdmi_cec_set_menu_language_decline" msgid="7650721096558646011">"Palikti dabartinę kalbą"</string>
- <!-- no translation found for share_wifi_button_text (1285273973812029240) -->
- <skip />
+ <string name="share_wifi_button_text" msgid="1285273973812029240">"Bendrinti „Wi‑Fi“"</string>
<string name="wifi_debugging_title" msgid="7300007687492186076">"Leisti belaidžio ryšio derinimą prisijungus prie šio tinklo?"</string>
<string name="wifi_debugging_message" msgid="5461204211731802995">"Tinklo pavadinimas (SSID)\n<xliff:g id="SSID_0">%1$s</xliff:g>\n\n„Wi‑Fi“ adresas (BSSID)\n<xliff:g id="BSSID_1">%2$s</xliff:g>"</string>
<string name="wifi_debugging_always" msgid="2968383799517975155">"Visada leisti naudojant šį tinklą"</string>
@@ -160,8 +159,7 @@
<string name="biometric_dialog_wrong_pattern" msgid="8954812279840889029">"Netinkamas atrakinimo piešinys"</string>
<string name="biometric_dialog_wrong_password" msgid="69477929306843790">"Netinkamas slaptažodis"</string>
<string name="biometric_dialog_credential_too_many_attempts" msgid="3083141271737748716">"Per daug klaidingų bandymų.\nBandykite dar kartą po <xliff:g id="NUMBER">%d</xliff:g> sek."</string>
- <!-- no translation found for work_challenge_emergency_button_text (8946588434515599288) -->
- <skip />
+ <string name="work_challenge_emergency_button_text" msgid="8946588434515599288">"Skamb. pagalbos nr."</string>
<string name="biometric_dialog_credential_attempts_before_wipe" msgid="6751859711975516999">"Bandykite dar kartą. <xliff:g id="ATTEMPTS_0">%1$d</xliff:g> bandymas iš <xliff:g id="MAX_ATTEMPTS">%2$d</xliff:g>."</string>
<string name="biometric_dialog_last_attempt_before_wipe_dialog_title" msgid="2874250099278693477">"Duomenys bus ištrinti"</string>
<string name="biometric_dialog_last_pattern_attempt_before_wipe_device" msgid="6562299244825817598">"Jei kitu bandymu nupiešite netinkamą atrakinimo piešinį, šio įrenginio duomenys bus ištrinti."</string>
@@ -415,8 +413,7 @@
<string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="8736391633234144237">"Kai bendrinate, įrašote ar perduodate turinį, „<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>“ gali pasiekti viską, kas rodoma ekrane ar leidžiama įrenginyje. Todėl būkite atsargūs naudodami slaptažodžius, išsamią mokėjimo metodo informaciją, pranešimus, nuotraukas ir garso bei vaizdo įrašus."</string>
<string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="5211695779082563959">"Kai bendrinate, įrašote ar perduodate programą, „<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>“ gali pasiekti viską, kas rodoma ar leidžiama programoje. Todėl būkite atsargūs naudodami slaptažodžius, išsamią mokėjimo metodo informaciją, pranešimus, nuotraukas ir garso bei vaizdo įrašus."</string>
<string name="media_projection_entry_app_permission_dialog_continue" msgid="295463518195075840">"Pradėti"</string>
- <!-- no translation found for media_projection_entry_app_permission_dialog_single_app_disabled (8999903044874669995) -->
- <skip />
+ <string name="media_projection_entry_app_permission_dialog_single_app_disabled" msgid="8999903044874669995">"Programoje „<xliff:g id="APP_NAME">%1$s</xliff:g>“ ši parinktis išjungta"</string>
<string name="media_projection_entry_cast_permission_dialog_title" msgid="8860150223172993547">"Pradėti perdavimą?"</string>
<string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="1986212276016817231">"Kai perduodate turinį, „Android“ gali pasiekti viską, kas rodoma ekrane ar leidžiama įrenginyje. Todėl būkite atsargūs naudodami slaptažodžius, išsamią mokėjimo metodo informaciją, pranešimus, nuotraukas ir garso bei vaizdo įrašus."</string>
<string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="9900961380294292">"Kai perduodate programą, „Android“ gali pasiekti viską, kas rodoma ar leidžiama toje programoje. Todėl būkite atsargūs naudodami slaptažodžius, išsamią mokėjimo metodo informaciją, pranešimus, nuotraukas ir garso bei vaizdo įrašus."</string>
@@ -1173,6 +1170,10 @@
<string name="assistant_attention_content_description" msgid="6830215897604642875">"Padėjėjas klauso"</string>
<string name="set_default_notes_app_toast_content" msgid="2812374329662610753">"Nustatykite numatytąją užrašų programą Nustatymuose"</string>
<string name="install_app" msgid="5066668100199613936">"Įdiegti programą"</string>
+ <!-- no translation found for connected_display_dialog_start_mirroring (6237895789920854982) -->
+ <skip />
+ <!-- no translation found for enable_display (8308309634883321977) -->
+ <skip />
<string name="privacy_dialog_title" msgid="7839968133469098311">"Mikrofonas ir fotoaparatas"</string>
<string name="privacy_dialog_summary" msgid="2458769652125995409">"Pastarasis programos naudojimas"</string>
<string name="privacy_dialog_more_button" msgid="7610604080293562345">"Žr. pastarąją prieigą"</string>
diff --git a/packages/SystemUI/res/values-lv/strings.xml b/packages/SystemUI/res/values-lv/strings.xml
index c577473f8b53..4b5fea3050f2 100644
--- a/packages/SystemUI/res/values-lv/strings.xml
+++ b/packages/SystemUI/res/values-lv/strings.xml
@@ -57,8 +57,7 @@
<string name="hdmi_cec_set_menu_language_description" msgid="8176716678074126619">"Sistēmas valodas maiņu pieprasīja cita ierīce."</string>
<string name="hdmi_cec_set_menu_language_accept" msgid="2513689457281009578">"Mainīt valodu"</string>
<string name="hdmi_cec_set_menu_language_decline" msgid="7650721096558646011">"Paturēt pašreizējo valodu"</string>
- <!-- no translation found for share_wifi_button_text (1285273973812029240) -->
- <skip />
+ <string name="share_wifi_button_text" msgid="1285273973812029240">"Koplietot Wi-Fi"</string>
<string name="wifi_debugging_title" msgid="7300007687492186076">"Vai atļaut bezvadu atkļūdošanu šajā tīklā?"</string>
<string name="wifi_debugging_message" msgid="5461204211731802995">"Tīkla nosaukums (SSID)\n<xliff:g id="SSID_0">%1$s</xliff:g>\n\nWi‑Fi adrese (BSSID)\n<xliff:g id="BSSID_1">%2$s</xliff:g>"</string>
<string name="wifi_debugging_always" msgid="2968383799517975155">"Vienmēr atļaut šajā tīklā"</string>
@@ -160,8 +159,7 @@
<string name="biometric_dialog_wrong_pattern" msgid="8954812279840889029">"Nepareiza kombinācija"</string>
<string name="biometric_dialog_wrong_password" msgid="69477929306843790">"Nepareiza parole"</string>
<string name="biometric_dialog_credential_too_many_attempts" msgid="3083141271737748716">"Pārāk daudz neveiksmīgu mēģinājumu.\nMēģiniet vēlreiz pēc <xliff:g id="NUMBER">%d</xliff:g> sekundēm."</string>
- <!-- no translation found for work_challenge_emergency_button_text (8946588434515599288) -->
- <skip />
+ <string name="work_challenge_emergency_button_text" msgid="8946588434515599288">"Ārkārtas situācija"</string>
<string name="biometric_dialog_credential_attempts_before_wipe" msgid="6751859711975516999">"Mēģiniet vēlreiz (<xliff:g id="ATTEMPTS_0">%1$d</xliff:g>. mēģinājums no <xliff:g id="MAX_ATTEMPTS">%2$d</xliff:g>)."</string>
<string name="biometric_dialog_last_attempt_before_wipe_dialog_title" msgid="2874250099278693477">"Jūsu dati tiks dzēsti"</string>
<string name="biometric_dialog_last_pattern_attempt_before_wipe_device" msgid="6562299244825817598">"Ja nākamajā mēģinājumā ievadīsiet nepareizu kombināciju, dati šajā ierīcē tiks dzēsti."</string>
@@ -415,8 +413,7 @@
<string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="8736391633234144237">"Kopīgošanas, ierakstīšanas vai apraides laikā <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> var piekļūt visam, kas tiek rādīts jūsu ekrānā vai atskaņots jūsu ierīcē. Tāpēc piesardzīgi apejieties ar parolēm, maksājumu informāciju, ziņojumiem, fotoattēliem un audio un video saturu."</string>
<string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="5211695779082563959">"Lietotnes kopīgošanas, ierakstīšanas vai apraides laikā <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> var piekļūt visam, kas tiek rādīts vai atskaņots attiecīgajā lietotnē. Tāpēc piesardzīgi apejieties ar parolēm, maksājumu informāciju, ziņojumiem, fotoattēliem un audio un video saturu."</string>
<string name="media_projection_entry_app_permission_dialog_continue" msgid="295463518195075840">"Sākt"</string>
- <!-- no translation found for media_projection_entry_app_permission_dialog_single_app_disabled (8999903044874669995) -->
- <skip />
+ <string name="media_projection_entry_app_permission_dialog_single_app_disabled" msgid="8999903044874669995">"Lietotnē <xliff:g id="APP_NAME">%1$s</xliff:g> tika atspējota šī opcija"</string>
<string name="media_projection_entry_cast_permission_dialog_title" msgid="8860150223172993547">"Vai sākt apraidi?"</string>
<string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="1986212276016817231">"Apraides laikā Android var piekļūt visam, kas tiek rādīts jūsu ekrānā vai atskaņots jūsu ierīcē. Tāpēc piesardzīgi apejieties ar parolēm, maksājumu informāciju, ziņojumiem, fotoattēliem un audio un video saturu."</string>
<string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="9900961380294292">"Lietotnes apraides laikā Android var piekļūt visam, kas tiek rādīts vai atskaņots attiecīgajā lietotnē. Tāpēc piesardzīgi apejieties ar parolēm, maksājumu informāciju, ziņojumiem, fotoattēliem un audio un video saturu."</string>
@@ -1173,6 +1170,10 @@
<string name="assistant_attention_content_description" msgid="6830215897604642875">"Asistents klausās"</string>
<string name="set_default_notes_app_toast_content" msgid="2812374329662610753">"Iestatījumos iestatiet noklusējuma piezīmju lietotni."</string>
<string name="install_app" msgid="5066668100199613936">"Instalēt lietotni"</string>
+ <!-- no translation found for connected_display_dialog_start_mirroring (6237895789920854982) -->
+ <skip />
+ <!-- no translation found for enable_display (8308309634883321977) -->
+ <skip />
<string name="privacy_dialog_title" msgid="7839968133469098311">"Mikrofons un kamera"</string>
<string name="privacy_dialog_summary" msgid="2458769652125995409">"Nesen izmantoja lietotnes"</string>
<string name="privacy_dialog_more_button" msgid="7610604080293562345">"Skatīt neseno piekļuvi"</string>
diff --git a/packages/SystemUI/res/values-mk/strings.xml b/packages/SystemUI/res/values-mk/strings.xml
index 9d92b5f7acbf..80aa943505ff 100644
--- a/packages/SystemUI/res/values-mk/strings.xml
+++ b/packages/SystemUI/res/values-mk/strings.xml
@@ -57,8 +57,7 @@
<string name="hdmi_cec_set_menu_language_description" msgid="8176716678074126619">"Побарана е промена на системскиот јазик од друг уред"</string>
<string name="hdmi_cec_set_menu_language_accept" msgid="2513689457281009578">"Промени го јазикот"</string>
<string name="hdmi_cec_set_menu_language_decline" msgid="7650721096558646011">"Зачувај го тековниот јазик"</string>
- <!-- no translation found for share_wifi_button_text (1285273973812029240) -->
- <skip />
+ <string name="share_wifi_button_text" msgid="1285273973812029240">"Сподели Wi‑Fi"</string>
<string name="wifi_debugging_title" msgid="7300007687492186076">"Да се дозволи безжично отстранување грешки на мрежава?"</string>
<string name="wifi_debugging_message" msgid="5461204211731802995">"Име на мрежата (SSID)\n<xliff:g id="SSID_0">%1$s</xliff:g>\n\nWi‑Fi адреса (BSSID)\n<xliff:g id="BSSID_1">%2$s</xliff:g>"</string>
<string name="wifi_debugging_always" msgid="2968383799517975155">"Секогаш дозволувај на оваа мрежа"</string>
@@ -160,8 +159,7 @@
<string name="biometric_dialog_wrong_pattern" msgid="8954812279840889029">"Погрешна шема"</string>
<string name="biometric_dialog_wrong_password" msgid="69477929306843790">"Погрешна лозинка"</string>
<string name="biometric_dialog_credential_too_many_attempts" msgid="3083141271737748716">"Премногу погрешни обиди.\nОбидете се повторно за <xliff:g id="NUMBER">%d</xliff:g>секунди."</string>
- <!-- no translation found for work_challenge_emergency_button_text (8946588434515599288) -->
- <skip />
+ <string name="work_challenge_emergency_button_text" msgid="8946588434515599288">"Итен случај"</string>
<string name="biometric_dialog_credential_attempts_before_wipe" msgid="6751859711975516999">"Обидете се повторно. Обид <xliff:g id="ATTEMPTS_0">%1$d</xliff:g> од <xliff:g id="MAX_ATTEMPTS">%2$d</xliff:g>."</string>
<string name="biometric_dialog_last_attempt_before_wipe_dialog_title" msgid="2874250099278693477">"Податоците ќе се избришат"</string>
<string name="biometric_dialog_last_pattern_attempt_before_wipe_device" msgid="6562299244825817598">"Ако внесете погрешна шема при следниот обид, податоците на уредов ќе се избришат."</string>
@@ -415,8 +413,7 @@
<string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="8736391633234144237">"Кога споделувате, снимате или емитувате, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> има пристап до сѐ што е видливо на вашиот екран или пуштено на вашиот уред. Затоа, бидете внимателни со работи како лозинки, детали за плаќање, пораки, фотографии и аудио и видео."</string>
<string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="5211695779082563959">"Кога споделувате, снимате или емитувате апликација, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> има пристап до сѐ што се прикажува или пушта на таа апликација. Затоа, бидете внимателни со работи како лозинки, детали за плаќање, пораки, фотографии и аудио и видео."</string>
<string name="media_projection_entry_app_permission_dialog_continue" msgid="295463518195075840">"Започни"</string>
- <!-- no translation found for media_projection_entry_app_permission_dialog_single_app_disabled (8999903044874669995) -->
- <skip />
+ <string name="media_projection_entry_app_permission_dialog_single_app_disabled" msgid="8999903044874669995">"<xliff:g id="APP_NAME">%1$s</xliff:g> ја оневозможи опцијава"</string>
<string name="media_projection_entry_cast_permission_dialog_title" msgid="8860150223172993547">"Да се започне со емитување?"</string>
<string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="1986212276016817231">"Кога емитувате, Android има пристап до сѐ што е видливо на вашиот екран или пуштено на вашиот уред. Затоа, бидете внимателни со работи како лозинки, детали за плаќање, пораки, фотографии и аудио и видео."</string>
<string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="9900961380294292">"Додека емитувате апликација, Android има пристап до сѐ што се прикажува или пушта на таа апликација. Затоа, бидете внимателни со лозинки, детали за плаќање, пораки фотографии и аудио и видео."</string>
@@ -1173,6 +1170,10 @@
<string name="assistant_attention_content_description" msgid="6830215897604642875">"Вниманието на „Помошникот“ е вклучено"</string>
<string name="set_default_notes_app_toast_content" msgid="2812374329662610753">"Поставете стандардна апликација за белешки во „Поставки“"</string>
<string name="install_app" msgid="5066668100199613936">"Инсталирајте ја апликацијата"</string>
+ <!-- no translation found for connected_display_dialog_start_mirroring (6237895789920854982) -->
+ <skip />
+ <!-- no translation found for enable_display (8308309634883321977) -->
+ <skip />
<string name="privacy_dialog_title" msgid="7839968133469098311">"Микрофон и камера"</string>
<string name="privacy_dialog_summary" msgid="2458769652125995409">"Неодамнешно користење на апликација"</string>
<string name="privacy_dialog_more_button" msgid="7610604080293562345">"Видете го скорешниот пристап"</string>
diff --git a/packages/SystemUI/res/values-ml/strings.xml b/packages/SystemUI/res/values-ml/strings.xml
index a33eb4b092e7..021607d5508b 100644
--- a/packages/SystemUI/res/values-ml/strings.xml
+++ b/packages/SystemUI/res/values-ml/strings.xml
@@ -57,8 +57,7 @@
<string name="hdmi_cec_set_menu_language_description" msgid="8176716678074126619">"സിസ്റ്റത്തിന്റെ ഭാഷ മാറ്റാൻ മറ്റൊരു ഉപകരണം അഭ്യർത്ഥിച്ചു"</string>
<string name="hdmi_cec_set_menu_language_accept" msgid="2513689457281009578">"ഭാഷ മാറ്റുക"</string>
<string name="hdmi_cec_set_menu_language_decline" msgid="7650721096558646011">"നിലവിലെ ഭാഷ നിലനിർത്തുക"</string>
- <!-- no translation found for share_wifi_button_text (1285273973812029240) -->
- <skip />
+ <string name="share_wifi_button_text" msgid="1285273973812029240">"വൈഫൈ പങ്കിടുക"</string>
<string name="wifi_debugging_title" msgid="7300007687492186076">"ഈ നെറ്റ്‌വർക്കിൽ വയർലെസ് ഡീബഗ്ഗിംഗ് അനുവദിക്കണോ?"</string>
<string name="wifi_debugging_message" msgid="5461204211731802995">"നെറ്റ്‌വർക്കിന്റെ പേര് (SSID)\n<xliff:g id="SSID_0">%1$s</xliff:g>\n\nവൈഫൈ വിലാസം (BSSID)\n<xliff:g id="BSSID_1">%2$s</xliff:g>"</string>
<string name="wifi_debugging_always" msgid="2968383799517975155">"ഈ നെറ്റ്‌വർക്കിൽ എപ്പോഴും അനുവദിക്കുക"</string>
@@ -160,8 +159,7 @@
<string name="biometric_dialog_wrong_pattern" msgid="8954812279840889029">"പാറ്റേൺ തെറ്റാണ്"</string>
<string name="biometric_dialog_wrong_password" msgid="69477929306843790">"പാസ്‌വേഡ് തെറ്റാണ്"</string>
<string name="biometric_dialog_credential_too_many_attempts" msgid="3083141271737748716">"നിരവധി തെറ്റായ ശ്രമങ്ങൾ. \n<xliff:g id="NUMBER">%d</xliff:g> സെക്കൻഡിൽ വീണ്ടും ശ്രമിക്കുക."</string>
- <!-- no translation found for work_challenge_emergency_button_text (8946588434515599288) -->
- <skip />
+ <string name="work_challenge_emergency_button_text" msgid="8946588434515599288">"അടിയന്തരം"</string>
<string name="biometric_dialog_credential_attempts_before_wipe" msgid="6751859711975516999">"വീണ്ടും ശ്രമിക്കുക. <xliff:g id="MAX_ATTEMPTS">%2$d</xliff:g> ശ്രമങ്ങളിൽ <xliff:g id="ATTEMPTS_0">%1$d</xliff:g> ശ്രമം."</string>
<string name="biometric_dialog_last_attempt_before_wipe_dialog_title" msgid="2874250099278693477">"നിങ്ങളുടെ ഡാറ്റ ഇല്ലാതാക്കപ്പെടും"</string>
<string name="biometric_dialog_last_pattern_attempt_before_wipe_device" msgid="6562299244825817598">"അടുത്ത തവണയും നിങ്ങൾ തെറ്റായ പാറ്റേൺ നൽകിയാൽ, ഈ ഉപകരണത്തിലെ ഡാറ്റ ഇല്ലാതാക്കപ്പെടും."</string>
@@ -415,8 +413,7 @@
<string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="8736391633234144237">"പങ്കിടുമ്പോൾ, റെക്കോർഡ് ചെയ്യുമ്പോൾ അല്ലെങ്കിൽ കാസ്റ്റ് ചെയ്യുമ്പോൾ, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> എന്നതിന് നിങ്ങളുടെ സ്ക്രീനിൽ ദൃശ്യമാകുന്നതോ ഉപകരണത്തിൽ പ്ലേ ചെയ്യുന്നതോ ആയ ഏത് കാര്യത്തിലേക്കും ആക്സസ് ഉണ്ട്. അതിനാൽ പാസ്‍വേഡുകൾ, പേയ്‌മെന്റ് വിശദാംശങ്ങൾ, സന്ദേശങ്ങൾ, ഫോട്ടോകൾ, ഓഡിയോ, വീഡിയോ എന്നിവ പോലുള്ള കാര്യങ്ങൾ നൽകുമ്പോൾ സൂക്ഷിക്കുക."</string>
<string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="5211695779082563959">"ഒരു ആപ്പ് പങ്കിടുമ്പോൾ, റെക്കോർഡ് ചെയ്യുമ്പോൾ അല്ലെങ്കിൽ കാസ്റ്റ് ചെയ്യുമ്പോൾ, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> എന്നതിന് ആ ആപ്പിൽ കാണിക്കുന്ന അല്ലെങ്കിൽ പ്ലേ ചെയ്യുന്ന എല്ലാത്തിലേക്കും ആക്സസ് ഉണ്ട്. അതിനാൽ പാസ്‍വേഡുകൾ, പേയ്‌മെന്റ് വിശദാംശങ്ങൾ, സന്ദേശങ്ങൾ, ഫോട്ടോകൾ, ഓഡിയോ, വീഡിയോ എന്നിവ പോലുള്ള കാര്യങ്ങൾ നൽകുമ്പോൾ സൂക്ഷിക്കുക."</string>
<string name="media_projection_entry_app_permission_dialog_continue" msgid="295463518195075840">"ആരംഭിക്കുക"</string>
- <!-- no translation found for media_projection_entry_app_permission_dialog_single_app_disabled (8999903044874669995) -->
- <skip />
+ <string name="media_projection_entry_app_permission_dialog_single_app_disabled" msgid="8999903044874669995">"<xliff:g id="APP_NAME">%1$s</xliff:g> ഈ ഓപ്‌ഷൻ പ്രവർത്തനരഹിതമാക്കി"</string>
<string name="media_projection_entry_cast_permission_dialog_title" msgid="8860150223172993547">"കാസ്റ്റ് ചെയ്യാൻ ആരംഭിക്കണോ?"</string>
<string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="1986212276016817231">"നിങ്ങൾ കാസ്റ്റ് ചെയ്യുമ്പോൾ, Android-ന് സ്ക്രീനിൽ ദൃശ്യമാകുന്നതോ ഉപകരണത്തിൽ പ്ലേ ചെയ്യുന്നതോ ആയ ഏത് കാര്യത്തിലേക്കും ആക്സസ് ഉണ്ട്. അതിനാൽ പാസ്‍വേഡുകൾ, പേയ്‌മെന്റ് വിശദാംശങ്ങൾ, സന്ദേശങ്ങൾ, ഫോട്ടോകൾ, ഓഡിയോ, വീഡിയോ എന്നിവ പോലുള്ള കാര്യങ്ങൾ നൽകുമ്പോൾ സൂക്ഷിക്കുക."</string>
<string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="9900961380294292">"നിങ്ങൾ ഒരു ആപ്പ് കാസ്റ്റ് ചെയ്യുമ്പോൾ, Android-ന് ആ ആപ്പിൽ കാണിക്കുന്നതോ പ്ലേ ചെയ്യുന്നതോ ആയ എല്ലാത്തിലേക്കും ആക്സസ് ഉണ്ട്. അതിനാൽ പാസ്‍വേഡുകൾ, പേയ്‌മെന്റ് വിശദാംശങ്ങൾ, സന്ദേശങ്ങൾ, ഫോട്ടോകൾ, ഓഡിയോ, വീഡിയോ എന്നിവ പോലുള്ള കാര്യങ്ങൾ നൽകുമ്പോൾ സൂക്ഷിക്കുക."</string>
@@ -1173,6 +1170,10 @@
<string name="assistant_attention_content_description" msgid="6830215897604642875">"Assistant സജീവമാണ്"</string>
<string name="set_default_notes_app_toast_content" msgid="2812374329662610753">"ക്രമീകരണത്തിൽ കുറിപ്പുകൾക്കുള്ള ഡിഫോൾട്ട് ആപ്പ് സജ്ജീകരിക്കുക"</string>
<string name="install_app" msgid="5066668100199613936">"ആപ്പ് ഇൻസ്റ്റാൾ ചെയ്യൂ"</string>
+ <!-- no translation found for connected_display_dialog_start_mirroring (6237895789920854982) -->
+ <skip />
+ <!-- no translation found for enable_display (8308309634883321977) -->
+ <skip />
<string name="privacy_dialog_title" msgid="7839968133469098311">"മൈക്രോഫോണും ക്യാമറയും"</string>
<string name="privacy_dialog_summary" msgid="2458769652125995409">"അടുത്തിടെയുള്ള ആപ്പ് ഉപയോഗം"</string>
<string name="privacy_dialog_more_button" msgid="7610604080293562345">"അടുത്തിടെയുള്ള ആക്‌സസ് കാണുക"</string>
diff --git a/packages/SystemUI/res/values-mn/strings.xml b/packages/SystemUI/res/values-mn/strings.xml
index da9d794b4250..9c7cf8ba932d 100644
--- a/packages/SystemUI/res/values-mn/strings.xml
+++ b/packages/SystemUI/res/values-mn/strings.xml
@@ -57,8 +57,7 @@
<string name="hdmi_cec_set_menu_language_description" msgid="8176716678074126619">"Өөр төхөөрөмжөөс системийн хэлийг өөрчлөх хүсэлт тавьсан"</string>
<string name="hdmi_cec_set_menu_language_accept" msgid="2513689457281009578">"Хэл солих"</string>
<string name="hdmi_cec_set_menu_language_decline" msgid="7650721096558646011">"Одоогийн хэлээр байлгах"</string>
- <!-- no translation found for share_wifi_button_text (1285273973812029240) -->
- <skip />
+ <string name="share_wifi_button_text" msgid="1285273973812029240">"Wi‑Fi-г хуваалцах"</string>
<string name="wifi_debugging_title" msgid="7300007687492186076">"Энэ сүлжээн дээр wireless debugging-г зөвшөөрөх үү?"</string>
<string name="wifi_debugging_message" msgid="5461204211731802995">"Сүлжээний нэр (SSID)\n<xliff:g id="SSID_0">%1$s</xliff:g>\n\nWi‑Fi хаяг (BSSID)\n<xliff:g id="BSSID_1">%2$s</xliff:g>"</string>
<string name="wifi_debugging_always" msgid="2968383799517975155">"Энэ сүлжээн дээр үргэлж зөвшөөрөх"</string>
@@ -160,8 +159,7 @@
<string name="biometric_dialog_wrong_pattern" msgid="8954812279840889029">"Хээ буруу байна"</string>
<string name="biometric_dialog_wrong_password" msgid="69477929306843790">"Нууц үг буруу байна"</string>
<string name="biometric_dialog_credential_too_many_attempts" msgid="3083141271737748716">"Хэт олон удаа буруу оруулсан байна.\n<xliff:g id="NUMBER">%d</xliff:g> секундийн дараа дахин оролдоно уу."</string>
- <!-- no translation found for work_challenge_emergency_button_text (8946588434515599288) -->
- <skip />
+ <string name="work_challenge_emergency_button_text" msgid="8946588434515599288">"Яаралтай тусламж"</string>
<string name="biometric_dialog_credential_attempts_before_wipe" msgid="6751859711975516999">"Дахин оролдоно уу. <xliff:g id="MAX_ATTEMPTS">%2$d</xliff:g>-с <xliff:g id="ATTEMPTS_0">%1$d</xliff:g> оролдлого үлдлээ."</string>
<string name="biometric_dialog_last_attempt_before_wipe_dialog_title" msgid="2874250099278693477">"Таны өгөгдлийг устгах болно"</string>
<string name="biometric_dialog_last_pattern_attempt_before_wipe_device" msgid="6562299244825817598">"Та дараагийн оролдлогоор буруу хээ оруулбал энэ төхөөрөмжийн өгөгдлийг устгах болно."</string>
@@ -415,8 +413,7 @@
<string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="8736391633234144237">"Таныг хуваалцаж, бичиж эсвэл дамжуулж байх үед <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> нь таны дэлгэцэд харагдаж буй зүйл эсвэл төхөөрөмжид тань тоглуулсан аливаа зүйлд хандах эрхтэй. Тиймээс нууц үг, төлбөрийн мэдээлэл, мессеж, зураг, аудио болон видео зэрэг зүйлд болгоомжтой хандаарай."</string>
<string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="5211695779082563959">"Таныг хуваалцаж, бичлэг хийж эсвэл апп дамжуулж байх үед <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> нь тухайн аппад харуулсан эсвэл тоглуулсан аливаа зүйлд хандах эрхтэй. Тиймээс нууц үг, төлбөрийн дэлгэрэнгүй, мессеж, зураг, аудио болон видео зэрэг бусад зүйлд болгоомжтой хандаарай."</string>
<string name="media_projection_entry_app_permission_dialog_continue" msgid="295463518195075840">"Эхлүүлэх"</string>
- <!-- no translation found for media_projection_entry_app_permission_dialog_single_app_disabled (8999903044874669995) -->
- <skip />
+ <string name="media_projection_entry_app_permission_dialog_single_app_disabled" msgid="8999903044874669995">"<xliff:g id="APP_NAME">%1$s</xliff:g> энэ сонголтыг идэвхгүй болгосон"</string>
<string name="media_projection_entry_cast_permission_dialog_title" msgid="8860150223172993547">"Дамжуулж эхлэх үү?"</string>
<string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="1986212276016817231">"Таныг дамжуулж байх үед Android таны дэлгэцэд харагдаж буй эсвэл төхөөрөмжид тань тоглуулсан аливаа зүйлд хандах эрхтэй. Тиймээс нууц үг, төлбөрийн мэдээлэл, мессеж, зураг, аудио болон видео зэрэг зүйлд болгоомжтой хандаарай."</string>
<string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="9900961380294292">"Таныг апп дамжуулж байх үед Android тухайн аппад харуулсан эсвэл тоглуулсан аливаа зүйлд хандах эрхтэй. Тиймээс нууц үг, төлбөрийн мэдээлэл, мессеж, зураг, аудио болон видео зэрэг зүйлд болгоомжтой хандаарай."</string>
@@ -1173,6 +1170,10 @@
<string name="assistant_attention_content_description" msgid="6830215897604642875">"Туслах анхаарлаа хандуулж байна"</string>
<string name="set_default_notes_app_toast_content" msgid="2812374329662610753">"Тохиргоонд тэмдэглэлийн өгөгдмөл апп тохируулна уу"</string>
<string name="install_app" msgid="5066668100199613936">"Аппыг суулгах"</string>
+ <!-- no translation found for connected_display_dialog_start_mirroring (6237895789920854982) -->
+ <skip />
+ <!-- no translation found for enable_display (8308309634883321977) -->
+ <skip />
<string name="privacy_dialog_title" msgid="7839968133469098311">"Микрофон болон камер"</string>
<string name="privacy_dialog_summary" msgid="2458769652125995409">"Аппын саяхны ашиглалт"</string>
<string name="privacy_dialog_more_button" msgid="7610604080293562345">"Саяхны хандалтыг харах"</string>
diff --git a/packages/SystemUI/res/values-mr/strings.xml b/packages/SystemUI/res/values-mr/strings.xml
index 5fcf947018ce..72c5cb63fb52 100644
--- a/packages/SystemUI/res/values-mr/strings.xml
+++ b/packages/SystemUI/res/values-mr/strings.xml
@@ -57,8 +57,7 @@
<string name="hdmi_cec_set_menu_language_description" msgid="8176716678074126619">"दुसऱ्या डिव्हाइसद्वारे सिस्टीमची भाषा बदलण्याची विनंती केली गेली"</string>
<string name="hdmi_cec_set_menu_language_accept" msgid="2513689457281009578">"भाषा बदला"</string>
<string name="hdmi_cec_set_menu_language_decline" msgid="7650721096558646011">"सध्याची भाषा ठेवा"</string>
- <!-- no translation found for share_wifi_button_text (1285273973812029240) -->
- <skip />
+ <string name="share_wifi_button_text" msgid="1285273973812029240">"वाय-फाय शेअर करा"</string>
<string name="wifi_debugging_title" msgid="7300007687492186076">"या नेटवर्कवर वायरलेस डीबगिंग करण्यासाठी अनुमती द्यायची का?"</string>
<string name="wifi_debugging_message" msgid="5461204211731802995">"नेटवर्कचे नाव (SSID)\n<xliff:g id="SSID_0">%1$s</xliff:g>\n\nवाय-फाय ॲड्रेस (BSSID)\n<xliff:g id="BSSID_1">%2$s</xliff:g>"</string>
<string name="wifi_debugging_always" msgid="2968383799517975155">"या नेटवर्कवर नेहमी अनुमती द्या"</string>
@@ -160,8 +159,7 @@
<string name="biometric_dialog_wrong_pattern" msgid="8954812279840889029">"चुकीचा पॅटर्न"</string>
<string name="biometric_dialog_wrong_password" msgid="69477929306843790">"चुकीचा पासवर्ड"</string>
<string name="biometric_dialog_credential_too_many_attempts" msgid="3083141271737748716">"बरेच चुकीचे प्रयत्न. \n <xliff:g id="NUMBER">%d</xliff:g> सेकंदांमध्‍ये पुन्हा प्रयत्न करा."</string>
- <!-- no translation found for work_challenge_emergency_button_text (8946588434515599288) -->
- <skip />
+ <string name="work_challenge_emergency_button_text" msgid="8946588434515599288">"आणीबाणी"</string>
<string name="biometric_dialog_credential_attempts_before_wipe" msgid="6751859711975516999">"पुन्हा प्रयत्न करा. <xliff:g id="MAX_ATTEMPTS">%2$d</xliff:g> पैकी <xliff:g id="ATTEMPTS_0">%1$d</xliff:g> प्रयत्न."</string>
<string name="biometric_dialog_last_attempt_before_wipe_dialog_title" msgid="2874250099278693477">"तुमचा डेटा हटवला जाईल"</string>
<string name="biometric_dialog_last_pattern_attempt_before_wipe_device" msgid="6562299244825817598">"तुम्‍ही पुढील प्रयत्‍नात चुकीचा पॅटर्न एंटर केल्यास, या डिव्‍हाइसचा डेटा हटवला जाईल."</string>
@@ -415,8 +413,7 @@
<string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="8736391633234144237">"तुम्ही शेअर, रेकॉर्ड किंवा कास्ट करत असताना, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> ला तुमच्या स्क्रीनवर दाखवलेल्या किंवा डिव्हाइसवर प्ले केलेल्या कोणत्याही गोष्टीचा अ‍ॅक्सेस असतो. त्यामुळे पासवर्ड, पेमेंट तपशील, मेसेज, फोटो आणि ऑडिओ व व्हिडिओ यांसारख्या गोष्टींबाबत सावधगिरी बाळगा."</string>
<string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="5211695779082563959">"तुम्ही एखादे अ‍ॅप शेअर, रेकॉर्ड किंवा कास्ट करत असताना, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> ला त्या अ‍ॅपवर दाखवलेल्या किंवा प्ले केलेल्या कोणत्याही गोष्टीचा अ‍ॅक्सेस असतो. त्यामुळे पासवर्ड, पेमेंट तपशील, मेसेज, फोटो आणि ऑडिओ व व्हिडिओ यांसारख्या गोष्टींबाबत सावधगिरी बाळगा."</string>
<string name="media_projection_entry_app_permission_dialog_continue" msgid="295463518195075840">"सुरुवात करा"</string>
- <!-- no translation found for media_projection_entry_app_permission_dialog_single_app_disabled (8999903044874669995) -->
- <skip />
+ <string name="media_projection_entry_app_permission_dialog_single_app_disabled" msgid="8999903044874669995">"<xliff:g id="APP_NAME">%1$s</xliff:g> हा पर्याय बंद केला आहे"</string>
<string name="media_projection_entry_cast_permission_dialog_title" msgid="8860150223172993547">"कास्ट करणे सुरू करायचे आहे का?"</string>
<string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="1986212276016817231">"तुम्ही कास्ट करत असताना, Android ला तुमच्या स्क्रीनवर दाखवलेल्या किंवा डिव्हाइसवर प्ले केलेल्या कोणत्याही गोष्टीचा अ‍ॅक्सेस असतो. त्यामुळे पासवर्ड, पेमेंट तपशील, मेसेज, फोटो आणि ऑडिओ व व्हिडिओ यांसारख्या गोष्टींबाबत सावधगिरी बाळगा."</string>
<string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="9900961380294292">"तुम्ही एखादे अ‍ॅप कास्ट करत असताना, Android ला त्या अ‍ॅपवर दाखवलेल्या किंवा प्ले केलेल्या कोणत्याही गोष्टीचा अ‍ॅक्सेस असतो. त्यामुळे पासवर्ड, पेमेंट तपशील, मेसेज, फोटो आणि ऑडिओ व व्हिडिओ यांसारख्या गोष्टींबाबत सावधगिरी बाळगा."</string>
@@ -1173,6 +1170,10 @@
<string name="assistant_attention_content_description" msgid="6830215897604642875">"Assistant चे लक्ष हे आता अ‍ॅक्टिव्ह आहे"</string>
<string name="set_default_notes_app_toast_content" msgid="2812374329662610753">"सेटिंग्ज मध्ये डीफॉल्ट टिपा अ‍ॅप सेट करा"</string>
<string name="install_app" msgid="5066668100199613936">"अ‍ॅप इंस्टॉल करा"</string>
+ <!-- no translation found for connected_display_dialog_start_mirroring (6237895789920854982) -->
+ <skip />
+ <!-- no translation found for enable_display (8308309634883321977) -->
+ <skip />
<string name="privacy_dialog_title" msgid="7839968133469098311">"मायक्रोफोन आणि कॅमेरा"</string>
<string name="privacy_dialog_summary" msgid="2458769652125995409">"अलीकडील अ‍ॅप वापर"</string>
<string name="privacy_dialog_more_button" msgid="7610604080293562345">"अलीकडील अ‍ॅक्सेस पहा"</string>
diff --git a/packages/SystemUI/res/values-ms/strings.xml b/packages/SystemUI/res/values-ms/strings.xml
index de88987c9609..fd4e6b51001c 100644
--- a/packages/SystemUI/res/values-ms/strings.xml
+++ b/packages/SystemUI/res/values-ms/strings.xml
@@ -57,8 +57,7 @@
<string name="hdmi_cec_set_menu_language_description" msgid="8176716678074126619">"Permintaan pertukaran bahasa sistem oleh peranti lain"</string>
<string name="hdmi_cec_set_menu_language_accept" msgid="2513689457281009578">"Tukar bahasa"</string>
<string name="hdmi_cec_set_menu_language_decline" msgid="7650721096558646011">"Kekalkan bahasa semasa"</string>
- <!-- no translation found for share_wifi_button_text (1285273973812029240) -->
- <skip />
+ <string name="share_wifi_button_text" msgid="1285273973812029240">"Kongsi Wi‑Fi"</string>
<string name="wifi_debugging_title" msgid="7300007687492186076">"Benarkan penyahpepijatan wayarles pada rangkaian ini?"</string>
<string name="wifi_debugging_message" msgid="5461204211731802995">"Nama Rangkaian (SSID)\n<xliff:g id="SSID_0">%1$s</xliff:g>\n\nAlamat Wi‑Fi (BSSID)\n<xliff:g id="BSSID_1">%2$s</xliff:g>"</string>
<string name="wifi_debugging_always" msgid="2968383799517975155">"Sentiasa benarkan pada rangkaian ini"</string>
@@ -160,8 +159,7 @@
<string name="biometric_dialog_wrong_pattern" msgid="8954812279840889029">"Corak salah"</string>
<string name="biometric_dialog_wrong_password" msgid="69477929306843790">"Kata laluan salah"</string>
<string name="biometric_dialog_credential_too_many_attempts" msgid="3083141271737748716">"Terlalu banyak percubaan yang salah.\nCuba lagi dalam masa <xliff:g id="NUMBER">%d</xliff:g> saat."</string>
- <!-- no translation found for work_challenge_emergency_button_text (8946588434515599288) -->
- <skip />
+ <string name="work_challenge_emergency_button_text" msgid="8946588434515599288">"Kecemasan"</string>
<string name="biometric_dialog_credential_attempts_before_wipe" msgid="6751859711975516999">"Cuba lagi. Percubaan <xliff:g id="ATTEMPTS_0">%1$d</xliff:g> daripada <xliff:g id="MAX_ATTEMPTS">%2$d</xliff:g>."</string>
<string name="biometric_dialog_last_attempt_before_wipe_dialog_title" msgid="2874250099278693477">"Data anda akan dipadamkan"</string>
<string name="biometric_dialog_last_pattern_attempt_before_wipe_device" msgid="6562299244825817598">"Jika anda memasukkan corak yang salah pada percubaan seterusnya, data peranti ini akan dipadamkan."</string>
@@ -415,8 +413,7 @@
<string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="8736391633234144237">"Apabila anda membuat perkongsian, rakaman atau penghantaran, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> boleh mengakses apa-apa sahaja yang boleh dilihat pada skrin anda atau dimainkan pada peranti anda. Oleh hal yang demikian, berhati-hati dengan perkara seperti kata laluan, butiran pembayaran, mesej, foto dan audio serta video."</string>
<string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="5211695779082563959">"Apabila anda berkongsi, merakam atau menghantar apl, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> boleh mengakses apa-apa sahaja yang ditunjukan atau dimainkan pada apl tersebut. Oleh hal yang demikian, berhati-hati dengan perkara seperti kata laluan, butiran pembayaran, mesej, foto dan audio serta video."</string>
<string name="media_projection_entry_app_permission_dialog_continue" msgid="295463518195075840">"Mula"</string>
- <!-- no translation found for media_projection_entry_app_permission_dialog_single_app_disabled (8999903044874669995) -->
- <skip />
+ <string name="media_projection_entry_app_permission_dialog_single_app_disabled" msgid="8999903044874669995">"<xliff:g id="APP_NAME">%1$s</xliff:g> telah melumpuhkan pilihan ini"</string>
<string name="media_projection_entry_cast_permission_dialog_title" msgid="8860150223172993547">"Mulakan penghantaran?"</string>
<string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="1986212276016817231">"Apabila anda membuat penghantaran, Android boleh mengakses apa-apa sahaja yang boleh dilihat pada skrin anda atau dimainkan pada peranti anda. Oleh hal yang demikian, berhati-hati dengan perkara seperti kata laluan, butiran pembayaran, mesej, foto dan audio serta video."</string>
<string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="9900961380294292">"Apabila anda menghantar apl, Android boleh mengakses apa-apa sahaja yang ditunjukan atau dimainkan pada apl itu. Oleh hal yang demikian, berhati-hati dengan perkara seperti kata laluan, butiran pembayaran, mesej, foto dan audio serta video."</string>
@@ -1173,6 +1170,8 @@
<string name="assistant_attention_content_description" msgid="6830215897604642875">"Perhatian pembantu dihidupkan"</string>
<string name="set_default_notes_app_toast_content" msgid="2812374329662610753">"Tetapkan apl nota lalai dalam Tetapan"</string>
<string name="install_app" msgid="5066668100199613936">"Pasang apl"</string>
+ <string name="connected_display_dialog_start_mirroring" msgid="6237895789920854982">"Paparkan pada paparan luaran?"</string>
+ <string name="enable_display" msgid="8308309634883321977">"Dayakan paparan"</string>
<string name="privacy_dialog_title" msgid="7839968133469098311">"Mikrofon &amp; Kamera"</string>
<string name="privacy_dialog_summary" msgid="2458769652125995409">"Penggunaan apl terbaharu"</string>
<string name="privacy_dialog_more_button" msgid="7610604080293562345">"Lihat akses terbaharu"</string>
diff --git a/packages/SystemUI/res/values-my/strings.xml b/packages/SystemUI/res/values-my/strings.xml
index 1f54ef6c32a0..5d249dec93b0 100644
--- a/packages/SystemUI/res/values-my/strings.xml
+++ b/packages/SystemUI/res/values-my/strings.xml
@@ -57,8 +57,7 @@
<string name="hdmi_cec_set_menu_language_description" msgid="8176716678074126619">"စက်နောက်တစ်ခုက စနစ်၏ ဘာသာစကားပြောင်းရန် တောင်းဆိုထားသည်"</string>
<string name="hdmi_cec_set_menu_language_accept" msgid="2513689457281009578">"ဘာသာစကားပြောင်းရန်"</string>
<string name="hdmi_cec_set_menu_language_decline" msgid="7650721096558646011">"လက်ရှိဘာသာစကားဆက်သုံးရန်"</string>
- <!-- no translation found for share_wifi_button_text (1285273973812029240) -->
- <skip />
+ <string name="share_wifi_button_text" msgid="1285273973812029240">"Wi‑Fi မျှဝေရန်"</string>
<string name="wifi_debugging_title" msgid="7300007687492186076">"ဤကွန်ရက်တွင် ကြိုးမဲ့ အမှားရှာပြင်ခြင်းကို ခွင့်ပြုမလား။"</string>
<string name="wifi_debugging_message" msgid="5461204211731802995">"ကွန်ရက်အမည် (SSID)\n<xliff:g id="SSID_0">%1$s</xliff:g>\n\nWi‑Fi လိပ်စာ (BSSID)\n<xliff:g id="BSSID_1">%2$s</xliff:g>"</string>
<string name="wifi_debugging_always" msgid="2968383799517975155">"ဤကွန်ရက်ကို အမြဲခွင့်ပြုပါ"</string>
@@ -160,8 +159,7 @@
<string name="biometric_dialog_wrong_pattern" msgid="8954812279840889029">"ပုံစံ မှားနေသည်"</string>
<string name="biometric_dialog_wrong_password" msgid="69477929306843790">"စကားဝှက် မှားနေသည်"</string>
<string name="biometric_dialog_credential_too_many_attempts" msgid="3083141271737748716">"မှားသည့် အကြိမ် အရေအတွက် အလွန်များသည်။\n<xliff:g id="NUMBER">%d</xliff:g>စက္ကန့်အကြာတွင် ထပ်စမ်းကြည့်ပါ။"</string>
- <!-- no translation found for work_challenge_emergency_button_text (8946588434515599288) -->
- <skip />
+ <string name="work_challenge_emergency_button_text" msgid="8946588434515599288">"အရေးပေါ်"</string>
<string name="biometric_dialog_credential_attempts_before_wipe" msgid="6751859711975516999">"ထပ်စမ်းကြည့်ပါ။ <xliff:g id="MAX_ATTEMPTS">%2$d</xliff:g> ကြိမ်အနက်မှ <xliff:g id="ATTEMPTS_0">%1$d</xliff:g> ကြိမ် ဖြစ်သည်။"</string>
<string name="biometric_dialog_last_attempt_before_wipe_dialog_title" msgid="2874250099278693477">"သင်၏ဒေတာများ ပျက်သွားပါလိမ့်မည်"</string>
<string name="biometric_dialog_last_pattern_attempt_before_wipe_device" msgid="6562299244825817598">"မှားယွင်းသည့် ပုံစံကို နောက်တစ်ကြိမ်ထည့်သွင်းပါက ဤစက်ပစ္စည်းပေါ်ရှိ ဒေတာများကို ဖျက်လိုက်ပါမည်။"</string>
@@ -415,8 +413,7 @@
<string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="8736391633234144237">"မျှဝေ၊ ရုပ်သံဖမ်း (သို့) ကာစ်လုပ်သည့်အခါ <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> သည် သင့်ဖန်သားပြင်ရှိ မြင်နိုင်သည့် (သို့) သင့်စက်တွင် ဖွင့်ထားသည့် အရာအားလုံးကို တွေ့နိုင်သည်။ စကားဝှက်၊ ငွေပေးချေမှု အချက်အလက်၊ မက်ဆေ့ဂျ်၊ ဓာတ်ပုံ၊ အသံနှင့် ဗီဒီယိုကဲ့သို့ အရာများကို ဂရုစိုက်ပါ။"</string>
<string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="5211695779082563959">"အက်ပ်တစ်ခုဖြင့် မျှဝေ၊ ရုပ်သံဖမ်း (သို့) ကာစ်လုပ်သည့်အခါ <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> သည် ယင်းအက်ပ်တွင် ပြထားသည့် (သို့) ဖွင့်ထားသည့် အရာအားလုံးကို တွေ့နိုင်သည်။ ထို့ကြောင့် စကားဝှက်၊ ငွေပေးချေမှု အချက်အလက်၊ မက်ဆေ့ဂျ်၊ ဓာတ်ပုံ၊ အသံနှင့် ဗီဒီယိုကဲ့သို့အရာများကို ဂရုစိုက်ပါ။"</string>
<string name="media_projection_entry_app_permission_dialog_continue" msgid="295463518195075840">"စတင်ရန်"</string>
- <!-- no translation found for media_projection_entry_app_permission_dialog_single_app_disabled (8999903044874669995) -->
- <skip />
+ <string name="media_projection_entry_app_permission_dialog_single_app_disabled" msgid="8999903044874669995">"<xliff:g id="APP_NAME">%1$s</xliff:g> သည် ဤရွေးစရာကို ပိတ်ထားသည်"</string>
<string name="media_projection_entry_cast_permission_dialog_title" msgid="8860150223172993547">"ကာစ်လုပ်ခြင်း စမလား။"</string>
<string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="1986212276016817231">"ကာစ်လုပ်သည့်အခါ Android သည် သင့်ဖန်သားပြင်ရှိ မြင်နိုင်သည့် (သို့) သင့်စက်တွင် ဖွင့်ထားသည့် အရာအားလုံးကို တွေ့နိုင်သည်။ စကားဝှက်၊ ငွေပေးချေမှု အချက်အလက်၊ မက်ဆေ့ဂျ်၊ ဓာတ်ပုံ၊ အသံနှင့် ဗီဒီယိုကဲ့သို့ အရာများကို ဂရုစိုက်ပါ။"</string>
<string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="9900961380294292">"အက်ပ်တစ်ခုကို ကာစ်လုပ်သည့်အခါ Android သည် ယင်းအက်ပ်တွင် ပြထားသည့် (သို့) ဖွင့်ထားသည့် အရာအားလုံးကို တွေ့နိုင်သည်။ ထို့ကြောင့် စကားဝှက်၊ ငွေပေးချေမှု အချက်အလက်၊ မက်ဆေ့ဂျ်၊ ဓာတ်ပုံ၊ အသံနှင့် ဗီဒီယိုကဲ့သို့ အရာများကို ဂရုစိုက်ပါ။"</string>
@@ -1173,6 +1170,10 @@
<string name="assistant_attention_content_description" msgid="6830215897604642875">"Assistant နားထောင်နေသည်"</string>
<string name="set_default_notes_app_toast_content" msgid="2812374329662610753">"ဆက်တင်များတွင် မူရင်းမှတ်စုများအက်ပ် သတ်မှတ်ပါ"</string>
<string name="install_app" msgid="5066668100199613936">"အက်ပ် ထည့်သွင်းရန်"</string>
+ <!-- no translation found for connected_display_dialog_start_mirroring (6237895789920854982) -->
+ <skip />
+ <!-- no translation found for enable_display (8308309634883321977) -->
+ <skip />
<string name="privacy_dialog_title" msgid="7839968133469098311">"မိုက်ခရိုဖုန်းနှင့် ကင်မရာ"</string>
<string name="privacy_dialog_summary" msgid="2458769652125995409">"လတ်တလော အက်ပ်အသုံးပြုမှု"</string>
<string name="privacy_dialog_more_button" msgid="7610604080293562345">"လတ်တလောအသုံးပြုမှုကို ကြည့်ရန်"</string>
diff --git a/packages/SystemUI/res/values-nb/strings.xml b/packages/SystemUI/res/values-nb/strings.xml
index 54a5341fda2c..17846751a258 100644
--- a/packages/SystemUI/res/values-nb/strings.xml
+++ b/packages/SystemUI/res/values-nb/strings.xml
@@ -57,8 +57,7 @@
<string name="hdmi_cec_set_menu_language_description" msgid="8176716678074126619">"Bytte av systemspråk er forespurt av en annen enhet"</string>
<string name="hdmi_cec_set_menu_language_accept" msgid="2513689457281009578">"Bytt språk"</string>
<string name="hdmi_cec_set_menu_language_decline" msgid="7650721096558646011">"Behold gjeldende språk"</string>
- <!-- no translation found for share_wifi_button_text (1285273973812029240) -->
- <skip />
+ <string name="share_wifi_button_text" msgid="1285273973812029240">"Del wifi"</string>
<string name="wifi_debugging_title" msgid="7300007687492186076">"Vil du tillate trådløs feilsøking på dette nettverket?"</string>
<string name="wifi_debugging_message" msgid="5461204211731802995">"Nettverksnavn (SSID)\n<xliff:g id="SSID_0">%1$s</xliff:g>\n\nWi‑Fi-adresse (BSSID)\n<xliff:g id="BSSID_1">%2$s</xliff:g>"</string>
<string name="wifi_debugging_always" msgid="2968383799517975155">"Tillat alltid på dette nettverket"</string>
@@ -160,8 +159,7 @@
<string name="biometric_dialog_wrong_pattern" msgid="8954812279840889029">"Feil mønster"</string>
<string name="biometric_dialog_wrong_password" msgid="69477929306843790">"Feil passord"</string>
<string name="biometric_dialog_credential_too_many_attempts" msgid="3083141271737748716">"For mange ugyldige forsøk.\nPrøv på nytt om <xliff:g id="NUMBER">%d</xliff:g> sekunder."</string>
- <!-- no translation found for work_challenge_emergency_button_text (8946588434515599288) -->
- <skip />
+ <string name="work_challenge_emergency_button_text" msgid="8946588434515599288">"Nødssituasjon"</string>
<string name="biometric_dialog_credential_attempts_before_wipe" msgid="6751859711975516999">"Prøv på nytt. Forsøk <xliff:g id="ATTEMPTS_0">%1$d</xliff:g> av <xliff:g id="MAX_ATTEMPTS">%2$d</xliff:g>."</string>
<string name="biometric_dialog_last_attempt_before_wipe_dialog_title" msgid="2874250099278693477">"Dataene dine blir slettet"</string>
<string name="biometric_dialog_last_pattern_attempt_before_wipe_device" msgid="6562299244825817598">"Hvis du oppgir feil mønster på neste forsøk, slettes dataene på denne enheten."</string>
@@ -415,8 +413,7 @@
<string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="8736391633234144237">"Når du deler, tar opp eller caster noe, har <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> tilgang til alt som vises på skjermen eller spilles av på enheten. Derfor bør du være forsiktig med for eksempel passord, betalingsopplysninger, meldinger, bilder, lyd og video."</string>
<string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="5211695779082563959">"Når du deler, tar opp eller caster en app, har <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> tilgang til alt som vises eller spilles av i den aktuelle appen. Derfor bør du være forsiktig med for eksempel passord, betalingsopplysninger, meldinger, bilder, lyd og video."</string>
<string name="media_projection_entry_app_permission_dialog_continue" msgid="295463518195075840">"Begynn"</string>
- <!-- no translation found for media_projection_entry_app_permission_dialog_single_app_disabled (8999903044874669995) -->
- <skip />
+ <string name="media_projection_entry_app_permission_dialog_single_app_disabled" msgid="8999903044874669995">"<xliff:g id="APP_NAME">%1$s</xliff:g> har deaktivert dette alternativet"</string>
<string name="media_projection_entry_cast_permission_dialog_title" msgid="8860150223172993547">"Vil du begynne å caste?"</string>
<string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="1986212276016817231">"Når du caster, har Android tilgang til alt som vises på skjermen eller spilles av på enheten. Derfor bør du være forsiktig med for eksempel passord, betalingsopplysninger, meldinger, bilder, lyd og video."</string>
<string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="9900961380294292">"Når du caster en app, har Android tilgang til alt som vises eller spilles av i den aktuelle appen. Derfor bør du være forsiktig med for eksempel passord, betalingsopplysninger, meldinger, bilder, lyd og video."</string>
@@ -1173,6 +1170,10 @@
<string name="assistant_attention_content_description" msgid="6830215897604642875">"Assistentoppmerksomhet er på"</string>
<string name="set_default_notes_app_toast_content" msgid="2812374329662610753">"Du kan velge en standardapp for notater i Innstillinger"</string>
<string name="install_app" msgid="5066668100199613936">"Installer appen"</string>
+ <!-- no translation found for connected_display_dialog_start_mirroring (6237895789920854982) -->
+ <skip />
+ <!-- no translation found for enable_display (8308309634883321977) -->
+ <skip />
<string name="privacy_dialog_title" msgid="7839968133469098311">"Mikrofon og kamera"</string>
<string name="privacy_dialog_summary" msgid="2458769652125995409">"Nylig appbruk"</string>
<string name="privacy_dialog_more_button" msgid="7610604080293562345">"Se nylig tilgang"</string>
diff --git a/packages/SystemUI/res/values-ne/strings.xml b/packages/SystemUI/res/values-ne/strings.xml
index 29b5098d0273..94ac4b7fcfc4 100644
--- a/packages/SystemUI/res/values-ne/strings.xml
+++ b/packages/SystemUI/res/values-ne/strings.xml
@@ -57,8 +57,7 @@
<string name="hdmi_cec_set_menu_language_description" msgid="8176716678074126619">"अर्को डिभाइसले सिस्टमको भाषा परिवर्तन गर्न अनुरोध गरेको छ"</string>
<string name="hdmi_cec_set_menu_language_accept" msgid="2513689457281009578">"भाषा परिवर्तन गर्नुहोस्"</string>
<string name="hdmi_cec_set_menu_language_decline" msgid="7650721096558646011">"अहिलेको भाषा राख्नुहोस्"</string>
- <!-- no translation found for share_wifi_button_text (1285273973812029240) -->
- <skip />
+ <string name="share_wifi_button_text" msgid="1285273973812029240">"Wi‑Fi सेयर गर्नुहोस्"</string>
<string name="wifi_debugging_title" msgid="7300007687492186076">"यस नेटवर्कमा वायरलेस डिबगिङ सेवा प्रयोग गर्न दिने हो?"</string>
<string name="wifi_debugging_message" msgid="5461204211731802995">"नेटवर्कको नाम (SSID)\n<xliff:g id="SSID_0">%1$s</xliff:g>\n\nWi‑Fi ठेगाना (BSSID)\n<xliff:g id="BSSID_1">%2$s</xliff:g>"</string>
<string name="wifi_debugging_always" msgid="2968383799517975155">"यस नेटवर्कमा सधैँ अनुमति दिइयोस्"</string>
@@ -160,8 +159,7 @@
<string name="biometric_dialog_wrong_pattern" msgid="8954812279840889029">"प्याटर्न मिलेन"</string>
<string name="biometric_dialog_wrong_password" msgid="69477929306843790">"पासवर्ड मिलेन"</string>
<string name="biometric_dialog_credential_too_many_attempts" msgid="3083141271737748716">"अत्यन्तै धेरै पटक गलत प्रयास गरिए। \n <xliff:g id="NUMBER">%d</xliff:g>सेकेन्ड पछि पुनः प्रयास गर्नुहोस्।"</string>
- <!-- no translation found for work_challenge_emergency_button_text (8946588434515599288) -->
- <skip />
+ <string name="work_challenge_emergency_button_text" msgid="8946588434515599288">"आपत्कालीन"</string>
<string name="biometric_dialog_credential_attempts_before_wipe" msgid="6751859711975516999">"फेरि प्रयास गर्नुहोस्। <xliff:g id="MAX_ATTEMPTS">%2$d</xliff:g> मध्ये <xliff:g id="ATTEMPTS_0">%1$d</xliff:g> प्रयास।"</string>
<string name="biometric_dialog_last_attempt_before_wipe_dialog_title" msgid="2874250099278693477">"तपाईंको डेटा मेटाइने छ"</string>
<string name="biometric_dialog_last_pattern_attempt_before_wipe_device" msgid="6562299244825817598">"तपाईंले अर्को पटक पनि गलत ढाँचा प्रविष्टि गर्नुभयो भने यो डिभाइसको डेटा मेटाइने छ।"</string>
@@ -415,8 +413,7 @@
<string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="8736391633234144237">"तपाईंले सेयर गर्दा, रेकर्ड गर्दा वा कास्ट गर्दा <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> ले तपाईंको स्क्रिनमा देखिने वा डिभाइसमा प्ले गरिने सबै कुरा हेर्न तथा प्रयोग गर्न सक्छ। त्यसैले पासवर्ड, भुक्तानीसम्बन्धी विवरण, म्यासेज, फोटो र अडियो तथा भिडियो जस्ता कुरा हेर्दा वा प्ले गर्दा सावधानी अपनाउनुहोला।"</string>
<string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="5211695779082563959">"तपाईंले कुनै एप सेयर गर्दा, रेकर्ड गर्दा वा कास्ट गर्दा <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> ले उक्त एपमा देखाइने वा प्ले गरिने सबै कुरा हेर्न तथा प्रयोग गर्न सक्छ। त्यसैले पासवर्ड, भुक्तानीसम्बन्धी विवरण, म्यासेज, फोटो र अडियो तथा भिडियो जस्ता कुरा हेर्दा वा प्ले गर्दा सावधानी अपनाउनुहोला।"</string>
<string name="media_projection_entry_app_permission_dialog_continue" msgid="295463518195075840">"सुरु गर्नुहोस्"</string>
- <!-- no translation found for media_projection_entry_app_permission_dialog_single_app_disabled (8999903044874669995) -->
- <skip />
+ <string name="media_projection_entry_app_permission_dialog_single_app_disabled" msgid="8999903044874669995">"<xliff:g id="APP_NAME">%1$s</xliff:g> ले यो विकल्प अफ गर्नुभएको छ"</string>
<string name="media_projection_entry_cast_permission_dialog_title" msgid="8860150223172993547">"कास्ट गर्न थाल्ने हो?"</string>
<string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="1986212276016817231">"तपाईंले कास्ट गर्दा Android ले तपाईंको स्क्रिनमा देखिने वा डिभाइसमा प्ले गरिने सबै कुरा हेर्न तथा प्रयोग गर्न सक्छ। त्यसैले पासवर्ड, भुक्तानीसम्बन्धी विवरण, म्यासेज, फोटो र अडियो तथा भिडियो जस्ता कुरा हेर्दा वा प्ले गर्दा सावधानी अपनाउनुहोला।"</string>
<string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="9900961380294292">"तपाईंले कुनै एप कास्ट गर्दा Android ले उक्त एपमा देखाइने वा प्ले गरिने सबै कुरा हेर्न तथा प्रयोग गर्न सक्छ। त्यसैले पासवर्ड, भुक्तानीसम्बन्धी विवरण, म्यासेज, फोटो र अडियो तथा भिडियो जस्ता कुरा हेर्दा वा प्ले गर्दा सावधानी अपनाउनुहोला।"</string>
@@ -1173,6 +1170,10 @@
<string name="assistant_attention_content_description" msgid="6830215897604642875">"सहायकले सुनिरहेको छ"</string>
<string name="set_default_notes_app_toast_content" msgid="2812374329662610753">"सेटिङमा गई नोट बनाउने डिफल्ट एप तोक्नुहोस्"</string>
<string name="install_app" msgid="5066668100199613936">"एप इन्स्टल गर्नुहोस्"</string>
+ <!-- no translation found for connected_display_dialog_start_mirroring (6237895789920854982) -->
+ <skip />
+ <!-- no translation found for enable_display (8308309634883321977) -->
+ <skip />
<string name="privacy_dialog_title" msgid="7839968133469098311">"माइक्रोफोन तथा क्यामेरा"</string>
<string name="privacy_dialog_summary" msgid="2458769652125995409">"एपको हालसालैको प्रयोग"</string>
<string name="privacy_dialog_more_button" msgid="7610604080293562345">"हालसालै एक्सेस गर्ने एप हेर्नुहोस्"</string>
diff --git a/packages/SystemUI/res/values-nl/strings.xml b/packages/SystemUI/res/values-nl/strings.xml
index 5799c3516275..f15eda0eaec0 100644
--- a/packages/SystemUI/res/values-nl/strings.xml
+++ b/packages/SystemUI/res/values-nl/strings.xml
@@ -57,8 +57,7 @@
<string name="hdmi_cec_set_menu_language_description" msgid="8176716678074126619">"Wijziging van systeemtaal aangevraagd door een ander apparaat"</string>
<string name="hdmi_cec_set_menu_language_accept" msgid="2513689457281009578">"Taal wijzigen"</string>
<string name="hdmi_cec_set_menu_language_decline" msgid="7650721096558646011">"Huidige taal houden"</string>
- <!-- no translation found for share_wifi_button_text (1285273973812029240) -->
- <skip />
+ <string name="share_wifi_button_text" msgid="1285273973812029240">"Wifi delen"</string>
<string name="wifi_debugging_title" msgid="7300007687492186076">"Draadloze foutopsporing toestaan in dit netwerk?"</string>
<string name="wifi_debugging_message" msgid="5461204211731802995">"Netwerknaam (SSID)\n<xliff:g id="SSID_0">%1$s</xliff:g>\n\nWifi-adres (BSSID)\n<xliff:g id="BSSID_1">%2$s</xliff:g>"</string>
<string name="wifi_debugging_always" msgid="2968383799517975155">"Altijd toestaan in dit netwerk"</string>
@@ -160,8 +159,7 @@
<string name="biometric_dialog_wrong_pattern" msgid="8954812279840889029">"Onjuist patroon"</string>
<string name="biometric_dialog_wrong_password" msgid="69477929306843790">"Onjuist wachtwoord"</string>
<string name="biometric_dialog_credential_too_many_attempts" msgid="3083141271737748716">"Te veel onjuiste pogingen.\nProbeer het over <xliff:g id="NUMBER">%d</xliff:g> seconden opnieuw."</string>
- <!-- no translation found for work_challenge_emergency_button_text (8946588434515599288) -->
- <skip />
+ <string name="work_challenge_emergency_button_text" msgid="8946588434515599288">"Noodgeval"</string>
<string name="biometric_dialog_credential_attempts_before_wipe" msgid="6751859711975516999">"Probeer het opnieuw. Poging <xliff:g id="ATTEMPTS_0">%1$d</xliff:g> van <xliff:g id="MAX_ATTEMPTS">%2$d</xliff:g>."</string>
<string name="biometric_dialog_last_attempt_before_wipe_dialog_title" msgid="2874250099278693477">"Je gegevens worden verwijderd"</string>
<string name="biometric_dialog_last_pattern_attempt_before_wipe_device" msgid="6562299244825817598">"Als je bij de volgende poging een onjuist patroon opgeeft, worden de gegevens van dit apparaat verwijderd."</string>
@@ -415,8 +413,7 @@
<string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="8736391633234144237">"Als je deelt, opneemt of cast, heeft <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> toegang tot alles dat zichtbaar is op je scherm of wordt afgespeeld op je apparaat. Wees daarom voorzichtig met bijvoorbeeld wachtwoorden, betalingsgegevens, berichten, foto\'s, en audio en video."</string>
<string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="5211695779082563959">"Als je deelt, opneemt of cast, heeft <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> toegang tot alles dat wordt getoond of afgespeeld in die app. Wees daarom voorzichtig met bijvoorbeeld wachtwoorden, betalingsgegevens, berichten, foto\'s, en audio en video."</string>
<string name="media_projection_entry_app_permission_dialog_continue" msgid="295463518195075840">"Starten"</string>
- <!-- no translation found for media_projection_entry_app_permission_dialog_single_app_disabled (8999903044874669995) -->
- <skip />
+ <string name="media_projection_entry_app_permission_dialog_single_app_disabled" msgid="8999903044874669995">"Voor <xliff:g id="APP_NAME">%1$s</xliff:g> staat deze optie uit"</string>
<string name="media_projection_entry_cast_permission_dialog_title" msgid="8860150223172993547">"Casten starten?"</string>
<string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="1986212276016817231">"Als je cast, heeft Android toegang tot alles dat zichtbaar is op je scherm of wordt afgespeeld op je apparaat. Wees daarom voorzichtig met bijvoorbeeld wachtwoorden, betalingsgegevens, berichten, foto\'s, en audio en video."</string>
<string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="9900961380294292">"Als je een app cast, heeft Android toegang tot alles dat zichtbaar is op je scherm of wordt afgespeeld op je apparaat. Wees daarom voorzichtig met bijvoorbeeld wachtwoorden, betalingsgegevens, berichten, foto\'s, en audio en video."</string>
@@ -1173,6 +1170,10 @@
<string name="assistant_attention_content_description" msgid="6830215897604642875">"Assistent-aandacht aan"</string>
<string name="set_default_notes_app_toast_content" msgid="2812374329662610753">"Standaard notitie-app instellen in Instellingen"</string>
<string name="install_app" msgid="5066668100199613936">"App installeren"</string>
+ <!-- no translation found for connected_display_dialog_start_mirroring (6237895789920854982) -->
+ <skip />
+ <!-- no translation found for enable_display (8308309634883321977) -->
+ <skip />
<string name="privacy_dialog_title" msgid="7839968133469098311">"Microfoon en camera"</string>
<string name="privacy_dialog_summary" msgid="2458769652125995409">"Recent app-gebruik"</string>
<string name="privacy_dialog_more_button" msgid="7610604080293562345">"Recente toegang bekijken"</string>
diff --git a/packages/SystemUI/res/values-or/strings.xml b/packages/SystemUI/res/values-or/strings.xml
index 68acfc041a38..8e34628e67de 100644
--- a/packages/SystemUI/res/values-or/strings.xml
+++ b/packages/SystemUI/res/values-or/strings.xml
@@ -57,8 +57,7 @@
<string name="hdmi_cec_set_menu_language_description" msgid="8176716678074126619">"ଅନ୍ୟ ଏକ ଡିଭାଇସ ଦ୍ୱାରା ସିଷ୍ଟମ ଭାଷା ପରିବର୍ତ୍ତନ ପାଇଁ ଅନୁରୋଧ କରାଯାଇଛି"</string>
<string name="hdmi_cec_set_menu_language_accept" msgid="2513689457281009578">"ଭାଷା ପରିବର୍ତ୍ତନ କରନ୍ତୁ"</string>
<string name="hdmi_cec_set_menu_language_decline" msgid="7650721096558646011">"ବର୍ତ୍ତମାନର ଭାଷା ରଖନ୍ତୁ"</string>
- <!-- no translation found for share_wifi_button_text (1285273973812029240) -->
- <skip />
+ <string name="share_wifi_button_text" msgid="1285273973812029240">"ୱାଇ-ଫାଇ ସେୟାର କରନ୍ତୁ"</string>
<string name="wifi_debugging_title" msgid="7300007687492186076">"ଏହି ନେଟୱାର୍କରେ ୱାୟାରଲେସ୍ ଡିବଗିଂ ପାଇଁ ଅନୁମତି ଦେବେ?"</string>
<string name="wifi_debugging_message" msgid="5461204211731802995">"ନେଟୱାର୍କ ନାମ (SSID)\n<xliff:g id="SSID_0">%1$s</xliff:g>\n\nୱାଇଫାଇ ଠିକଣା (BSSID)\n<xliff:g id="BSSID_1">%2$s</xliff:g>"</string>
<string name="wifi_debugging_always" msgid="2968383799517975155">"ସର୍ବଦା ଏହି ନେଟୱାର୍କରେ ଅନୁମତି ଦିଅନ୍ତୁ"</string>
@@ -160,8 +159,7 @@
<string name="biometric_dialog_wrong_pattern" msgid="8954812279840889029">"ଭୁଲ ପାଟର୍ନ"</string>
<string name="biometric_dialog_wrong_password" msgid="69477929306843790">"ଭୁଲ ପାସ୍‌ୱାର୍ଡ"</string>
<string name="biometric_dialog_credential_too_many_attempts" msgid="3083141271737748716">"ଅନେକ ଥର ଭୁଲ ଚେଷ୍ଟା। \n <xliff:g id="NUMBER">%d</xliff:g>ସେକେଣ୍ଡରେ ପୁଣି ଚେଷ୍ଟା କରନ୍ତୁ।"</string>
- <!-- no translation found for work_challenge_emergency_button_text (8946588434515599288) -->
- <skip />
+ <string name="work_challenge_emergency_button_text" msgid="8946588434515599288">"ଜରୁରୀକାଳୀନ"</string>
<string name="biometric_dialog_credential_attempts_before_wipe" msgid="6751859711975516999">"ପୁଣି ଚେଷ୍ଟା କରନ୍ତୁ। <xliff:g id="MAX_ATTEMPTS">%2$d</xliff:g>ଟିରୁ <xliff:g id="ATTEMPTS_0">%1$d</xliff:g>ଟି ପ୍ରଚେଷ୍ଟା।"</string>
<string name="biometric_dialog_last_attempt_before_wipe_dialog_title" msgid="2874250099278693477">"ଆପଣଙ୍କ ଡାଟାକୁ ଡିଲିଟ୍ କରିଦିଆଯିବ"</string>
<string name="biometric_dialog_last_pattern_attempt_before_wipe_device" msgid="6562299244825817598">"ଆପଣ ପରବର୍ତ୍ତୀ ପ୍ରଚେଷ୍ଟାରେ ଏକ ଭୁଲ ପାଟର୍ନ ପ୍ରବେଶ କଲେ, ଏହି ଡିଭାଇସର ଡାଟାକୁ ଡିଲିଟ୍ କରିଦିଆଯିବ।"</string>
@@ -415,8 +413,7 @@
<string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="8736391633234144237">"ଆପଣ ସେୟାର, ରେକର୍ଡ କିମ୍ବା କାଷ୍ଟ କରିବା ସମୟରେ, ଆପଣଙ୍କ ସ୍କ୍ରିନରେ ଦେଖାଯାଉଥିବା କିମ୍ବା ଆପଣଙ୍କ ଡିଭାଇସରେ ପ୍ଲେ ହେଉଥିବା ସବୁକିଛିକୁ <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>ର ଆକ୍ସେସ ଅଛି। ତେଣୁ ପାସୱାର୍ଡ, ପେମେଣ୍ଟ ବିବରଣୀ, ମେସେଜ, ଫଟୋ ଏବଂ ଅଡିଓ ଓ ଭିଡିଓ ପରି ବିଷୟଗୁଡ଼ିକ ପ୍ରତି ସତର୍କ ରୁହନ୍ତୁ।"</string>
<string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="5211695779082563959">"ଆପଣ ଏକ ଆପ ସେୟାର, ରେକର୍ଡ କିମ୍ବା କାଷ୍ଟ କରିବା ସମୟରେ, ସେହି ଆପରେ ଦେଖାଯାଉଥିବା କିମ୍ବା ପ୍ଲେ ହେଉଥିବା ସବୁକିଛିକୁ <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>ର ଆକ୍ସେସ ଅଛି। ତେଣୁ ପାସୱାର୍ଡ, ପେମେଣ୍ଟ ବିବରଣୀ, ମେସେଜ, ଫଟୋ ଏବଂ ଅଡିଓ ଓ ଭିଡିଓ ପରି ବିଷୟଗୁଡ଼ିକ ପ୍ରତି ସତର୍କ ରୁହନ୍ତୁ।"</string>
<string name="media_projection_entry_app_permission_dialog_continue" msgid="295463518195075840">"ଆରମ୍ଭ କରନ୍ତୁ"</string>
- <!-- no translation found for media_projection_entry_app_permission_dialog_single_app_disabled (8999903044874669995) -->
- <skip />
+ <string name="media_projection_entry_app_permission_dialog_single_app_disabled" msgid="8999903044874669995">"<xliff:g id="APP_NAME">%1$s</xliff:g> ଏହି ବିକଳ୍ପକୁ ଅକ୍ଷମ କରିଛି"</string>
<string name="media_projection_entry_cast_permission_dialog_title" msgid="8860150223172993547">"କାଷ୍ଟିଂ ଆରମ୍ଭ କରିବେ?"</string>
<string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="1986212276016817231">"ଆପଣ କାଷ୍ଟ କରିବା ସମୟରେ, ଆପଣଙ୍କ ସ୍କ୍ରିନରେ ଦେଖାଯାଉଥିବା କିମ୍ବା ଆପଣଙ୍କ ଡିଭାଇସରେ ପ୍ଲେ ହେଉଥିବା ସବୁକିଛିକୁ Androidର ଆକ୍ସେସ ଅଛି। ତେଣୁ ପାସୱାର୍ଡ, ପେମେଣ୍ଟ ବିବରଣୀ, ମେସେଜ, ଫଟୋ ଏବଂ ଅଡିଓ ଓ ଭିଡିଓ ପରି ବିଷୟଗୁଡ଼ିକ ପ୍ରତି ସତର୍କ ରୁହନ୍ତୁ।"</string>
<string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="9900961380294292">"ଆପଣ ଏକ ଆପ କାଷ୍ଟ କରିବା ସମୟରେ, ସେହି ଆପରେ ଦେଖାଯାଉଥିବା କିମ୍ବା ପ୍ଲେ ହେଉଥିବା ସବୁକିଛିକୁ Androidର ଆକ୍ସେସ ଅଛି। ତେଣୁ ପାସୱାର୍ଡ, ପେମେଣ୍ଟ ବିବରଣୀ, ମେସେଜ, ଫଟୋ ଏବଂ ଅଡିଓ ଓ ଭିଡିଓ ପରି ବିଷୟଗୁଡ଼ିକ ପ୍ରତି ସତର୍କ ରୁହନ୍ତୁ।"</string>
@@ -1173,6 +1170,10 @@
<string name="assistant_attention_content_description" msgid="6830215897604642875">"Assistant ଆଟେନସନ ଚାଲୁ ଅଛି"</string>
<string name="set_default_notes_app_toast_content" msgid="2812374329662610753">"ସେଟିଂସରେ ଡିଫଲ୍ଟ ନୋଟ୍ସ ଆପ ସେଟ କରନ୍ତୁ"</string>
<string name="install_app" msgid="5066668100199613936">"ଆପ ଇନଷ୍ଟଲ କରନ୍ତୁ"</string>
+ <!-- no translation found for connected_display_dialog_start_mirroring (6237895789920854982) -->
+ <skip />
+ <!-- no translation found for enable_display (8308309634883321977) -->
+ <skip />
<string name="privacy_dialog_title" msgid="7839968133469098311">"ମାଇକ୍ରୋଫୋନ ଏବଂ କେମେରା"</string>
<string name="privacy_dialog_summary" msgid="2458769652125995409">"ବର୍ତ୍ତମାନର ଆପ ବ୍ୟବହାର"</string>
<string name="privacy_dialog_more_button" msgid="7610604080293562345">"ବର୍ତ୍ତମାନର ଆକ୍ସେସ ଦେଖନ୍ତୁ"</string>
diff --git a/packages/SystemUI/res/values-pa/strings.xml b/packages/SystemUI/res/values-pa/strings.xml
index f8aac7593697..0861ca3ac1be 100644
--- a/packages/SystemUI/res/values-pa/strings.xml
+++ b/packages/SystemUI/res/values-pa/strings.xml
@@ -57,8 +57,7 @@
<string name="hdmi_cec_set_menu_language_description" msgid="8176716678074126619">"ਕਿਸੇ ਹੋਰ ਡੀਵਾਈਸ ਵੱਲੋਂ ਸਿਸਟਮ ਦੀ ਭਾਸ਼ਾ ਬਦਲਣ ਦੀ ਬੇਨਤੀ ਕੀਤੀ ਗਈ"</string>
<string name="hdmi_cec_set_menu_language_accept" msgid="2513689457281009578">"ਭਾਸ਼ਾ ਬਦਲੋ"</string>
<string name="hdmi_cec_set_menu_language_decline" msgid="7650721096558646011">"ਮੌਜੂਦਾ ਭਾਸ਼ਾ ਰੱਖੋ"</string>
- <!-- no translation found for share_wifi_button_text (1285273973812029240) -->
- <skip />
+ <string name="share_wifi_button_text" msgid="1285273973812029240">"ਵਾਈ-ਫਾਈ ਸਾਂਝਾ ਕਰੋ"</string>
<string name="wifi_debugging_title" msgid="7300007687492186076">"ਕੀ ਇਸ ਨੈੱਟਵਰਕ \'ਤੇ ਵਾਇਰਲੈੱਸ ਡੀਬੱਗਿੰਗ ਦੀ ਆਗਿਆ ਦੇਣੀ ਹੈ?"</string>
<string name="wifi_debugging_message" msgid="5461204211731802995">"ਨੈੱਟਵਰਕ ਨਾਮ (SSID)\n<xliff:g id="SSID_0">%1$s</xliff:g>\n\nਵਾਈ-ਫਾਈ ਪਤਾ (BSSID)\n<xliff:g id="BSSID_1">%2$s</xliff:g>"</string>
<string name="wifi_debugging_always" msgid="2968383799517975155">"ਇਸ ਨੈੱਟਵਰਕ \'ਤੇ ਹਮੇਸ਼ਾਂ ਆਗਿਆ ਦਿਓ"</string>
@@ -160,8 +159,7 @@
<string name="biometric_dialog_wrong_pattern" msgid="8954812279840889029">"ਗਲਤ ਪੈਟਰਨ"</string>
<string name="biometric_dialog_wrong_password" msgid="69477929306843790">"ਗਲਤ ਪਾਸਵਰਡ"</string>
<string name="biometric_dialog_credential_too_many_attempts" msgid="3083141271737748716">"ਬਹੁਤ ਸਾਰੀਆਂ ਗ਼ਲਤ ਕੋਸ਼ਿਸ਼ਾਂ।\n<xliff:g id="NUMBER">%d</xliff:g> ਸਕਿੰਟਾਂ ਵਿੱਚ ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ।"</string>
- <!-- no translation found for work_challenge_emergency_button_text (8946588434515599288) -->
- <skip />
+ <string name="work_challenge_emergency_button_text" msgid="8946588434515599288">"ਐਮਰਜੈਂਸੀ"</string>
<string name="biometric_dialog_credential_attempts_before_wipe" msgid="6751859711975516999">"ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ। <xliff:g id="MAX_ATTEMPTS">%2$d</xliff:g> ਵਿੱਚੋਂ <xliff:g id="ATTEMPTS_0">%1$d</xliff:g> ਕੋਸ਼ਿਸ਼।"</string>
<string name="biometric_dialog_last_attempt_before_wipe_dialog_title" msgid="2874250099278693477">"ਤੁਹਾਡਾ ਡਾਟਾ ਮਿਟਾ ਦਿੱਤਾ ਜਾਵੇਗਾ"</string>
<string name="biometric_dialog_last_pattern_attempt_before_wipe_device" msgid="6562299244825817598">"ਜੇ ਤੁਸੀਂ ਅਗਲੀ ਕੋਸ਼ਿਸ਼ ਵਿੱਚ ਕੋਈ ਗਲਤ ਪੈਟਰਨ ਦਾਖਲ ਕਰਦੇ ਹੋ, ਤਾਂ ਇਸ ਡੀਵਾਈਸ ਦਾ ਡਾਟਾ ਮਿਟਾ ਦਿੱਤਾ ਜਾਵੇਗਾ।"</string>
@@ -415,8 +413,7 @@
<string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="8736391633234144237">"ਤੁਹਾਡੇ ਵੱਲੋਂ ਸਾਂਝਾ ਕਰਨ, ਰਿਕਾਰਡਿੰਗ ਜਾਂ ਕਾਸਟ ਕਰਨ \'ਤੇ, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> ਕੋਲ ਤੁਹਾਡੀ ਸਕ੍ਰੀਨ \'ਤੇ ਦਿਖਣ ਵਾਲੀ ਜਾਂ ਤੁਹਾਡੇ ਡੀਵਾਈਸ \'ਤੇ ਚਲਾਈ ਜਾਣ ਵਾਲੀ ਹਰੇਕ ਚੀਜ਼ ਤੱਕ ਪਹੁੰਚ ਹੁੰਦੀ ਹੈ। ਇਸ ਲਈ ਪਾਸਵਰਡਾਂ, ਭੁਗਤਾਨ ਵੇਰਵਿਆਂ, ਸੁਨੇਹਿਆਂ, ਫ਼ੋਟੋਆਂ ਅਤੇ ਆਡੀਓ ਅਤੇ ਵੀਡੀਓ ਵਰਗੀਆਂ ਚੀਜ਼ਾਂ ਵਾਸਤੇ ਸਾਵਧਾਨ ਰਹੋ।"</string>
<string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="5211695779082563959">"ਤੁਹਾਡੇ ਵੱਲੋਂ ਸਾਂਝਾ ਕਰਨ, ਰਿਕਾਰਡ ਕਰਨ, ਜਾਂ ਕਾਸਟ ਕਰਨ \'ਤੇ, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> ਕੋਲ ਉਸ ਐਪ \'ਤੇ ਦਿਖਾਈ ਗਈ ਜਾਂ ਚਲਾਈ ਗਈ ਹਰੇਕ ਚੀਜ਼ ਤੱਕ ਪਹੁੰਚ ਹੁੰਦੀ ਹੈ। ਇਸ ਲਈ ਪਾਸਵਰਡਾਂ, ਭੁਗਤਾਨ ਵੇਰਵਿਆਂ, ਸੁਨੇਹਿਆਂ, ਫ਼ੋਟੋਆਂ ਅਤੇ ਆਡੀਓ ਅਤੇ ਵੀਡੀਓ ਵਰਗੀਆਂ ਚੀਜ਼ਾਂ ਸੰਬੰਧੀ ਸਾਵਧਾਨ ਰਹੋ।"</string>
<string name="media_projection_entry_app_permission_dialog_continue" msgid="295463518195075840">"ਸ਼ੁਰੂ ਕਰੋ"</string>
- <!-- no translation found for media_projection_entry_app_permission_dialog_single_app_disabled (8999903044874669995) -->
- <skip />
+ <string name="media_projection_entry_app_permission_dialog_single_app_disabled" msgid="8999903044874669995">"<xliff:g id="APP_NAME">%1$s</xliff:g> ਨੇ ਇਸ ਵਿਕਲਪ ਨੂੰ ਬੰਦ ਕਰ ਦਿੱਤਾ ਹੈ"</string>
<string name="media_projection_entry_cast_permission_dialog_title" msgid="8860150223172993547">"ਕੀ ਕਾਸਟ ਕਰਨਾ ਸ਼ੁਰੂ ਕਰਨਾ ਹੈ?"</string>
<string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="1986212276016817231">"ਤੁਹਾਡੇ ਵੱਲੋਂ ਕਾਸਟ ਕਰਨ \'ਤੇ, Android ਕੋਲ ਤੁਹਾਡੀ ਸਕ੍ਰੀਨ \'ਤੇ ਦਿਸਣ ਵਾਲੀ ਜਾਂ ਤੁਹਾਡੇ ਡੀਵਾਈਸ \'ਤੇ ਚਲਾਈ ਜਾਣ ਵਾਲੀ ਹਰੇਕ ਚੀਜ਼ ਤੱਕ ਪਹੁੰਚ ਹੁੰਦੀ ਹੈ। ਇਸ ਲਈ ਪਾਸਵਰਡਾਂ, ਭੁਗਤਾਨ ਵੇਰਵਿਆਂ, ਸੁਨੇਹਿਆਂ, ਫ਼ੋਟੋਆਂ ਅਤੇ ਆਡੀਓ ਅਤੇ ਵੀਡੀਓ ਵਰਗੀਆਂ ਚੀਜ਼ਾਂ ਵਾਸਤੇ ਸਾਵਧਾਨ ਰਹੋ।"</string>
<string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="9900961380294292">"ਤੁਹਾਡੇ ਵੱਲੋਂ ਕਾਸਟ ਕਰਨ \'ਤੇ, Android ਕੋਲ ਉਸ ਐਪ \'ਤੇ ਦਿਖਾਈ ਗਈ ਜਾਂ ਚਲਾਈ ਗਈ ਹਰੇਕ ਚੀਜ਼ ਤੱਕ ਪਹੁੰਚ ਹੁੰਦੀ ਹੈ। ਇਸ ਲਈ ਪਾਸਵਰਡਾਂ, ਭੁਗਤਾਨ ਵੇਰਵਿਆਂ, ਸੁਨੇਹਿਆਂ, ਫ਼ੋਟੋਆਂ ਅਤੇ ਆਡੀਓ ਅਤੇ ਵੀਡੀਓ ਵਰਗੀਆਂ ਚੀਜ਼ਾਂ ਸੰਬੰਧੀ ਸਾਵਧਾਨ ਰਹੋ।"</string>
@@ -1173,6 +1170,10 @@
<string name="assistant_attention_content_description" msgid="6830215897604642875">"Assistant ਧਿਆਨ ਸੁਵਿਧਾ ਨੂੰ ਚਾਲੂ ਹੈ"</string>
<string name="set_default_notes_app_toast_content" msgid="2812374329662610753">"ਸੈਟਿੰਗਾਂ ਵਿੱਚ ਜਾ ਕੇ ਪੂਰਵ-ਨਿਰਧਾਰਿਤ ਨੋਟ ਐਪ ਨੂੰ ਸੈੱਟ ਕਰੋ"</string>
<string name="install_app" msgid="5066668100199613936">"ਐਪ ਸਥਾਪਤ ਕਰੋ"</string>
+ <!-- no translation found for connected_display_dialog_start_mirroring (6237895789920854982) -->
+ <skip />
+ <!-- no translation found for enable_display (8308309634883321977) -->
+ <skip />
<string name="privacy_dialog_title" msgid="7839968133469098311">"ਮਾਈਕ੍ਰੋਫ਼ੋਨ ਅਤੇ ਕੈਮਰਾ"</string>
<string name="privacy_dialog_summary" msgid="2458769652125995409">"ਹਾਲ ਹੀ ਵਿੱਚ ਵਰਤੀ ਗਈ ਐਪ"</string>
<string name="privacy_dialog_more_button" msgid="7610604080293562345">"ਹਾਲੀਆ ਪਹੁੰਚ ਦੇਖੋ"</string>
diff --git a/packages/SystemUI/res/values-pl/strings.xml b/packages/SystemUI/res/values-pl/strings.xml
index ad63d1ead9a9..fff57dba3b7c 100644
--- a/packages/SystemUI/res/values-pl/strings.xml
+++ b/packages/SystemUI/res/values-pl/strings.xml
@@ -57,8 +57,7 @@
<string name="hdmi_cec_set_menu_language_description" msgid="8176716678074126619">"Inny użytkownik poprosił o zmianę języka systemu"</string>
<string name="hdmi_cec_set_menu_language_accept" msgid="2513689457281009578">"Zmień język"</string>
<string name="hdmi_cec_set_menu_language_decline" msgid="7650721096558646011">"Zachowaj bieżący język"</string>
- <!-- no translation found for share_wifi_button_text (1285273973812029240) -->
- <skip />
+ <string name="share_wifi_button_text" msgid="1285273973812029240">"Udostępnij Wi‑Fi"</string>
<string name="wifi_debugging_title" msgid="7300007687492186076">"Zezwolić na debugowanie bezprzewodowe w tej sieci?"</string>
<string name="wifi_debugging_message" msgid="5461204211731802995">"Nazwa sieci (SSID)\n<xliff:g id="SSID_0">%1$s</xliff:g>\n\nAdres Wi‑Fi (BSSID)\n<xliff:g id="BSSID_1">%2$s</xliff:g>"</string>
<string name="wifi_debugging_always" msgid="2968383799517975155">"Zawsze zezwalaj w tej sieci"</string>
@@ -160,8 +159,7 @@
<string name="biometric_dialog_wrong_pattern" msgid="8954812279840889029">"Nieprawidłowy wzór"</string>
<string name="biometric_dialog_wrong_password" msgid="69477929306843790">"Nieprawidłowe hasło"</string>
<string name="biometric_dialog_credential_too_many_attempts" msgid="3083141271737748716">"Zbyt wiele nieudanych prób.\n Spróbuj ponownie za <xliff:g id="NUMBER">%d</xliff:g> s."</string>
- <!-- no translation found for work_challenge_emergency_button_text (8946588434515599288) -->
- <skip />
+ <string name="work_challenge_emergency_button_text" msgid="8946588434515599288">"Połączenie alarmowe"</string>
<string name="biometric_dialog_credential_attempts_before_wipe" msgid="6751859711975516999">"Spróbuj ponownie. Próba <xliff:g id="ATTEMPTS_0">%1$d</xliff:g> z <xliff:g id="MAX_ATTEMPTS">%2$d</xliff:g>."</string>
<string name="biometric_dialog_last_attempt_before_wipe_dialog_title" msgid="2874250099278693477">"Dane zostaną usunięte"</string>
<string name="biometric_dialog_last_pattern_attempt_before_wipe_device" msgid="6562299244825817598">"Jeśli następnym razem podasz nieprawidłowy wzór, dane na urządzeniu zostaną usunięte."</string>
@@ -415,8 +413,7 @@
<string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="8736391633234144237">"Podczas udostępniania, nagrywania lub przesyłania treści aplikacja <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> ma dostęp do wszystkiego, co jest widoczne na ekranie lub odtwarzane na urządzeniu. Dlatego zachowaj ostrożność w zakresie haseł, danych do płatności, wiadomości, zdjęć, audio i filmów."</string>
<string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="5211695779082563959">"Podczas udostępniania, nagrywania lub przesyłania treści aplikacja <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> ma dostęp do wszystkiego, co jest w niej wyświetlane lub odtwarzane. Dlatego zachowaj ostrożność w zakresie haseł, danych do płatności, wiadomości, zdjęć, audio i filmów."</string>
<string name="media_projection_entry_app_permission_dialog_continue" msgid="295463518195075840">"Rozpocznij"</string>
- <!-- no translation found for media_projection_entry_app_permission_dialog_single_app_disabled (8999903044874669995) -->
- <skip />
+ <string name="media_projection_entry_app_permission_dialog_single_app_disabled" msgid="8999903044874669995">"<xliff:g id="APP_NAME">%1$s</xliff:g> ma wyłączoną tę opcję"</string>
<string name="media_projection_entry_cast_permission_dialog_title" msgid="8860150223172993547">"Rozpocząć przesyłanie?"</string>
<string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="1986212276016817231">"Podczas przesyłania, Android ma dostęp do wszystkiego, co jest widoczne na ekranie lub odtwarzane na urządzeniu. Dlatego zachowaj ostrożność w zakresie haseł, danych do płatności, wiadomości, zdjęć, audio i filmów."</string>
<string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="9900961380294292">"Podczas przesyłania treści z aplikacji Android ma dostęp do wszystkiego, co jest w niej wyświetlane lub odtwarzane. Dlatego zachowaj ostrożność w zakresie haseł, danych do płatności, wiadomości, zdjęć, audio i filmów."</string>
@@ -1173,6 +1170,10 @@
<string name="assistant_attention_content_description" msgid="6830215897604642875">"Asystent jest aktywny"</string>
<string name="set_default_notes_app_toast_content" msgid="2812374329662610753">"Ustaw domyślną aplikację do obsługi notatek w Ustawieniach"</string>
<string name="install_app" msgid="5066668100199613936">"Zainstaluj aplikację"</string>
+ <!-- no translation found for connected_display_dialog_start_mirroring (6237895789920854982) -->
+ <skip />
+ <!-- no translation found for enable_display (8308309634883321977) -->
+ <skip />
<string name="privacy_dialog_title" msgid="7839968133469098311">"Mikrofon i aparat"</string>
<string name="privacy_dialog_summary" msgid="2458769652125995409">"Aplikacje korzystające w ostatnim czasie"</string>
<string name="privacy_dialog_more_button" msgid="7610604080293562345">"Zobacz ostatni dostęp"</string>
diff --git a/packages/SystemUI/res/values-pt-rBR/strings.xml b/packages/SystemUI/res/values-pt-rBR/strings.xml
index 7f917c8d99f5..431863e62ecf 100644
--- a/packages/SystemUI/res/values-pt-rBR/strings.xml
+++ b/packages/SystemUI/res/values-pt-rBR/strings.xml
@@ -57,8 +57,7 @@
<string name="hdmi_cec_set_menu_language_description" msgid="8176716678074126619">"Mudança do idioma do sistema solicitada por outro dispositivo"</string>
<string name="hdmi_cec_set_menu_language_accept" msgid="2513689457281009578">"Alterar idioma"</string>
<string name="hdmi_cec_set_menu_language_decline" msgid="7650721096558646011">"Manter idioma atual"</string>
- <!-- no translation found for share_wifi_button_text (1285273973812029240) -->
- <skip />
+ <string name="share_wifi_button_text" msgid="1285273973812029240">"Compartilhar Wi‑Fi"</string>
<string name="wifi_debugging_title" msgid="7300007687492186076">"Permitir a depuração por Wi-Fi nesta rede?"</string>
<string name="wifi_debugging_message" msgid="5461204211731802995">"Nome da rede (SSID)\n<xliff:g id="SSID_0">%1$s</xliff:g>\n\nEndereço do Wi-Fi (BSSID)\n<xliff:g id="BSSID_1">%2$s</xliff:g>"</string>
<string name="wifi_debugging_always" msgid="2968383799517975155">"Sempre permitir nesta rede"</string>
@@ -160,8 +159,7 @@
<string name="biometric_dialog_wrong_pattern" msgid="8954812279840889029">"Padrão incorreto"</string>
<string name="biometric_dialog_wrong_password" msgid="69477929306843790">"Senha incorreta"</string>
<string name="biometric_dialog_credential_too_many_attempts" msgid="3083141271737748716">"Excesso de tentativas incorretas.\nTente novamente em <xliff:g id="NUMBER">%d</xliff:g> segundos."</string>
- <!-- no translation found for work_challenge_emergency_button_text (8946588434515599288) -->
- <skip />
+ <string name="work_challenge_emergency_button_text" msgid="8946588434515599288">"Emergência"</string>
<string name="biometric_dialog_credential_attempts_before_wipe" msgid="6751859711975516999">"Tente novamente. Tentativa <xliff:g id="ATTEMPTS_0">%1$d</xliff:g> de <xliff:g id="MAX_ATTEMPTS">%2$d</xliff:g>."</string>
<string name="biometric_dialog_last_attempt_before_wipe_dialog_title" msgid="2874250099278693477">"Seus dados serão excluídos"</string>
<string name="biometric_dialog_last_pattern_attempt_before_wipe_device" msgid="6562299244825817598">"Se você informar um padrão incorreto na próxima tentativa, os dados deste dispositivo serão excluídos."</string>
@@ -415,8 +413,7 @@
<string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="8736391633234144237">"Quando você compartilha, grava ou transmite a tela, o <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> tem acesso a todas as informações visíveis nela ou reproduzidas no dispositivo. Portanto, tenha cuidado com senhas, detalhes de pagamento, mensagens, fotos, áudios e vídeos."</string>
<string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="5211695779082563959">"Quando você compartilha, grava ou transmite um app, o <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> tem acesso a todas as informações visíveis ou reproduzidas no dispositivo. Tenha cuidado com senhas, detalhes de pagamento, mensagens, fotos, áudios e vídeos."</string>
<string name="media_projection_entry_app_permission_dialog_continue" msgid="295463518195075840">"Início"</string>
- <!-- no translation found for media_projection_entry_app_permission_dialog_single_app_disabled (8999903044874669995) -->
- <skip />
+ <string name="media_projection_entry_app_permission_dialog_single_app_disabled" msgid="8999903044874669995">"O app <xliff:g id="APP_NAME">%1$s</xliff:g> desativou essa opção"</string>
<string name="media_projection_entry_cast_permission_dialog_title" msgid="8860150223172993547">"Começar a transmissão?"</string>
<string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="1986212276016817231">"Quando você transmite a tela, o Android tem acesso a todas as informações visíveis nela ou reproduzidas no dispositivo. Portanto, tenha cuidado com senhas, detalhes de pagamento, mensagens, fotos, áudios e vídeos."</string>
<string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="9900961380294292">"Quando você transmite um app, o Android tem acesso a todas as informações visíveis ou reproduzidas nele. Tenha cuidado com senhas, detalhes de pagamento, mensagens fotos, áudios e vídeos."</string>
@@ -1173,6 +1170,10 @@
<string name="assistant_attention_content_description" msgid="6830215897604642875">"Atenção do Assistente ativada"</string>
<string name="set_default_notes_app_toast_content" msgid="2812374329662610753">"Defina o app de notas padrão nas Configurações"</string>
<string name="install_app" msgid="5066668100199613936">"Instalar o app"</string>
+ <!-- no translation found for connected_display_dialog_start_mirroring (6237895789920854982) -->
+ <skip />
+ <!-- no translation found for enable_display (8308309634883321977) -->
+ <skip />
<string name="privacy_dialog_title" msgid="7839968133469098311">"Microfone e câmera"</string>
<string name="privacy_dialog_summary" msgid="2458769652125995409">"Uso recente do app"</string>
<string name="privacy_dialog_more_button" msgid="7610604080293562345">"Consultar acessos recentes"</string>
diff --git a/packages/SystemUI/res/values-pt-rPT/strings.xml b/packages/SystemUI/res/values-pt-rPT/strings.xml
index e455f01fb768..1c0ff6b1a105 100644
--- a/packages/SystemUI/res/values-pt-rPT/strings.xml
+++ b/packages/SystemUI/res/values-pt-rPT/strings.xml
@@ -57,8 +57,7 @@
<string name="hdmi_cec_set_menu_language_description" msgid="8176716678074126619">"Alteração do idioma do sistema solicitada por outro dispositivo"</string>
<string name="hdmi_cec_set_menu_language_accept" msgid="2513689457281009578">"Alterar idioma"</string>
<string name="hdmi_cec_set_menu_language_decline" msgid="7650721096558646011">"Manter idioma atual"</string>
- <!-- no translation found for share_wifi_button_text (1285273973812029240) -->
- <skip />
+ <string name="share_wifi_button_text" msgid="1285273973812029240">"Partilhar Wi‑Fi"</string>
<string name="wifi_debugging_title" msgid="7300007687492186076">"Permitir a depuração sem fios nesta rede?"</string>
<string name="wifi_debugging_message" msgid="5461204211731802995">"Nome da rede (SSID)\n<xliff:g id="SSID_0">%1$s</xliff:g>\n\nEndereço Wi-Fi (BSSID)\n<xliff:g id="BSSID_1">%2$s</xliff:g>"</string>
<string name="wifi_debugging_always" msgid="2968383799517975155">"Permitir sempre nesta rede"</string>
@@ -160,8 +159,7 @@
<string name="biometric_dialog_wrong_pattern" msgid="8954812279840889029">"Padrão incorreto."</string>
<string name="biometric_dialog_wrong_password" msgid="69477929306843790">"Palavra-passe incorreta."</string>
<string name="biometric_dialog_credential_too_many_attempts" msgid="3083141271737748716">"Demasiadas tentativas incorretas.\nTente novamente dentro de <xliff:g id="NUMBER">%d</xliff:g> segundos."</string>
- <!-- no translation found for work_challenge_emergency_button_text (8946588434515599288) -->
- <skip />
+ <string name="work_challenge_emergency_button_text" msgid="8946588434515599288">"Emergência"</string>
<string name="biometric_dialog_credential_attempts_before_wipe" msgid="6751859711975516999">"Tente novamente. Tentativa <xliff:g id="ATTEMPTS_0">%1$d</xliff:g> de <xliff:g id="MAX_ATTEMPTS">%2$d</xliff:g>."</string>
<string name="biometric_dialog_last_attempt_before_wipe_dialog_title" msgid="2874250099278693477">"Os seus dados serão eliminados"</string>
<string name="biometric_dialog_last_pattern_attempt_before_wipe_device" msgid="6562299244825817598">"Se introduzir um padrão incorreto na tentativa seguinte, os dados deste dispositivo serão eliminados."</string>
@@ -415,8 +413,7 @@
<string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="8736391633234144237">"Quando está a partilhar, gravar ou transmitir, a app <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> tem acesso a tudo o que está visível no seu ecrã ou é reproduzido no seu dispositivo. Por isso, tenha cuidado com, por exemplo, palavras-passe, detalhes de pagamento, mensagens, fotos, áudio e vídeo."</string>
<string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="5211695779082563959">"Quando está a partilhar, gravar ou transmitir uma app, a app <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> tem acesso a tudo o que é apresentado ou reproduzido nessa app. Por isso, tenha cuidado com, por exemplo, palavras-passe, detalhes de pagamento, mensagens, fotos, áudio e vídeo."</string>
<string name="media_projection_entry_app_permission_dialog_continue" msgid="295463518195075840">"Iniciar"</string>
- <!-- no translation found for media_projection_entry_app_permission_dialog_single_app_disabled (8999903044874669995) -->
- <skip />
+ <string name="media_projection_entry_app_permission_dialog_single_app_disabled" msgid="8999903044874669995">"A app <xliff:g id="APP_NAME">%1$s</xliff:g> desativou esta opção"</string>
<string name="media_projection_entry_cast_permission_dialog_title" msgid="8860150223172993547">"Começar a transmitir?"</string>
<string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="1986212276016817231">"Quando está a transmitir conteúdo, o Android tem acesso a tudo o que está visível no seu ecrã ou é reproduzido no seu dispositivo. Por isso, tenha cuidado com, por exemplo, palavras-passe, detalhes de pagamento, mensagens, fotos, áudio e vídeo."</string>
<string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="9900961380294292">"Quando está a transmitir uma app, o Android tem acesso a tudo o que é apresentado ou reproduzido nessa app. Por isso, tenha cuidado com, por exemplo, palavras-passe, detalhes de pagamento, mensagens, fotos, áudio e vídeo."</string>
@@ -1173,6 +1170,8 @@
<string name="assistant_attention_content_description" msgid="6830215897604642875">"Atenção do Assistente ativada"</string>
<string name="set_default_notes_app_toast_content" msgid="2812374329662610753">"Predefina a app de notas nas Definições"</string>
<string name="install_app" msgid="5066668100199613936">"Instalar app"</string>
+ <string name="connected_display_dialog_start_mirroring" msgid="6237895789920854982">"Espelhar para o ecrã externo?"</string>
+ <string name="enable_display" msgid="8308309634883321977">"Ativar ecrã"</string>
<string name="privacy_dialog_title" msgid="7839968133469098311">"Microfone e câmara"</string>
<string name="privacy_dialog_summary" msgid="2458769652125995409">"Utilização recente da app"</string>
<string name="privacy_dialog_more_button" msgid="7610604080293562345">"Ver acesso recente"</string>
diff --git a/packages/SystemUI/res/values-pt/strings.xml b/packages/SystemUI/res/values-pt/strings.xml
index 7f917c8d99f5..431863e62ecf 100644
--- a/packages/SystemUI/res/values-pt/strings.xml
+++ b/packages/SystemUI/res/values-pt/strings.xml
@@ -57,8 +57,7 @@
<string name="hdmi_cec_set_menu_language_description" msgid="8176716678074126619">"Mudança do idioma do sistema solicitada por outro dispositivo"</string>
<string name="hdmi_cec_set_menu_language_accept" msgid="2513689457281009578">"Alterar idioma"</string>
<string name="hdmi_cec_set_menu_language_decline" msgid="7650721096558646011">"Manter idioma atual"</string>
- <!-- no translation found for share_wifi_button_text (1285273973812029240) -->
- <skip />
+ <string name="share_wifi_button_text" msgid="1285273973812029240">"Compartilhar Wi‑Fi"</string>
<string name="wifi_debugging_title" msgid="7300007687492186076">"Permitir a depuração por Wi-Fi nesta rede?"</string>
<string name="wifi_debugging_message" msgid="5461204211731802995">"Nome da rede (SSID)\n<xliff:g id="SSID_0">%1$s</xliff:g>\n\nEndereço do Wi-Fi (BSSID)\n<xliff:g id="BSSID_1">%2$s</xliff:g>"</string>
<string name="wifi_debugging_always" msgid="2968383799517975155">"Sempre permitir nesta rede"</string>
@@ -160,8 +159,7 @@
<string name="biometric_dialog_wrong_pattern" msgid="8954812279840889029">"Padrão incorreto"</string>
<string name="biometric_dialog_wrong_password" msgid="69477929306843790">"Senha incorreta"</string>
<string name="biometric_dialog_credential_too_many_attempts" msgid="3083141271737748716">"Excesso de tentativas incorretas.\nTente novamente em <xliff:g id="NUMBER">%d</xliff:g> segundos."</string>
- <!-- no translation found for work_challenge_emergency_button_text (8946588434515599288) -->
- <skip />
+ <string name="work_challenge_emergency_button_text" msgid="8946588434515599288">"Emergência"</string>
<string name="biometric_dialog_credential_attempts_before_wipe" msgid="6751859711975516999">"Tente novamente. Tentativa <xliff:g id="ATTEMPTS_0">%1$d</xliff:g> de <xliff:g id="MAX_ATTEMPTS">%2$d</xliff:g>."</string>
<string name="biometric_dialog_last_attempt_before_wipe_dialog_title" msgid="2874250099278693477">"Seus dados serão excluídos"</string>
<string name="biometric_dialog_last_pattern_attempt_before_wipe_device" msgid="6562299244825817598">"Se você informar um padrão incorreto na próxima tentativa, os dados deste dispositivo serão excluídos."</string>
@@ -415,8 +413,7 @@
<string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="8736391633234144237">"Quando você compartilha, grava ou transmite a tela, o <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> tem acesso a todas as informações visíveis nela ou reproduzidas no dispositivo. Portanto, tenha cuidado com senhas, detalhes de pagamento, mensagens, fotos, áudios e vídeos."</string>
<string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="5211695779082563959">"Quando você compartilha, grava ou transmite um app, o <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> tem acesso a todas as informações visíveis ou reproduzidas no dispositivo. Tenha cuidado com senhas, detalhes de pagamento, mensagens, fotos, áudios e vídeos."</string>
<string name="media_projection_entry_app_permission_dialog_continue" msgid="295463518195075840">"Início"</string>
- <!-- no translation found for media_projection_entry_app_permission_dialog_single_app_disabled (8999903044874669995) -->
- <skip />
+ <string name="media_projection_entry_app_permission_dialog_single_app_disabled" msgid="8999903044874669995">"O app <xliff:g id="APP_NAME">%1$s</xliff:g> desativou essa opção"</string>
<string name="media_projection_entry_cast_permission_dialog_title" msgid="8860150223172993547">"Começar a transmissão?"</string>
<string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="1986212276016817231">"Quando você transmite a tela, o Android tem acesso a todas as informações visíveis nela ou reproduzidas no dispositivo. Portanto, tenha cuidado com senhas, detalhes de pagamento, mensagens, fotos, áudios e vídeos."</string>
<string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="9900961380294292">"Quando você transmite um app, o Android tem acesso a todas as informações visíveis ou reproduzidas nele. Tenha cuidado com senhas, detalhes de pagamento, mensagens fotos, áudios e vídeos."</string>
@@ -1173,6 +1170,10 @@
<string name="assistant_attention_content_description" msgid="6830215897604642875">"Atenção do Assistente ativada"</string>
<string name="set_default_notes_app_toast_content" msgid="2812374329662610753">"Defina o app de notas padrão nas Configurações"</string>
<string name="install_app" msgid="5066668100199613936">"Instalar o app"</string>
+ <!-- no translation found for connected_display_dialog_start_mirroring (6237895789920854982) -->
+ <skip />
+ <!-- no translation found for enable_display (8308309634883321977) -->
+ <skip />
<string name="privacy_dialog_title" msgid="7839968133469098311">"Microfone e câmera"</string>
<string name="privacy_dialog_summary" msgid="2458769652125995409">"Uso recente do app"</string>
<string name="privacy_dialog_more_button" msgid="7610604080293562345">"Consultar acessos recentes"</string>
diff --git a/packages/SystemUI/res/values-ro/strings.xml b/packages/SystemUI/res/values-ro/strings.xml
index 844027a4924d..513abc28a33d 100644
--- a/packages/SystemUI/res/values-ro/strings.xml
+++ b/packages/SystemUI/res/values-ro/strings.xml
@@ -57,8 +57,7 @@
<string name="hdmi_cec_set_menu_language_description" msgid="8176716678074126619">"Alt dispozitiv solicită schimbarea limbii de sistem"</string>
<string name="hdmi_cec_set_menu_language_accept" msgid="2513689457281009578">"Schimbă limba"</string>
<string name="hdmi_cec_set_menu_language_decline" msgid="7650721096558646011">"Păstrează limba actuală"</string>
- <!-- no translation found for share_wifi_button_text (1285273973812029240) -->
- <skip />
+ <string name="share_wifi_button_text" msgid="1285273973812029240">"Permite accesul la Wi‑Fi"</string>
<string name="wifi_debugging_title" msgid="7300007687492186076">"Permiți remedierea erorilor wireless în această rețea?"</string>
<string name="wifi_debugging_message" msgid="5461204211731802995">"Numele rețelei (SSID)\n<xliff:g id="SSID_0">%1$s</xliff:g>\n\nAdresa Wi‑Fi (BSSID)\n<xliff:g id="BSSID_1">%2$s</xliff:g>"</string>
<string name="wifi_debugging_always" msgid="2968383799517975155">"Permite întotdeauna în această rețea"</string>
@@ -160,8 +159,7 @@
<string name="biometric_dialog_wrong_pattern" msgid="8954812279840889029">"Model greșit"</string>
<string name="biometric_dialog_wrong_password" msgid="69477929306843790">"Parolă greșită"</string>
<string name="biometric_dialog_credential_too_many_attempts" msgid="3083141271737748716">"Prea multe încercări incorecte.\nÎncearcă din nou peste <xliff:g id="NUMBER">%d</xliff:g> secunde."</string>
- <!-- no translation found for work_challenge_emergency_button_text (8946588434515599288) -->
- <skip />
+ <string name="work_challenge_emergency_button_text" msgid="8946588434515599288">"Urgență"</string>
<string name="biometric_dialog_credential_attempts_before_wipe" msgid="6751859711975516999">"Încearcă din nou. Încercarea <xliff:g id="ATTEMPTS_0">%1$d</xliff:g> din <xliff:g id="MAX_ATTEMPTS">%2$d</xliff:g>."</string>
<string name="biometric_dialog_last_attempt_before_wipe_dialog_title" msgid="2874250099278693477">"Datele tale vor fi șterse"</string>
<string name="biometric_dialog_last_pattern_attempt_before_wipe_device" msgid="6562299244825817598">"Dacă la următoarea încercare introduci un model incorect, datele de pe acest dispozitiv vor fi șterse."</string>
@@ -415,8 +413,7 @@
<string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="8736391633234144237">"Când permiți accesul, înregistrezi sau proiectezi, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> are acces la orice este vizibil pe ecran sau se redă pe dispozitiv. Prin urmare, ai grijă cu parolele, detaliile de plată, mesajele, fotografiile și conținutul audio și video."</string>
<string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="5211695779082563959">"Când permiți accesul, înregistrezi sau proiectezi o aplicație, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> are acces la orice se afișează pe ecran sau se redă în aplicație. Prin urmare, ai grijă cu informații cum ar fi parolele, detaliile de plată, mesajele, fotografiile și conținutul audio și video."</string>
<string name="media_projection_entry_app_permission_dialog_continue" msgid="295463518195075840">"Începe"</string>
- <!-- no translation found for media_projection_entry_app_permission_dialog_single_app_disabled (8999903044874669995) -->
- <skip />
+ <string name="media_projection_entry_app_permission_dialog_single_app_disabled" msgid="8999903044874669995">"<xliff:g id="APP_NAME">%1$s</xliff:g> a dezactivat această opțiune"</string>
<string name="media_projection_entry_cast_permission_dialog_title" msgid="8860150223172993547">"Începi să proiectezi?"</string>
<string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="1986212276016817231">"Când proiectezi, Android are acces la orice este vizibil pe ecran sau se redă pe dispozitiv. Prin urmare, ai grijă cu parolele, detaliile de plată, mesajele, fotografiile și conținutul audio și video."</string>
<string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="9900961380294292">"Când proiectezi o aplicație, Android are acces la orice se afișează sau se redă în aplicație. Prin urmare, ai grijă cu parolele, detaliile de plată, mesajele, fotografiile și conținutul audio și video."</string>
@@ -1173,6 +1170,10 @@
<string name="assistant_attention_content_description" msgid="6830215897604642875">"Asistentul este atent"</string>
<string name="set_default_notes_app_toast_content" msgid="2812374329662610753">"Setează aplicația prestabilită de note din Setări"</string>
<string name="install_app" msgid="5066668100199613936">"Instalează aplicația"</string>
+ <!-- no translation found for connected_display_dialog_start_mirroring (6237895789920854982) -->
+ <skip />
+ <!-- no translation found for enable_display (8308309634883321977) -->
+ <skip />
<string name="privacy_dialog_title" msgid="7839968133469098311">"Microfon și cameră"</string>
<string name="privacy_dialog_summary" msgid="2458769652125995409">"Utilizare recentă în aplicații"</string>
<string name="privacy_dialog_more_button" msgid="7610604080293562345">"Vezi accesarea recentă"</string>
diff --git a/packages/SystemUI/res/values-ru/strings.xml b/packages/SystemUI/res/values-ru/strings.xml
index 9728103a0e9a..694ccdf1aeb1 100644
--- a/packages/SystemUI/res/values-ru/strings.xml
+++ b/packages/SystemUI/res/values-ru/strings.xml
@@ -57,8 +57,7 @@
<string name="hdmi_cec_set_menu_language_description" msgid="8176716678074126619">"Получен запрос на изменение системного языка от другого устройства."</string>
<string name="hdmi_cec_set_menu_language_accept" msgid="2513689457281009578">"Изменить язык"</string>
<string name="hdmi_cec_set_menu_language_decline" msgid="7650721096558646011">"Оставить текущий язык"</string>
- <!-- no translation found for share_wifi_button_text (1285273973812029240) -->
- <skip />
+ <string name="share_wifi_button_text" msgid="1285273973812029240">"Поделиться Wi‑Fi"</string>
<string name="wifi_debugging_title" msgid="7300007687492186076">"Разрешить отладку по Wi-Fi в этой сети?"</string>
<string name="wifi_debugging_message" msgid="5461204211731802995">"Название сети (SSID):\n<xliff:g id="SSID_0">%1$s</xliff:g>\n\nMAC-адрес точки доступа (BSSID):\n<xliff:g id="BSSID_1">%2$s</xliff:g>"</string>
<string name="wifi_debugging_always" msgid="2968383799517975155">"Всегда разрешать отладку в этой сети"</string>
@@ -160,8 +159,7 @@
<string name="biometric_dialog_wrong_pattern" msgid="8954812279840889029">"Неверный графический ключ."</string>
<string name="biometric_dialog_wrong_password" msgid="69477929306843790">"Неверный пароль."</string>
<string name="biometric_dialog_credential_too_many_attempts" msgid="3083141271737748716">"Слишком много неудачных попыток.\nПовторите через <xliff:g id="NUMBER">%d</xliff:g> сек."</string>
- <!-- no translation found for work_challenge_emergency_button_text (8946588434515599288) -->
- <skip />
+ <string name="work_challenge_emergency_button_text" msgid="8946588434515599288">"Экстренный вызов"</string>
<string name="biometric_dialog_credential_attempts_before_wipe" msgid="6751859711975516999">"Попробуйте ещё раз. Попытка <xliff:g id="ATTEMPTS_0">%1$d</xliff:g> из <xliff:g id="MAX_ATTEMPTS">%2$d</xliff:g>."</string>
<string name="biometric_dialog_last_attempt_before_wipe_dialog_title" msgid="2874250099278693477">"Осталась одна попытка"</string>
<string name="biometric_dialog_last_pattern_attempt_before_wipe_device" msgid="6562299244825817598">"Если вы неправильно введете графический ключ ещё раз, с устройства будут удалены все данные."</string>
@@ -415,8 +413,7 @@
<string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="8736391633234144237">"Когда вы демонстрируете, транслируете экран или записываете видео с него, приложение \"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>\" получает доступ ко всему, что видно или воспроизводится на устройстве. Поэтому будьте осторожны с паролями, сведениями о способах оплаты, сообщениями, фотографиями, аудио- и видеозаписями."</string>
<string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="5211695779082563959">"Когда вы демонстрируете, записываете или транслируете экран приложения, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> получает доступ ко всему, что видно или воспроизводится в этом приложении. Будьте осторожны с паролями, сведениями о способах оплаты, сообщениями, фотографиями, аудио- и видеозаписями."</string>
<string name="media_projection_entry_app_permission_dialog_continue" msgid="295463518195075840">"Начать"</string>
- <!-- no translation found for media_projection_entry_app_permission_dialog_single_app_disabled (8999903044874669995) -->
- <skip />
+ <string name="media_projection_entry_app_permission_dialog_single_app_disabled" msgid="8999903044874669995">"Приложение \"<xliff:g id="APP_NAME">%1$s</xliff:g>\" отключило эту возможность"</string>
<string name="media_projection_entry_cast_permission_dialog_title" msgid="8860150223172993547">"Начать трансляцию?"</string>
<string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="1986212276016817231">"Во время трансляции система Android получает доступ ко всему, что видно или воспроизводится на устройстве. Поэтому будьте осторожны с паролями, сведениями о способах оплаты, сообщениями, фотографиями, аудио- и видеозаписями."</string>
<string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="9900961380294292">"Когда вы транслируете экран приложения, система Android получает доступ ко всему, что видно или воспроизводится в нем. Поэтому будьте осторожны с паролями, сведениями о способах оплаты, сообщениями, фотографиями, аудио- и видеозаписями."</string>
@@ -1173,6 +1170,10 @@
<string name="assistant_attention_content_description" msgid="6830215897604642875">"Ассистент готов слушать"</string>
<string name="set_default_notes_app_toast_content" msgid="2812374329662610753">"Задайте стандартное приложение для заметок в настройках."</string>
<string name="install_app" msgid="5066668100199613936">"Установить приложение"</string>
+ <!-- no translation found for connected_display_dialog_start_mirroring (6237895789920854982) -->
+ <skip />
+ <!-- no translation found for enable_display (8308309634883321977) -->
+ <skip />
<string name="privacy_dialog_title" msgid="7839968133469098311">"Микрофон и камера"</string>
<string name="privacy_dialog_summary" msgid="2458769652125995409">"Недавнее использование приложениями"</string>
<string name="privacy_dialog_more_button" msgid="7610604080293562345">"Посмотреть недавний доступ"</string>
diff --git a/packages/SystemUI/res/values-si/strings.xml b/packages/SystemUI/res/values-si/strings.xml
index 2424fe11f50a..7ac474d67c8f 100644
--- a/packages/SystemUI/res/values-si/strings.xml
+++ b/packages/SystemUI/res/values-si/strings.xml
@@ -57,8 +57,7 @@
<string name="hdmi_cec_set_menu_language_description" msgid="8176716678074126619">"වෙනත් උපාංගයකින් පද්ධති භාෂාව වෙනස් කිරීම ඉල්ලා ඇත"</string>
<string name="hdmi_cec_set_menu_language_accept" msgid="2513689457281009578">"භාෂාව වෙනස් කරන්න"</string>
<string name="hdmi_cec_set_menu_language_decline" msgid="7650721096558646011">"වත්මන් භාෂාව තබා ගන්න"</string>
- <!-- no translation found for share_wifi_button_text (1285273973812029240) -->
- <skip />
+ <string name="share_wifi_button_text" msgid="1285273973812029240">"Wi‑Fi බෙදා ගන්න"</string>
<string name="wifi_debugging_title" msgid="7300007687492186076">"මෙම ජාලයේ නොරැහැන් නිදොස්කරණය ඉඩ දෙන්නද?"</string>
<string name="wifi_debugging_message" msgid="5461204211731802995">"ජාල නම (SSID)\n<xliff:g id="SSID_0">%1$s</xliff:g>\n\nWi‑Fi ලිපිනය (BSSID)\n<xliff:g id="BSSID_1">%2$s</xliff:g>"</string>
<string name="wifi_debugging_always" msgid="2968383799517975155">"මෙම ජාලයේ සැමවිට ඉඩ දෙන්න"</string>
@@ -160,8 +159,7 @@
<string name="biometric_dialog_wrong_pattern" msgid="8954812279840889029">"වැරදි රටාවකි"</string>
<string name="biometric_dialog_wrong_password" msgid="69477929306843790">"වැරදි මුරපදයකි"</string>
<string name="biometric_dialog_credential_too_many_attempts" msgid="3083141271737748716">"වැරදි උත්සාහයන් ගණන වැඩියි. තත්පර \n තත්පර <xliff:g id="NUMBER">%d</xliff:g>කින් නැවත උත්සාහ කරන්න."</string>
- <!-- no translation found for work_challenge_emergency_button_text (8946588434515599288) -->
- <skip />
+ <string name="work_challenge_emergency_button_text" msgid="8946588434515599288">"හදිසි අවස්ථාව"</string>
<string name="biometric_dialog_credential_attempts_before_wipe" msgid="6751859711975516999">"නැවත උත්සාහ කරන්න. <xliff:g id="MAX_ATTEMPTS">%2$d</xliff:g>කින් <xliff:g id="ATTEMPTS_0">%1$d</xliff:g> උත්සාහය."</string>
<string name="biometric_dialog_last_attempt_before_wipe_dialog_title" msgid="2874250099278693477">"ඔබේ දත්ත මකනු ඇත"</string>
<string name="biometric_dialog_last_pattern_attempt_before_wipe_device" msgid="6562299244825817598">"ඔබ ඊළඟ උත්සාහයේදී වැරදි රටාවක් ඇතුළු කළහොත්, මෙම උපාංගයෙහි දත්ත මකනු ඇත."</string>
@@ -415,8 +413,7 @@
<string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="8736391633234144237">"ඔබ බෙදා ගන්නා විට, පටිගත කරන විට, හෝ විකාශනය කරන විට, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> හට ඔබේ තිරයේ පෙනෙන හෝ ඔබේ උපාංගයේ වාදනය වන ඕනෑම දෙයකට ප්‍රවේශය ඇත. ඒ නිසා මුරපද, ගෙවීම් විස්තර, පණිවුඩ, ඡායාරූප, සහ ශ්‍රව්‍ය සහ දෘශ්‍ය වැනි දේවල් පිළිබඳ ප්‍රවේශම් වන්න."</string>
<string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="5211695779082563959">"ඔබ යෙදුමක් බෙදා ගන්නා විට, පටිගත කරන විට හෝ විකාශය කරන විට, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> හට එම යෙදුමේ පෙන්වන හෝ වාදනය කරන ඕනෑම දෙයකට ප්‍රවේශය ඇත. ඒ නිසා මුරපද, ගෙවීම් විස්තර, පණිවුඩ, ඡායාරූප, සහ ශ්‍රව්‍ය සහ දෘශ්‍ය වැනි දේවල් පිළිබඳ ප්‍රවේශම් වන්න."</string>
<string name="media_projection_entry_app_permission_dialog_continue" msgid="295463518195075840">"අරඹන්න"</string>
- <!-- no translation found for media_projection_entry_app_permission_dialog_single_app_disabled (8999903044874669995) -->
- <skip />
+ <string name="media_projection_entry_app_permission_dialog_single_app_disabled" msgid="8999903044874669995">"<xliff:g id="APP_NAME">%1$s</xliff:g> මෙම විකල්පය අබල කර ඇත"</string>
<string name="media_projection_entry_cast_permission_dialog_title" msgid="8860150223172993547">"විකාශය ආරම්භ කරන්න ද?"</string>
<string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="1986212276016817231">"ඔබ විකාශය කරන විට, Android හට ඔබේ තිරයේ පෙනෙන හෝ ඔබේ උපාංගයේ වාදනය වන ඕනෑම දෙයකට ප්‍රවේශය ඇත. ඒ නිසා මුරපද, ගෙවීම් විස්තර, පණිවුඩ, ඡායාරූප, සහ ශ්‍රව්‍ය සහ දෘශ්‍ය වැනි දේවල් පිළිබඳ ප්‍රවේශම් වන්න."</string>
<string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="9900961380294292">"ඔබ යෙදුමක් විකාශය කරන විට, Android හට එම යෙදුමේ පෙන්වන හෝ වාදනය කරන ඕනෑම දෙයකට ප්‍රවේශය ඇත. ඒ නිසා මුරපද, ගෙවීම් විස්තර, පණිවුඩ, ඡායාරූප, සහ ශ්‍රව්‍ය සහ දෘශ්‍ය වැනි දේවල් පිළිබඳ ප්‍රවේශම් වන්න."</string>
@@ -1173,6 +1170,10 @@
<string name="assistant_attention_content_description" msgid="6830215897604642875">"සහයක අවධානය යොමු කරයි"</string>
<string name="set_default_notes_app_toast_content" msgid="2812374329662610753">"සැකසීම් තුළ පෙරනිමි සටහන් යෙදුම සකසන්න"</string>
<string name="install_app" msgid="5066668100199613936">"යෙදුම ස්ථාපනය කරන්න"</string>
+ <!-- no translation found for connected_display_dialog_start_mirroring (6237895789920854982) -->
+ <skip />
+ <!-- no translation found for enable_display (8308309634883321977) -->
+ <skip />
<string name="privacy_dialog_title" msgid="7839968133469098311">"මයික්‍රොෆෝනය සහ කැමරාව"</string>
<string name="privacy_dialog_summary" msgid="2458769652125995409">"මෑත යෙදුම් භාවිතය"</string>
<string name="privacy_dialog_more_button" msgid="7610604080293562345">"මෑත ප්‍රවේශය බලන්න"</string>
diff --git a/packages/SystemUI/res/values-sk/strings.xml b/packages/SystemUI/res/values-sk/strings.xml
index 4e1b46bf7660..92813d026370 100644
--- a/packages/SystemUI/res/values-sk/strings.xml
+++ b/packages/SystemUI/res/values-sk/strings.xml
@@ -57,8 +57,7 @@
<string name="hdmi_cec_set_menu_language_description" msgid="8176716678074126619">"Zmenu jazyka systému vyžiadalo iné zariadenie"</string>
<string name="hdmi_cec_set_menu_language_accept" msgid="2513689457281009578">"Zmeniť jazyk"</string>
<string name="hdmi_cec_set_menu_language_decline" msgid="7650721096558646011">"Ponechať aktuálny jazyk"</string>
- <!-- no translation found for share_wifi_button_text (1285273973812029240) -->
- <skip />
+ <string name="share_wifi_button_text" msgid="1285273973812029240">"Zdieľať Wi‑Fi"</string>
<string name="wifi_debugging_title" msgid="7300007687492186076">"Chcete povoliť bezdrôtové ladenie v tejto sieti?"</string>
<string name="wifi_debugging_message" msgid="5461204211731802995">"Názov siete (SSID)\n<xliff:g id="SSID_0">%1$s</xliff:g>\n\nAdresa Wi‑Fi (BSSID)\n<xliff:g id="BSSID_1">%2$s</xliff:g>"</string>
<string name="wifi_debugging_always" msgid="2968383799517975155">"Vždy povoliť v tejto sieti"</string>
@@ -160,8 +159,7 @@
<string name="biometric_dialog_wrong_pattern" msgid="8954812279840889029">"Nesprávny vzor"</string>
<string name="biometric_dialog_wrong_password" msgid="69477929306843790">"Nesprávne heslo"</string>
<string name="biometric_dialog_credential_too_many_attempts" msgid="3083141271737748716">"Príliš veľa nesprávnych pokusov. \nSkúste to znova o <xliff:g id="NUMBER">%d</xliff:g> s."</string>
- <!-- no translation found for work_challenge_emergency_button_text (8946588434515599288) -->
- <skip />
+ <string name="work_challenge_emergency_button_text" msgid="8946588434515599288">"Tieseň"</string>
<string name="biometric_dialog_credential_attempts_before_wipe" msgid="6751859711975516999">"Skúste to znova. <xliff:g id="ATTEMPTS_0">%1$d</xliff:g>. z <xliff:g id="MAX_ATTEMPTS">%2$d</xliff:g> pokusov."</string>
<string name="biometric_dialog_last_attempt_before_wipe_dialog_title" msgid="2874250099278693477">"Vaše dáta budú odstránené"</string>
<string name="biometric_dialog_last_pattern_attempt_before_wipe_device" msgid="6562299244825817598">"Ak pri ďalšom pokuse zadáte nesprávny vzor, dáta tohto zariadenia budú odstránené."</string>
@@ -415,8 +413,7 @@
<string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="8736391633234144237">"Počas zdieľania, nahrávania alebo prenosu bude mať <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> prístup k všetkému, čo sa zobrazuje na obrazovke alebo prehráva v zariadení. Preto zvýšte pozornosť v prípade položiek, ako sú heslá, platobné údaje, správy, fotky a zvuk či video."</string>
<string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="5211695779082563959">"Počas zdieľania, nahrávania alebo prenosu v aplikácii bude mať <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> prístup k všetkému, čo sa v danej aplikácii zobrazuje alebo prehráva. Preto zvýšte pozornosť v prípade položiek, ako sú heslá, platobné údaje, správy, fotky a zvuk či video."</string>
<string name="media_projection_entry_app_permission_dialog_continue" msgid="295463518195075840">"Začať"</string>
- <!-- no translation found for media_projection_entry_app_permission_dialog_single_app_disabled (8999903044874669995) -->
- <skip />
+ <string name="media_projection_entry_app_permission_dialog_single_app_disabled" msgid="8999903044874669995">"Aplikácia <xliff:g id="APP_NAME">%1$s</xliff:g> túto možnosť zakázala"</string>
<string name="media_projection_entry_cast_permission_dialog_title" msgid="8860150223172993547">"Chcete spustiť prenos?"</string>
<string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="1986212276016817231">"Počas prenosu bude mať Android prístup k všetkému, čo sa zobrazuje na obrazovke alebo prehráva v zariadení. Preto zvýšte pozornosť v prípade položiek, ako sú heslá, platobné údaje, správy, fotky a zvuk či video."</string>
<string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="9900961380294292">"Počas prenosu v aplikácii bude mať Android prístup k všetkému, čo sa v danej aplikácii zobrazuje alebo prehráva. Preto zvýšte pozornosť v prípade položiek, ako sú heslá, platobné údaje, správy, fotky a zvuk či video."</string>
@@ -1173,6 +1170,10 @@
<string name="assistant_attention_content_description" msgid="6830215897604642875">"Pozornosť Asistenta je zapnutá"</string>
<string name="set_default_notes_app_toast_content" msgid="2812374329662610753">"Nastavte predvolenú aplikáciu na poznámky v Nastaveniach"</string>
<string name="install_app" msgid="5066668100199613936">"Inštalovať aplikáciu"</string>
+ <!-- no translation found for connected_display_dialog_start_mirroring (6237895789920854982) -->
+ <skip />
+ <!-- no translation found for enable_display (8308309634883321977) -->
+ <skip />
<string name="privacy_dialog_title" msgid="7839968133469098311">"Mikrofón a fotoaparát"</string>
<string name="privacy_dialog_summary" msgid="2458769652125995409">"Nedávne využitie aplikácie"</string>
<string name="privacy_dialog_more_button" msgid="7610604080293562345">"Zobraziť nedávny prístup"</string>
diff --git a/packages/SystemUI/res/values-sl/strings.xml b/packages/SystemUI/res/values-sl/strings.xml
index 89e9276377ec..065035480574 100644
--- a/packages/SystemUI/res/values-sl/strings.xml
+++ b/packages/SystemUI/res/values-sl/strings.xml
@@ -57,8 +57,7 @@
<string name="hdmi_cec_set_menu_language_description" msgid="8176716678074126619">"Spremembo jezika sistema je zahtevala druga naprava."</string>
<string name="hdmi_cec_set_menu_language_accept" msgid="2513689457281009578">"Spremeni jezik"</string>
<string name="hdmi_cec_set_menu_language_decline" msgid="7650721096558646011">"Obdrži trenutni jezik"</string>
- <!-- no translation found for share_wifi_button_text (1285273973812029240) -->
- <skip />
+ <string name="share_wifi_button_text" msgid="1285273973812029240">"Delite omrežje Wi‑Fi"</string>
<string name="wifi_debugging_title" msgid="7300007687492186076">"Ali dovolite brezžično odpravljanje napak v tem omrežju?"</string>
<string name="wifi_debugging_message" msgid="5461204211731802995">"Ime omrežja (SSID)\n<xliff:g id="SSID_0">%1$s</xliff:g>\n\nNaslov omrežja Wi‑Fi (BSSID)\n<xliff:g id="BSSID_1">%2$s</xliff:g>"</string>
<string name="wifi_debugging_always" msgid="2968383799517975155">"Vedno dovoli v tem omrežju"</string>
@@ -160,8 +159,7 @@
<string name="biometric_dialog_wrong_pattern" msgid="8954812279840889029">"Napačen vzorec"</string>
<string name="biometric_dialog_wrong_password" msgid="69477929306843790">"Napačno geslo"</string>
<string name="biometric_dialog_credential_too_many_attempts" msgid="3083141271737748716">"Preveč napačnih poskusov.\nPoskusite znova čez <xliff:g id="NUMBER">%d</xliff:g> s."</string>
- <!-- no translation found for work_challenge_emergency_button_text (8946588434515599288) -->
- <skip />
+ <string name="work_challenge_emergency_button_text" msgid="8946588434515599288">"Nujni primer"</string>
<string name="biometric_dialog_credential_attempts_before_wipe" msgid="6751859711975516999">"Poskusite znova. Poskus <xliff:g id="ATTEMPTS_0">%1$d</xliff:g> od <xliff:g id="MAX_ATTEMPTS">%2$d</xliff:g>."</string>
<string name="biometric_dialog_last_attempt_before_wipe_dialog_title" msgid="2874250099278693477">"Vaši podatki bodo izbrisani"</string>
<string name="biometric_dialog_last_pattern_attempt_before_wipe_device" msgid="6562299244825817598">"Če pri naslednjem poskusu vnesete napačen vzorec, bodo podatki v tej napravi izbrisani."</string>
@@ -415,8 +413,7 @@
<string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="8736391633234144237">"Pri deljenju, snemanju ali predvajanju ima aplikacija <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> dostop do vsega, kar je prikazano na zaslonu ali se predvaja v napravi. Zato bodite previdni z gesli, podatki za plačilo, sporočili, fotografijami ter z zvokom in videom."</string>
<string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="5211695779082563959">"Pri deljenju, snemanju ali predvajanju aplikacije ima aplikacija <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> dostop do vsega, kar je prikazano ali predvajano v tej aplikaciji, zato bodite previdni z gesli, podatki za plačilo, sporočili, fotografijami ter z zvokom in videom."</string>
<string name="media_projection_entry_app_permission_dialog_continue" msgid="295463518195075840">"Začni"</string>
- <!-- no translation found for media_projection_entry_app_permission_dialog_single_app_disabled (8999903044874669995) -->
- <skip />
+ <string name="media_projection_entry_app_permission_dialog_single_app_disabled" msgid="8999903044874669995">"Aplikacija <xliff:g id="APP_NAME">%1$s</xliff:g> je onemogočila to možnost"</string>
<string name="media_projection_entry_cast_permission_dialog_title" msgid="8860150223172993547">"Želite začeti predvajati?"</string>
<string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="1986212276016817231">"Pri predvajanju ima Android dostop do vsega, kar je prikazano na zaslonu ali se predvaja v napravi. Zato bodite previdni z gesli, podatki za plačilo, sporočili, fotografijami ter z zvokom in videom."</string>
<string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="9900961380294292">"Pri predvajanju aplikacije ima Android dostop do vsega, kar je prikazano ali predvajano v tej aplikaciji, zato bodite previdni z gesli, podatki za plačilo, sporočili, fotografijami ter z zvokom in videom."</string>
@@ -1173,6 +1170,10 @@
<string name="assistant_attention_content_description" msgid="6830215897604642875">"Zaznavanje pomočnika je vklopljeno."</string>
<string name="set_default_notes_app_toast_content" msgid="2812374329662610753">"Nastavite privzeto aplikacijo za zapiske v nastavitvah."</string>
<string name="install_app" msgid="5066668100199613936">"Namesti aplikacijo"</string>
+ <!-- no translation found for connected_display_dialog_start_mirroring (6237895789920854982) -->
+ <skip />
+ <!-- no translation found for enable_display (8308309634883321977) -->
+ <skip />
<string name="privacy_dialog_title" msgid="7839968133469098311">"Mikrofon in fotoaparat"</string>
<string name="privacy_dialog_summary" msgid="2458769652125995409">"Nedavna uporaba v aplikacijah"</string>
<string name="privacy_dialog_more_button" msgid="7610604080293562345">"Ogled nedavnih dostopov"</string>
diff --git a/packages/SystemUI/res/values-sq/strings.xml b/packages/SystemUI/res/values-sq/strings.xml
index 2c61054b1074..08d3c55381da 100644
--- a/packages/SystemUI/res/values-sq/strings.xml
+++ b/packages/SystemUI/res/values-sq/strings.xml
@@ -57,8 +57,7 @@
<string name="hdmi_cec_set_menu_language_description" msgid="8176716678074126619">"Një pajisje tjetër kërkoi ndryshimin e gjuhës së sistemit"</string>
<string name="hdmi_cec_set_menu_language_accept" msgid="2513689457281009578">"Ndrysho gjuhën"</string>
<string name="hdmi_cec_set_menu_language_decline" msgid="7650721096558646011">"Mbaj gjuhën aktuale"</string>
- <!-- no translation found for share_wifi_button_text (1285273973812029240) -->
- <skip />
+ <string name="share_wifi_button_text" msgid="1285273973812029240">"Ndaj Wi‑Fi"</string>
<string name="wifi_debugging_title" msgid="7300007687492186076">"Të lejohet korrigjimi përmes Wi-Fi në këtë rrjet?"</string>
<string name="wifi_debugging_message" msgid="5461204211731802995">"Emri i rrjetit (SSID)\n<xliff:g id="SSID_0">%1$s</xliff:g>\n\nAdresa Wi‑Fi (BSSID)\n<xliff:g id="BSSID_1">%2$s</xliff:g>"</string>
<string name="wifi_debugging_always" msgid="2968383799517975155">"Lejo gjithmonë në këtë rrjet"</string>
@@ -160,8 +159,7 @@
<string name="biometric_dialog_wrong_pattern" msgid="8954812279840889029">"Motiv i gabuar"</string>
<string name="biometric_dialog_wrong_password" msgid="69477929306843790">"Fjalëkalim i gabuar"</string>
<string name="biometric_dialog_credential_too_many_attempts" msgid="3083141271737748716">"Shumë tentativa të pasakta.\nProvo përsëri brenda <xliff:g id="NUMBER">%d</xliff:g> sekondash."</string>
- <!-- no translation found for work_challenge_emergency_button_text (8946588434515599288) -->
- <skip />
+ <string name="work_challenge_emergency_button_text" msgid="8946588434515599288">"Urgjencë"</string>
<string name="biometric_dialog_credential_attempts_before_wipe" msgid="6751859711975516999">"Provo sërish. Tentativa <xliff:g id="ATTEMPTS_0">%1$d</xliff:g> nga <xliff:g id="MAX_ATTEMPTS">%2$d</xliff:g>."</string>
<string name="biometric_dialog_last_attempt_before_wipe_dialog_title" msgid="2874250099278693477">"Të dhënat e tua do të fshihen"</string>
<string name="biometric_dialog_last_pattern_attempt_before_wipe_device" msgid="6562299244825817598">"Nëse fut një motiv të pasaktë në tentativën tjetër, të dhënat e kësaj pajisjeje do të fshihen."</string>
@@ -415,8 +413,7 @@
<string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="8736391633234144237">"Kur ti ndan, regjistron ose transmeton, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> ka qasje te çdo gjë e dukshme në ekranin tënd ose që po luhet në pajisjen tënde. Prandaj, ki kujdes me gjërat si fjalëkalimet, detajet e pagesave, mesazhet, fotografitë, si dhe audion dhe videon."</string>
<string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="5211695779082563959">"Kur ti ndan, regjistron ose transmeton një aplikacion, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> ka qasje te çdo gjë e dukshme në ekranin tënd ose që po luhet në atë aplikacion. Prandaj, ki kujdes me gjërat si fjalëkalimet, detajet e pagesave, mesazhet, fotografitë, si dhe audion dhe videon."</string>
<string name="media_projection_entry_app_permission_dialog_continue" msgid="295463518195075840">"Nis"</string>
- <!-- no translation found for media_projection_entry_app_permission_dialog_single_app_disabled (8999903044874669995) -->
- <skip />
+ <string name="media_projection_entry_app_permission_dialog_single_app_disabled" msgid="8999903044874669995">"<xliff:g id="APP_NAME">%1$s</xliff:g> e ka çaktivizuar këtë opsion"</string>
<string name="media_projection_entry_cast_permission_dialog_title" msgid="8860150223172993547">"Të niset transmetimi?"</string>
<string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="1986212276016817231">"Kur ti transmeton, Android ka qasje te çdo gjë e dukshme në ekranin tënd ose që po luhet në pajisjen tënde. Prandaj, ki kujdes me gjërat si fjalëkalimet, detajet e pagesave, mesazhet, fotografitë, si dhe audion dhe videon."</string>
<string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="9900961380294292">"Kur ti transmeton një aplikacion, Android ka qasje te çdo gjë e dukshme ose që po luhet në atë aplikacion. Prandaj, ki kujdes me gjërat si fjalëkalimet, detajet e pagesës, mesazhet, fotografitë, si dhe audion dhe videon."</string>
@@ -1173,6 +1170,10 @@
<string name="assistant_attention_content_description" msgid="6830215897604642875">"Vëmendja e \"Asistentit\" aktive"</string>
<string name="set_default_notes_app_toast_content" msgid="2812374329662610753">"Cakto aplikacionin e parazgjedhur të shënimeve te \"Cilësimet\""</string>
<string name="install_app" msgid="5066668100199613936">"Instalo aplikacionin"</string>
+ <!-- no translation found for connected_display_dialog_start_mirroring (6237895789920854982) -->
+ <skip />
+ <!-- no translation found for enable_display (8308309634883321977) -->
+ <skip />
<string name="privacy_dialog_title" msgid="7839968133469098311">"Mikrofoni dhe kamera"</string>
<string name="privacy_dialog_summary" msgid="2458769652125995409">"Përdorimi i fundit i aplikacionit"</string>
<string name="privacy_dialog_more_button" msgid="7610604080293562345">"Shiko qasjen e fundit"</string>
diff --git a/packages/SystemUI/res/values-sr/strings.xml b/packages/SystemUI/res/values-sr/strings.xml
index 7b2082900690..1856303313f5 100644
--- a/packages/SystemUI/res/values-sr/strings.xml
+++ b/packages/SystemUI/res/values-sr/strings.xml
@@ -57,8 +57,7 @@
<string name="hdmi_cec_set_menu_language_description" msgid="8176716678074126619">"Други уређај је затражио промену језика система"</string>
<string name="hdmi_cec_set_menu_language_accept" msgid="2513689457281009578">"Промени језик"</string>
<string name="hdmi_cec_set_menu_language_decline" msgid="7650721096558646011">"Задржи актуелни језик"</string>
- <!-- no translation found for share_wifi_button_text (1285273973812029240) -->
- <skip />
+ <string name="share_wifi_button_text" msgid="1285273973812029240">"Дели WiFi"</string>
<string name="wifi_debugging_title" msgid="7300007687492186076">"Желите да дозволите бежично отклањање грешака на овој мрежи?"</string>
<string name="wifi_debugging_message" msgid="5461204211731802995">"Назив мреже (SSID)\n<xliff:g id="SSID_0">%1$s</xliff:g>\n\nWi‑Fi адреса (BSSID)\n<xliff:g id="BSSID_1">%2$s</xliff:g>"</string>
<string name="wifi_debugging_always" msgid="2968383799517975155">"Увек дозволи на овој мрежи"</string>
@@ -160,8 +159,7 @@
<string name="biometric_dialog_wrong_pattern" msgid="8954812279840889029">"Погрешан шаблон"</string>
<string name="biometric_dialog_wrong_password" msgid="69477929306843790">"Погрешна лозинка"</string>
<string name="biometric_dialog_credential_too_many_attempts" msgid="3083141271737748716">"Превише нетачних покушаја.\n Пробајте поново за <xliff:g id="NUMBER">%d</xliff:g> сек."</string>
- <!-- no translation found for work_challenge_emergency_button_text (8946588434515599288) -->
- <skip />
+ <string name="work_challenge_emergency_button_text" msgid="8946588434515599288">"Хитан случај"</string>
<string name="biometric_dialog_credential_attempts_before_wipe" msgid="6751859711975516999">"Пробајте поново. <xliff:g id="ATTEMPTS_0">%1$d</xliff:g>. покушај од <xliff:g id="MAX_ATTEMPTS">%2$d</xliff:g>."</string>
<string name="biometric_dialog_last_attempt_before_wipe_dialog_title" msgid="2874250099278693477">"Подаци ће се избрисати"</string>
<string name="biometric_dialog_last_pattern_attempt_before_wipe_device" msgid="6562299244825817598">"Ако унесете нетачан шаблон при следећем покушају, избрисаћемо податке са овог уређаја."</string>
@@ -415,8 +413,7 @@
<string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="8736391633234144237">"Када делите, снимате или пребацујете, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> има приступ комплетном садржају који је видљив на екрану или се пушта на уређају. Зато будите пажљиви са лозинкама, информацијама о плаћању, порукама, сликама и аудио и видео снимцима."</string>
<string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="5211695779082563959">"Када делите, снимате или пребацујете апликацију, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> има приступ комплетном садржају који је видљив или се пушта у тој апликацији. Зато будите пажљиви са лозинкама, информацијама о плаћању, порукама, сликама и аудио и видео снимцима."</string>
<string name="media_projection_entry_app_permission_dialog_continue" msgid="295463518195075840">"Покрени"</string>
- <!-- no translation found for media_projection_entry_app_permission_dialog_single_app_disabled (8999903044874669995) -->
- <skip />
+ <string name="media_projection_entry_app_permission_dialog_single_app_disabled" msgid="8999903044874669995">"Апликација <xliff:g id="APP_NAME">%1$s</xliff:g> је онемогућила ову опцију"</string>
<string name="media_projection_entry_cast_permission_dialog_title" msgid="8860150223172993547">"Желите да започнете пребацивање?"</string>
<string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="1986212276016817231">"Када пребацујете, Android има приступ комплетном садржају који је видљив на екрану или се пушта на уређају. Зато будите пажљиви са лозинкама, информацијама о плаћању, порукама, сликама и аудио и видео снимцима."</string>
<string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="9900961380294292">"Када пребацујете апликацију, Android има приступ комплетном садржају који је видљив или се пушта у тој апликацији. Зато будите пажљиви са лозинкама, информацијама о плаћању, порукама, сликама и аудио и видео снимцима."</string>
@@ -1173,6 +1170,10 @@
<string name="assistant_attention_content_description" msgid="6830215897604642875">"Помоћник је у активном стању"</string>
<string name="set_default_notes_app_toast_content" msgid="2812374329662610753">"Подесите подразумевану апликацију за белешке у Подешавањима"</string>
<string name="install_app" msgid="5066668100199613936">"Инсталирај апликацију"</string>
+ <!-- no translation found for connected_display_dialog_start_mirroring (6237895789920854982) -->
+ <skip />
+ <!-- no translation found for enable_display (8308309634883321977) -->
+ <skip />
<string name="privacy_dialog_title" msgid="7839968133469098311">"Микрофон и камера"</string>
<string name="privacy_dialog_summary" msgid="2458769652125995409">"Недавно користила апликација"</string>
<string name="privacy_dialog_more_button" msgid="7610604080293562345">"Прикажи недавни приступ"</string>
diff --git a/packages/SystemUI/res/values-sv/strings.xml b/packages/SystemUI/res/values-sv/strings.xml
index 0ebb7784d4a5..76b6f1db9e45 100644
--- a/packages/SystemUI/res/values-sv/strings.xml
+++ b/packages/SystemUI/res/values-sv/strings.xml
@@ -57,8 +57,7 @@
<string name="hdmi_cec_set_menu_language_description" msgid="8176716678074126619">"Ändring av systemspråk har begärts av en annan enhet"</string>
<string name="hdmi_cec_set_menu_language_accept" msgid="2513689457281009578">"Ändra språk"</string>
<string name="hdmi_cec_set_menu_language_decline" msgid="7650721096558646011">"Behåll nuvarande språk"</string>
- <!-- no translation found for share_wifi_button_text (1285273973812029240) -->
- <skip />
+ <string name="share_wifi_button_text" msgid="1285273973812029240">"Dela wifi"</string>
<string name="wifi_debugging_title" msgid="7300007687492186076">"Vill du tillåta trådlös felsökning i det här nätverket?"</string>
<string name="wifi_debugging_message" msgid="5461204211731802995">"Nätverksnamn (SSID)\n<xliff:g id="SSID_0">%1$s</xliff:g>\n\nWi‑Fi-adress (BSSID)\n<xliff:g id="BSSID_1">%2$s</xliff:g>"</string>
<string name="wifi_debugging_always" msgid="2968383799517975155">"Tillåt alltid i det här nätverket"</string>
@@ -160,8 +159,7 @@
<string name="biometric_dialog_wrong_pattern" msgid="8954812279840889029">"Fel mönster"</string>
<string name="biometric_dialog_wrong_password" msgid="69477929306843790">"Fel lösenord"</string>
<string name="biometric_dialog_credential_too_many_attempts" msgid="3083141271737748716">"För många felaktiga försök.\nFörsök igen om <xliff:g id="NUMBER">%d</xliff:g> sekunder."</string>
- <!-- no translation found for work_challenge_emergency_button_text (8946588434515599288) -->
- <skip />
+ <string name="work_challenge_emergency_button_text" msgid="8946588434515599288">"Nödsituation"</string>
<string name="biometric_dialog_credential_attempts_before_wipe" msgid="6751859711975516999">"Försök igen. Försök <xliff:g id="ATTEMPTS_0">%1$d</xliff:g> av <xliff:g id="MAX_ATTEMPTS">%2$d</xliff:g>."</string>
<string name="biometric_dialog_last_attempt_before_wipe_dialog_title" msgid="2874250099278693477">"Din data raderas."</string>
<string name="biometric_dialog_last_pattern_attempt_before_wipe_device" msgid="6562299244825817598">"Enhetens data raderas om du ritar fel mönster vid nästa försök."</string>
@@ -415,8 +413,7 @@
<string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="8736391633234144237">"När du delar, spelar in eller castar har <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> åtkomst till allt som visas på skärmen eller spelas upp på enheten. Var försiktig med sådant som lösenord, betalningsuppgifter, meddelanden, foton och ljud och video."</string>
<string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="5211695779082563959">"När du delar, spelar in eller castar en app har <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> åtkomst till allt som visas eller spelas upp i appen. Var försiktig med sådant som lösenord, betalningsuppgifter, meddelanden, foton och ljud och video."</string>
<string name="media_projection_entry_app_permission_dialog_continue" msgid="295463518195075840">"Börja"</string>
- <!-- no translation found for media_projection_entry_app_permission_dialog_single_app_disabled (8999903044874669995) -->
- <skip />
+ <string name="media_projection_entry_app_permission_dialog_single_app_disabled" msgid="8999903044874669995">"<xliff:g id="APP_NAME">%1$s</xliff:g> har inaktiverat alternativet"</string>
<string name="media_projection_entry_cast_permission_dialog_title" msgid="8860150223172993547">"Vill du börja casta?"</string>
<string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="1986212276016817231">"När du castar har Android åtkomst till allt som visas på skärmen eller spelas upp på enheten. Var försiktig med sådant som lösenord, betalningsuppgifter, meddelanden, foton och ljud och video."</string>
<string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="9900961380294292">"När du castar en app har Android åtkomst till allt som visas eller spelas upp i appen. Var försiktig med sådant som lösenord, betalningsuppgifter, meddelanden, foton och ljud och video."</string>
@@ -1173,6 +1170,10 @@
<string name="assistant_attention_content_description" msgid="6830215897604642875">"Assistenten är aktiverad"</string>
<string name="set_default_notes_app_toast_content" msgid="2812374329662610753">"Ställ in en standardapp för anteckningar i inställningarna"</string>
<string name="install_app" msgid="5066668100199613936">"Installera appen"</string>
+ <!-- no translation found for connected_display_dialog_start_mirroring (6237895789920854982) -->
+ <skip />
+ <!-- no translation found for enable_display (8308309634883321977) -->
+ <skip />
<string name="privacy_dialog_title" msgid="7839968133469098311">"Mikrofon och kamera"</string>
<string name="privacy_dialog_summary" msgid="2458769652125995409">"Senaste appanvändning"</string>
<string name="privacy_dialog_more_button" msgid="7610604080293562345">"Se senaste åtkomst"</string>
diff --git a/packages/SystemUI/res/values-sw/strings.xml b/packages/SystemUI/res/values-sw/strings.xml
index 29d64052bc9c..17135446878f 100644
--- a/packages/SystemUI/res/values-sw/strings.xml
+++ b/packages/SystemUI/res/values-sw/strings.xml
@@ -57,8 +57,7 @@
<string name="hdmi_cec_set_menu_language_description" msgid="8176716678074126619">"Mabadiliko ya lugha ya mfumo yameombwa na kifaa kingine"</string>
<string name="hdmi_cec_set_menu_language_accept" msgid="2513689457281009578">"Badilisha lugha"</string>
<string name="hdmi_cec_set_menu_language_decline" msgid="7650721096558646011">"Usibadilishe lugha ya sasa"</string>
- <!-- no translation found for share_wifi_button_text (1285273973812029240) -->
- <skip />
+ <string name="share_wifi_button_text" msgid="1285273973812029240">"Shiriki Wi‑Fi"</string>
<string name="wifi_debugging_title" msgid="7300007687492186076">"Ungependa kuruhusu utatuzi usiotumia waya kwenye mtandao huu?"</string>
<string name="wifi_debugging_message" msgid="5461204211731802995">"Jina la Mtandao (SSID)\n<xliff:g id="SSID_0">%1$s</xliff:g>\n\nAnwani ya Wi-Fi (BSSID)\n<xliff:g id="BSSID_1">%2$s</xliff:g>"</string>
<string name="wifi_debugging_always" msgid="2968383799517975155">"Ruhusu kila wakati kwenye mtandao huu"</string>
@@ -160,8 +159,7 @@
<string name="biometric_dialog_wrong_pattern" msgid="8954812279840889029">"Mchoro si sahihi"</string>
<string name="biometric_dialog_wrong_password" msgid="69477929306843790">"Nenosiri si sahihi"</string>
<string name="biometric_dialog_credential_too_many_attempts" msgid="3083141271737748716">"Majaribio mengi mno yasiyo sahihi.\nJaribu tena baada ya sekunde <xliff:g id="NUMBER">%d</xliff:g>."</string>
- <!-- no translation found for work_challenge_emergency_button_text (8946588434515599288) -->
- <skip />
+ <string name="work_challenge_emergency_button_text" msgid="8946588434515599288">"Simu za dharura"</string>
<string name="biometric_dialog_credential_attempts_before_wipe" msgid="6751859711975516999">"Jaribu tena. Jaribio la <xliff:g id="ATTEMPTS_0">%1$d</xliff:g> kati ya <xliff:g id="MAX_ATTEMPTS">%2$d</xliff:g>."</string>
<string name="biometric_dialog_last_attempt_before_wipe_dialog_title" msgid="2874250099278693477">"Data yako itafutwa"</string>
<string name="biometric_dialog_last_pattern_attempt_before_wipe_device" msgid="6562299244825817598">"Ukiweka mchoro usio sahihi utakapojaribu tena, data iliyo kwenye kifaa hiki itafutwa."</string>
@@ -415,8 +413,7 @@
<string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="8736391633234144237">"Unaposhiriki, kurekodi au kutuma, programu ya <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> inaweza kufikia kitu chochote kitakachoonekana kwenye skrini yako au kuchezwa kwenye kifaa chako. Kwa hivyo kuwa mwangalifu na vitu kama vile manenosiri, maelezo ya malipo, ujumbe, picha na sauti na video."</string>
<string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="5211695779082563959">"Unaposhiriki, kurekodi au kutuma programu, programu, programu ya <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> inaweza kufikia kitu chochote kitakachoonekana au kuchezwa kwenye programu hiyo. Kwa hivyo kuwa mwangalifu na vitu kama vile manenosiri, maelezo ya malipo, ujumbe, picha na sauti na video."</string>
<string name="media_projection_entry_app_permission_dialog_continue" msgid="295463518195075840">"Anza"</string>
- <!-- no translation found for media_projection_entry_app_permission_dialog_single_app_disabled (8999903044874669995) -->
- <skip />
+ <string name="media_projection_entry_app_permission_dialog_single_app_disabled" msgid="8999903044874669995">"<xliff:g id="APP_NAME">%1$s</xliff:g> imezima chaguo hili"</string>
<string name="media_projection_entry_cast_permission_dialog_title" msgid="8860150223172993547">"Ungependa kuanza kutuma?"</string>
<string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="1986212276016817231">"Unapotuma, Android inaweza kufikia kitu chochote kitakachoonekana kwenye skrini yako au kuchezwa kwenye kifaa chako. Kwa hivyo kuwa mwangalifu na vitu kama vile manenosiri, maelezo ya malipo, ujumbe, picha na sauti na video."</string>
<string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="9900961380294292">"Unapotuma programu, Android inaweza kufikia kitu chochote kitakachoonekana au kuchezwa kwenye programu hiyo. Kwa hivyo kuwa mwangalifu na vitu kama vile manenosiri, maelezo ya malipo, ujumbe, picha na sauti na video."</string>
@@ -1173,6 +1170,10 @@
<string name="assistant_attention_content_description" msgid="6830215897604642875">"Programu ya Mratibu imewashwa"</string>
<string name="set_default_notes_app_toast_content" msgid="2812374329662610753">"Teua programu chaguomsingi ya madokezo katika Mipangilio"</string>
<string name="install_app" msgid="5066668100199613936">"Sakinisha programu"</string>
+ <!-- no translation found for connected_display_dialog_start_mirroring (6237895789920854982) -->
+ <skip />
+ <!-- no translation found for enable_display (8308309634883321977) -->
+ <skip />
<string name="privacy_dialog_title" msgid="7839968133469098311">"Maikrofoni na Kamera"</string>
<string name="privacy_dialog_summary" msgid="2458769652125995409">"Matumizi ya programu hivi majuzi"</string>
<string name="privacy_dialog_more_button" msgid="7610604080293562345">"Angalia ufikiaji wa majuzi"</string>
diff --git a/packages/SystemUI/res/values-sw600dp/bools.xml b/packages/SystemUI/res/values-sw600dp/bools.xml
index 05e38bdb8389..d7ddf00f91c2 100644
--- a/packages/SystemUI/res/values-sw600dp/bools.xml
+++ b/packages/SystemUI/res/values-sw600dp/bools.xml
@@ -18,4 +18,12 @@
<resources>
<!-- Whether to show the user switcher in quick settings when only a single user is present. -->
<bool name="qs_show_user_switcher_for_single_user">true</bool>
+
+ <!-- Do update bouncer constraints (port or land) on rotation.
+ Needed for bouncer refactor to use motion layout, because constraints should only be
+ changed on small screens. Only used when flag "lockscreen.enable_landscape" (b/293252410)
+ is enabled
+
+ False here so bouncers constraints are not updated when rotating on large screens -->
+ <bool name="update_bouncer_constraints">false</bool>
</resources>
diff --git a/packages/SystemUI/res/values-ta/strings.xml b/packages/SystemUI/res/values-ta/strings.xml
index 13e92e5cfcfd..c0e4c3d716ee 100644
--- a/packages/SystemUI/res/values-ta/strings.xml
+++ b/packages/SystemUI/res/values-ta/strings.xml
@@ -57,8 +57,7 @@
<string name="hdmi_cec_set_menu_language_description" msgid="8176716678074126619">"சிஸ்டம் மொழியை மாற்றும்படி வேறொரு சாதனம் கோருகிறது"</string>
<string name="hdmi_cec_set_menu_language_accept" msgid="2513689457281009578">"மொழியை மாற்று"</string>
<string name="hdmi_cec_set_menu_language_decline" msgid="7650721096558646011">"தற்போதைய மொழியை வைத்திரு"</string>
- <!-- no translation found for share_wifi_button_text (1285273973812029240) -->
- <skip />
+ <string name="share_wifi_button_text" msgid="1285273973812029240">"வைஃபையைப் பகிர்"</string>
<string name="wifi_debugging_title" msgid="7300007687492186076">"இந்த நெட்வொர்க்கில் வைஃபை பிழைதிருத்தத்தை அனுமதிக்கவா?"</string>
<string name="wifi_debugging_message" msgid="5461204211731802995">"நெட்வொர்க் பெயர் (SSID)\n<xliff:g id="SSID_0">%1$s</xliff:g>\n\nவைஃபை முகவரி (BSSID)\n<xliff:g id="BSSID_1">%2$s</xliff:g>"</string>
<string name="wifi_debugging_always" msgid="2968383799517975155">"இந்த நெட்வொர்க்கில் எப்போதும் அனுமதி"</string>
@@ -160,8 +159,7 @@
<string name="biometric_dialog_wrong_pattern" msgid="8954812279840889029">"தவறான பேட்டர்ன்"</string>
<string name="biometric_dialog_wrong_password" msgid="69477929306843790">"தவறான கடவுச்சொல்"</string>
<string name="biometric_dialog_credential_too_many_attempts" msgid="3083141271737748716">"பல தவறான முயற்சிகள்.\n<xliff:g id="NUMBER">%d</xliff:g> வினாடிகளில் மீண்டும் முயலவும்."</string>
- <!-- no translation found for work_challenge_emergency_button_text (8946588434515599288) -->
- <skip />
+ <string name="work_challenge_emergency_button_text" msgid="8946588434515599288">"அவசர அழைப்பு"</string>
<string name="biometric_dialog_credential_attempts_before_wipe" msgid="6751859711975516999">"மீண்டும் முயலவும். <xliff:g id="ATTEMPTS_0">%1$d</xliff:g>/<xliff:g id="MAX_ATTEMPTS">%2$d</xliff:g> முறை முயன்றுவிட்டீர்கள்."</string>
<string name="biometric_dialog_last_attempt_before_wipe_dialog_title" msgid="2874250099278693477">"உங்கள் தரவு நீக்கப்படும்"</string>
<string name="biometric_dialog_last_pattern_attempt_before_wipe_device" msgid="6562299244825817598">"அடுத்த முறை தவறான பேட்டர்னை வரைந்தால் இந்தச் சாதனத்தின் தரவு நீக்கப்படும்."</string>
@@ -415,8 +413,7 @@
<string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="8736391633234144237">"நீங்கள் பகிரும்போதோ ரெக்கார்டு செய்யும்போதோ அலைபரப்பும்போதோ உங்கள் திரையில் காட்டப்படுகின்ற அல்லது சாதனத்தில் பிளே செய்யப்படுகின்ற அனைத்தையும் <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> ஆப்ஸால் அணுக முடியும். எனவே கடவுச்சொற்கள், பேமெண்ட் விவரங்கள், மெசேஜ்கள், படங்கள், ஆடியோ, வீடியோ போன்றவை குறித்துக் கவனத்துடன் இருங்கள்."</string>
<string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="5211695779082563959">"நீங்கள் ஓர் ஆப்ஸைப் பகிரும்போதோ ரெக்கார்டு செய்யும்போதோ அலைபரப்பும்போதோ அந்த ஆப்ஸில் காட்டப்படுகின்ற அல்லது பிளே செய்யப்படுகின்ற அனைத்தையும் <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> ஆப்ஸால் அணுக முடியும். எனவே கடவுச்சொற்கள், பேமெண்ட் விவரங்கள், மெசேஜ்கள், படங்கள், ஆடியோ, வீடியோ போன்றவை குறித்துக் கவனத்துடன் இருங்கள்."</string>
<string name="media_projection_entry_app_permission_dialog_continue" msgid="295463518195075840">"தொடங்கு"</string>
- <!-- no translation found for media_projection_entry_app_permission_dialog_single_app_disabled (8999903044874669995) -->
- <skip />
+ <string name="media_projection_entry_app_permission_dialog_single_app_disabled" msgid="8999903044874669995">"<xliff:g id="APP_NAME">%1$s</xliff:g> ஆப்ஸ் இந்த விருப்பத்தை முடக்கியுள்ளது"</string>
<string name="media_projection_entry_cast_permission_dialog_title" msgid="8860150223172993547">"அலைபரப்பைத் தொடங்கவா?"</string>
<string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="1986212276016817231">"நீங்கள் அலைபரப்பும்போது உங்கள் திரையில் காட்டப்படுகின்ற அல்லது சாதனத்தில் பிளே செய்யப்படுகின்ற அனைத்தையும் Android அணுக முடியும். எனவே கடவுச்சொற்கள், பேமெண்ட் விவரங்கள், மெசேஜ்கள், படங்கள், ஆடியோ, வீடியோ போன்றவை குறித்துக் கவனத்துடன் இருங்கள்."</string>
<string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="9900961380294292">"ஓர் ஆப்ஸை நீங்கள் அலைபரப்பும்போது அந்த ஆப்ஸில் காட்டப்படுகின்ற அல்லது பிளே செய்யப்படுகின்ற அனைத்தையும் Android அணுக முடியும். எனவே கடவுச்சொற்கள், பேமெண்ட் விவரங்கள், மெசேஜ்கள், படங்கள், ஆடியோ, வீடியோ போன்றவை குறித்துக் கவனத்துடன் இருங்கள்."</string>
@@ -1173,6 +1170,10 @@
<string name="assistant_attention_content_description" msgid="6830215897604642875">"அசிஸ்டண்ட்டின் கவனம் இயக்கத்தில் உள்ளது"</string>
<string name="set_default_notes_app_toast_content" msgid="2812374329662610753">"குறிப்பு எடுப்பதற்கான இயல்புநிலை ஆப்ஸை அமைப்புகளில் அமையுங்கள்"</string>
<string name="install_app" msgid="5066668100199613936">"ஆப்ஸை நிறுவுங்கள்"</string>
+ <!-- no translation found for connected_display_dialog_start_mirroring (6237895789920854982) -->
+ <skip />
+ <!-- no translation found for enable_display (8308309634883321977) -->
+ <skip />
<string name="privacy_dialog_title" msgid="7839968133469098311">"மைக்ரோஃபோனும் கேமராவும்"</string>
<string name="privacy_dialog_summary" msgid="2458769652125995409">"சமீபத்திய ஆப்ஸ் பயன்பாடு"</string>
<string name="privacy_dialog_more_button" msgid="7610604080293562345">"சமீபத்திய அணுகலைக் காட்டு"</string>
diff --git a/packages/SystemUI/res/values-te/strings.xml b/packages/SystemUI/res/values-te/strings.xml
index 421fec66424f..22a329b4e648 100644
--- a/packages/SystemUI/res/values-te/strings.xml
+++ b/packages/SystemUI/res/values-te/strings.xml
@@ -57,8 +57,7 @@
<string name="hdmi_cec_set_menu_language_description" msgid="8176716678074126619">"మరొక పరికరం ద్వారా సిస్టమ్ భాష మార్పు రిక్వెస్ట్ చేయబడింది"</string>
<string name="hdmi_cec_set_menu_language_accept" msgid="2513689457281009578">"భాషను మార్చండి"</string>
<string name="hdmi_cec_set_menu_language_decline" msgid="7650721096558646011">"ప్రస్తుత భాషను అలా ఉంచండి"</string>
- <!-- no translation found for share_wifi_button_text (1285273973812029240) -->
- <skip />
+ <string name="share_wifi_button_text" msgid="1285273973812029240">"Wi‑Fi షేర్ చేయండి"</string>
<string name="wifi_debugging_title" msgid="7300007687492186076">"ఈ నెట్‌వర్క్ ద్వారా వైర్‌లెస్ డీబగ్గింగ్‌ను అనుమతించాలా?"</string>
<string name="wifi_debugging_message" msgid="5461204211731802995">"నెట్‌వర్క్ పేరు (SSID)\n<xliff:g id="SSID_0">%1$s</xliff:g>\n\nWi‑Fi అడ్రస్ (BSSID)\n<xliff:g id="BSSID_1">%2$s</xliff:g>"</string>
<string name="wifi_debugging_always" msgid="2968383799517975155">"ఈ నెట్‌వర్క్ నుండి ఎల్లప్పుడూ అనుమతించండి"</string>
@@ -160,8 +159,7 @@
<string name="biometric_dialog_wrong_pattern" msgid="8954812279840889029">"ఆకృతి తప్పు"</string>
<string name="biometric_dialog_wrong_password" msgid="69477929306843790">"పాస్‌వర్డ్ తప్పు"</string>
<string name="biometric_dialog_credential_too_many_attempts" msgid="3083141271737748716">"చాలా ఎక్కువ తప్పు ప్రయత్నాలు చేశారు.\n<xliff:g id="NUMBER">%d</xliff:g> సెకన్ల తర్వాత మళ్లీ ట్రై చేయండి."</string>
- <!-- no translation found for work_challenge_emergency_button_text (8946588434515599288) -->
- <skip />
+ <string name="work_challenge_emergency_button_text" msgid="8946588434515599288">"ఎమర్జెన్సీ"</string>
<string name="biometric_dialog_credential_attempts_before_wipe" msgid="6751859711975516999">"మళ్లీ ట్రై చేయండి. <xliff:g id="MAX_ATTEMPTS">%2$d</xliff:g>లో <xliff:g id="ATTEMPTS_0">%1$d</xliff:g> ప్రయత్నం చేశారు."</string>
<string name="biometric_dialog_last_attempt_before_wipe_dialog_title" msgid="2874250099278693477">"మీ డేటా తొలగించబడుతుంది"</string>
<string name="biometric_dialog_last_pattern_attempt_before_wipe_device" msgid="6562299244825817598">"మీరు ఒకవేళ తర్వాతి ప్రయత్నంలో తప్పు ఆకృతిని ఎంటర్ చేస్తే, ఈ పరికరం యొక్క డేటా తొలగించబడుతుంది."</string>
@@ -415,8 +413,7 @@
<string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="8736391633234144237">"మీరు షేర్ చేస్తున్నప్పుడు, రికార్డ్ చేస్తున్నప్పుడు, లేదా ప్రసారం చేస్తున్నప్పుడు, మీ స్క్రీన్‌పై కనిపించే దేనికైనా లేదా మీ పరికరంలో ప్లే అయిన దేనికైనా <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>‌కు యాక్సెస్ ఉంటుంది. కాబట్టి పాస్‌వర్డ్‌లు, పేమెంట్ వివరాలు, మెసేజ్‌లు, ఫోటోలు, ఆడియో, ఇంకా వీడియో వంటి విషయాల్లో జాగ్రత్త వహించండి."</string>
<string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="5211695779082563959">"మీరు ఏదైనా యాప్‌ను షేర్ చేస్తున్నప్పుడు, రికార్డ్ చేస్తున్నప్పుడు, లేదా ప్రసారం చేస్తున్నప్పుడు, ఆ యాప్‌లో చూపబడిన దేనికైనా లేదా ప్లే అయిన దేనికైనా <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>‌కు యాక్సెస్ ఉంటుంది. కాబట్టి పాస్‌వర్డ్‌లు, పేమెంట్ వివరాలు, మెసేజ్‌లు, ఫోటోలు, ఆడియో, ఇంకా వీడియో వంటి విషయాల్లో జాగ్రత్త వహించండి."</string>
<string name="media_projection_entry_app_permission_dialog_continue" msgid="295463518195075840">"ప్రారంభించండి"</string>
- <!-- no translation found for media_projection_entry_app_permission_dialog_single_app_disabled (8999903044874669995) -->
- <skip />
+ <string name="media_projection_entry_app_permission_dialog_single_app_disabled" msgid="8999903044874669995">"<xliff:g id="APP_NAME">%1$s</xliff:g> ఈ ఆప్షన్‌ను డిజేబుల్ చేసింది"</string>
<string name="media_projection_entry_cast_permission_dialog_title" msgid="8860150223172993547">"ప్రసారాన్ని ప్రారంభించాలా?"</string>
<string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="1986212276016817231">"మీరు ప్రసారం చేసేటప్పుడు, మీ స్క్రీన్‌పై కనిపించే దేనికైనా లేదా మీ పరికరంలో ప్లే అయిన దేనికైనా Androidకు యాక్సెస్ ఉంటుంది. కాబట్టి పాస్‌వర్డ్‌లు, పేమెంట్ వివరాలు, మెసేజ్‌లు, ఫోటోలు, ఆడియో, ఇంకా వీడియో వంటి విషయాల్లో జాగ్రత్త వహించండి."</string>
<string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="9900961380294292">"మీరు ఏదైనా యాప్‌ను ప్రసారం చేసేటప్పుడు, ఆ యాప్‌లో చూపబడిన దేనికైనా లేదా ప్లే అయిన దేనికైనా Androidకు యాక్సెస్ ఉంటుంది. కాబట్టి పాస్‌వర్డ్‌లు, పేమెంట్ వివరాలు, మెసేజ్‌లు, ఫోటోలు, ఆడియో, ఇంకా వీడియో వంటి విషయాల్లో జాగ్రత్త వహించండి."</string>
@@ -1173,6 +1170,10 @@
<string name="assistant_attention_content_description" msgid="6830215897604642875">"Assistant అటెన్షన్ ఆన్‌లో ఉంది"</string>
<string name="set_default_notes_app_toast_content" msgid="2812374329662610753">"సెట్టింగ్‌లలో ఆటోమేటిక్‌గా ఉండేలా ఒక నోట్స్ యాప్‌ను సెట్ చేసుకోండి"</string>
<string name="install_app" msgid="5066668100199613936">"యాప్‌ను ఇన్‌స్టాల్ చేయండి"</string>
+ <!-- no translation found for connected_display_dialog_start_mirroring (6237895789920854982) -->
+ <skip />
+ <!-- no translation found for enable_display (8308309634883321977) -->
+ <skip />
<string name="privacy_dialog_title" msgid="7839968133469098311">"మైక్రోఫోన్ &amp; కెమెరా"</string>
<string name="privacy_dialog_summary" msgid="2458769652125995409">"ఇటీవలి యాప్ వినియోగం"</string>
<string name="privacy_dialog_more_button" msgid="7610604080293562345">"ఇటీవలి యాక్సెస్‌ను చూడండి"</string>
diff --git a/packages/SystemUI/res/values-th/strings.xml b/packages/SystemUI/res/values-th/strings.xml
index 05908069f0a2..3887b9f8b9c4 100644
--- a/packages/SystemUI/res/values-th/strings.xml
+++ b/packages/SystemUI/res/values-th/strings.xml
@@ -57,8 +57,7 @@
<string name="hdmi_cec_set_menu_language_description" msgid="8176716678074126619">"คำขอเปลี่ยนภาษาของระบบโดยอุปกรณ์อื่น"</string>
<string name="hdmi_cec_set_menu_language_accept" msgid="2513689457281009578">"เปลี่ยนภาษา"</string>
<string name="hdmi_cec_set_menu_language_decline" msgid="7650721096558646011">"ใช้ภาษาปัจจุบันต่อไป"</string>
- <!-- no translation found for share_wifi_button_text (1285273973812029240) -->
- <skip />
+ <string name="share_wifi_button_text" msgid="1285273973812029240">"แชร์ Wi‑Fi"</string>
<string name="wifi_debugging_title" msgid="7300007687492186076">"อนุญาตให้แก้ไขข้อบกพร่องผ่าน Wi-Fi ในเครือข่ายนี้ใช่ไหม"</string>
<string name="wifi_debugging_message" msgid="5461204211731802995">"ชื่อเครือข่าย (SSID)\n<xliff:g id="SSID_0">%1$s</xliff:g>\n\nที่อยู่ Wi‑Fi (BSSID)\n<xliff:g id="BSSID_1">%2$s</xliff:g>"</string>
<string name="wifi_debugging_always" msgid="2968383799517975155">"อนุญาตเสมอในเครือข่ายนี้"</string>
@@ -160,8 +159,7 @@
<string name="biometric_dialog_wrong_pattern" msgid="8954812279840889029">"รูปแบบไม่ถูกต้อง"</string>
<string name="biometric_dialog_wrong_password" msgid="69477929306843790">"รหัสผ่านไม่ถูกต้อง"</string>
<string name="biometric_dialog_credential_too_many_attempts" msgid="3083141271737748716">"ดำเนินการไม่ถูกต้องหลายครั้งเกินไป\nลองอีกครั้งใน <xliff:g id="NUMBER">%d</xliff:g> วินาที"</string>
- <!-- no translation found for work_challenge_emergency_button_text (8946588434515599288) -->
- <skip />
+ <string name="work_challenge_emergency_button_text" msgid="8946588434515599288">"ฉุกเฉิน"</string>
<string name="biometric_dialog_credential_attempts_before_wipe" msgid="6751859711975516999">"ลองอีกครั้ง ความพยายามครั้งที่ <xliff:g id="ATTEMPTS_0">%1$d</xliff:g> จาก <xliff:g id="MAX_ATTEMPTS">%2$d</xliff:g>"</string>
<string name="biometric_dialog_last_attempt_before_wipe_dialog_title" msgid="2874250099278693477">"ระบบจะลบข้อมูลของคุณ"</string>
<string name="biometric_dialog_last_pattern_attempt_before_wipe_device" msgid="6562299244825817598">"หากคุณป้อนรูปแบบไม่ถูกต้องในความพยายามครั้งถัดไป ระบบจะลบข้อมูลในอุปกรณ์เครื่องนี้"</string>
@@ -415,8 +413,7 @@
<string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="8736391633234144237">"เมื่อกำลังแชร์ บันทึก หรือแคสต์ <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> จะมีสิทธิ์เข้าถึงทุกสิ่งที่ปรากฏบนหน้าจอหรือเล่นอยู่ในอุปกรณ์ ดังนั้นโปรดระวังสิ่งต่างๆ อย่างเช่นรหัสผ่าน รายละเอียดการชำระเงิน ข้อความ รูปภาพ รวมถึงเสียงและวิดีโอ"</string>
<string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="5211695779082563959">"เมื่อกำลังแชร์ บันทึก หรือแคสต์แอป <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> จะมีสิทธิ์เข้าถึงทุกสิ่งที่แสดงหรือเล่นอยู่ในแอปดังกล่าว ดังนั้นโปรดระวังสิ่งต่างๆ อย่างเช่นรหัสผ่าน รายละเอียดการชำระเงิน ข้อความ รูปภาพ รวมถึงเสียงและวิดีโอ"</string>
<string name="media_projection_entry_app_permission_dialog_continue" msgid="295463518195075840">"เริ่ม"</string>
- <!-- no translation found for media_projection_entry_app_permission_dialog_single_app_disabled (8999903044874669995) -->
- <skip />
+ <string name="media_projection_entry_app_permission_dialog_single_app_disabled" msgid="8999903044874669995">"<xliff:g id="APP_NAME">%1$s</xliff:g> ปิดใช้ตัวเลือกนี้"</string>
<string name="media_projection_entry_cast_permission_dialog_title" msgid="8860150223172993547">"เริ่มแคสต์เลยไหม"</string>
<string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="1986212276016817231">"เมื่อกำลังแคสต์ Android จะมีสิทธิ์เข้าถึงทุกสิ่งที่ปรากฏบนหน้าจอหรือเล่นอยู่ในอุปกรณ์ ดังนั้นโปรดระวังสิ่งต่างๆ อย่างเช่นรหัสผ่าน รายละเอียดการชำระเงิน ข้อความ รูปภาพ รวมถึงเสียงและวิดีโอ"</string>
<string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="9900961380294292">"เมื่อกำลังแคสต์แอป Android จะมีสิทธิ์เข้าถึงทุกสิ่งที่แสดงหรือเล่นอยู่ในแอปดังกล่าว ดังนั้นโปรดระวังสิ่งต่างๆ อย่างเช่นรหัสผ่าน รายละเอียดการชำระเงิน ข้อความ รูปภาพ รวมถึงเสียงและวิดีโอ"</string>
@@ -1173,6 +1170,10 @@
<string name="assistant_attention_content_description" msgid="6830215897604642875">"การเรียกใช้งาน Assistant เปิดอยู่"</string>
<string name="set_default_notes_app_toast_content" msgid="2812374329662610753">"กำหนดแอปการจดบันทึกเริ่มต้นในการตั้งค่า"</string>
<string name="install_app" msgid="5066668100199613936">"ติดตั้งแอป"</string>
+ <!-- no translation found for connected_display_dialog_start_mirroring (6237895789920854982) -->
+ <skip />
+ <!-- no translation found for enable_display (8308309634883321977) -->
+ <skip />
<string name="privacy_dialog_title" msgid="7839968133469098311">"ไมโครโฟนและกล้อง"</string>
<string name="privacy_dialog_summary" msgid="2458769652125995409">"การใช้แอปครั้งล่าสุด"</string>
<string name="privacy_dialog_more_button" msgid="7610604080293562345">"ดูการเข้าถึงล่าสุด"</string>
diff --git a/packages/SystemUI/res/values-tl/strings.xml b/packages/SystemUI/res/values-tl/strings.xml
index 859191a1fba9..2fdee7220e6c 100644
--- a/packages/SystemUI/res/values-tl/strings.xml
+++ b/packages/SystemUI/res/values-tl/strings.xml
@@ -57,8 +57,7 @@
<string name="hdmi_cec_set_menu_language_description" msgid="8176716678074126619">"Hiniling ng ibang device na palitan ang wika ng system"</string>
<string name="hdmi_cec_set_menu_language_accept" msgid="2513689457281009578">"Palitan ang wika"</string>
<string name="hdmi_cec_set_menu_language_decline" msgid="7650721096558646011">"Huwag palitan ang wika"</string>
- <!-- no translation found for share_wifi_button_text (1285273973812029240) -->
- <skip />
+ <string name="share_wifi_button_text" msgid="1285273973812029240">"Ibahagi ang Wi‑Fi"</string>
<string name="wifi_debugging_title" msgid="7300007687492186076">"Payagan ang wireless na pag-debug sa network na ito?"</string>
<string name="wifi_debugging_message" msgid="5461204211731802995">"Pangalan ng Network (SSID)\n<xliff:g id="SSID_0">%1$s</xliff:g>\n\nAddress ng Wi‑Fi (BSSID)\n<xliff:g id="BSSID_1">%2$s</xliff:g>"</string>
<string name="wifi_debugging_always" msgid="2968383799517975155">"Palaging payagan sa network na ito"</string>
@@ -160,8 +159,7 @@
<string name="biometric_dialog_wrong_pattern" msgid="8954812279840889029">"Maling pattern"</string>
<string name="biometric_dialog_wrong_password" msgid="69477929306843790">"Maling password"</string>
<string name="biometric_dialog_credential_too_many_attempts" msgid="3083141271737748716">"Masyadong maraming maling pagsubok.\nSubukan ulit sa loob ng <xliff:g id="NUMBER">%d</xliff:g> (na) segundo."</string>
- <!-- no translation found for work_challenge_emergency_button_text (8946588434515599288) -->
- <skip />
+ <string name="work_challenge_emergency_button_text" msgid="8946588434515599288">"Emergency"</string>
<string name="biometric_dialog_credential_attempts_before_wipe" msgid="6751859711975516999">"Subukan ulit. ika-<xliff:g id="ATTEMPTS_0">%1$d</xliff:g> (na) pagsubok sa <xliff:g id="MAX_ATTEMPTS">%2$d</xliff:g>."</string>
<string name="biometric_dialog_last_attempt_before_wipe_dialog_title" msgid="2874250099278693477">"Made-delete ang iyong data"</string>
<string name="biometric_dialog_last_pattern_attempt_before_wipe_device" msgid="6562299244825817598">"Kung maling pattern ang mailalagay mo sa susunod na pagsubok, made-delete ang data ng device na ito."</string>
@@ -415,8 +413,7 @@
<string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="8736391633234144237">"Kapag nagbabahagi, nagre-record, o nagka-cast ka, may access ang <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> sa kahit anong nakikita sa iyong screen o pine-play sa device mo. Kaya mag-ingat sa mga bagay-bagay tulad ng mga password, detalye ng pagbabayad, mensahe, larawan, at audio at video."</string>
<string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="5211695779082563959">"Kapag nagbabahagi, nagre-record, o nagka-cast ka ng app, may access ang <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> sa kahit anong ipinapakita o pine-play sa app na iyon. Kaya mag-ingat sa mga bagay-bagay tulad ng mga password, detalye ng pagbabayad, mensahe, larawan, at audio at video."</string>
<string name="media_projection_entry_app_permission_dialog_continue" msgid="295463518195075840">"Simulan"</string>
- <!-- no translation found for media_projection_entry_app_permission_dialog_single_app_disabled (8999903044874669995) -->
- <skip />
+ <string name="media_projection_entry_app_permission_dialog_single_app_disabled" msgid="8999903044874669995">"Na-disable ng <xliff:g id="APP_NAME">%1$s</xliff:g> ang opsyong ito"</string>
<string name="media_projection_entry_cast_permission_dialog_title" msgid="8860150223172993547">"Simulan ang pag-cast?"</string>
<string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="1986212276016817231">"Kapag nagka-cast ka, may access ang Android sa kahit anong nakikita sa iyong screen o pine-play sa device mo. Kaya mag-ingat sa mga bagay-bagay tulad ng mga password, detalye ng pagbabayad, mensahe, larawan, at audio at video."</string>
<string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="9900961380294292">"Kapag nagka-cast ka ng app, may access ang Android sa kahit anong ipinapakita o pine-play sa app na iyon. Kaya mag-ingat sa mga bagay-bagay tulad ng mga password, detalye ng pagbabayad, mensahe, larawan, at audio at video."</string>
@@ -1173,6 +1170,8 @@
<string name="assistant_attention_content_description" msgid="6830215897604642875">"Naka-on ang atensyon ng Assistant"</string>
<string name="set_default_notes_app_toast_content" msgid="2812374329662610753">"Magtakda ng default na app sa pagtatala sa Mga Setting"</string>
<string name="install_app" msgid="5066668100199613936">"I-install ang app"</string>
+ <string name="connected_display_dialog_start_mirroring" msgid="6237895789920854982">"I-mirror sa external na display?"</string>
+ <string name="enable_display" msgid="8308309634883321977">"I-enable ang display"</string>
<string name="privacy_dialog_title" msgid="7839968133469098311">"Mikropono at Camera"</string>
<string name="privacy_dialog_summary" msgid="2458769652125995409">"Kamakailang paggamit ng app"</string>
<string name="privacy_dialog_more_button" msgid="7610604080293562345">"Tingnan ang kamakailang access"</string>
diff --git a/packages/SystemUI/res/values-tr/strings.xml b/packages/SystemUI/res/values-tr/strings.xml
index f217f131fd73..b01fee15ec5a 100644
--- a/packages/SystemUI/res/values-tr/strings.xml
+++ b/packages/SystemUI/res/values-tr/strings.xml
@@ -57,8 +57,7 @@
<string name="hdmi_cec_set_menu_language_description" msgid="8176716678074126619">"Başka bir cihaz tarafından sistem dilinin değiştirilmesi istendi"</string>
<string name="hdmi_cec_set_menu_language_accept" msgid="2513689457281009578">"Dili değiştir"</string>
<string name="hdmi_cec_set_menu_language_decline" msgid="7650721096558646011">"Mevcut dili koru"</string>
- <!-- no translation found for share_wifi_button_text (1285273973812029240) -->
- <skip />
+ <string name="share_wifi_button_text" msgid="1285273973812029240">"Kablosuz ağı paylaşın"</string>
<string name="wifi_debugging_title" msgid="7300007687492186076">"Bu ağda kablosuz hata ayıklamaya izin verilsin mi?"</string>
<string name="wifi_debugging_message" msgid="5461204211731802995">"Ağ Adı (SSID)\n<xliff:g id="SSID_0">%1$s</xliff:g>\n\nKablosuz Adresi (BSSID)\n<xliff:g id="BSSID_1">%2$s</xliff:g>"</string>
<string name="wifi_debugging_always" msgid="2968383799517975155">"Bu ağda her zaman izin ver"</string>
@@ -160,8 +159,7 @@
<string name="biometric_dialog_wrong_pattern" msgid="8954812279840889029">"Yanlış desen"</string>
<string name="biometric_dialog_wrong_password" msgid="69477929306843790">"Yanlış şifre"</string>
<string name="biometric_dialog_credential_too_many_attempts" msgid="3083141271737748716">"Çok fazla yanlış giriş yapıldı.\n<xliff:g id="NUMBER">%d</xliff:g> saniye içinde tekrar deneyin."</string>
- <!-- no translation found for work_challenge_emergency_button_text (8946588434515599288) -->
- <skip />
+ <string name="work_challenge_emergency_button_text" msgid="8946588434515599288">"Acil durum"</string>
<string name="biometric_dialog_credential_attempts_before_wipe" msgid="6751859711975516999">"Tekrar deneyin. Deneme sayısı: <xliff:g id="ATTEMPTS_0">%1$d</xliff:g>/<xliff:g id="MAX_ATTEMPTS">%2$d</xliff:g>."</string>
<string name="biometric_dialog_last_attempt_before_wipe_dialog_title" msgid="2874250099278693477">"Verileriniz silinecek"</string>
<string name="biometric_dialog_last_pattern_attempt_before_wipe_device" msgid="6562299244825817598">"Bir sonraki denemenizde yanlış desen girerseniz bu cihazın verileri silinir."</string>
@@ -415,8 +413,7 @@
<string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="8736391633234144237">"Paylaşma, kaydetme ve yayınlama özelliklerini kullandığınızda <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>, ekranınızda görünen veya cihazınızda oynatılan her şeye erişebilir. Bu nedenle şifre, ödeme ayrıntıları, mesaj, fotoğraf, ses ve video gibi öğeler konusunda dikkatli olun."</string>
<string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="5211695779082563959">"Bir uygulamayı paylaştığınızda, kaydettiğinizde veya yayınladığınızda <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>, söz konusu uygulamada gösterilen veya oynatılan her şeye erişebilir. Bu nedenle şifre, ödeme ayrıntıları, mesaj, fotoğraf, ses ve video gibi öğeler konusunda dikkatli olun."</string>
<string name="media_projection_entry_app_permission_dialog_continue" msgid="295463518195075840">"Başlat"</string>
- <!-- no translation found for media_projection_entry_app_permission_dialog_single_app_disabled (8999903044874669995) -->
- <skip />
+ <string name="media_projection_entry_app_permission_dialog_single_app_disabled" msgid="8999903044874669995">"<xliff:g id="APP_NAME">%1$s</xliff:g> bu seçeneği devre dışı bıraktı"</string>
<string name="media_projection_entry_cast_permission_dialog_title" msgid="8860150223172993547">"Yayın başlatılsın mı?"</string>
<string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="1986212276016817231">"Yayınlama özelliğini kullandığınızda Android, ekranınızda görünen veya cihazınızda oynatılan her şeye erişebilir. Bu nedenle şifre, ödeme ayrıntıları, mesaj, fotoğraf, ses ve video gibi öğeler konusunda dikkatli olun."</string>
<string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="9900961380294292">"Bir uygulamayı yayınladığınızda Android, söz konusu uygulamada gösterilen veya oynatılan her şeye erişebilir. Bu nedenle şifre, ödeme ayrıntıları, mesaj, fotoğraf, ses ve video gibi öğeler konusunda dikkatli olun."</string>
@@ -1173,6 +1170,10 @@
<string name="assistant_attention_content_description" msgid="6830215897604642875">"Asistan dinliyor"</string>
<string name="set_default_notes_app_toast_content" msgid="2812374329662610753">"Ayarlar\'ı kullanarak varsayılan notlar ayarlayın"</string>
<string name="install_app" msgid="5066668100199613936">"Uygulamayı yükle"</string>
+ <!-- no translation found for connected_display_dialog_start_mirroring (6237895789920854982) -->
+ <skip />
+ <!-- no translation found for enable_display (8308309634883321977) -->
+ <skip />
<string name="privacy_dialog_title" msgid="7839968133469098311">"Mikrofon ve Kamera"</string>
<string name="privacy_dialog_summary" msgid="2458769652125995409">"Son uygulama kullanımı"</string>
<string name="privacy_dialog_more_button" msgid="7610604080293562345">"Son erişimi göster"</string>
diff --git a/packages/SystemUI/res/values-uk/strings.xml b/packages/SystemUI/res/values-uk/strings.xml
index 83bfd6382c72..db3441352422 100644
--- a/packages/SystemUI/res/values-uk/strings.xml
+++ b/packages/SystemUI/res/values-uk/strings.xml
@@ -57,8 +57,7 @@
<string name="hdmi_cec_set_menu_language_description" msgid="8176716678074126619">"Запит на змінення мови системи надіслано з іншого пристрою"</string>
<string name="hdmi_cec_set_menu_language_accept" msgid="2513689457281009578">"Змінити мову"</string>
<string name="hdmi_cec_set_menu_language_decline" msgid="7650721096558646011">"Залишити поточну мову"</string>
- <!-- no translation found for share_wifi_button_text (1285273973812029240) -->
- <skip />
+ <string name="share_wifi_button_text" msgid="1285273973812029240">"Поділитися Wi‑Fi"</string>
<string name="wifi_debugging_title" msgid="7300007687492186076">"Дозволити налагодження через Wi-Fi у цій мережі?"</string>
<string name="wifi_debugging_message" msgid="5461204211731802995">"Ім\'я мережі (SSID)\n<xliff:g id="SSID_0">%1$s</xliff:g>\n\nАдреса Wi‑Fi (BSSID)\n<xliff:g id="BSSID_1">%2$s</xliff:g>"</string>
<string name="wifi_debugging_always" msgid="2968383799517975155">"Завжди дозволяти в цій мережі"</string>
@@ -160,8 +159,7 @@
<string name="biometric_dialog_wrong_pattern" msgid="8954812279840889029">"Неправильний ключ"</string>
<string name="biometric_dialog_wrong_password" msgid="69477929306843790">"Неправильний пароль"</string>
<string name="biometric_dialog_credential_too_many_attempts" msgid="3083141271737748716">"Забагато невдалих спроб.\nПовторіть за <xliff:g id="NUMBER">%d</xliff:g> с."</string>
- <!-- no translation found for work_challenge_emergency_button_text (8946588434515599288) -->
- <skip />
+ <string name="work_challenge_emergency_button_text" msgid="8946588434515599288">"Екстрений виклик"</string>
<string name="biometric_dialog_credential_attempts_before_wipe" msgid="6751859711975516999">"Спробуйте ще. Спроба <xliff:g id="ATTEMPTS_0">%1$d</xliff:g> із <xliff:g id="MAX_ATTEMPTS">%2$d</xliff:g>."</string>
<string name="biometric_dialog_last_attempt_before_wipe_dialog_title" msgid="2874250099278693477">"Ваші дані буде видалено"</string>
<string name="biometric_dialog_last_pattern_attempt_before_wipe_device" msgid="6562299244825817598">"Якщо наступного разу ви введете неправильний ключ, дані на цьому пристрої буде видалено."</string>
@@ -415,8 +413,7 @@
<string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="8736391633234144237">"Коли ви показуєте, записуєте або транслюєте екран, додаток <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> отримує доступ до всього, що відображається на екрані чи відтворюється на пристрої. Тому будьте уважні з паролями, повідомленнями, фотографіями, аудіо, відео, платіжною інформацією тощо."</string>
<string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="5211695779082563959">"Коли ви показуєте, записуєте або транслюєте додаток, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> отримує доступ до всього, що відображається або відтворюється в цьому додатку. Тому будьте уважні з паролями, повідомленнями, фотографіями, аудіо, відео, платіжною інформацією тощо."</string>
<string name="media_projection_entry_app_permission_dialog_continue" msgid="295463518195075840">"Почати"</string>
- <!-- no translation found for media_projection_entry_app_permission_dialog_single_app_disabled (8999903044874669995) -->
- <skip />
+ <string name="media_projection_entry_app_permission_dialog_single_app_disabled" msgid="8999903044874669995">"Додаток <xliff:g id="APP_NAME">%1$s</xliff:g> вимкнув цю опцію"</string>
<string name="media_projection_entry_cast_permission_dialog_title" msgid="8860150223172993547">"Почати трансляцію?"</string>
<string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="1986212276016817231">"Під час трансляції ОС Android отримує доступ до всього, що відображається на екрані чи відтворюється на пристрої. Тому будьте уважні з паролями, повідомленнями, фотографіями, аудіо, відео, платіжною інформацією тощо."</string>
<string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="9900961380294292">"Коли ви транслюєте додаток, ОС Android отримує доступ до всього, що відображається або відтворюється в ньому. Тому будьте уважні з паролями, повідомленнями, фотографіями, аудіо, відео, платіжною інформацією тощо."</string>
@@ -1173,6 +1170,10 @@
<string name="assistant_attention_content_description" msgid="6830215897604642875">"Асистента активовано"</string>
<string name="set_default_notes_app_toast_content" msgid="2812374329662610753">"Призначте стандартний додаток для нотаток у налаштуваннях"</string>
<string name="install_app" msgid="5066668100199613936">"Установити додаток"</string>
+ <!-- no translation found for connected_display_dialog_start_mirroring (6237895789920854982) -->
+ <skip />
+ <!-- no translation found for enable_display (8308309634883321977) -->
+ <skip />
<string name="privacy_dialog_title" msgid="7839968133469098311">"Мікрофон і камера"</string>
<string name="privacy_dialog_summary" msgid="2458769652125995409">"Нещодавнє використання додатками"</string>
<string name="privacy_dialog_more_button" msgid="7610604080293562345">"Переглянути нещодавній доступ"</string>
diff --git a/packages/SystemUI/res/values-ur/strings.xml b/packages/SystemUI/res/values-ur/strings.xml
index eac34ce72266..8115e2e086ca 100644
--- a/packages/SystemUI/res/values-ur/strings.xml
+++ b/packages/SystemUI/res/values-ur/strings.xml
@@ -57,8 +57,7 @@
<string name="hdmi_cec_set_menu_language_description" msgid="8176716678074126619">"کسی دوسرے آلے کے ذریعے سسٹم کی زبان میں تبدیلی کی درخواست کی گئی"</string>
<string name="hdmi_cec_set_menu_language_accept" msgid="2513689457281009578">"زبان تبدیل کریں"</string>
<string name="hdmi_cec_set_menu_language_decline" msgid="7650721096558646011">"موجودہ زبان برقرار رکھیں"</string>
- <!-- no translation found for share_wifi_button_text (1285273973812029240) -->
- <skip />
+ <string name="share_wifi_button_text" msgid="1285273973812029240">"‏Wi-Fi کا اشتراک کریں"</string>
<string name="wifi_debugging_title" msgid="7300007687492186076">"اس نیٹ ورک پر وائرلیس ڈیبگنگ کرنے کی اجازت دیں؟"</string>
<string name="wifi_debugging_message" msgid="5461204211731802995">"‏نیٹ ورک کا نام (SSID)\n<xliff:g id="SSID_0">%1$s</xliff:g>\n\n‏ Wi-Fi کا پتہ (BSSID)\n<xliff:g id="BSSID_1">%2$s</xliff:g>"</string>
<string name="wifi_debugging_always" msgid="2968383799517975155">"اس نیٹ ورک پر ہمیشہ اجازت دیں"</string>
@@ -160,8 +159,7 @@
<string name="biometric_dialog_wrong_pattern" msgid="8954812279840889029">"غلط پیٹرن"</string>
<string name="biometric_dialog_wrong_password" msgid="69477929306843790">"غلط پاس ورڈ"</string>
<string name="biometric_dialog_credential_too_many_attempts" msgid="3083141271737748716">"کافی زیادہ غلط کوششیں کی گئیں۔\n <xliff:g id="NUMBER">%d</xliff:g> سیکنڈ بعد دوبارہ کوشش کریں۔"</string>
- <!-- no translation found for work_challenge_emergency_button_text (8946588434515599288) -->
- <skip />
+ <string name="work_challenge_emergency_button_text" msgid="8946588434515599288">"ایمرجنسی"</string>
<string name="biometric_dialog_credential_attempts_before_wipe" msgid="6751859711975516999">"دوبارہ کوشش کریں۔ کوشش <xliff:g id="ATTEMPTS_0">%1$d</xliff:g> از <xliff:g id="MAX_ATTEMPTS">%2$d</xliff:g>۔"</string>
<string name="biometric_dialog_last_attempt_before_wipe_dialog_title" msgid="2874250099278693477">"آپ کا ڈیٹا حذف کر دیا جائے گا"</string>
<string name="biometric_dialog_last_pattern_attempt_before_wipe_device" msgid="6562299244825817598">"اگر آپ نے اگلی کوشش میں غلط پیٹرن درج کیا تو اس آلے کا ڈیٹا حذف کر دیا جائے گا۔"</string>
@@ -415,8 +413,7 @@
<string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="8736391633234144237">"جب آپ اشتراک، ریکارڈنگ یا کاسٹ کر رہے ہوتے ہیں تو <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> کو آپ کی اسکرین پر دکھائی دینے والی یا آپ کے آلے پر چلائی گئی ہر چیز تک رسائی حاصل ہوتی ہے۔ لہذا، پاس ورڈز، ادائیگی کی تفصیلات، پیغامات، تصاویر، ساتھ ہی آڈیو اور ویڈیو جیسی چیزوں کے سلسلے میں محتاط رہیں۔"</string>
<string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="5211695779082563959">"جب آپ اشتراک، ریکارڈنگ یا کسی ایپ کو کاسٹ کر رہے ہوتے ہیں تو <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> کو اس ایپ پر دکھائی گئی یا چلائی گئی ہر چیز تک رسائی حاصل ہوتی ہے۔ لہذا، پاس ورڈز، ادائیگی کی تفصیلات، پیغامات، تصاویر، ساتھ ہی آڈیو اور ویڈیو جیسی چیزوں کے سلسلے میں محتاط رہیں۔"</string>
<string name="media_projection_entry_app_permission_dialog_continue" msgid="295463518195075840">"شروع کریں"</string>
- <!-- no translation found for media_projection_entry_app_permission_dialog_single_app_disabled (8999903044874669995) -->
- <skip />
+ <string name="media_projection_entry_app_permission_dialog_single_app_disabled" msgid="8999903044874669995">"<xliff:g id="APP_NAME">%1$s</xliff:g> نے اس اختیار کو غیر فعال کر دیا ہے"</string>
<string name="media_projection_entry_cast_permission_dialog_title" msgid="8860150223172993547">"کاسٹ کرنا شروع کریں؟"</string>
<string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="1986212276016817231">"‏جب آپ کاسٹ کر رہے ہوتے ہیں، تو Android کو آپ کی اسکرین پر دکھائی دینے والی یا آپ کے آلے پر چلائی گئی ہر چیز تک رسائی حاصل ہوتی ہے۔ لہذا، پاس ورڈز، ادائیگی کی تفصیلات، پیغامات، تصاویر، ساتھ ہی آڈیو اور ویڈیو جیسی چیزوں کے سلسلے میں محتاط رہیں۔"</string>
<string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="9900961380294292">"‏جب آپ کسی ایپ کو کاسٹ کر رہے ہوتے ہیں تو Android کو اس ایپ پر دکھائی گئی یا چلائی گئی ہر چیز تک رسائی حاصل ہوتی ہے۔ لہذا، پاس ورڈز، ادائیگی کی تفصیلات، پیغامات، تصاویر، ساتھ ہی آڈیو اور ویڈیو جیسی چیزوں کے سلسلے میں محتاط رہیں۔"</string>
@@ -1173,6 +1170,10 @@
<string name="assistant_attention_content_description" msgid="6830215897604642875">"اسسٹنٹ کی توجہ آن ہے"</string>
<string name="set_default_notes_app_toast_content" msgid="2812374329662610753">"ترتیبات میں ڈیفالٹ نوٹس ایپ سیٹ کریں"</string>
<string name="install_app" msgid="5066668100199613936">"ایپ انسٹال کریں"</string>
+ <!-- no translation found for connected_display_dialog_start_mirroring (6237895789920854982) -->
+ <skip />
+ <!-- no translation found for enable_display (8308309634883321977) -->
+ <skip />
<string name="privacy_dialog_title" msgid="7839968133469098311">"مائیکروفون اور کیمرا"</string>
<string name="privacy_dialog_summary" msgid="2458769652125995409">"حالیہ ایپ کا استعمال"</string>
<string name="privacy_dialog_more_button" msgid="7610604080293562345">"حالیہ رسائی دیکھیں"</string>
diff --git a/packages/SystemUI/res/values-uz/strings.xml b/packages/SystemUI/res/values-uz/strings.xml
index 66c874d28dc4..30e0618c1563 100644
--- a/packages/SystemUI/res/values-uz/strings.xml
+++ b/packages/SystemUI/res/values-uz/strings.xml
@@ -57,8 +57,7 @@
<string name="hdmi_cec_set_menu_language_description" msgid="8176716678074126619">"Tizim tilini oʻzgartirishni boshqa qurilma soʻragan"</string>
<string name="hdmi_cec_set_menu_language_accept" msgid="2513689457281009578">"Tilni almashtirish"</string>
<string name="hdmi_cec_set_menu_language_decline" msgid="7650721096558646011">"Joriy tilni qoldirish"</string>
- <!-- no translation found for share_wifi_button_text (1285273973812029240) -->
- <skip />
+ <string name="share_wifi_button_text" msgid="1285273973812029240">"Wi‑Fi ulashuv"</string>
<string name="wifi_debugging_title" msgid="7300007687492186076">"Wi-Fi orqali debagging uchun ruxsat berilsinmi?"</string>
<string name="wifi_debugging_message" msgid="5461204211731802995">"Tarmoq nomi (SSID):\n<xliff:g id="SSID_0">%1$s</xliff:g>\n\nWi‑Fi Manzil (BSSID):\n<xliff:g id="BSSID_1">%2$s</xliff:g>"</string>
<string name="wifi_debugging_always" msgid="2968383799517975155">"Bu tarmoqda doim ruxsat etilsin"</string>
@@ -160,8 +159,7 @@
<string name="biometric_dialog_wrong_pattern" msgid="8954812279840889029">"Grafik kalit xato"</string>
<string name="biometric_dialog_wrong_password" msgid="69477929306843790">"Parol xato"</string>
<string name="biometric_dialog_credential_too_many_attempts" msgid="3083141271737748716">"Xato urinishlar soni oshib ketdi! \n <xliff:g id="NUMBER">%d</xliff:g> soniyadan keyin qayta urining."</string>
- <!-- no translation found for work_challenge_emergency_button_text (8946588434515599288) -->
- <skip />
+ <string name="work_challenge_emergency_button_text" msgid="8946588434515599288">"Favqulodda holat"</string>
<string name="biometric_dialog_credential_attempts_before_wipe" msgid="6751859711975516999">"Qaytadan urining. Urinish: <xliff:g id="ATTEMPTS_0">%1$d</xliff:g> / <xliff:g id="MAX_ATTEMPTS">%2$d</xliff:g>."</string>
<string name="biometric_dialog_last_attempt_before_wipe_dialog_title" msgid="2874250099278693477">"Bitta urinish qoldi"</string>
<string name="biometric_dialog_last_pattern_attempt_before_wipe_device" msgid="6562299244825817598">"Agar grafik kalitni xato kiritsangiz, bu qurilmadagi maʼlumotlar oʻchirib tashlanadi."</string>
@@ -415,8 +413,7 @@
<string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="8736391633234144237">"Ulashish, yozib olish va translatsiya qilish vaqtida <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> ilovasi ekranda chiqadigan yoki qurilmada ijro qilinadigan kontentni koʻra oladi. Shu sababli parollar, toʻlov tafsilotlari, xabarlar, suratlar, audio va video chiqmasligi uchun ehtiyot boʻling."</string>
<string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="5211695779082563959">"Ulashish, yozib olish va translatsiya qilish vaqtida <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> ilovasi ekranda chiqadigan yoki qurilmada ijro qilinadigan kontentni koʻra oladi. Shu sababli parollar, toʻlov tafsilotlari, xabarlar, suratlar, audio va video chiqmasligi uchun ehtiyot boʻling."</string>
<string name="media_projection_entry_app_permission_dialog_continue" msgid="295463518195075840">"Boshlash"</string>
- <!-- no translation found for media_projection_entry_app_permission_dialog_single_app_disabled (8999903044874669995) -->
- <skip />
+ <string name="media_projection_entry_app_permission_dialog_single_app_disabled" msgid="8999903044874669995">"<xliff:g id="APP_NAME">%1$s</xliff:g> bu sozlamani faolsizlantirgan"</string>
<string name="media_projection_entry_cast_permission_dialog_title" msgid="8860150223172993547">"Translatsiya boshlansinmi?"</string>
<string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="1986212276016817231">"Translatsiya qilayotganingizda Android ekranda chiqadigan yoki qurilmada ijro qilinadigan kontentni koʻra oladi. Shu sababli parollar, toʻlov tafsilotlari, xabarlar, suratlar, audio va video chiqmasligi uchun ehtiyot boʻling."</string>
<string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="9900961380294292">"Translatsiya qilayotganingizda Android ekranda chiqadigan yoki qurilmada ijro qilinadigan kontentni koʻra oladi. Shu sababli parollar, toʻlov tafsilotlari, xabarlar, suratlar, audio va video chiqmasligi uchun ehtiyot boʻling."</string>
@@ -1173,6 +1170,10 @@
<string name="assistant_attention_content_description" msgid="6830215897604642875">"Assistent diqqati yoniq"</string>
<string name="set_default_notes_app_toast_content" msgid="2812374329662610753">"Standart qaydlar ilovasini Sozlamalar orqali tanlang"</string>
<string name="install_app" msgid="5066668100199613936">"Ilovani oʻrnatish"</string>
+ <!-- no translation found for connected_display_dialog_start_mirroring (6237895789920854982) -->
+ <skip />
+ <!-- no translation found for enable_display (8308309634883321977) -->
+ <skip />
<string name="privacy_dialog_title" msgid="7839968133469098311">"Mikrofon va kamera"</string>
<string name="privacy_dialog_summary" msgid="2458769652125995409">"Ilovadan oxirgi foydalanish"</string>
<string name="privacy_dialog_more_button" msgid="7610604080293562345">"Oxirgi ruxsatni koʻrish"</string>
diff --git a/packages/SystemUI/res/values-vi/strings.xml b/packages/SystemUI/res/values-vi/strings.xml
index 2648d786ed72..f4c62a5297fe 100644
--- a/packages/SystemUI/res/values-vi/strings.xml
+++ b/packages/SystemUI/res/values-vi/strings.xml
@@ -57,8 +57,7 @@
<string name="hdmi_cec_set_menu_language_description" msgid="8176716678074126619">"Thiết bị khác yêu cầu thay đổi ngôn ngữ hệ thống"</string>
<string name="hdmi_cec_set_menu_language_accept" msgid="2513689457281009578">"Thay đổi ngôn ngữ"</string>
<string name="hdmi_cec_set_menu_language_decline" msgid="7650721096558646011">"Giữ ngôn ngữ hiện tại"</string>
- <!-- no translation found for share_wifi_button_text (1285273973812029240) -->
- <skip />
+ <string name="share_wifi_button_text" msgid="1285273973812029240">"Chia sẻ Wi‑Fi"</string>
<string name="wifi_debugging_title" msgid="7300007687492186076">"Cho phép gỡ lỗi qua Wi-Fi trên mạng này?"</string>
<string name="wifi_debugging_message" msgid="5461204211731802995">"Tên mạng (SSID)\n<xliff:g id="SSID_0">%1$s</xliff:g>\n\nĐịa chỉ Wi‑Fi (BSSID)\n<xliff:g id="BSSID_1">%2$s</xliff:g>"</string>
<string name="wifi_debugging_always" msgid="2968383799517975155">"Luôn cho phép trên mạng này"</string>
@@ -160,8 +159,7 @@
<string name="biometric_dialog_wrong_pattern" msgid="8954812279840889029">"Hình mở khóa không chính xác"</string>
<string name="biometric_dialog_wrong_password" msgid="69477929306843790">"Mật khẩu sai"</string>
<string name="biometric_dialog_credential_too_many_attempts" msgid="3083141271737748716">"Bạn đã nhập sai quá nhiều lần.\nHãy thử lại sau <xliff:g id="NUMBER">%d</xliff:g> giây."</string>
- <!-- no translation found for work_challenge_emergency_button_text (8946588434515599288) -->
- <skip />
+ <string name="work_challenge_emergency_button_text" msgid="8946588434515599288">"Khẩn cấp"</string>
<string name="biometric_dialog_credential_attempts_before_wipe" msgid="6751859711975516999">"Thử lại. Lần thử <xliff:g id="ATTEMPTS_0">%1$d</xliff:g>/<xliff:g id="MAX_ATTEMPTS">%2$d</xliff:g>."</string>
<string name="biometric_dialog_last_attempt_before_wipe_dialog_title" msgid="2874250099278693477">"Dữ liệu của bạn sẽ bị xóa"</string>
<string name="biometric_dialog_last_pattern_attempt_before_wipe_device" msgid="6562299244825817598">"Nếu bạn nhập hình mở khóa không chính xác vào lần thử tiếp theo, thì dữ liệu trên thiết bị này sẽ bị xóa."</string>
@@ -415,8 +413,7 @@
<string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="8736391633234144237">"Khi bạn chia sẻ, ghi hoặc truyền, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> sẽ có quyền truy cập vào mọi nội dung xuất hiện trên màn hình hoặc phát trên thiết bị của bạn. Vì vậy, hãy thận trọng để không làm lộ thông tin như mật khẩu, thông tin thanh toán, tin nhắn, ảnh, âm thanh và video."</string>
<string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="5211695779082563959">"Khi bạn chia sẻ, ghi hoặc truyền ứng dụng, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> sẽ có quyền truy cập vào mọi nội dung xuất hiện hoặc phát trên ứng dụng đó. Vì vậy, hãy thận trọng để không làm lộ các thông tin như mật khẩu, thông tin thanh toán, tin nhắn, ảnh, âm thanh và video."</string>
<string name="media_projection_entry_app_permission_dialog_continue" msgid="295463518195075840">"Bắt đầu"</string>
- <!-- no translation found for media_projection_entry_app_permission_dialog_single_app_disabled (8999903044874669995) -->
- <skip />
+ <string name="media_projection_entry_app_permission_dialog_single_app_disabled" msgid="8999903044874669995">"<xliff:g id="APP_NAME">%1$s</xliff:g> đã tắt lựa chọn này"</string>
<string name="media_projection_entry_cast_permission_dialog_title" msgid="8860150223172993547">"Bắt đầu truyền?"</string>
<string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="1986212276016817231">"Khi bạn truyền, Android sẽ có quyền truy cập vào mọi nội dung xuất hiện trên màn hình hoặc phát trên thiết bị của bạn. Vì vậy, hãy thận trọng để không làm lộ thông tin như mật khẩu, thông tin thanh toán, tin nhắn, ảnh, âm thanh và video."</string>
<string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="9900961380294292">"Khi bạn truyền một ứng dụng, Android sẽ có quyền truy cập vào mọi nội dung xuất hiện hoặc phát trên ứng dụng đó. Vì vậy, hãy thận trọng để không làm lộ các thông tin như mật khẩu, thông tin thanh toán, tin nhắn, ảnh, âm thanh và video."</string>
@@ -1173,6 +1170,10 @@
<string name="assistant_attention_content_description" msgid="6830215897604642875">"Trợ lý đang bật"</string>
<string name="set_default_notes_app_toast_content" msgid="2812374329662610753">"Đặt ứng dụng ghi chú mặc định trong phần Cài đặt"</string>
<string name="install_app" msgid="5066668100199613936">"Cài đặt ứng dụng"</string>
+ <!-- no translation found for connected_display_dialog_start_mirroring (6237895789920854982) -->
+ <skip />
+ <!-- no translation found for enable_display (8308309634883321977) -->
+ <skip />
<string name="privacy_dialog_title" msgid="7839968133469098311">"Micrô và máy ảnh"</string>
<string name="privacy_dialog_summary" msgid="2458769652125995409">"Hoạt động sử dụng gần đây của ứng dụng"</string>
<string name="privacy_dialog_more_button" msgid="7610604080293562345">"Xem hoạt động truy cập gần đây"</string>
diff --git a/packages/SystemUI/res/values-zh-rCN/strings.xml b/packages/SystemUI/res/values-zh-rCN/strings.xml
index 3072fa494bc7..f3ade0390797 100644
--- a/packages/SystemUI/res/values-zh-rCN/strings.xml
+++ b/packages/SystemUI/res/values-zh-rCN/strings.xml
@@ -57,8 +57,7 @@
<string name="hdmi_cec_set_menu_language_description" msgid="8176716678074126619">"另一台设备请求更改系统语言"</string>
<string name="hdmi_cec_set_menu_language_accept" msgid="2513689457281009578">"更改语言"</string>
<string name="hdmi_cec_set_menu_language_decline" msgid="7650721096558646011">"保持当前语言"</string>
- <!-- no translation found for share_wifi_button_text (1285273973812029240) -->
- <skip />
+ <string name="share_wifi_button_text" msgid="1285273973812029240">"分享 WLAN"</string>
<string name="wifi_debugging_title" msgid="7300007687492186076">"要允许通过此网络进行无线调试吗?"</string>
<string name="wifi_debugging_message" msgid="5461204211731802995">"网络名称 (SSID)\n<xliff:g id="SSID_0">%1$s</xliff:g>\n\nWLAN 地址 (BSSID)\n<xliff:g id="BSSID_1">%2$s</xliff:g>"</string>
<string name="wifi_debugging_always" msgid="2968383799517975155">"始终允许通过此网络进行调试"</string>
@@ -160,8 +159,7 @@
<string name="biometric_dialog_wrong_pattern" msgid="8954812279840889029">"图案错误"</string>
<string name="biometric_dialog_wrong_password" msgid="69477929306843790">"密码错误"</string>
<string name="biometric_dialog_credential_too_many_attempts" msgid="3083141271737748716">"输错次数过多。\n请在 <xliff:g id="NUMBER">%d</xliff:g> 秒后重试。"</string>
- <!-- no translation found for work_challenge_emergency_button_text (8946588434515599288) -->
- <skip />
+ <string name="work_challenge_emergency_button_text" msgid="8946588434515599288">"紧急呼叫"</string>
<string name="biometric_dialog_credential_attempts_before_wipe" msgid="6751859711975516999">"请重试。您目前已尝试 <xliff:g id="ATTEMPTS_0">%1$d</xliff:g> 次,最多可尝试 <xliff:g id="MAX_ATTEMPTS">%2$d</xliff:g> 次。"</string>
<string name="biometric_dialog_last_attempt_before_wipe_dialog_title" msgid="2874250099278693477">"您的数据将会被删除"</string>
<string name="biometric_dialog_last_pattern_attempt_before_wipe_device" msgid="6562299244825817598">"如果您下次绘制的解锁图案仍然有误,此设备上的数据将会被删除。"</string>
@@ -415,8 +413,7 @@
<string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="8736391633234144237">"在分享、录制或投放内容时,<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>可以访问屏幕上显示或设备中播放的所有内容。因此,请务必小心操作,谨防密码、付款信息、消息、照片、音频和视频等内容遭到泄露。"</string>
<string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="5211695779082563959">"在分享、录制或投放内容时,<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>可以访问通过此应用显示或播放的所有内容。因此,请务必小心操作,谨防密码、付款信息、消息、照片、音频和视频等内容遭到泄露。"</string>
<string name="media_projection_entry_app_permission_dialog_continue" msgid="295463518195075840">"开始"</string>
- <!-- no translation found for media_projection_entry_app_permission_dialog_single_app_disabled (8999903044874669995) -->
- <skip />
+ <string name="media_projection_entry_app_permission_dialog_single_app_disabled" msgid="8999903044874669995">"“<xliff:g id="APP_NAME">%1$s</xliff:g>”已停用此选项"</string>
<string name="media_projection_entry_cast_permission_dialog_title" msgid="8860150223172993547">"开始投放?"</string>
<string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="1986212276016817231">"在投放内容时,Android 可以访问屏幕上显示或设备中播放的所有内容。因此,请务必小心操作,谨防密码、付款信息、消息、照片、音频和视频等内容遭到泄露。"</string>
<string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="9900961380294292">"在投放某个应用时,Android 可以访问此应用显示或播放的所有内容。因此,请务必小心操作,谨防密码、付款信息、消息、照片、音频和视频等内容遭到泄露。"</string>
@@ -1173,6 +1170,10 @@
<string name="assistant_attention_content_description" msgid="6830215897604642875">"已开启 Google 助理感知功能"</string>
<string name="set_default_notes_app_toast_content" msgid="2812374329662610753">"在设置中设置默认记事应用"</string>
<string name="install_app" msgid="5066668100199613936">"安装应用"</string>
+ <!-- no translation found for connected_display_dialog_start_mirroring (6237895789920854982) -->
+ <skip />
+ <!-- no translation found for enable_display (8308309634883321977) -->
+ <skip />
<string name="privacy_dialog_title" msgid="7839968133469098311">"麦克风和摄像头"</string>
<string name="privacy_dialog_summary" msgid="2458769652125995409">"近期应用对手机传感器的使用情况"</string>
<string name="privacy_dialog_more_button" msgid="7610604080293562345">"查看近期使用情况"</string>
diff --git a/packages/SystemUI/res/values-zh-rHK/strings.xml b/packages/SystemUI/res/values-zh-rHK/strings.xml
index 8f4adc05069e..efc567107d8f 100644
--- a/packages/SystemUI/res/values-zh-rHK/strings.xml
+++ b/packages/SystemUI/res/values-zh-rHK/strings.xml
@@ -57,8 +57,7 @@
<string name="hdmi_cec_set_menu_language_description" msgid="8176716678074126619">"另一部裝置要求變更系統語言"</string>
<string name="hdmi_cec_set_menu_language_accept" msgid="2513689457281009578">"變更語言"</string>
<string name="hdmi_cec_set_menu_language_decline" msgid="7650721096558646011">"保留目前語言"</string>
- <!-- no translation found for share_wifi_button_text (1285273973812029240) -->
- <skip />
+ <string name="share_wifi_button_text" msgid="1285273973812029240">"分享 Wi‑Fi"</string>
<string name="wifi_debugging_title" msgid="7300007687492186076">"要在此網絡上允許無線偵錯功能嗎?"</string>
<string name="wifi_debugging_message" msgid="5461204211731802995">"網絡名稱 (SSID)\n<xliff:g id="SSID_0">%1$s</xliff:g>\n\nWi‑Fi 地址 (BSSID)\n<xliff:g id="BSSID_1">%2$s</xliff:g>"</string>
<string name="wifi_debugging_always" msgid="2968383799517975155">"一律允許在此網絡上執行"</string>
@@ -160,8 +159,7 @@
<string name="biometric_dialog_wrong_pattern" msgid="8954812279840889029">"圖案錯誤"</string>
<string name="biometric_dialog_wrong_password" msgid="69477929306843790">"密碼錯誤"</string>
<string name="biometric_dialog_credential_too_many_attempts" msgid="3083141271737748716">"輸入錯誤的次數太多,\n請於 <xliff:g id="NUMBER">%d</xliff:g> 秒後再試。"</string>
- <!-- no translation found for work_challenge_emergency_button_text (8946588434515599288) -->
- <skip />
+ <string name="work_challenge_emergency_button_text" msgid="8946588434515599288">"緊急"</string>
<string name="biometric_dialog_credential_attempts_before_wipe" msgid="6751859711975516999">"請再試一次。你已嘗試 <xliff:g id="ATTEMPTS_0">%1$d</xliff:g> 次,最多可試 <xliff:g id="MAX_ATTEMPTS">%2$d</xliff:g> 次。"</string>
<string name="biometric_dialog_last_attempt_before_wipe_dialog_title" msgid="2874250099278693477">"你的資料將會刪除"</string>
<string name="biometric_dialog_last_pattern_attempt_before_wipe_device" msgid="6562299244825817598">"如果你下次畫出錯誤的上鎖圖案,系統將會刪除此裝置上的資料。"</string>
@@ -415,8 +413,7 @@
<string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="8736391633234144237">"當你分享、錄影或投放時,「<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>」可存取顯示在螢幕畫面上或在裝置上播放的所有內容。因此,請謹慎處理密碼、付款資料、訊息、相片、音訊和影片等。"</string>
<string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="5211695779082563959">"當你分享、錄影或投放應用程式時,「<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>」可存取顯示在該應用程式中顯示或播放的所有內容。因此,請謹慎處理密碼、付款資料、訊息、相片、音訊和影片等。"</string>
<string name="media_projection_entry_app_permission_dialog_continue" msgid="295463518195075840">"開始"</string>
- <!-- no translation found for media_projection_entry_app_permission_dialog_single_app_disabled (8999903044874669995) -->
- <skip />
+ <string name="media_projection_entry_app_permission_dialog_single_app_disabled" msgid="8999903044874669995">"「<xliff:g id="APP_NAME">%1$s</xliff:g>」已停用此選項"</string>
<string name="media_projection_entry_cast_permission_dialog_title" msgid="8860150223172993547">"要開始投放嗎?"</string>
<string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="1986212276016817231">"當你投放時,Android 可存取顯示在螢幕畫面上或在裝置上播放的所有內容。因此,請謹慎處理密碼、付款資料、訊息、相片、音訊和影片等。"</string>
<string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="9900961380294292">"當你投放應用程式時,Android 可存取在該應用程式中顯示或播放的所有內容。因此,請謹慎處理密碼、付款資料、訊息、相片、音訊和影片等。"</string>
@@ -1173,6 +1170,10 @@
<string name="assistant_attention_content_description" msgid="6830215897604642875">"「Google 助理」感應功能已開啟"</string>
<string name="set_default_notes_app_toast_content" msgid="2812374329662610753">"在「設定」中指定預設筆記應用程式"</string>
<string name="install_app" msgid="5066668100199613936">"安裝應用程式"</string>
+ <!-- no translation found for connected_display_dialog_start_mirroring (6237895789920854982) -->
+ <skip />
+ <!-- no translation found for enable_display (8308309634883321977) -->
+ <skip />
<string name="privacy_dialog_title" msgid="7839968133469098311">"麥克風和相機"</string>
<string name="privacy_dialog_summary" msgid="2458769652125995409">"近期應用程式使用情況"</string>
<string name="privacy_dialog_more_button" msgid="7610604080293562345">"查看近期存取記錄"</string>
diff --git a/packages/SystemUI/res/values-zh-rTW/strings.xml b/packages/SystemUI/res/values-zh-rTW/strings.xml
index 35b7231bd23b..af84a3122289 100644
--- a/packages/SystemUI/res/values-zh-rTW/strings.xml
+++ b/packages/SystemUI/res/values-zh-rTW/strings.xml
@@ -57,8 +57,7 @@
<string name="hdmi_cec_set_menu_language_description" msgid="8176716678074126619">"另一部裝置要求變更系統語言"</string>
<string name="hdmi_cec_set_menu_language_accept" msgid="2513689457281009578">"變更語言"</string>
<string name="hdmi_cec_set_menu_language_decline" msgid="7650721096558646011">"繼續使用目前的語言"</string>
- <!-- no translation found for share_wifi_button_text (1285273973812029240) -->
- <skip />
+ <string name="share_wifi_button_text" msgid="1285273973812029240">"分享 Wi-Fi"</string>
<string name="wifi_debugging_title" msgid="7300007687492186076">"要允許透過這個網路執行無線偵錯嗎?"</string>
<string name="wifi_debugging_message" msgid="5461204211731802995">"網路名稱 (SSID)\n<xliff:g id="SSID_0">%1$s</xliff:g>\n\nWi‑Fi 位址 (BSSID)\n<xliff:g id="BSSID_1">%2$s</xliff:g>"</string>
<string name="wifi_debugging_always" msgid="2968383799517975155">"一律允許透過這個網路執行"</string>
@@ -160,8 +159,7 @@
<string name="biometric_dialog_wrong_pattern" msgid="8954812279840889029">"圖案錯誤"</string>
<string name="biometric_dialog_wrong_password" msgid="69477929306843790">"密碼錯誤"</string>
<string name="biometric_dialog_credential_too_many_attempts" msgid="3083141271737748716">"錯誤次數過多,\n請於 <xliff:g id="NUMBER">%d</xliff:g> 秒後再試。"</string>
- <!-- no translation found for work_challenge_emergency_button_text (8946588434515599288) -->
- <skip />
+ <string name="work_challenge_emergency_button_text" msgid="8946588434515599288">"緊急"</string>
<string name="biometric_dialog_credential_attempts_before_wipe" msgid="6751859711975516999">"請再試一次。你目前已嘗試 <xliff:g id="ATTEMPTS_0">%1$d</xliff:g> 次,最多可試 <xliff:g id="MAX_ATTEMPTS">%2$d</xliff:g> 次。"</string>
<string name="biometric_dialog_last_attempt_before_wipe_dialog_title" msgid="2874250099278693477">"你的資料將遭到刪除"</string>
<string name="biometric_dialog_last_pattern_attempt_before_wipe_device" msgid="6562299244825817598">"如果下次輸入的解鎖圖案仍不正確,系統將刪除這部裝置中的資料。"</string>
@@ -415,8 +413,7 @@
<string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="8736391633234144237">"當你分享、錄製或投放內容時,「<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>」可存取畫面上顯示的任何資訊或裝置播放的任何內容。因此,請謹慎處理密碼、付款資料、訊息、相片和影音內容等資訊。"</string>
<string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="5211695779082563959">"當你分享、錄製或投放應用程式內容時,「<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>」可存取應用程式中顯示的任何資訊或播放的任何內容。因此,請謹慎處理密碼、付款資料、訊息、相片和影音內容等資訊。"</string>
<string name="media_projection_entry_app_permission_dialog_continue" msgid="295463518195075840">"開始"</string>
- <!-- no translation found for media_projection_entry_app_permission_dialog_single_app_disabled (8999903044874669995) -->
- <skip />
+ <string name="media_projection_entry_app_permission_dialog_single_app_disabled" msgid="8999903044874669995">"「<xliff:g id="APP_NAME">%1$s</xliff:g>」已停用此選項"</string>
<string name="media_projection_entry_cast_permission_dialog_title" msgid="8860150223172993547">"要開始投放嗎?"</string>
<string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="1986212276016817231">"當你投放內容時,Android 可存取畫面上顯示的任何資訊或裝置播放的任何內容。因此,請謹慎處理密碼、付款資料、訊息、相片和影音內容等資訊。"</string>
<string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="9900961380294292">"當你投放應用程式內容時,Android 可存取應用程式中顯示的任何資訊或播放的任何內容。因此,請謹慎處理密碼、付款資料、訊息、相片和影音內容等資訊。"</string>
@@ -1173,6 +1170,10 @@
<string name="assistant_attention_content_description" msgid="6830215897604642875">"Google 助理感知功能已開啟"</string>
<string name="set_default_notes_app_toast_content" msgid="2812374329662610753">"在「設定」中指定預設記事應用程式"</string>
<string name="install_app" msgid="5066668100199613936">"安裝應用程式"</string>
+ <!-- no translation found for connected_display_dialog_start_mirroring (6237895789920854982) -->
+ <skip />
+ <!-- no translation found for enable_display (8308309634883321977) -->
+ <skip />
<string name="privacy_dialog_title" msgid="7839968133469098311">"麥克風和相機"</string>
<string name="privacy_dialog_summary" msgid="2458769652125995409">"最近曾使用感應器的應用程式"</string>
<string name="privacy_dialog_more_button" msgid="7610604080293562345">"查看近期存取記錄"</string>
diff --git a/packages/SystemUI/res/values-zu/strings.xml b/packages/SystemUI/res/values-zu/strings.xml
index 19c00e612b1c..11cf44b4e2e6 100644
--- a/packages/SystemUI/res/values-zu/strings.xml
+++ b/packages/SystemUI/res/values-zu/strings.xml
@@ -57,8 +57,7 @@
<string name="hdmi_cec_set_menu_language_description" msgid="8176716678074126619">"Ushintsho lolimi lwesistimu lucelwe enye idivayisi"</string>
<string name="hdmi_cec_set_menu_language_accept" msgid="2513689457281009578">"Shintsha ulimi"</string>
<string name="hdmi_cec_set_menu_language_decline" msgid="7650721096558646011">"Gcina ulimi lwamanje"</string>
- <!-- no translation found for share_wifi_button_text (1285273973812029240) -->
- <skip />
+ <string name="share_wifi_button_text" msgid="1285273973812029240">"Yaba i-Wi‑Fi"</string>
<string name="wifi_debugging_title" msgid="7300007687492186076">"Vumela ukulungisa amaphutha okungenantambo kule nethiwekhi?"</string>
<string name="wifi_debugging_message" msgid="5461204211731802995">"Igama Lenethiwekhi (SSID)\n<xliff:g id="SSID_0">%1$s</xliff:g>\n\nIkheli le-Wi‑Fi (BSSID)\n<xliff:g id="BSSID_1">%2$s</xliff:g>"</string>
<string name="wifi_debugging_always" msgid="2968383799517975155">"Njalo nje vumela le nethiwekhi"</string>
@@ -160,8 +159,7 @@
<string name="biometric_dialog_wrong_pattern" msgid="8954812279840889029">"Iphethini engalungile"</string>
<string name="biometric_dialog_wrong_password" msgid="69477929306843790">"Iphasiwedi engalungile"</string>
<string name="biometric_dialog_credential_too_many_attempts" msgid="3083141271737748716">"Imizamo eminingi kakhulu engalungile.\nZama futhi kumasekhondi angu-<xliff:g id="NUMBER">%d</xliff:g>."</string>
- <!-- no translation found for work_challenge_emergency_button_text (8946588434515599288) -->
- <skip />
+ <string name="work_challenge_emergency_button_text" msgid="8946588434515599288">"Isimo esiphuthumayo"</string>
<string name="biometric_dialog_credential_attempts_before_wipe" msgid="6751859711975516999">"Zama futhi. Umzamo ongu-<xliff:g id="ATTEMPTS_0">%1$d</xliff:g> kwengu-<xliff:g id="MAX_ATTEMPTS">%2$d</xliff:g>."</string>
<string name="biometric_dialog_last_attempt_before_wipe_dialog_title" msgid="2874250099278693477">"Idatha yakho izosuswa"</string>
<string name="biometric_dialog_last_pattern_attempt_before_wipe_device" msgid="6562299244825817598">"Uma ufaka iphethini engalungile kumzamo olandelayo, idatha yale divayisi izosuswa."</string>
@@ -415,8 +413,7 @@
<string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="8736391633234144237">"Uma wabelana, urekhoda, noma usakaza, i-<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> inokufinyelela kunoma yini ebonakalayo kusikrini sakho noma edlalwa kudivayisi yakho. Ngakho-ke qaphela ngezinto ezifana namaphasiwedi, imininingwane yokukhokha, imilayezo, izithombe, nomsindo nevidiyo."</string>
<string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="5211695779082563959">"Uma wabelana, ukurekhoda, noma ukusakaza ku-app, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> inokufinyelela kunoma yini eboniswayo noma edlalwa kuleyo app. Ngakho-ke qaphela ngezinto ezfana namaphasiwedi, imininingwane yokukhokha, imilayezo, izithombe, nomsindo nevidiyo."</string>
<string name="media_projection_entry_app_permission_dialog_continue" msgid="295463518195075840">"Qala"</string>
- <!-- no translation found for media_projection_entry_app_permission_dialog_single_app_disabled (8999903044874669995) -->
- <skip />
+ <string name="media_projection_entry_app_permission_dialog_single_app_disabled" msgid="8999903044874669995">"<xliff:g id="APP_NAME">%1$s</xliff:g> ivale le nketho"</string>
<string name="media_projection_entry_cast_permission_dialog_title" msgid="8860150223172993547">"Qala ukusakaza?"</string>
<string name="media_projection_entry_cast_permission_dialog_warning_entire_screen" msgid="1986212276016817231">"Uma usakaza, i-Android inokufinyelela kunoma yini ebonakalayo kusikrini sakho noma edlalwa kudivayisi yakho. Ngakho-ke qaphela ngezinto ezifana namaphasiwedi, imininingwane yokukhokha, imilayezo, izithombe, nomsindo nevidiyo."</string>
<string name="media_projection_entry_cast_permission_dialog_warning_single_app" msgid="9900961380294292">"Uma usakaza i-app, i-Android inokufinyelela kunoma yini eboniswayo noma edlalwa kuleyo app. Ngakho-ke qaphela ngezinto ezifana namaphasiwedi, imininingwane yenkokhelo, imilayezo, izithombe, nomsindo nevidiyo."</string>
@@ -1173,6 +1170,10 @@
<string name="assistant_attention_content_description" msgid="6830215897604642875">"Ukunaka kwe-Assistant kuvuliwe"</string>
<string name="set_default_notes_app_toast_content" msgid="2812374329662610753">"Setha i-app yamanothi azenzakalelayo Kumsethingi"</string>
<string name="install_app" msgid="5066668100199613936">"Faka i-app"</string>
+ <!-- no translation found for connected_display_dialog_start_mirroring (6237895789920854982) -->
+ <skip />
+ <!-- no translation found for enable_display (8308309634883321977) -->
+ <skip />
<string name="privacy_dialog_title" msgid="7839968133469098311">"Imakrofoni Nekhamera"</string>
<string name="privacy_dialog_summary" msgid="2458769652125995409">"Ukusetshenziswa kwakamuva kwe-app"</string>
<string name="privacy_dialog_more_button" msgid="7610604080293562345">"Bona ukufinyelela kwakamuva"</string>
diff --git a/packages/SystemUI/res/values/bools.xml b/packages/SystemUI/res/values/bools.xml
index 405a59fe1cc7..91d3a88dcc89 100644
--- a/packages/SystemUI/res/values/bools.xml
+++ b/packages/SystemUI/res/values/bools.xml
@@ -51,4 +51,12 @@
This configuration will only apply when config_remoteInsetsControllerControlsSystemBars.
is set to true. -->
<bool name="config_remoteInsetsControllerSystemBarsCanBeShownByUserAction">false</bool>
+
+ <!-- Do update bouncer constraints (port or land) on rotation.
+ Needed for bouncer refactor to use motion layout, because constraints should only be
+ changed on small screens. Only used when flag "lockscreen.enable_landscape" (b/293252410)
+ is enabled
+
+ True here so bouncers constraints are updated when rotating on small screens -->
+ <bool name="update_bouncer_constraints">true</bool>
</resources>
diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml
index 016936aae956..c13480672102 100644
--- a/packages/SystemUI/res/values/config.xml
+++ b/packages/SystemUI/res/values/config.xml
@@ -934,4 +934,12 @@
<!-- Flag controlling whether visual query attention detection has been enabled. -->
<bool name="config_enableVisualQueryAttentionDetection">false</bool>
+
+ <!--
+ Whether the scene container framework is enabled.
+
+ The scene container framework is a newer (2023) way to organize the various "scenes" between the
+ bouncer, lockscreen, shade, and quick settings.
+ -->
+ <bool name="config_sceneContainerFrameworkEnabled">true</bool>
</resources>
diff --git a/packages/SystemUI/res/values/ids.xml b/packages/SystemUI/res/values/ids.xml
index 579358fe709b..d8c808054fff 100644
--- a/packages/SystemUI/res/values/ids.xml
+++ b/packages/SystemUI/res/values/ids.xml
@@ -233,4 +233,7 @@
removed later.
-->
<item type="id" name="tag_smartspace_view" />
+
+ <!-- Tag set on the Compose implementation of the QS footer actions. -->
+ <item type="id" name="tag_compose_qs_footer_actions" />
</resources>
diff --git a/packages/SystemUI/res/xml/media_session_expanded.xml b/packages/SystemUI/res/xml/media_session_expanded.xml
index 0cdc0f9505bc..8bf7560d6ddb 100644
--- a/packages/SystemUI/res/xml/media_session_expanded.xml
+++ b/packages/SystemUI/res/xml/media_session_expanded.xml
@@ -54,10 +54,12 @@
android:layout_marginStart="@dimen/qs_media_padding"
android:layout_marginEnd="@dimen/qs_media_padding"
app:layout_constraintEnd_toStartOf="@id/actionPlayPause"
+ app:layout_constraintTop_toBottomOf="@id/media_seamless"
app:layout_constrainedWidth="true"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintBottom_toTopOf="@id/header_artist"
- app:layout_constraintHorizontal_bias="0" />
+ app:layout_constraintHorizontal_bias="0"
+ app:layout_constraintVertical_bias="1" />
<Constraint
android:id="@+id/media_explicit_indicator"
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardInputView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardInputView.java
index c9d906911dbc..a72d8137663b 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardInputView.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardInputView.java
@@ -64,6 +64,11 @@ public abstract class KeyguardInputView extends LinearLayout {
return false;
}
+ /** Change motion layout constraint set based on orientation */
+ protected void updateConstraints(int orientation) {
+ //Unless overridden, never update constrains (keeping default portrait constraints)
+ }
+
protected AnimatorListenerAdapter getAnimationListener(int cuj) {
return new AnimatorListenerAdapter() {
private boolean mIsCancel;
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java
index d90785dd266d..a2d8c50fdca7 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java
@@ -83,6 +83,7 @@ import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInterac
import com.android.systemui.log.SessionTracker;
import com.android.systemui.plugins.ActivityStarter;
import com.android.systemui.plugins.FalsingManager;
+import com.android.systemui.scene.shared.flag.SceneContainerFlags;
import com.android.systemui.shared.system.SysUiStatsLog;
import com.android.systemui.statusbar.policy.ConfigurationController;
import com.android.systemui.statusbar.policy.DeviceProvisionedController;
@@ -123,6 +124,7 @@ public class KeyguardSecurityContainerController extends ViewController<Keyguard
private final UserSwitcherController mUserSwitcherController;
private final GlobalSettings mGlobalSettings;
private final FeatureFlags mFeatureFlags;
+ private final SceneContainerFlags mSceneContainerFlags;
private final SessionTracker mSessionTracker;
private final Optional<SideFpsController> mSideFpsController;
private final FalsingA11yDelegate mFalsingA11yDelegate;
@@ -369,11 +371,9 @@ public class KeyguardSecurityContainerController extends ViewController<Keyguard
@Override
public void onOrientationChanged(int orientation) {
- if (mFeatureFlags.isEnabled(LOCKSCREEN_ENABLE_LANDSCAPE)) {
- // TODO(b/295603468)
- // Fix reinflation of views when flag is enabled.
- KeyguardSecurityContainerController.this
- .onDensityOrFontScaleOrOrientationChanged();
+ if (mFeatureFlags.isEnabled(LOCKSCREEN_ENABLE_LANDSCAPE)
+ && getResources().getBoolean(R.bool.update_bouncer_constraints)) {
+ mSecurityViewFlipperController.updateConstraints(orientation);
}
}
};
@@ -433,6 +433,7 @@ public class KeyguardSecurityContainerController extends ViewController<Keyguard
FalsingManager falsingManager,
UserSwitcherController userSwitcherController,
FeatureFlags featureFlags,
+ SceneContainerFlags sceneContainerFlags,
GlobalSettings globalSettings,
SessionTracker sessionTracker,
Optional<SideFpsController> sideFpsController,
@@ -466,6 +467,7 @@ public class KeyguardSecurityContainerController extends ViewController<Keyguard
mFalsingManager = falsingManager;
mUserSwitcherController = userSwitcherController;
mFeatureFlags = featureFlags;
+ mSceneContainerFlags = sceneContainerFlags;
mGlobalSettings = globalSettings;
mSessionTracker = sessionTracker;
mSideFpsController = sideFpsController;
@@ -503,7 +505,7 @@ public class KeyguardSecurityContainerController extends ViewController<Keyguard
showPrimarySecurityScreen(false);
- if (mFeatureFlags.isEnabled(Flags.SCENE_CONTAINER)) {
+ if (mSceneContainerFlags.isEnabled()) {
// When the scene framework says that the lockscreen has been dismissed, dismiss the
// keyguard here, revealing the underlying app or launcher:
mSceneTransitionCollectionJob = mJavaAdapter.get().alwaysCollectFlow(
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityViewFlipper.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityViewFlipper.java
index 4d2391ad5596..891eb149427b 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityViewFlipper.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityViewFlipper.java
@@ -83,6 +83,14 @@ public class KeyguardSecurityViewFlipper extends ViewFlipper {
return "";
}
+ /** Updates the keyguard view's constraints based on orientation */
+ public void updateConstraints(int orientation) {
+ KeyguardInputView securityView = getSecurityView();
+ if (securityView != null) {
+ securityView.updateConstraints(orientation);
+ }
+ }
+
@Override
protected boolean checkLayoutParams(ViewGroup.LayoutParams p) {
return p instanceof LayoutParams;
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityViewFlipperController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityViewFlipperController.java
index bc5b1ba9a294..74f0beb71eb2 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityViewFlipperController.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityViewFlipperController.java
@@ -16,6 +16,8 @@
package com.android.keyguard;
+import static com.android.systemui.flags.Flags.LOCKSCREEN_ENABLE_LANDSCAPE;
+
import android.util.Log;
import android.view.LayoutInflater;
@@ -116,30 +118,38 @@ public class KeyguardSecurityViewFlipperController
public void asynchronouslyInflateView(SecurityMode securityMode,
KeyguardSecurityCallback keyguardSecurityCallback,
@Nullable OnViewInflatedCallback onViewInflatedListener) {
- int layoutId = getLayoutIdFor(securityMode);
- int viewID = getKeyguardInputViewId(securityMode);
- if (layoutId != 0 && viewID != 0) {
+ int layoutId = mFeatureFlags.isEnabled(LOCKSCREEN_ENABLE_LANDSCAPE)
+ ? getLayoutIdFor(securityMode) : getLegacyLayoutIdFor(securityMode);
+ if (layoutId != 0) {
if (DEBUG) {
- Log.v(TAG, "inflating on bg thread id = "
- + layoutId + " . viewID = " + viewID);
+ Log.v(TAG, "inflating on bg thread id = " + layoutId + " .");
}
mAsyncLayoutInflater.inflate(layoutId, mView,
(view, resId, parent) -> {
mView.addView(view);
KeyguardInputViewController<KeyguardInputView> childController =
mKeyguardSecurityViewControllerFactory.create(
- (KeyguardInputView) view.findViewById(viewID),
+ (KeyguardInputView) view,
securityMode, keyguardSecurityCallback);
childController.init();
mChildren.add(childController);
if (onViewInflatedListener != null) {
onViewInflatedListener.onViewInflated(childController);
+
+ // Portrait constrains are default
+ if (mFeatureFlags.isEnabled(LOCKSCREEN_ENABLE_LANDSCAPE)
+ &&
+ getResources().getBoolean(R.bool.update_bouncer_constraints)) {
+ // updateConstraints based on orientation (only on small screens)
+ updateConstraints(getResources().getConfiguration().orientation);
+ }
}
});
}
}
private int getLayoutIdFor(SecurityMode securityMode) {
+ // TODO (b/297863911, b/297864907) - implement motion layout for other bouncers
switch (securityMode) {
case Pattern: return R.layout.keyguard_pattern_view;
case PIN: return R.layout.keyguard_pin_view;
@@ -151,19 +161,23 @@ public class KeyguardSecurityViewFlipperController
}
}
- private int getKeyguardInputViewId(SecurityMode securityMode) {
- //Keyguard Input View is not the root view of the layout, use these IDs for lookup.
+ private int getLegacyLayoutIdFor(SecurityMode securityMode) {
switch (securityMode) {
- case Pattern: return R.id.keyguard_pattern_view;
- case PIN: return R.id.keyguard_pin_view;
- case Password: return R.id.keyguard_password_view;
- case SimPin: return R.id.keyguard_sim_pin_view;
- case SimPuk: return R.id.keyguard_sim_puk_view;
+ case Pattern: return R.layout.keyguard_pattern_view;
+ case PIN: return R.layout.keyguard_pin_view;
+ case Password: return R.layout.keyguard_password_view;
+ case SimPin: return R.layout.keyguard_sim_pin_view;
+ case SimPuk: return R.layout.keyguard_sim_puk_view;
default:
return 0;
}
}
+ /** Updates the keyguard view's constraints based on orientation */
+ public void updateConstraints(int orientation) {
+ mView.updateConstraints(orientation);
+ }
+
/** Makes the supplied child visible if it is contained win this view, */
public void show(KeyguardInputViewController<KeyguardInputView> childController) {
int index = childController.getIndexIn(mView);
diff --git a/packages/SystemUI/src/com/android/keyguard/PinShapeNonHintingView.java b/packages/SystemUI/src/com/android/keyguard/PinShapeNonHintingView.java
index 56c0953cd822..5f33ef91ed9c 100644
--- a/packages/SystemUI/src/com/android/keyguard/PinShapeNonHintingView.java
+++ b/packages/SystemUI/src/com/android/keyguard/PinShapeNonHintingView.java
@@ -61,7 +61,7 @@ public class PinShapeNonHintingView extends LinearLayout implements PinShapeInpu
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
super.onLayout(changed, l, t, r, b);
- if (getChildCount() > 0) {
+ if (getChildCount() > 2) {
View firstChild = getChildAt(0);
boolean isVisible = firstChild.getLocalVisibleRect(mFirstChildVisibleRect);
boolean clipped = mFirstChildVisibleRect.left > 0
diff --git a/packages/SystemUI/src/com/android/keyguard/dagger/KeyguardBouncerScope.java b/packages/SystemUI/src/com/android/keyguard/dagger/KeyguardBouncerScope.java
index 8dbe5e00ab7e..d59f51ffe030 100644
--- a/packages/SystemUI/src/com/android/keyguard/dagger/KeyguardBouncerScope.java
+++ b/packages/SystemUI/src/com/android/keyguard/dagger/KeyguardBouncerScope.java
@@ -24,7 +24,7 @@ import java.lang.annotation.Retention;
import javax.inject.Scope;
/**
- * Scope annotation for singleton items within the CentralSurfacesComponent.
+ * Scope annotation for singleton items within the {@link KeyguardBouncerComponent}.
*/
@Documented
@Retention(RUNTIME)
diff --git a/packages/SystemUI/src/com/android/keyguard/dagger/KeyguardStatusBarViewScope.java b/packages/SystemUI/src/com/android/keyguard/dagger/KeyguardStatusBarViewScope.java
index f498ef3466ef..394d63171b39 100644
--- a/packages/SystemUI/src/com/android/keyguard/dagger/KeyguardStatusBarViewScope.java
+++ b/packages/SystemUI/src/com/android/keyguard/dagger/KeyguardStatusBarViewScope.java
@@ -24,7 +24,7 @@ import java.lang.annotation.Retention;
import javax.inject.Scope;
/**
- * Scope annotation for singleton items within the CentralSurfacesComponent.
+ * Scope annotation for singleton items within the {@link KeyguardStatusBarViewComponent}.
*/
@Documented
@Retention(RUNTIME)
diff --git a/packages/SystemUI/src/com/android/keyguard/dagger/KeyguardStatusViewScope.java b/packages/SystemUI/src/com/android/keyguard/dagger/KeyguardStatusViewScope.java
index aeae8e3d4b27..6c2c9f2d8e2f 100644
--- a/packages/SystemUI/src/com/android/keyguard/dagger/KeyguardStatusViewScope.java
+++ b/packages/SystemUI/src/com/android/keyguard/dagger/KeyguardStatusViewScope.java
@@ -24,7 +24,7 @@ import java.lang.annotation.Retention;
import javax.inject.Scope;
/**
- * Scope annotation for singleton items within the CentralSurfacesComponent.
+ * Scope annotation for singleton items within the {@link KeyguardStatusViewComponent}.
*/
@Documented
@Retention(RUNTIME)
diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/MenuView.java b/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/MenuView.java
index f29077d00439..e1612b071458 100644
--- a/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/MenuView.java
+++ b/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/MenuView.java
@@ -38,7 +38,7 @@ import androidx.recyclerview.widget.RecyclerView;
import androidx.recyclerview.widget.RecyclerViewAccessibilityDelegate;
import com.android.internal.accessibility.dialog.AccessibilityTarget;
-import com.android.systemui.aconfig.Flags;
+import com.android.systemui.Flags;
import java.util.ArrayList;
import java.util.Collections;
diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/MenuViewAppearance.java b/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/MenuViewAppearance.java
index 3822936d5d8e..df2c05d9f53c 100644
--- a/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/MenuViewAppearance.java
+++ b/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/MenuViewAppearance.java
@@ -34,8 +34,8 @@ import android.view.WindowMetrics;
import androidx.annotation.DimenRes;
+import com.android.systemui.Flags;
import com.android.systemui.R;
-import com.android.systemui.aconfig.Flags;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/MenuViewLayerController.java b/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/MenuViewLayerController.java
index cc18c305a112..1f549525256b 100644
--- a/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/MenuViewLayerController.java
+++ b/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/MenuViewLayerController.java
@@ -24,7 +24,7 @@ import android.view.WindowInsets;
import android.view.WindowManager;
import android.view.accessibility.AccessibilityManager;
-import com.android.systemui.aconfig.Flags;
+import com.android.systemui.Flags;
import com.android.systemui.util.settings.SecureSettings;
/**
diff --git a/packages/SystemUI/src/com/android/systemui/aconfig/AConfigModule.kt b/packages/SystemUI/src/com/android/systemui/aconfig/AConfigModule.kt
index 251a699be38c..fa61bba6922d 100644
--- a/packages/SystemUI/src/com/android/systemui/aconfig/AConfigModule.kt
+++ b/packages/SystemUI/src/com/android/systemui/aconfig/AConfigModule.kt
@@ -16,6 +16,8 @@
package com.android.systemui.aconfig
+import com.android.systemui.FeatureFlags
+import com.android.systemui.FeatureFlagsImpl
import com.android.systemui.dagger.SysUISingleton
import dagger.Module
import dagger.Provides
diff --git a/packages/SystemUI/src/com/android/systemui/appops/AppOpsControllerImpl.java b/packages/SystemUI/src/com/android/systemui/appops/AppOpsControllerImpl.java
index eec16e6dc301..c9801d77fa43 100644
--- a/packages/SystemUI/src/com/android/systemui/appops/AppOpsControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/appops/AppOpsControllerImpl.java
@@ -52,6 +52,7 @@ import com.android.systemui.util.time.SystemClock;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;
+import java.util.Map;
import java.util.Set;
import javax.inject.Inject;
@@ -184,6 +185,10 @@ public class AppOpsControllerImpl extends BroadcastReceiver implements AppOpsCon
protected void setListening(boolean listening) {
mListening = listening;
if (listening) {
+ // System UI could be restarted while ops are active, so fetch the currently active ops
+ // once System UI starts listening again.
+ fetchCurrentActiveOps();
+
mAppOps.startWatchingActive(OPS, this);
mAppOps.startWatchingNoted(OPS, this);
mAudioManager.registerAudioRecordingCallback(mAudioRecordingCallback, mBGHandler);
@@ -216,6 +221,29 @@ public class AppOpsControllerImpl extends BroadcastReceiver implements AppOpsCon
}
}
+ private void fetchCurrentActiveOps() {
+ List<AppOpsManager.PackageOps> packageOps = mAppOps.getPackagesForOps(OPS);
+ for (AppOpsManager.PackageOps op : packageOps) {
+ for (AppOpsManager.OpEntry entry : op.getOps()) {
+ for (Map.Entry<String, AppOpsManager.AttributedOpEntry> attributedOpEntry :
+ entry.getAttributedOpEntries().entrySet()) {
+ if (attributedOpEntry.getValue().isRunning()) {
+ onOpActiveChanged(
+ entry.getOpStr(),
+ op.getUid(),
+ op.getPackageName(),
+ /* attributionTag= */ attributedOpEntry.getKey(),
+ /* active= */ true,
+ // AppOpsManager doesn't have a way to fetch attribution flags or
+ // chain ID given an op entry, so default them to none.
+ AppOpsManager.ATTRIBUTION_FLAGS_NONE,
+ AppOpsManager.ATTRIBUTION_CHAIN_ID_NONE);
+ }
+ }
+ }
+ }
+ }
+
/**
* Adds a callback that will get notifified when an AppOp of the type the controller tracks
* changes
diff --git a/packages/SystemUI/src/com/android/systemui/assist/AssistManager.java b/packages/SystemUI/src/com/android/systemui/assist/AssistManager.java
index 165bb6c6f68c..f26404cad02b 100644
--- a/packages/SystemUI/src/com/android/systemui/assist/AssistManager.java
+++ b/packages/SystemUI/src/com/android/systemui/assist/AssistManager.java
@@ -154,12 +154,12 @@ public class AssistManager {
new IVisualQueryDetectionAttentionListener.Stub() {
@Override
public void onAttentionGained() {
- mVisualQueryAttentionListeners.forEach(VisualQueryAttentionListener::onAttentionGained);
+ handleVisualAttentionChanged(true);
}
@Override
public void onAttentionLost() {
- mVisualQueryAttentionListeners.forEach(VisualQueryAttentionListener::onAttentionLost);
+ handleVisualAttentionChanged(false);
}
};
@@ -433,11 +433,21 @@ public class AssistManager {
@Override
public void onStopPerceiving() {
+ // Treat this as a signal that attention has been lost (and inform listeners
+ // accordingly).
+ handleVisualAttentionChanged(false);
mAssistUtils.disableVisualQueryDetection();
}
});
}
+ private void handleVisualAttentionChanged(boolean attentionGained) {
+ mVisualQueryAttentionListeners.forEach(
+ attentionGained
+ ? VisualQueryAttentionListener::onAttentionGained
+ : VisualQueryAttentionListener::onAttentionLost);
+ }
+
public void launchVoiceAssistFromKeyguard() {
mAssistUtils.launchVoiceAssistFromKeyguard();
}
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/SideFpsController.kt b/packages/SystemUI/src/com/android/systemui/biometrics/SideFpsController.kt
index 0d7d9cc9c9e5..017ac6019b65 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/SideFpsController.kt
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/SideFpsController.kt
@@ -446,7 +446,9 @@ private fun LottieAnimationView.addOverlayDynamicColor(
for (key in listOf(".blue600", ".blue400")) {
addValueCallback(KeyPath(key, "**"), LottieProperty.COLOR_FILTER) {
PorterDuffColorFilter(
- context.getColor(com.android.settingslib.R.color.settingslib_color_blue400),
+ context.getColor(
+ com.android.settingslib.color.R.color.settingslib_color_blue400
+ ),
PorterDuff.Mode.SRC_ATOP
)
}
diff --git a/packages/SystemUI/src/com/android/systemui/bouncer/domain/interactor/BouncerInteractor.kt b/packages/SystemUI/src/com/android/systemui/bouncer/domain/interactor/BouncerInteractor.kt
index fc32f4c138d7..9527f327a837 100644
--- a/packages/SystemUI/src/com/android/systemui/bouncer/domain/interactor/BouncerInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/bouncer/domain/interactor/BouncerInteractor.kt
@@ -26,9 +26,8 @@ import com.android.systemui.classifier.FalsingClassifier
import com.android.systemui.classifier.domain.interactor.FalsingInteractor
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Application
-import com.android.systemui.flags.FeatureFlags
-import com.android.systemui.flags.Flags
import com.android.systemui.scene.domain.interactor.SceneInteractor
+import com.android.systemui.scene.shared.flag.SceneContainerFlags
import com.android.systemui.scene.shared.model.SceneKey
import com.android.systemui.scene.shared.model.SceneModel
import com.android.systemui.util.kotlin.pairwise
@@ -51,7 +50,7 @@ constructor(
private val repository: BouncerRepository,
private val authenticationInteractor: AuthenticationInteractor,
private val sceneInteractor: SceneInteractor,
- featureFlags: FeatureFlags,
+ flags: SceneContainerFlags,
private val falsingInteractor: FalsingInteractor,
) {
@@ -94,7 +93,7 @@ constructor(
val isPatternVisible: StateFlow<Boolean> = authenticationInteractor.isPatternVisible
init {
- if (featureFlags.isEnabled(Flags.SCENE_CONTAINER)) {
+ if (flags.isEnabled()) {
// Clear the message if moved from throttling to no-longer throttling.
applicationScope.launch {
isThrottled.pairwise().collect { (wasThrottled, currentlyThrottled) ->
diff --git a/packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/BouncerViewModel.kt b/packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/BouncerViewModel.kt
index 5b1998d1e5f6..f6794d4f40b3 100644
--- a/packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/BouncerViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/BouncerViewModel.kt
@@ -23,8 +23,7 @@ import com.android.systemui.authentication.domain.model.AuthenticationMethodMode
import com.android.systemui.bouncer.domain.interactor.BouncerInteractor
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Application
-import com.android.systemui.flags.FeatureFlags
-import com.android.systemui.flags.Flags
+import com.android.systemui.scene.shared.flag.SceneContainerFlags
import javax.inject.Inject
import kotlin.math.ceil
import kotlinx.coroutines.CoroutineScope
@@ -47,7 +46,7 @@ constructor(
@Application private val applicationScope: CoroutineScope,
private val bouncerInteractor: BouncerInteractor,
private val authenticationInteractor: AuthenticationInteractor,
- featureFlags: FeatureFlags,
+ flags: SceneContainerFlags,
) {
private val isInputEnabled: StateFlow<Boolean> =
bouncerInteractor.isThrottled
@@ -102,7 +101,7 @@ constructor(
)
init {
- if (featureFlags.isEnabled(Flags.SCENE_CONTAINER)) {
+ if (flags.isEnabled()) {
applicationScope.launch {
bouncerInteractor.isThrottled
.map { isThrottled ->
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/FalsingModule.java b/packages/SystemUI/src/com/android/systemui/classifier/FalsingModule.java
index 3195d093a711..0a1aed65c205 100644
--- a/packages/SystemUI/src/com/android/systemui/classifier/FalsingModule.java
+++ b/packages/SystemUI/src/com/android/systemui/classifier/FalsingModule.java
@@ -22,8 +22,7 @@ import android.view.ViewConfiguration;
import com.android.systemui.R;
import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.dagger.qualifiers.Main;
-import com.android.systemui.flags.FeatureFlagsClassic;
-import com.android.systemui.flags.Flags;
+import com.android.systemui.scene.shared.flag.SceneContainerFlags;
import com.android.systemui.statusbar.phone.NotificationTapHelper;
import dagger.Binds;
@@ -53,8 +52,8 @@ public interface FalsingModule {
static FalsingCollector providesFalsingCollectorLegacy(
FalsingCollectorImpl impl,
FalsingCollectorNoOp noOp,
- FeatureFlagsClassic featureFlags) {
- return featureFlags.isEnabled(Flags.SCENE_CONTAINER) ? noOp : impl;
+ SceneContainerFlags flags) {
+ return flags.isEnabled() ? noOp : impl;
}
/** Provides the actual {@link FalsingCollector}. */
diff --git a/packages/SystemUI/src/com/android/systemui/communal/ui/view/layout/blueprints/DefaultCommunalBlueprint.kt b/packages/SystemUI/src/com/android/systemui/communal/ui/view/layout/blueprints/DefaultCommunalBlueprint.kt
index 970b475fe702..3ff1f09cc0f1 100644
--- a/packages/SystemUI/src/com/android/systemui/communal/ui/view/layout/blueprints/DefaultCommunalBlueprint.kt
+++ b/packages/SystemUI/src/com/android/systemui/communal/ui/view/layout/blueprints/DefaultCommunalBlueprint.kt
@@ -31,7 +31,7 @@ constructor(
defaultCommunalWidgetSection: DefaultCommunalWidgetSection,
) : KeyguardBlueprint {
override val id: String = COMMUNAL
- override val sections: Array<KeyguardSection> = arrayOf(defaultCommunalWidgetSection)
+ override val sections: Set<KeyguardSection> = setOf(defaultCommunalWidgetSection)
companion object {
const val COMMUNAL = "communal"
diff --git a/packages/SystemUI/src/com/android/systemui/communal/ui/view/layout/sections/DefaultCommunalWidgetSection.kt b/packages/SystemUI/src/com/android/systemui/communal/ui/view/layout/sections/DefaultCommunalWidgetSection.kt
index 4fb9384630a5..8640c97bb1e1 100644
--- a/packages/SystemUI/src/com/android/systemui/communal/ui/view/layout/sections/DefaultCommunalWidgetSection.kt
+++ b/packages/SystemUI/src/com/android/systemui/communal/ui/view/layout/sections/DefaultCommunalWidgetSection.kt
@@ -42,9 +42,12 @@ constructor(
private val communalWidgetViewModel: CommunalWidgetViewModel,
private val communalWidgetViewAdapter: CommunalWidgetViewAdapter,
private val keyguardBlueprintInteractor: Lazy<KeyguardBlueprintInteractor>,
-) : KeyguardSection {
+) : KeyguardSection() {
private val widgetAreaViewId = R.id.communal_widget_wrapper
- override fun addViews(constraintLayout: ConstraintLayout) {
+
+ override fun addViews(constraintLayout: ConstraintLayout) {}
+
+ override fun bindData(constraintLayout: ConstraintLayout) {
if (!featureFlags.isEnabled(Flags.WIDGET_ON_KEYGUARD)) {
return
}
@@ -65,4 +68,6 @@ constructor(
connect(widgetAreaViewId, END, PARENT_ID, END)
}
}
+
+ override fun removeViews(constraintLayout: ConstraintLayout) {}
}
diff --git a/packages/SystemUI/src/com/android/systemui/controls/dagger/ControlsComponent.kt b/packages/SystemUI/src/com/android/systemui/controls/dagger/ControlsComponent.kt
index 94e563319524..88b9612e8efd 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/dagger/ControlsComponent.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/dagger/ControlsComponent.kt
@@ -16,7 +16,6 @@
package com.android.systemui.controls.dagger
-import android.content.Context
import com.android.internal.widget.LockPatternUtils
import com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_BOOT
import com.android.systemui.controls.controller.ControlsController
@@ -44,10 +43,9 @@ class ControlsComponent
@Inject
constructor(
@ControlsFeatureEnabled private val featureEnabled: Boolean,
- private val context: Context,
- private val lazyControlsController: Lazy<ControlsController>,
- private val lazyControlsUiController: Lazy<ControlsUiController>,
- private val lazyControlsListingController: Lazy<ControlsListingController>,
+ lazyControlsController: Lazy<ControlsController>,
+ lazyControlsUiController: Lazy<ControlsUiController>,
+ lazyControlsListingController: Lazy<ControlsListingController>,
private val lockPatternUtils: LockPatternUtils,
private val keyguardStateController: KeyguardStateController,
private val userTracker: UserTracker,
@@ -55,27 +53,25 @@ constructor(
optionalControlsTileResourceConfiguration: Optional<ControlsTileResourceConfiguration>
) {
+ private val controlsController: Optional<ControlsController> =
+ optionalIf(isEnabled(), lazyControlsController)
+ private val controlsUiController: Optional<ControlsUiController> =
+ optionalIf(isEnabled(), lazyControlsUiController)
+ private val controlsListingController: Optional<ControlsListingController> =
+ optionalIf(isEnabled(), lazyControlsListingController)
+
val canShowWhileLockedSetting: StateFlow<Boolean> =
controlsSettingsRepository.canShowControlsInLockscreen
private val controlsTileResourceConfiguration: ControlsTileResourceConfiguration =
optionalControlsTileResourceConfiguration.orElse(ControlsTileResourceConfigurationImpl())
- fun getControlsController(): Optional<ControlsController> {
- return if (featureEnabled) Optional.of(lazyControlsController.get()) else Optional.empty()
- }
+ fun getControlsController(): Optional<ControlsController> = controlsController
- fun getControlsUiController(): Optional<ControlsUiController> {
- return if (featureEnabled) Optional.of(lazyControlsUiController.get()) else Optional.empty()
- }
+ fun getControlsUiController(): Optional<ControlsUiController> = controlsUiController
- fun getControlsListingController(): Optional<ControlsListingController> {
- return if (featureEnabled) {
- Optional.of(lazyControlsListingController.get())
- } else {
- Optional.empty()
- }
- }
+ fun getControlsListingController(): Optional<ControlsListingController> =
+ controlsListingController
/** @return true if controls are feature-enabled and the user has the setting enabled */
fun isEnabled() = featureEnabled
@@ -118,4 +114,11 @@ constructor(
fun getTileImageId(): Int {
return controlsTileResourceConfiguration.getTileImageId()
}
+
+ private fun <T : Any> optionalIf(condition: Boolean, provider: Lazy<T>): Optional<T> =
+ if (condition) {
+ Optional.of(provider.get())
+ } else {
+ Optional.empty()
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/controls/ui/ThumbnailBehavior.kt b/packages/SystemUI/src/com/android/systemui/controls/ui/ThumbnailBehavior.kt
index 0b57e792f9f7..d011dd421f7f 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/ui/ThumbnailBehavior.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/ui/ThumbnailBehavior.kt
@@ -22,6 +22,7 @@ import android.graphics.drawable.ClipDrawable
import android.graphics.drawable.LayerDrawable
import android.view.View
import android.service.controls.Control
+import android.service.controls.templates.TemperatureControlTemplate
import android.service.controls.templates.ThumbnailTemplate
import android.util.TypedValue
@@ -68,7 +69,9 @@ class ThumbnailBehavior(currentUserId: Int) : Behavior {
override fun bind(cws: ControlWithState, colorOffset: Int) {
this.control = cws.control!!
cvh.setStatusText(control.getStatusText())
- template = control.getControlTemplate() as ThumbnailTemplate
+ template = control.controlTemplate as? ThumbnailTemplate
+ ?: (control.controlTemplate as TemperatureControlTemplate).template
+ as ThumbnailTemplate
val ld = cvh.layout.getBackground() as LayerDrawable
val clipLayer = ld.findDrawableByLayerId(R.id.clip_layer) as ClipDrawable
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/ReferenceSystemUIModule.java b/packages/SystemUI/src/com/android/systemui/dagger/ReferenceSystemUIModule.java
index 35624770b712..7b58b1fe3014 100644
--- a/packages/SystemUI/src/com/android/systemui/dagger/ReferenceSystemUIModule.java
+++ b/packages/SystemUI/src/com/android/systemui/dagger/ReferenceSystemUIModule.java
@@ -40,6 +40,7 @@ import com.android.systemui.qs.tileimpl.QSFactoryImpl;
import com.android.systemui.recents.Recents;
import com.android.systemui.recents.RecentsImplementation;
import com.android.systemui.rotationlock.RotationLockModule;
+import com.android.systemui.scene.SceneContainerFrameworkModule;
import com.android.systemui.screenshot.ReferenceScreenshotModule;
import com.android.systemui.settings.dagger.MultiUserUtilsModule;
import com.android.systemui.shade.NotificationShadeWindowControllerImpl;
@@ -57,6 +58,7 @@ import com.android.systemui.statusbar.phone.DozeServiceHost;
import com.android.systemui.statusbar.phone.HeadsUpManagerPhone;
import com.android.systemui.statusbar.phone.KeyguardBypassController;
import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager;
+import com.android.systemui.statusbar.phone.fragment.CollapsedStatusBarFragmentStartableModule;
import com.android.systemui.statusbar.policy.AccessibilityManagerWrapper;
import com.android.systemui.statusbar.policy.AospPolicyModule;
import com.android.systemui.statusbar.policy.ConfigurationController;
@@ -95,6 +97,7 @@ import javax.inject.Named;
@Module(includes = {
AospPolicyModule.class,
BatterySaverModule.class,
+ CollapsedStatusBarFragmentStartableModule.class,
GestureModule.class,
MediaModule.class,
MultiUserUtilsModule.class,
@@ -102,6 +105,7 @@ import javax.inject.Named;
QSModule.class,
ReferenceScreenshotModule.class,
RotationLockModule.class,
+ SceneContainerFrameworkModule.class,
StatusBarEventsModule.class,
StartCentralSurfacesModule.class,
VolumeModule.class,
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java
index ade768486f08..7ee0ff4568be 100644
--- a/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java
+++ b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java
@@ -76,7 +76,6 @@ import com.android.systemui.qs.QSFragmentStartableModule;
import com.android.systemui.qs.footer.dagger.FooterActionsModule;
import com.android.systemui.recents.Recents;
import com.android.systemui.retail.dagger.RetailModeModule;
-import com.android.systemui.scene.SceneContainerFrameworkModule;
import com.android.systemui.scene.ui.view.WindowRootViewComponent;
import com.android.systemui.screenrecord.ScreenRecordModule;
import com.android.systemui.screenshot.dagger.ScreenshotModule;
@@ -109,7 +108,6 @@ import com.android.systemui.statusbar.notification.row.dagger.NotificationShelfC
import com.android.systemui.statusbar.phone.CentralSurfaces;
import com.android.systemui.statusbar.phone.LetterboxModule;
import com.android.systemui.statusbar.phone.NotificationIconAreaControllerModule;
-import com.android.systemui.statusbar.phone.dagger.CentralSurfacesComponent;
import com.android.systemui.statusbar.pipeline.dagger.StatusBarPipelineModule;
import com.android.systemui.statusbar.policy.HeadsUpManager;
import com.android.systemui.statusbar.policy.KeyguardStateController;
@@ -126,7 +124,6 @@ import com.android.systemui.user.UserModule;
import com.android.systemui.util.concurrency.SysUIConcurrencyModule;
import com.android.systemui.util.dagger.UtilModule;
import com.android.systemui.util.kotlin.CoroutinesModule;
-import com.android.systemui.util.leak.GarbageMonitorModule;
import com.android.systemui.util.sensors.SensorModule;
import com.android.systemui.util.settings.SettingsUtilModule;
import com.android.systemui.util.time.SystemClock;
@@ -179,7 +176,6 @@ import javax.inject.Named;
FlagsModule.class,
SystemPropertiesFlagsModule.class,
FooterActionsModule.class,
- GarbageMonitorModule.class,
KeyboardModule.class,
LetterboxModule.class,
KeyguardBlueprintModule.class,
@@ -196,7 +192,6 @@ import javax.inject.Named;
QRCodeScannerModule.class,
QSFragmentStartableModule.class,
RetailModeModule.class,
- SceneContainerFrameworkModule.class,
ScreenshotModule.class,
SensorModule.class,
SecurityRepositoryModule.class,
@@ -219,7 +214,6 @@ import javax.inject.Named;
WalletModule.class
},
subcomponents = {
- CentralSurfacesComponent.class,
ComplicationComponent.class,
NavigationBarComponent.class,
NotificationRowComponent.class,
diff --git a/packages/SystemUI/src/com/android/systemui/display/data/repository/DisplayRepository.kt b/packages/SystemUI/src/com/android/systemui/display/data/repository/DisplayRepository.kt
index e7bbf97e3b51..82b032450938 100644
--- a/packages/SystemUI/src/com/android/systemui/display/data/repository/DisplayRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/display/data/repository/DisplayRepository.kt
@@ -22,21 +22,28 @@ import android.hardware.display.DisplayManager.EVENT_FLAG_DISPLAY_ADDED
import android.hardware.display.DisplayManager.EVENT_FLAG_DISPLAY_CHANGED
import android.hardware.display.DisplayManager.EVENT_FLAG_DISPLAY_REMOVED
import android.os.Handler
+import android.os.Trace
import android.util.Log
import android.view.Display
import com.android.systemui.common.coroutine.ConflatedCallbackFlow.conflatedCallbackFlow
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Application
import com.android.systemui.dagger.qualifiers.Background
+import com.android.systemui.util.Compile
import com.android.systemui.util.traceSection
import javax.inject.Inject
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.channels.awaitClose
import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.SharingStarted
+import kotlinx.coroutines.flow.StateFlow
+import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.flowOn
+import kotlinx.coroutines.flow.map
+import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.flow.stateIn
/** Provides a [Flow] of [Display] as returned by [DisplayManager]. */
@@ -49,7 +56,25 @@ interface DisplayRepository {
*
* When `null`, it means there is no pending display waiting to be enabled.
*/
- val pendingDisplayId: Flow<Int?>
+ val pendingDisplay: Flow<PendingDisplay?>
+
+ /** Represents a connected display that has not been enabled yet. */
+ interface PendingDisplay {
+ /** Id of the pending display. */
+ val id: Int
+
+ /** Enables the display, making it available to the system. */
+ suspend fun enable()
+
+ /**
+ * Ignores the pending display. When called, this specific display id doesn't appear as
+ * pending anymore until the display is disconnected and reconnected again.
+ */
+ suspend fun ignore()
+
+ /** Disables the display, making it unavailable to the system. */
+ suspend fun disable()
+ }
}
@SysUISingleton
@@ -62,7 +87,8 @@ constructor(
@Background backgroundCoroutineDispatcher: CoroutineDispatcher
) : DisplayRepository {
- override val displays: Flow<Set<Display>> =
+ // Displays are enabled only after receiving them in [onDisplayAdded]
+ private val enabledDisplays: StateFlow<Set<Display>> =
conflatedCallbackFlow {
val callback =
object : DisplayListener {
@@ -99,27 +125,38 @@ constructor(
displayManager.displays?.toSet() ?: emptySet()
}
- override val pendingDisplayId: Flow<Int?> =
+ /** Propagate to the listeners only enabled displays */
+ override val displays: Flow<Set<Display>> = enabledDisplays
+
+ private val enabledDisplayIds: Flow<Set<Int>> =
+ enabledDisplays
+ .map { enabledDisplaysSet -> enabledDisplaysSet.map { it.displayId }.toSet() }
+ .debugLog("enabledDisplayIds")
+
+ private val ignoredDisplayIds = MutableStateFlow<Set<Int>>(emptySet())
+
+ /* keeps connected displays until they are disconnected. */
+ private val connectedDisplayIds: StateFlow<Set<Int>> =
conflatedCallbackFlow {
val callback =
object : DisplayConnectionListener {
- private val pendingIds = mutableSetOf<Int>()
+ private val connectedIds = mutableSetOf<Int>()
override fun onDisplayConnected(id: Int) {
- pendingIds += id
- trySend(id)
+ if (DEBUG) {
+ Log.d(TAG, "$id connected")
+ }
+ connectedIds += id
+ ignoredDisplayIds.value -= id
+ trySend(connectedIds.toSet())
}
override fun onDisplayDisconnected(id: Int) {
- if (id in pendingIds) {
- pendingIds -= id
- trySend(null)
- } else {
- Log.e(
- TAG,
- "onDisplayDisconnected received for unknown display. " +
- "id=$id, knownIds=$pendingIds"
- )
+ connectedIds -= id
+ if (DEBUG) {
+ Log.d(TAG, "$id disconnected. Connected ids: $connectedIds")
}
+ ignoredDisplayIds.value -= id
+ trySend(connectedIds.toSet())
}
}
displayManager.registerDisplayListener(
@@ -130,15 +167,80 @@ constructor(
awaitClose { displayManager.unregisterDisplayListener(callback) }
}
.distinctUntilChanged()
+ .debugLog("connectedDisplayIds")
.flowOn(backgroundCoroutineDispatcher)
.stateIn(
applicationScope,
started = SharingStarted.WhileSubscribed(),
- initialValue = null
+ initialValue = emptySet()
)
+ /**
+ * Pending displays are the ones connected, but not enabled and not ignored. A connected display
+ * is ignored after the user makes the decision to use it or not. For now, the initial decision
+ * from the user is final and not reversible.
+ */
+ private val pendingDisplayIds: Flow<Set<Int>> =
+ combine(enabledDisplayIds, connectedDisplayIds, ignoredDisplayIds) {
+ enabledDisplaysIds,
+ connectedDisplayIds,
+ ignoredDisplayIds ->
+ if (DEBUG) {
+ Log.d(
+ TAG,
+ "combining enabled: $enabledDisplaysIds, " +
+ "connected: $connectedDisplayIds, ignored: $ignoredDisplayIds"
+ )
+ }
+ connectedDisplayIds - enabledDisplaysIds - ignoredDisplayIds
+ }
+ .debugLog("pendingDisplayIds")
+
+ override val pendingDisplay: Flow<DisplayRepository.PendingDisplay?> =
+ pendingDisplayIds
+ .map { pendingDisplayIds ->
+ val id = pendingDisplayIds.maxOrNull() ?: return@map null
+ object : DisplayRepository.PendingDisplay {
+ override val id = id
+ override suspend fun enable() {
+ traceSection("DisplayRepository#enable($id)") {
+ displayManager.enableConnectedDisplay(id)
+ }
+ // After the display has been enabled, it is automatically ignored.
+ ignore()
+ }
+
+ override suspend fun ignore() {
+ traceSection("DisplayRepository#ignore($id)") {
+ ignoredDisplayIds.value += id
+ }
+ }
+
+ override suspend fun disable() {
+ ignore()
+ traceSection("DisplayRepository#disable($id)") {
+ displayManager.disableConnectedDisplay(id)
+ }
+ }
+ }
+ }
+ .debugLog("pendingDisplay")
+
+ private fun <T> Flow<T>.debugLog(flowName: String): Flow<T> {
+ return if (DEBUG) {
+ this.onEach {
+ Log.d(TAG, "$flowName: $it")
+ Trace.asyncTraceForTrackEnd(Trace.TRACE_TAG_APP, "$TAG#$flowName", 0)
+ Trace.asyncTraceForTrackBegin(Trace.TRACE_TAG_APP, "$TAG#$flowName", "$it", 0)
+ }
+ } else {
+ this
+ }
+ }
+
private companion object {
const val TAG = "DisplayRepository"
+ val DEBUG = Log.isLoggable(TAG, Log.DEBUG) || Compile.IS_DEBUG
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/display/domain/interactor/ConnectedDisplayInteractor.kt b/packages/SystemUI/src/com/android/systemui/display/domain/interactor/ConnectedDisplayInteractor.kt
index ef6fa26420a3..11ed96d5c7eb 100644
--- a/packages/SystemUI/src/com/android/systemui/display/domain/interactor/ConnectedDisplayInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/display/domain/interactor/ConnectedDisplayInteractor.kt
@@ -16,14 +16,12 @@
package com.android.systemui.display.domain.interactor
-import android.hardware.display.DisplayManager
import android.view.Display
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.display.data.repository.DisplayRepository
import com.android.systemui.display.domain.interactor.ConnectedDisplayInteractor.PendingDisplay
import com.android.systemui.display.domain.interactor.ConnectedDisplayInteractor.State
import com.android.systemui.keyguard.data.repository.KeyguardRepository
-import com.android.systemui.util.traceSection
import javax.inject.Inject
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.combine
@@ -52,13 +50,18 @@ interface ConnectedDisplayInteractor {
CONNECTED_SECURE,
}
- /** Represents a connected display that has not been enabled yet. */
+ /** Represents a connected display that has not been enabled yet for the UI layer. */
interface PendingDisplay {
/** Enables the display, making it available to the system. */
- fun enable()
+ suspend fun enable()
- /** Disables the display, making it unavailable to the system. */
- fun disable()
+ /**
+ * Ignores the pending display.
+ *
+ * When called, this specific display id doesn't appear as pending anymore until the display
+ * is disconnected and reconnected again.
+ */
+ suspend fun ignore()
}
}
@@ -66,7 +69,6 @@ interface ConnectedDisplayInteractor {
class ConnectedDisplayInteractorImpl
@Inject
constructor(
- private val displayManager: DisplayManager,
keyguardRepository: KeyguardRepository,
displayRepository: DisplayRepository,
) : ConnectedDisplayInteractor {
@@ -92,28 +94,19 @@ constructor(
// Provides the pending display only if the lockscreen is unlocked
override val pendingDisplay: Flow<PendingDisplay?> =
- displayRepository.pendingDisplayId.combine(keyguardRepository.isKeyguardUnlocked) {
- pendingDisplayId,
- keyguardUnlocked ->
- if (pendingDisplayId != null && keyguardUnlocked) {
- pendingDisplayId.toPendingDisplay()
+ displayRepository.pendingDisplay.combine(keyguardRepository.isKeyguardShowing) {
+ repositoryPendingDisplay,
+ keyguardShowing ->
+ if (repositoryPendingDisplay != null && !keyguardShowing) {
+ repositoryPendingDisplay.toInteractorPendingDisplay()
} else {
null
}
}
- private fun Int.toPendingDisplay() =
+ private fun DisplayRepository.PendingDisplay.toInteractorPendingDisplay(): PendingDisplay =
object : PendingDisplay {
- val id = this@toPendingDisplay
- override fun enable() {
- traceSection("DisplayRepository#enable($id)") {
- displayManager.enableConnectedDisplay(id)
- }
- }
- override fun disable() {
- traceSection("DisplayRepository#enable($id)") {
- displayManager.disableConnectedDisplay(id)
- }
- }
+ override suspend fun enable() = this@toInteractorPendingDisplay.enable()
+ override suspend fun ignore() = this@toInteractorPendingDisplay.ignore()
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/display/ui/view/MirroringConfirmationDialog.kt b/packages/SystemUI/src/com/android/systemui/display/ui/view/MirroringConfirmationDialog.kt
index 174c6ff04a7d..ecc9d0ef7810 100644
--- a/packages/SystemUI/src/com/android/systemui/display/ui/view/MirroringConfirmationDialog.kt
+++ b/packages/SystemUI/src/com/android/systemui/display/ui/view/MirroringConfirmationDialog.kt
@@ -24,15 +24,22 @@ import android.view.WindowManager
import android.widget.TextView
import com.android.systemui.R
-/** Dialog used to decide what to do with a connected display. */
+/**
+ * Dialog used to decide what to do with a connected display.
+ *
+ * [onCancelMirroring] is called **only** if mirroring didn't start, or when the dismiss button is
+ * pressed.
+ */
class MirroringConfirmationDialog(
context: Context,
private val onStartMirroringClickListener: View.OnClickListener,
- private val onDismissClickListener: View.OnClickListener,
+ private val onCancelMirroring: View.OnClickListener,
) : Dialog(context, R.style.Theme_SystemUI_Dialog) {
private lateinit var mirrorButton: TextView
private lateinit var dismissButton: TextView
+ private var enabledPressed = false
+
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
window?.apply {
@@ -45,10 +52,15 @@ class MirroringConfirmationDialog(
mirrorButton =
requireViewById<TextView>(R.id.enable_display).apply {
setOnClickListener(onStartMirroringClickListener)
+ enabledPressed = true
}
dismissButton =
- requireViewById<TextView>(R.id.cancel).apply {
- setOnClickListener(onDismissClickListener)
+ requireViewById<TextView>(R.id.cancel).apply { setOnClickListener(onCancelMirroring) }
+
+ setOnDismissListener {
+ if (!enabledPressed) {
+ onCancelMirroring.onClick(null)
}
+ }
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/display/ui/viewmodel/ConnectingDisplayViewModel.kt b/packages/SystemUI/src/com/android/systemui/display/ui/viewmodel/ConnectingDisplayViewModel.kt
index ece33b7f6032..86ef439361b0 100644
--- a/packages/SystemUI/src/com/android/systemui/display/ui/viewmodel/ConnectingDisplayViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/display/ui/viewmodel/ConnectingDisplayViewModel.kt
@@ -19,13 +19,16 @@ import android.app.Dialog
import android.content.Context
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Application
+import com.android.systemui.dagger.qualifiers.Background
import com.android.systemui.display.domain.interactor.ConnectedDisplayInteractor
import com.android.systemui.display.domain.interactor.ConnectedDisplayInteractor.PendingDisplay
import com.android.systemui.display.ui.view.MirroringConfirmationDialog
import javax.inject.Inject
+import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
+import kotlinx.coroutines.launch
/**
* Shows/hides a dialog to allow the user to decide whether to use the external display for
@@ -38,6 +41,7 @@ constructor(
private val context: Context,
private val connectedDisplayInteractor: ConnectedDisplayInteractor,
@Application private val scope: CoroutineScope,
+ @Background private val bgDispatcher: CoroutineDispatcher
) {
private var dialog: Dialog? = null
@@ -61,10 +65,13 @@ constructor(
MirroringConfirmationDialog(
context,
onStartMirroringClickListener = {
- pendingDisplay.enable()
+ scope.launch(bgDispatcher) { pendingDisplay.enable() }
hideDialog()
},
- onDismissClickListener = { hideDialog() }
+ onCancelMirroring = {
+ scope.launch(bgDispatcher) { pendingDisplay.ignore() }
+ hideDialog()
+ }
)
.apply { show() }
}
diff --git a/packages/SystemUI/src/com/android/systemui/flags/Flags.kt b/packages/SystemUI/src/com/android/systemui/flags/Flags.kt
index 907e106d1151..2301e8602d18 100644
--- a/packages/SystemUI/src/com/android/systemui/flags/Flags.kt
+++ b/packages/SystemUI/src/com/android/systemui/flags/Flags.kt
@@ -43,6 +43,10 @@ object Flags {
val ADD_TRANSIENT_HUN_IN_STACK_STATE_ANIMATOR =
unreleasedFlag("add_transient_hun_in_stack_state_animator", teamfood = false)
+ // TODO(b/298308067): Tracking Bug
+ val SWIPE_UNCLEARED_TRANSIENT_VIEW_FIX =
+ unreleasedFlag("swipe_uncleared_transient_view_fix", teamfood = false)
+
// TODO(b/254512751): Tracking Bug
val NOTIFICATION_PIPELINE_DEVELOPER_LOGGING =
unreleasedFlag("notification_pipeline_developer_logging")
@@ -111,7 +115,7 @@ object Flags {
val BUILDER_EXTRAS_OVERRIDE =
sysPropBooleanFlag(
"persist.sysui.notification.builder_extras_override",
- default = true
+ default = false
)
/** Only notify group expansion listeners when a change happens. */
@@ -210,7 +214,8 @@ object Flags {
/** Inflate and bind views upon emitting a blueprint value . */
// TODO(b/297365780): Tracking Bug
- @JvmField val LAZY_INFLATE_KEYGUARD = unreleasedFlag("lazy_inflate_keyguard")
+ @JvmField
+ val LAZY_INFLATE_KEYGUARD = unreleasedFlag("lazy_inflate_keyguard", teamfood = true)
/** Enables UI updates for AI wallpapers in the wallpaper picker. */
// TODO(b/267722622): Tracking Bug
@@ -500,11 +505,6 @@ object Flags {
@Keep
@JvmField
- val WM_DESKTOP_WINDOWING =
- sysPropBooleanFlag("persist.wm.debug.desktop_mode", default = false)
-
- @Keep
- @JvmField
val WM_CAPTION_ON_SHELL =
sysPropBooleanFlag("persist.wm.debug.caption_on_shell", default = true)
@@ -636,8 +636,29 @@ object Flags {
val CLIPBOARD_SHARED_TRANSITIONS =
unreleasedFlag("clipboard_shared_transitions", teamfood = true)
+ /**
+ * Whether the scene container (Flexiglass) is enabled. Note that [SCENE_CONTAINER] should be
+ * checked and toggled together with [SCENE_CONTAINER_ENABLED] so that ProGuard can remove
+ * unused code from our APK at compile time.
+ */
// TODO(b/283300105): Tracking Bug
- @JvmField val SCENE_CONTAINER = unreleasedFlag("scene_container")
+ @JvmField val SCENE_CONTAINER_ENABLED = false
+ @Deprecated(
+ message = """
+ Do not use this flag directly. Please use
+ [com.android.systemui.scene.shared.flag.SceneContainerFlags#isEnabled].
+
+ (Not really deprecated but using this as a simple way to bring attention to the above).
+ """,
+ replaceWith = ReplaceWith(
+ "com.android.systemui.scene.shared.flag.SceneContainerFlags#isEnabled",
+ ),
+ level = DeprecationLevel.WARNING,
+ )
+ @JvmField val SCENE_CONTAINER = resourceBooleanFlag(
+ R.bool.config_sceneContainerFrameworkEnabled,
+ "scene_container",
+ )
// 1900
@JvmField val NOTE_TASKS = releasedFlag("keycode_flag")
@@ -674,6 +695,10 @@ object Flags {
// TODO:(b/283203305): Tracking bug
@JvmField val TRIM_FONT_CACHES_AT_UNLOCK = unreleasedFlag("trim_font_caches_on_unlock")
+ // TODO(b/298380520): Tracking Bug
+ @JvmField
+ val USER_TRACKER_BACKGROUND_CALLBACKS = unreleasedFlag("user_tracker_background_callbacks")
+
// 2700 - unfold transitions
// TODO(b/265764985): Tracking Bug
@Keep
@@ -698,7 +723,7 @@ object Flags {
@JvmField val KEYBOARD_BACKLIGHT_INDICATOR = releasedFlag("keyboard_backlight_indicator")
// TODO(b/277192623): Tracking Bug
- @JvmField val KEYBOARD_EDUCATION = unreleasedFlag("keyboard_education", teamfood = false)
+ @JvmField val KEYBOARD_EDUCATION = unreleasedFlag("keyboard_education", teamfood = true)
// TODO(b/277201412): Tracking Bug
@JvmField
@@ -764,15 +789,15 @@ object Flags {
/** Enable the Compose implementation of the PeopleSpaceActivity. */
@JvmField
- val COMPOSE_PEOPLE_SPACE = unreleasedFlag("compose_people_space")
+ val COMPOSE_PEOPLE_SPACE = unreleasedFlag("compose_people_space", teamfood = true)
/** Enable the Compose implementation of the Quick Settings footer actions. */
@JvmField
- val COMPOSE_QS_FOOTER_ACTIONS = unreleasedFlag("compose_qs_footer_actions")
+ val COMPOSE_QS_FOOTER_ACTIONS = unreleasedFlag("compose_qs_footer_actions", teamfood = true)
/** Enable the share wifi button in Quick Settings internet dialog. */
@JvmField
- val SHARE_WIFI_QS_BUTTON = unreleasedFlag("share_wifi_qs_button")
+ val SHARE_WIFI_QS_BUTTON = unreleasedFlag("share_wifi_qs_button", teamfood = true)
/** Enable haptic slider component in the brightness slider */
@JvmField
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewConfigurator.kt b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewConfigurator.kt
index 6bc9abf13cf7..257006e13201 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewConfigurator.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewConfigurator.kt
@@ -126,11 +126,11 @@ constructor(
}
override fun start() {
+ bindKeyguardRootView()
if (featureFlags.isEnabled(Flags.LAZY_INFLATE_KEYGUARD)) {
keyguardRootView.removeAllViews()
initializeViews()
} else {
- bindKeyguardRootView()
val notificationPanel =
notificationShadeWindowView.requireViewById(R.id.notification_panel) as ViewGroup
unbindKeyguardBottomArea(notificationPanel)
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractor.kt
index 0c05a0e33871..572785721b4f 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractor.kt
@@ -15,6 +15,8 @@
*
*/
+@file:OptIn(ExperimentalCoroutinesApi::class)
+
package com.android.systemui.keyguard.domain.interactor
import android.app.StatusBarManager
@@ -42,10 +44,15 @@ import com.android.systemui.keyguard.shared.model.KeyguardState
import com.android.systemui.keyguard.shared.model.ScreenModel
import com.android.systemui.keyguard.shared.model.StatusBarState
import com.android.systemui.keyguard.shared.model.WakefulnessModel
+import com.android.systemui.scene.domain.interactor.SceneInteractor
+import com.android.systemui.scene.shared.flag.SceneContainerFlags
+import com.android.systemui.scene.shared.model.SceneKey
import com.android.systemui.shade.data.repository.ShadeRepository
import com.android.systemui.statusbar.CommandQueue
import com.android.systemui.util.kotlin.sample
import javax.inject.Inject
+import javax.inject.Provider
+import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.channels.awaitClose
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.Flow
@@ -71,9 +78,11 @@ constructor(
private val repository: KeyguardRepository,
private val commandQueue: CommandQueue,
featureFlags: FeatureFlags,
+ sceneContainerFlags: SceneContainerFlags,
bouncerRepository: KeyguardBouncerRepository,
configurationRepository: ConfigurationRepository,
shadeRepository: ShadeRepository,
+ sceneInteractorProvider: Provider<SceneInteractor>,
) {
/** Position information for the shared notification container. */
val sharedNotificationContainerPosition =
@@ -187,7 +196,7 @@ constructor(
combine(isKeyguardShowing, isKeyguardOccluded) { showing, occluded -> showing && !occluded }
/** Whether camera is launched over keyguard. */
- var isSecureCameraActive =
+ val isSecureCameraActive: Flow<Boolean> by lazy {
if (featureFlags.isEnabled(Flags.FACE_AUTH_REFACTOR)) {
combine(
isKeyguardVisible,
@@ -204,6 +213,7 @@ constructor(
} else {
flowOf(false)
}
+ }
/** The approximate location on the screen of the fingerprint sensor, if one is available. */
val fingerprintSensorLocation: Flow<Point?> = repository.fingerprintSensorLocation
@@ -240,11 +250,29 @@ constructor(
}
/** Whether to animate the next doze mode transition. */
- val animateDozingTransitions: Flow<Boolean> = repository.animateBottomAreaDozingTransitions
+ val animateDozingTransitions: Flow<Boolean> by lazy {
+ if (sceneContainerFlags.isEnabled()) {
+ sceneInteractorProvider
+ .get()
+ .transitioningTo
+ .map { it == SceneKey.Lockscreen }
+ .distinctUntilChanged()
+ .flatMapLatest { isTransitioningToLockscreenScene ->
+ if (isTransitioningToLockscreenScene) {
+ flowOf(false)
+ } else {
+ repository.animateBottomAreaDozingTransitions
+ }
+ }
+ } else {
+ repository.animateBottomAreaDozingTransitions
+ }
+ }
fun dozeTransitionTo(vararg states: DozeStateModel): Flow<DozeTransitionModel> {
return dozeTransitionModel.filter { states.contains(it.to) }
}
+
fun isKeyguardShowing(): Boolean {
return repository.isKeyguardShowing()
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/KeyguardBlueprint.kt b/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/KeyguardBlueprint.kt
index 659c5f3007e8..35a9aaecc8cd 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/KeyguardBlueprint.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/KeyguardBlueprint.kt
@@ -22,17 +22,34 @@ import androidx.constraintlayout.widget.ConstraintSet
/** Determines the constraints for the ConstraintSet in the lockscreen root view. */
interface KeyguardBlueprint {
val id: String
- val sections: Array<KeyguardSection>
+ val sections: Set<KeyguardSection>
- fun addViews(constraintLayout: ConstraintLayout) {
- sections.forEach { it.addViews(constraintLayout) }
+ /**
+ * Add views to new blueprint.
+ *
+ * Finds sections that did not exist in the previous blueprint and add the corresponding views.
+ *
+ * @param previousBluePrint: KeyguardBlueprint the blueprint we are transitioning from.
+ */
+ fun addViews(previousBlueprint: KeyguardBlueprint?, constraintLayout: ConstraintLayout) {
+ sections.subtract((previousBlueprint?.sections ?: setOf()).toSet()).forEach {
+ it.addViews(constraintLayout)
+ it.bindData(constraintLayout)
+ }
}
- fun applyConstraints(constraintSet: ConstraintSet) {
- sections.forEach { it.applyConstraints(constraintSet) }
+ /**
+ * Remove views of old blueprint.
+ *
+ * Finds sections that are no longer in the next blueprint and remove the corresponding views.
+ *
+ * @param nextBluePrint: KeyguardBlueprint the blueprint we will transition to.
+ */
+ fun removeViews(nextBlueprint: KeyguardBlueprint, constraintLayout: ConstraintLayout) {
+ sections.subtract(nextBlueprint.sections).forEach { it.removeViews(constraintLayout) }
}
- fun onDestroy() {
- sections.forEach { it.onDestroy() }
+ fun applyConstraints(constraintSet: ConstraintSet) {
+ sections.forEach { it.applyConstraints(constraintSet) }
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/KeyguardSection.kt b/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/KeyguardSection.kt
index 19f50dec3032..48a214615733 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/KeyguardSection.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/KeyguardSection.kt
@@ -23,8 +23,34 @@ import androidx.constraintlayout.widget.ConstraintSet
* Lower level modules that determine constraints for a particular section in the lockscreen root
* view.
*/
-interface KeyguardSection {
- fun addViews(constraintLayout: ConstraintLayout)
- fun applyConstraints(constraintSet: ConstraintSet)
- fun onDestroy() {}
+abstract class KeyguardSection {
+ /** Adds the views to the root view. */
+ abstract fun addViews(constraintLayout: ConstraintLayout)
+ /** Binds the views to data. */
+ abstract fun bindData(constraintLayout: ConstraintLayout)
+ /** Applies layout constraints to the view in respect to the root view. */
+ abstract fun applyConstraints(constraintSet: ConstraintSet)
+ /** Removes views and does any data binding destruction. */
+ abstract fun removeViews(constraintLayout: ConstraintLayout)
+
+ /**
+ * Defines equality as same class.
+ *
+ * This is to enable set operations to be done as an optimization to blueprint transitions.
+ */
+ override fun equals(other: Any?): Boolean {
+ other?.let { other ->
+ return this::class == other::class
+ }
+ return false
+ }
+
+ /**
+ * Defines hashcode as class.
+ *
+ * This is to enable set operations to be done as an optimization to blueprint transitions.
+ */
+ override fun hashCode(): Int {
+ return this::class.hashCode()
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardBlueprintViewBinder.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardBlueprintViewBinder.kt
index c340e5df498b..78b72a9e5e6a 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardBlueprintViewBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardBlueprintViewBinder.kt
@@ -21,7 +21,6 @@ import android.os.Trace
import android.util.Log
import androidx.constraintlayout.widget.ConstraintLayout
import androidx.constraintlayout.widget.ConstraintSet
-import androidx.core.view.children
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.repeatOnLifecycle
import com.android.systemui.keyguard.ui.viewmodel.KeyguardBlueprintViewModel
@@ -37,26 +36,20 @@ class KeyguardBlueprintViewBinder {
repeatOnLifecycle(Lifecycle.State.CREATED) {
launch {
viewModel.blueprint.collect { blueprint ->
+ val prevBluePrint = viewModel.currentBluePrint
Trace.beginSection("KeyguardBlueprint#applyBlueprint")
Log.d(TAG, "applying blueprint: $blueprint")
- if (blueprint != viewModel.currentBluePrint) {
- viewModel.currentBluePrint?.onDestroy()
+ // Add and remove views of sections that are not contained by the other.
+ prevBluePrint?.removeViews(blueprint, constraintLayout)
+ blueprint.addViews(prevBluePrint, constraintLayout)
+
+ ConstraintSet().apply {
+ clone(constraintLayout)
+ val emptyLayout = ConstraintSet.Layout()
+ knownIds.forEach { getConstraint(it).layout.copyFrom(emptyLayout) }
+ blueprint.applyConstraints(this)
+ applyTo(constraintLayout)
}
- val constraintSet =
- ConstraintSet().apply {
- clone(constraintLayout)
- val emptyLayout = ConstraintSet.Layout()
- knownIds.forEach {
- getConstraint(it).layout.copyFrom(emptyLayout)
- }
- blueprint.addViews(constraintLayout)
- blueprint.applyConstraints(this)
- applyTo(constraintLayout)
- }
- // Remove all unconstrained views.
- constraintLayout.children
- .filterNot { constraintSet.knownIds.contains(it.id) }
- .forEach { constraintLayout.removeView(it) }
viewModel.currentBluePrint = blueprint
Trace.endSection()
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardRootViewBinder.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardRootViewBinder.kt
index 28147325c609..8b0b0ae543a7 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardRootViewBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardRootViewBinder.kt
@@ -78,6 +78,22 @@ object KeyguardRootViewBinder {
}
if (featureFlags.isEnabled(Flags.MIGRATE_SPLIT_KEYGUARD_BOTTOM_AREA)) {
+ launch { viewModel.alpha.collect { alpha -> view.alpha = alpha } }
+ }
+
+ if (featureFlags.isEnabled(Flags.MIGRATE_KEYGUARD_STATUS_VIEW)) {
+ launch {
+ viewModel.translationY.collect {
+ val statusView =
+ view.requireViewById<View>(R.id.keyguard_status_view)
+ statusView.translationY = it
+ }
+ }
+ }
+ }
+
+ repeatOnLifecycle(Lifecycle.State.STARTED) {
+ if (featureFlags.isEnabled(Flags.MIGRATE_SPLIT_KEYGUARD_BOTTOM_AREA)) {
launch {
viewModel.keyguardRootViewVisibilityState.collect { visibilityState ->
view.animate().cancel()
@@ -111,18 +127,6 @@ object KeyguardRootViewBinder {
}
}
}
-
- launch { viewModel.alpha.collect { alpha -> view.alpha = alpha } }
- }
-
- if (featureFlags.isEnabled(Flags.MIGRATE_KEYGUARD_STATUS_VIEW)) {
- launch {
- viewModel.translationY.collect {
- val statusView =
- view.requireViewById<View>(R.id.keyguard_status_view)
- statusView.translationY = it
- }
- }
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/blueprints/DefaultKeyguardBlueprint.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/blueprints/DefaultKeyguardBlueprint.kt
index 5a15fc236a0a..85b2b82cd44a 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/blueprints/DefaultKeyguardBlueprint.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/blueprints/DefaultKeyguardBlueprint.kt
@@ -55,7 +55,7 @@ constructor(
override val id: String = DEFAULT
override val sections =
- arrayOf(
+ setOf(
defaultIndicationAreaSection,
defaultLockIconSection,
defaultShortcutsSection,
@@ -66,9 +66,12 @@ constructor(
splitShadeGuidelines,
)
- override fun addViews(constraintLayout: ConstraintLayout) {
+ override fun addViews(
+ previousBlueprint: KeyguardBlueprint?,
+ constraintLayout: ConstraintLayout
+ ) {
if (featureFlags.isEnabled(Flags.LAZY_INFLATE_KEYGUARD)) {
- super.addViews(constraintLayout)
+ super.addViews(previousBlueprint, constraintLayout)
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/blueprints/ShortcutsBesideUdfpsKeyguardBlueprint.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/blueprints/ShortcutsBesideUdfpsKeyguardBlueprint.kt
index 5ef625e62d00..bb3af6cc86a2 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/blueprints/ShortcutsBesideUdfpsKeyguardBlueprint.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/blueprints/ShortcutsBesideUdfpsKeyguardBlueprint.kt
@@ -46,7 +46,7 @@ constructor(
override val id: String = SHORTCUTS_BESIDE_UDFPS
override val sections =
- arrayOf(
+ setOf(
defaultIndicationAreaSection,
defaultLockIconSection,
defaultAmbientIndicationAreaSection,
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/AlignShortcutsToUdfpsSection.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/AlignShortcutsToUdfpsSection.kt
index 587c6b7cb4ae..79b715799d31 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/AlignShortcutsToUdfpsSection.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/AlignShortcutsToUdfpsSection.kt
@@ -18,6 +18,8 @@
package com.android.systemui.keyguard.ui.view.layout.sections
import android.content.res.Resources
+import android.view.View
+import android.widget.ImageView
import androidx.constraintlayout.widget.ConstraintLayout
import androidx.constraintlayout.widget.ConstraintSet
import androidx.constraintlayout.widget.ConstraintSet.BOTTOM
@@ -25,7 +27,9 @@ import androidx.constraintlayout.widget.ConstraintSet.LEFT
import androidx.constraintlayout.widget.ConstraintSet.PARENT_ID
import androidx.constraintlayout.widget.ConstraintSet.RIGHT
import androidx.constraintlayout.widget.ConstraintSet.TOP
+import androidx.core.content.res.ResourcesCompat
import com.android.systemui.R
+import com.android.systemui.animation.view.LaunchableImageView
import com.android.systemui.dagger.qualifiers.Main
import com.android.systemui.flags.FeatureFlags
import com.android.systemui.flags.Flags
@@ -49,12 +53,19 @@ constructor(
private val falsingManager: FalsingManager,
private val indicationController: KeyguardIndicationController,
private val vibratorHelper: VibratorHelper,
-) : BaseShortcutsSection(), KeyguardSection {
+) : KeyguardSection() {
+ private var leftShortcutHandle: KeyguardQuickAffordanceViewBinder.Binding? = null
+ private var rightShortcutHandle: KeyguardQuickAffordanceViewBinder.Binding? = null
override fun addViews(constraintLayout: ConstraintLayout) {
if (featureFlags.isEnabled(Flags.MIGRATE_SPLIT_KEYGUARD_BOTTOM_AREA)) {
addLeftShortcut(constraintLayout)
addRightShortcut(constraintLayout)
+ }
+ }
+
+ override fun bindData(constraintLayout: ConstraintLayout) {
+ if (featureFlags.isEnabled(Flags.MIGRATE_SPLIT_KEYGUARD_BOTTOM_AREA)) {
leftShortcutHandle =
KeyguardQuickAffordanceViewBinder.bind(
constraintLayout.requireViewById(R.id.start_button),
@@ -98,4 +109,67 @@ constructor(
connect(R.id.end_button, BOTTOM, R.id.lock_icon_view, BOTTOM)
}
}
+
+ override fun removeViews(constraintLayout: ConstraintLayout) {
+ leftShortcutHandle?.destroy()
+ rightShortcutHandle?.destroy()
+ constraintLayout.removeView(R.id.start_button)
+ constraintLayout.removeView(R.id.end_button)
+ }
+
+ private fun addLeftShortcut(constraintLayout: ConstraintLayout) {
+ val padding =
+ constraintLayout.resources.getDimensionPixelSize(
+ R.dimen.keyguard_affordance_fixed_padding
+ )
+ val view =
+ LaunchableImageView(constraintLayout.context, null).apply {
+ id = R.id.start_button
+ scaleType = ImageView.ScaleType.FIT_CENTER
+ background =
+ ResourcesCompat.getDrawable(
+ context.resources,
+ R.drawable.keyguard_bottom_affordance_bg,
+ context.theme
+ )
+ foreground =
+ ResourcesCompat.getDrawable(
+ context.resources,
+ R.drawable.keyguard_bottom_affordance_selected_border,
+ context.theme
+ )
+ visibility = View.INVISIBLE
+ setPadding(padding, padding, padding, padding)
+ }
+ constraintLayout.addView(view)
+ }
+
+ private fun addRightShortcut(constraintLayout: ConstraintLayout) {
+ if (constraintLayout.findViewById<View>(R.id.end_button) != null) return
+
+ val padding =
+ constraintLayout.resources.getDimensionPixelSize(
+ R.dimen.keyguard_affordance_fixed_padding
+ )
+ val view =
+ LaunchableImageView(constraintLayout.context, null).apply {
+ id = R.id.end_button
+ scaleType = ImageView.ScaleType.FIT_CENTER
+ background =
+ ResourcesCompat.getDrawable(
+ context.resources,
+ R.drawable.keyguard_bottom_affordance_bg,
+ context.theme
+ )
+ foreground =
+ ResourcesCompat.getDrawable(
+ context.resources,
+ R.drawable.keyguard_bottom_affordance_selected_border,
+ context.theme
+ )
+ visibility = View.INVISIBLE
+ setPadding(padding, padding, padding, padding)
+ }
+ constraintLayout.addView(view)
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/BaseShortcutsSection.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/BaseShortcutsSection.kt
deleted file mode 100644
index db0cf5ad3000..000000000000
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/BaseShortcutsSection.kt
+++ /dev/null
@@ -1,101 +0,0 @@
-/*
- * Copyright (C) 2023 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-package com.android.systemui.keyguard.ui.view.layout.sections
-
-import android.view.View
-import android.widget.ImageView
-import androidx.constraintlayout.widget.ConstraintLayout
-import androidx.constraintlayout.widget.ConstraintSet
-import androidx.core.content.res.ResourcesCompat
-import com.android.systemui.R
-import com.android.systemui.animation.view.LaunchableImageView
-import com.android.systemui.keyguard.shared.model.KeyguardSection
-import com.android.systemui.keyguard.ui.binder.KeyguardQuickAffordanceViewBinder
-
-/** Base class for sections that add lockscreen shortcuts. */
-abstract class BaseShortcutsSection : KeyguardSection {
- protected open var leftShortcutHandle: KeyguardQuickAffordanceViewBinder.Binding? = null
- protected open var rightShortcutHandle: KeyguardQuickAffordanceViewBinder.Binding? = null
-
- override fun addViews(constraintLayout: ConstraintLayout) {}
-
- override fun applyConstraints(constraintSet: ConstraintSet) {}
-
- override fun onDestroy() {
- leftShortcutHandle?.destroy()
- rightShortcutHandle?.destroy()
- }
-
- protected open fun addLeftShortcut(constraintLayout: ConstraintLayout) {
- if (constraintLayout.findViewById<View>(R.id.start_button) != null) return
-
- val padding =
- constraintLayout.resources.getDimensionPixelSize(
- R.dimen.keyguard_affordance_fixed_padding
- )
- val view =
- LaunchableImageView(constraintLayout.context, null).apply {
- id = R.id.start_button
- scaleType = ImageView.ScaleType.FIT_CENTER
- background =
- ResourcesCompat.getDrawable(
- context.resources,
- R.drawable.keyguard_bottom_affordance_bg,
- context.theme
- )
- foreground =
- ResourcesCompat.getDrawable(
- context.resources,
- R.drawable.keyguard_bottom_affordance_selected_border,
- context.theme
- )
- visibility = View.INVISIBLE
- setPadding(padding, padding, padding, padding)
- }
- constraintLayout.addView(view)
- }
-
- protected open fun addRightShortcut(constraintLayout: ConstraintLayout) {
- if (constraintLayout.findViewById<View>(R.id.end_button) != null) return
-
- val padding =
- constraintLayout.resources.getDimensionPixelSize(
- R.dimen.keyguard_affordance_fixed_padding
- )
- val view =
- LaunchableImageView(constraintLayout.context, null).apply {
- id = R.id.end_button
- scaleType = ImageView.ScaleType.FIT_CENTER
- background =
- ResourcesCompat.getDrawable(
- context.resources,
- R.drawable.keyguard_bottom_affordance_bg,
- context.theme
- )
- foreground =
- ResourcesCompat.getDrawable(
- context.resources,
- R.drawable.keyguard_bottom_affordance_selected_border,
- context.theme
- )
- visibility = View.INVISIBLE
- setPadding(padding, padding, padding, padding)
- }
- constraintLayout.addView(view)
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultAmbientIndicationAreaSection.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultAmbientIndicationAreaSection.kt
index f8455c53a51f..ce86e9784180 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultAmbientIndicationAreaSection.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultAmbientIndicationAreaSection.kt
@@ -18,7 +18,6 @@
package com.android.systemui.keyguard.ui.view.layout.sections
import android.view.LayoutInflater
-import android.view.View
import android.view.ViewGroup.LayoutParams.MATCH_PARENT
import androidx.constraintlayout.widget.ConstraintLayout
import androidx.constraintlayout.widget.ConstraintSet
@@ -46,19 +45,21 @@ constructor(
private val featureFlags: FeatureFlags,
private val keyguardAmbientIndicationViewModel: KeyguardAmbientIndicationViewModel,
private val keyguardRootViewModel: KeyguardRootViewModel,
-) : KeyguardSection {
+) : KeyguardSection() {
private var ambientIndicationAreaHandle: KeyguardAmbientIndicationAreaViewBinder.Binding? = null
override fun addViews(constraintLayout: ConstraintLayout) {
if (featureFlags.isEnabled(Flags.MIGRATE_SPLIT_KEYGUARD_BOTTOM_AREA)) {
- if (constraintLayout.findViewById<View>(R.id.ambient_indication_container) == null) {
- val view =
- LayoutInflater.from(constraintLayout.context)
- .inflate(R.layout.ambient_indication, constraintLayout, false)
+ val view =
+ LayoutInflater.from(constraintLayout.context)
+ .inflate(R.layout.ambient_indication, constraintLayout, false)
- constraintLayout.addView(view)
- }
+ constraintLayout.addView(view)
+ }
+ }
+ override fun bindData(constraintLayout: ConstraintLayout) {
+ if (featureFlags.isEnabled(Flags.MIGRATE_SPLIT_KEYGUARD_BOTTOM_AREA)) {
ambientIndicationAreaHandle =
KeyguardAmbientIndicationAreaViewBinder.bind(
constraintLayout,
@@ -94,7 +95,9 @@ constructor(
}
}
- override fun onDestroy() {
+ override fun removeViews(constraintLayout: ConstraintLayout) {
ambientIndicationAreaHandle?.destroy()
+
+ constraintLayout.removeView(R.id.ambient_indication_container)
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultIndicationAreaSection.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultIndicationAreaSection.kt
index f04bfc675f1f..a45223cbd449 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultIndicationAreaSection.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultIndicationAreaSection.kt
@@ -18,7 +18,6 @@
package com.android.systemui.keyguard.ui.view.layout.sections
import android.content.Context
-import android.view.View
import android.view.ViewGroup
import androidx.constraintlayout.widget.ConstraintLayout
import androidx.constraintlayout.widget.ConstraintSet
@@ -42,17 +41,19 @@ constructor(
private val keyguardRootViewModel: KeyguardRootViewModel,
private val indicationController: KeyguardIndicationController,
private val featureFlags: FeatureFlags,
-) : KeyguardSection {
+) : KeyguardSection() {
private val indicationAreaViewId = R.id.keyguard_indication_area
private var indicationAreaHandle: DisposableHandle? = null
override fun addViews(constraintLayout: ConstraintLayout) {
if (featureFlags.isEnabled(Flags.MIGRATE_SPLIT_KEYGUARD_BOTTOM_AREA)) {
- if (constraintLayout.findViewById<View>(indicationAreaViewId) == null) {
- val view = KeyguardIndicationArea(context, null)
- constraintLayout.addView(view)
- }
+ val view = KeyguardIndicationArea(context, null)
+ constraintLayout.addView(view)
+ }
+ }
+ override fun bindData(constraintLayout: ConstraintLayout) {
+ if (featureFlags.isEnabled(Flags.MIGRATE_SPLIT_KEYGUARD_BOTTOM_AREA)) {
indicationAreaHandle =
KeyguardIndicationAreaBinder.bind(
constraintLayout,
@@ -90,7 +91,8 @@ constructor(
}
}
- override fun onDestroy() {
+ override fun removeViews(constraintLayout: ConstraintLayout) {
indicationAreaHandle?.dispose()
+ constraintLayout.removeView(indicationAreaViewId)
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultLockIconSection.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultLockIconSection.kt
index 3d62f3f1f985..3e91d9336b13 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultLockIconSection.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultLockIconSection.kt
@@ -47,19 +47,23 @@ constructor(
private val notificationPanelView: NotificationPanelView,
private val featureFlags: FeatureFlags,
private val lockIconViewController: LockIconViewController,
-) : KeyguardSection {
+) : KeyguardSection() {
private val lockIconViewId = R.id.lock_icon_view
override fun addViews(constraintLayout: ConstraintLayout) {
- if (featureFlags.isEnabled(Flags.MIGRATE_LOCK_ICON)) {
- notificationPanelView.findViewById<View>(R.id.lock_icon_view).let {
- notificationPanelView.removeView(it)
- }
- if (constraintLayout.findViewById<View>(R.id.lock_icon_view) == null) {
- val view = LockIconView(context, null).apply { id = R.id.lock_icon_view }
- constraintLayout.addView(view)
- lockIconViewController.setLockIconView(view)
- }
+ if (!featureFlags.isEnabled(Flags.MIGRATE_LOCK_ICON)) {
+ return
+ }
+ notificationPanelView.findViewById<View>(R.id.lock_icon_view).let {
+ notificationPanelView.removeView(it)
+ }
+ val view = LockIconView(context, null).apply { id = R.id.lock_icon_view }
+ constraintLayout.addView(view)
+ }
+
+ override fun bindData(constraintLayout: ConstraintLayout) {
+ constraintLayout.findViewById<LockIconView?>(R.id.lock_icon_view)?.let {
+ lockIconViewController.setLockIconView(it)
}
}
@@ -92,6 +96,10 @@ constructor(
}
}
+ override fun removeViews(constraintLayout: ConstraintLayout) {
+ constraintLayout.removeView(R.id.lock_icon_view)
+ }
+
@VisibleForTesting
internal fun centerLockIcon(center: Point, radius: Float, constraintSet: ConstraintSet) {
val sensorRect =
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultNotificationStackScrollLayoutSection.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultNotificationStackScrollLayoutSection.kt
index a203e41db86e..59c5d78bfce8 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultNotificationStackScrollLayoutSection.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultNotificationStackScrollLayoutSection.kt
@@ -40,22 +40,30 @@ constructor(
private val sharedNotificationContainer: SharedNotificationContainer,
private val sharedNotificationContainerViewModel: SharedNotificationContainerViewModel,
private val controller: NotificationStackScrollLayoutController,
-) : KeyguardSection {
+) : KeyguardSection() {
override fun addViews(constraintLayout: ConstraintLayout) {
+ if (!featureFlags.isEnabled(Flags.MIGRATE_NSSL)) {
+ return
+ }
+ // This moves the existing NSSL view to a different parent, as the controller is a
+ // singleton and recreating it has other bad side effects
+ notificationPanelView.findViewById<View?>(R.id.notification_stack_scroller)?.let {
+ (it.parent as ViewGroup).removeView(it)
+ sharedNotificationContainer.addNotificationStackScrollLayout(it)
+ }
+ }
+
+ override fun bindData(constraintLayout: ConstraintLayout) {
if (featureFlags.isEnabled(Flags.MIGRATE_NSSL)) {
- // This moves the existing NSSL view to a different parent, as the controller is a
- // singleton and recreating it has other bad side effects
- notificationPanelView.findViewById<View?>(R.id.notification_stack_scroller)?.let {
- (it.parent as ViewGroup).removeView(it)
- sharedNotificationContainer.addNotificationStackScrollLayout(it)
- SharedNotificationContainerBinder.bind(
- sharedNotificationContainer,
- sharedNotificationContainerViewModel,
- controller,
- )
- }
+ SharedNotificationContainerBinder.bind(
+ sharedNotificationContainer,
+ sharedNotificationContainerViewModel,
+ controller,
+ )
}
}
override fun applyConstraints(constraintSet: ConstraintSet) {}
+
+ override fun removeViews(constraintLayout: ConstraintLayout) {}
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultSettingsPopupMenuSection.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultSettingsPopupMenuSection.kt
index 660cc96f21e6..b25f9afc0d1e 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultSettingsPopupMenuSection.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultSettingsPopupMenuSection.kt
@@ -49,23 +49,26 @@ constructor(
private val keyguardSettingsMenuViewModel: KeyguardSettingsMenuViewModel,
private val vibratorHelper: VibratorHelper,
private val activityStarter: ActivityStarter,
-) : KeyguardSection {
+) : KeyguardSection() {
private var settingsPopupMenuHandle: DisposableHandle? = null
override fun addViews(constraintLayout: ConstraintLayout) {
- if (featureFlags.isEnabled(Flags.MIGRATE_SPLIT_KEYGUARD_BOTTOM_AREA)) {
- if (constraintLayout.findViewById<View?>(R.id.keyguard_settings_button) == null) {
- val view =
- LayoutInflater.from(constraintLayout.context)
- .inflate(R.layout.keyguard_settings_popup_menu, constraintLayout, false)
- .apply {
- id = R.id.keyguard_settings_button
- isVisible = false
- alpha = 0f
- } as LaunchableLinearLayout
- constraintLayout.addView(view)
- }
+ if (!featureFlags.isEnabled(Flags.MIGRATE_SPLIT_KEYGUARD_BOTTOM_AREA)) {
+ return
+ }
+ val view =
+ LayoutInflater.from(constraintLayout.context)
+ .inflate(R.layout.keyguard_settings_popup_menu, constraintLayout, false)
+ .apply {
+ id = R.id.keyguard_settings_button
+ isVisible = false
+ alpha = 0f
+ } as LaunchableLinearLayout
+ constraintLayout.addView(view)
+ }
+ override fun bindData(constraintLayout: ConstraintLayout) {
+ if (featureFlags.isEnabled(Flags.MIGRATE_SPLIT_KEYGUARD_BOTTOM_AREA)) {
settingsPopupMenuHandle =
KeyguardSettingsViewBinder.bind(
constraintLayout.requireViewById<View>(R.id.keyguard_settings_button),
@@ -100,7 +103,8 @@ constructor(
}
}
- override fun onDestroy() {
+ override fun removeViews(constraintLayout: ConstraintLayout) {
settingsPopupMenuHandle?.dispose()
+ constraintLayout.removeView(R.id.keyguard_settings_button)
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultShortcutsSection.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultShortcutsSection.kt
index 965910a1be66..c4980557c454 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultShortcutsSection.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultShortcutsSection.kt
@@ -18,13 +18,17 @@
package com.android.systemui.keyguard.ui.view.layout.sections
import android.content.res.Resources
+import android.view.View
+import android.widget.ImageView
import androidx.constraintlayout.widget.ConstraintLayout
import androidx.constraintlayout.widget.ConstraintSet
import androidx.constraintlayout.widget.ConstraintSet.BOTTOM
import androidx.constraintlayout.widget.ConstraintSet.LEFT
import androidx.constraintlayout.widget.ConstraintSet.PARENT_ID
import androidx.constraintlayout.widget.ConstraintSet.RIGHT
+import androidx.core.content.res.ResourcesCompat
import com.android.systemui.R
+import com.android.systemui.animation.view.LaunchableImageView
import com.android.systemui.dagger.qualifiers.Main
import com.android.systemui.flags.FeatureFlags
import com.android.systemui.flags.Flags
@@ -48,12 +52,19 @@ constructor(
private val falsingManager: FalsingManager,
private val indicationController: KeyguardIndicationController,
private val vibratorHelper: VibratorHelper,
-) : BaseShortcutsSection(), KeyguardSection {
+) : KeyguardSection() {
+ private var leftShortcutHandle: KeyguardQuickAffordanceViewBinder.Binding? = null
+ private var rightShortcutHandle: KeyguardQuickAffordanceViewBinder.Binding? = null
override fun addViews(constraintLayout: ConstraintLayout) {
if (featureFlags.isEnabled(Flags.MIGRATE_SPLIT_KEYGUARD_BOTTOM_AREA)) {
addLeftShortcut(constraintLayout)
addRightShortcut(constraintLayout)
+ }
+ }
+
+ override fun bindData(constraintLayout: ConstraintLayout) {
+ if (featureFlags.isEnabled(Flags.MIGRATE_SPLIT_KEYGUARD_BOTTOM_AREA)) {
leftShortcutHandle =
KeyguardQuickAffordanceViewBinder.bind(
constraintLayout.requireViewById(R.id.start_button),
@@ -98,6 +109,69 @@ constructor(
}
}
+ override fun removeViews(constraintLayout: ConstraintLayout) {
+ leftShortcutHandle?.destroy()
+ rightShortcutHandle?.destroy()
+ constraintLayout.removeView(R.id.start_button)
+ constraintLayout.removeView(R.id.end_button)
+ }
+
+ private fun addLeftShortcut(constraintLayout: ConstraintLayout) {
+ val padding =
+ constraintLayout.resources.getDimensionPixelSize(
+ R.dimen.keyguard_affordance_fixed_padding
+ )
+ val view =
+ LaunchableImageView(constraintLayout.context, null).apply {
+ id = R.id.start_button
+ scaleType = ImageView.ScaleType.FIT_CENTER
+ background =
+ ResourcesCompat.getDrawable(
+ context.resources,
+ R.drawable.keyguard_bottom_affordance_bg,
+ context.theme
+ )
+ foreground =
+ ResourcesCompat.getDrawable(
+ context.resources,
+ R.drawable.keyguard_bottom_affordance_selected_border,
+ context.theme
+ )
+ visibility = View.INVISIBLE
+ setPadding(padding, padding, padding, padding)
+ }
+ constraintLayout.addView(view)
+ }
+
+ private fun addRightShortcut(constraintLayout: ConstraintLayout) {
+ if (constraintLayout.findViewById<View>(R.id.end_button) != null) return
+
+ val padding =
+ constraintLayout.resources.getDimensionPixelSize(
+ R.dimen.keyguard_affordance_fixed_padding
+ )
+ val view =
+ LaunchableImageView(constraintLayout.context, null).apply {
+ id = R.id.end_button
+ scaleType = ImageView.ScaleType.FIT_CENTER
+ background =
+ ResourcesCompat.getDrawable(
+ context.resources,
+ R.drawable.keyguard_bottom_affordance_bg,
+ context.theme
+ )
+ foreground =
+ ResourcesCompat.getDrawable(
+ context.resources,
+ R.drawable.keyguard_bottom_affordance_selected_border,
+ context.theme
+ )
+ visibility = View.INVISIBLE
+ setPadding(padding, padding, padding, padding)
+ }
+ constraintLayout.addView(view)
+ }
+
/** Method to add shortcuts without applying any data binding. */
fun addShortcutViews(constraintLayout: ConstraintLayout) {
addLeftShortcut(constraintLayout)
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultStatusViewSection.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultStatusViewSection.kt
index 321d7a70b087..b144f7ae6906 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultStatusViewSection.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultStatusViewSection.kt
@@ -55,31 +55,34 @@ constructor(
private val keyguardViewConfigurator: Lazy<KeyguardViewConfigurator>,
private val notificationPanelViewController: Lazy<NotificationPanelViewController>,
private val keyguardMediaController: KeyguardMediaController,
-) : KeyguardSection {
+) : KeyguardSection() {
private val statusViewId = R.id.keyguard_status_view
- @OptIn(ExperimentalCoroutinesApi::class)
override fun addViews(constraintLayout: ConstraintLayout) {
+ if (!featureFlags.isEnabled(Flags.MIGRATE_KEYGUARD_STATUS_VIEW)) {
+ return
+ }
// At startup, 2 views with the ID `R.id.keyguard_status_view` will be available.
// Disable one of them
- if (featureFlags.isEnabled(Flags.MIGRATE_KEYGUARD_STATUS_VIEW)) {
- notificationPanelView.findViewById<View>(statusViewId)?.let {
- notificationPanelView.removeView(it)
- }
- if (constraintLayout.findViewById<View>(statusViewId) == null) {
- val keyguardStatusView =
- (LayoutInflater.from(context)
- .inflate(R.layout.keyguard_status_view, constraintLayout, false)
- as KeyguardStatusView)
- .apply { clipChildren = false }
+ notificationPanelView.findViewById<View>(statusViewId)?.let {
+ notificationPanelView.removeView(it)
+ }
+ val keyguardStatusView =
+ (LayoutInflater.from(context)
+ .inflate(R.layout.keyguard_status_view, constraintLayout, false)
+ as KeyguardStatusView)
+ .apply { clipChildren = false }
+ constraintLayout.addView(keyguardStatusView)
+ }
- val statusViewComponent =
- keyguardStatusViewComponentFactory.build(keyguardStatusView)
+ override fun bindData(constraintLayout: ConstraintLayout) {
+ if (featureFlags.isEnabled(Flags.MIGRATE_KEYGUARD_STATUS_VIEW)) {
+ constraintLayout.findViewById<KeyguardStatusView?>(R.id.keyguard_status_view)?.let {
+ val statusViewComponent = keyguardStatusViewComponentFactory.build(it)
val controller = statusViewComponent.keyguardStatusViewController
controller.init()
- constraintLayout.addView(keyguardStatusView)
keyguardMediaController.attachSplitShadeContainer(
- keyguardStatusView.requireViewById<ViewGroup>(R.id.status_view_media_container)
+ it.requireViewById<ViewGroup>(R.id.status_view_media_container)
)
keyguardViewConfigurator.get().keyguardStatusViewController = controller
notificationPanelViewController.get().updateStatusBarViewController()
@@ -107,7 +110,8 @@ constructor(
}
@OptIn(ExperimentalCoroutinesApi::class)
- override fun onDestroy() {
+ override fun removeViews(constraintLayout: ConstraintLayout) {
+ constraintLayout.removeView(statusViewId)
keyguardViewConfigurator.get().keyguardStatusViewController = null
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/Extensions.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/Extensions.kt
new file mode 100644
index 000000000000..94332d21f499
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/Extensions.kt
@@ -0,0 +1,8 @@
+package com.android.systemui.keyguard.ui.view.layout.sections
+
+import android.view.View
+import androidx.constraintlayout.widget.ConstraintLayout
+
+internal fun ConstraintLayout.removeView(viewId: Int) {
+ findViewById<View?>(viewId)?.let { removeView(it) }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/SplitShadeGuidelines.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/SplitShadeGuidelines.kt
index bd629d512614..5e3ea059ddd5 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/SplitShadeGuidelines.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/SplitShadeGuidelines.kt
@@ -17,7 +17,6 @@
package com.android.systemui.keyguard.ui.view.layout.sections
-import android.content.Context
import androidx.constraintlayout.widget.ConstraintLayout
import androidx.constraintlayout.widget.ConstraintSet
import androidx.constraintlayout.widget.ConstraintSet.VERTICAL
@@ -25,9 +24,11 @@ import com.android.systemui.R
import com.android.systemui.keyguard.shared.model.KeyguardSection
import javax.inject.Inject
-class SplitShadeGuidelines @Inject constructor(private val context: Context) : KeyguardSection {
+class SplitShadeGuidelines @Inject constructor() : KeyguardSection() {
override fun addViews(constraintLayout: ConstraintLayout) {}
+ override fun bindData(constraintLayout: ConstraintLayout) {}
+
override fun applyConstraints(constraintSet: ConstraintSet) {
constraintSet.apply {
// For use on large screens, it will provide a guideline vertically in the center to
@@ -36,4 +37,6 @@ class SplitShadeGuidelines @Inject constructor(private val context: Context) : K
setGuidelinePercent(R.id.split_shade_guideline, 0.5f)
}
}
+
+ override fun removeViews(constraintLayout: ConstraintLayout) {}
}
diff --git a/packages/SystemUI/src/com/android/systemui/log/dagger/LogModule.java b/packages/SystemUI/src/com/android/systemui/log/dagger/LogModule.java
index 5127d142d783..6c2ce7fa5156 100644
--- a/packages/SystemUI/src/com/android/systemui/log/dagger/LogModule.java
+++ b/packages/SystemUI/src/com/android/systemui/log/dagger/LogModule.java
@@ -80,6 +80,14 @@ public class LogModule {
return factory.create("NotifHeadsUpLog", 1000);
}
+ /** Provides a logging buffer for logs related to inflation of notifications. */
+ @Provides
+ @SysUISingleton
+ @NotifInflationLog
+ public static LogBuffer provideNotifInflationLogBuffer(LogBufferFactory factory) {
+ return factory.create("NotifInflationLog", 100);
+ }
+
/** Provides a logging buffer for notification interruption calculations. */
@Provides
@SysUISingleton
diff --git a/packages/SystemUI/src/com/android/systemui/log/dagger/NotifInflationLog.java b/packages/SystemUI/src/com/android/systemui/log/dagger/NotifInflationLog.java
new file mode 100644
index 000000000000..9f201c377850
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/log/dagger/NotifInflationLog.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.log.dagger;
+
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+import com.android.systemui.log.LogBuffer;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.Retention;
+
+import javax.inject.Qualifier;
+
+/** A {@link LogBuffer} for messages related to inflation of notifications. */
+@Qualifier
+@Documented
+@Retention(RUNTIME)
+public @interface NotifInflationLog {
+}
diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaProjectionPermissionActivity.java b/packages/SystemUI/src/com/android/systemui/media/MediaProjectionPermissionActivity.java
index a9d2b30c2b6f..4be572f8c0f6 100644
--- a/packages/SystemUI/src/com/android/systemui/media/MediaProjectionPermissionActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/media/MediaProjectionPermissionActivity.java
@@ -55,7 +55,6 @@ import com.android.systemui.flags.FeatureFlags;
import com.android.systemui.flags.Flags;
import com.android.systemui.mediaprojection.devicepolicy.ScreenCaptureDevicePolicyResolver;
import com.android.systemui.mediaprojection.devicepolicy.ScreenCaptureDisabledDialog;
-import com.android.systemui.plugins.ActivityStarter;
import com.android.systemui.screenrecord.MediaProjectionPermissionDialog;
import com.android.systemui.screenrecord.ScreenShareOption;
import com.android.systemui.statusbar.phone.SystemUIDialog;
@@ -73,7 +72,6 @@ public class MediaProjectionPermissionActivity extends Activity
private final FeatureFlags mFeatureFlags;
private final Lazy<ScreenCaptureDevicePolicyResolver> mScreenCaptureDevicePolicyResolver;
- private final ActivityStarter mActivityStarter;
private String mPackageName;
private int mUid;
@@ -89,10 +87,8 @@ public class MediaProjectionPermissionActivity extends Activity
@Inject
public MediaProjectionPermissionActivity(FeatureFlags featureFlags,
- Lazy<ScreenCaptureDevicePolicyResolver> screenCaptureDevicePolicyResolver,
- ActivityStarter activityStarter) {
+ Lazy<ScreenCaptureDevicePolicyResolver> screenCaptureDevicePolicyResolver) {
mFeatureFlags = featureFlags;
- mActivityStarter = activityStarter;
mScreenCaptureDevicePolicyResolver = screenCaptureDevicePolicyResolver;
}
@@ -313,16 +309,8 @@ public class MediaProjectionPermissionActivity extends Activity
// Start activity from the current foreground user to avoid creating a separate
// SystemUI process without access to recent tasks because it won't have
// WM Shell running inside.
- // It is also important to make sure the shade is dismissed, otherwise users won't
- // see the app selector.
mUserSelectingTask = true;
- mActivityStarter.startActivity(
- intent,
- /* dismissShade= */ true,
- /* animationController= */ null,
- /* showOverLockscreenWhenLocked= */ false,
- UserHandle.of(ActivityManager.getCurrentUser())
- );
+ startActivityAsUser(intent, UserHandle.of(ActivityManager.getCurrentUser()));
}
} catch (RemoteException e) {
Log.e(TAG, "Error granting projection permission", e);
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaCarouselScrollHandler.kt b/packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaCarouselScrollHandler.kt
index bbb61b4d1745..ec0c40ec69a3 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaCarouselScrollHandler.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaCarouselScrollHandler.kt
@@ -26,6 +26,7 @@ import android.view.ViewOutlineProvider
import androidx.core.view.GestureDetectorCompat
import androidx.dynamicanimation.animation.FloatPropertyCompat
import androidx.dynamicanimation.animation.SpringForce
+import com.android.internal.annotations.VisibleForTesting
import com.android.settingslib.Utils
import com.android.systemui.Gefingerpoken
import com.android.systemui.R
@@ -146,7 +147,8 @@ class MediaCarouselScrollHandler(
}
/** The touch listener for the scroll view */
- private val touchListener =
+ @VisibleForTesting
+ val touchListener =
object : Gefingerpoken {
override fun onTouchEvent(motionEvent: MotionEvent?) = onTouch(motionEvent!!)
override fun onInterceptTouchEvent(ev: MotionEvent?) = onInterceptTouch(ev!!)
@@ -279,15 +281,14 @@ class MediaCarouselScrollHandler(
} else if (isUp || motionEvent.action == MotionEvent.ACTION_CANCEL) {
// It's an up and the fling didn't take it above
val relativePos = scrollView.relativeScrollX % playerWidthPlusPadding
- val scrollXAmount: Int
- if (relativePos > playerWidthPlusPadding / 2) {
- scrollXAmount = playerWidthPlusPadding - relativePos
- } else {
- scrollXAmount = -1 * relativePos
- }
+ val scrollXAmount: Int =
+ if (isRtl xor (relativePos > playerWidthPlusPadding / 2)) {
+ playerWidthPlusPadding - relativePos
+ } else {
+ -1 * relativePos
+ }
if (scrollXAmount != 0) {
- val dx = if (isRtl) -scrollXAmount else scrollXAmount
- val newScrollX = scrollView.relativeScrollX + dx
+ val newScrollX = scrollView.relativeScrollX + scrollXAmount
// Delay the scrolling since scrollView calls springback which cancels
// the animation again..
mainExecutor.execute { scrollView.smoothScrollTo(newScrollX, scrollView.scrollY) }
diff --git a/packages/SystemUI/src/com/android/systemui/people/widget/PeopleSpaceWidgetManager.java b/packages/SystemUI/src/com/android/systemui/people/widget/PeopleSpaceWidgetManager.java
index 8d3b7451c90b..1d820a14be4e 100644
--- a/packages/SystemUI/src/com/android/systemui/people/widget/PeopleSpaceWidgetManager.java
+++ b/packages/SystemUI/src/com/android/systemui/people/widget/PeopleSpaceWidgetManager.java
@@ -70,6 +70,7 @@ import android.net.Uri;
import android.os.Bundle;
import android.os.RemoteException;
import android.os.ServiceManager;
+import android.os.Trace;
import android.os.UserHandle;
import android.os.UserManager;
import android.preference.PreferenceManager;
@@ -85,9 +86,11 @@ import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.logging.UiEventLogger;
import com.android.internal.logging.UiEventLoggerImpl;
+import com.android.systemui.Dumpable;
import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.dagger.qualifiers.Background;
+import com.android.systemui.dump.DumpManager;
import com.android.systemui.people.NotificationHelper;
import com.android.systemui.people.PeopleBackupFollowUpJob;
import com.android.systemui.people.PeopleSpaceUtils;
@@ -99,6 +102,7 @@ import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.collection.notifcollection.CommonNotifCollection;
import com.android.wm.shell.bubbles.Bubbles;
+import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
@@ -119,7 +123,8 @@ import javax.inject.Inject;
/** Manager for People Space widget. */
@SysUISingleton
-public class PeopleSpaceWidgetManager {
+public class PeopleSpaceWidgetManager implements Dumpable {
+
private static final String TAG = "PeopleSpaceWidgetMgr";
private static final boolean DEBUG = PeopleSpaceUtils.DEBUG;
@@ -160,7 +165,8 @@ public class PeopleSpaceWidgetManager {
CommonNotifCollection notifCollection,
PackageManager packageManager, Optional<Bubbles> bubblesOptional,
UserManager userManager, NotificationManager notificationManager,
- BroadcastDispatcher broadcastDispatcher, @Background Executor bgExecutor) {
+ BroadcastDispatcher broadcastDispatcher, @Background Executor bgExecutor,
+ DumpManager dumpManager) {
if (DEBUG) Log.d(TAG, "constructor");
mContext = context;
mAppWidgetManager = AppWidgetManager.getInstance(context);
@@ -180,6 +186,7 @@ public class PeopleSpaceWidgetManager {
mManager = this;
mBroadcastDispatcher = broadcastDispatcher;
mBgExecutor = bgExecutor;
+ dumpManager.registerNormalDumpable(TAG, this);
}
/** Initializes {@PeopleSpaceWidgetManager}. */
@@ -1364,4 +1371,40 @@ public class PeopleSpaceWidgetManager {
.filter(id -> !TextUtils.isEmpty(id))
.collect(Collectors.toSet());
}
+
+ @Override
+ public void dump(@NonNull PrintWriter pw, @NonNull String[] args) {
+ Trace.traceBegin(Trace.TRACE_TAG_APP, TAG + ".dump");
+ SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(mContext);
+ Map<String, ?> all = sp.getAll();
+ pw.println("People widget list:");
+ for (Map.Entry<String, ?> entry : all.entrySet()) {
+ String key = entry.getKey();
+ PeopleBackupHelper.SharedFileEntryType keyType = getEntryType(entry);
+ switch (keyType) {
+ case WIDGET_ID:
+ SharedPreferences widgetSp = mContext.getSharedPreferences(key,
+ Context.MODE_PRIVATE);
+ pw.print("People widget (valid) [");
+ pw.print(key);
+ pw.print("] shortcut id: \"");
+ pw.print(widgetSp.getString(SHORTCUT_ID, EMPTY_STRING));
+ pw.print("\", user id: ");
+ pw.print(widgetSp.getInt(USER_ID, INVALID_USER_ID));
+ pw.print(", package: ");
+ pw.println(widgetSp.getString(PACKAGE_NAME, EMPTY_STRING));
+ break;
+ case PEOPLE_TILE_KEY:
+ case CONTACT_URI:
+ pw.print("Extra data [");
+ pw.print(key);
+ pw.print(" : ");
+ pw.print((Set<String>) entry.getValue());
+ pw.println("]");
+ break;
+ }
+ }
+
+ Trace.traceEnd(Trace.TRACE_TAG_APP);
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSContainerImpl.java b/packages/SystemUI/src/com/android/systemui/qs/QSContainerImpl.java
index d2eac45754bd..37e750b86c21 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSContainerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSContainerImpl.java
@@ -235,11 +235,15 @@ public class QSContainerImpl extends FrameLayout implements Dumpable {
quickStatusBarHeaderController.setContentMargins(mContentHorizontalPadding,
mContentHorizontalPadding);
} else {
- view.setPaddingRelative(
- mContentHorizontalPadding,
- view.getPaddingTop(),
- mContentHorizontalPadding,
- view.getPaddingBottom());
+ // Set the horizontal paddings unless the view is the Compose implementation of the
+ // footer actions.
+ if (view.getTag(R.id.tag_compose_qs_footer_actions) == null) {
+ view.setPaddingRelative(
+ mContentHorizontalPadding,
+ view.getPaddingTop(),
+ mContentHorizontalPadding,
+ view.getPaddingBottom());
+ }
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java b/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java
index d801faa44b40..596d024958b0 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java
@@ -303,6 +303,17 @@ public class QSFragment extends LifecycleFragment implements QS, CommandQueue.Ca
// to all views except for qs_footer_actions, so we set it to the Compose view.
composeView.setId(R.id.qs_footer_actions);
+ // Set this tag so that QSContainerImpl does not add horizontal paddings to this Compose
+ // implementation of the footer actions. They will be set in Compose instead so that the
+ // background fills the full screen width.
+ composeView.setTag(R.id.tag_compose_qs_footer_actions, true);
+
+ // Set the same elevation as the View implementation, otherwise the footer actions will be
+ // drawn below the scroll view with QS grid and clicks won't get through on small devices
+ // where there isn't enough vertical space to show all the tiles and the footer actions.
+ composeView.setElevation(
+ composeView.getContext().getResources().getDimension(R.dimen.qs_panel_elevation));
+
// Replace the View by the Compose provided one.
ViewGroup parent = (ViewGroup) footerActionsView.getParent();
ViewGroup.LayoutParams layoutParams = footerActionsView.getLayoutParams();
diff --git a/packages/SystemUI/src/com/android/systemui/qs/TEST_MAPPING b/packages/SystemUI/src/com/android/systemui/qs/TEST_MAPPING
index 86ef7ef2ebce..66f020f24e80 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/TEST_MAPPING
+++ b/packages/SystemUI/src/com/android/systemui/qs/TEST_MAPPING
@@ -10,7 +10,9 @@
"exclude-annotation": "androidx.test.filters.FlakyTest"
}
]
- },
+ }
+ ],
+ "postsubmit": [
{
"name": "QuickSettingsDeviceResetTests",
"options": [
diff --git a/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java b/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java
index 3a64a6a989f2..d23bedace06f 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java
@@ -85,7 +85,6 @@ import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.dump.DumpManager;
import com.android.systemui.flags.FeatureFlags;
-import com.android.systemui.flags.Flags;
import com.android.systemui.keyguard.KeyguardUnlockAnimationController;
import com.android.systemui.keyguard.WakefulnessLifecycle;
import com.android.systemui.model.SysUiState;
@@ -96,6 +95,7 @@ import com.android.systemui.navigationbar.NavigationModeController;
import com.android.systemui.navigationbar.buttons.KeyButtonView;
import com.android.systemui.recents.OverviewProxyService.OverviewProxyListener;
import com.android.systemui.scene.domain.interactor.SceneInteractor;
+import com.android.systemui.scene.shared.flag.SceneContainerFlags;
import com.android.systemui.settings.DisplayTracker;
import com.android.systemui.settings.UserTracker;
import com.android.systemui.shade.ShadeViewController;
@@ -143,6 +143,7 @@ public class OverviewProxyService implements CallbackController<OverviewProxyLis
private final Context mContext;
private final FeatureFlags mFeatureFlags;
+ private final SceneContainerFlags mSceneContainerFlags;
private final Executor mMainExecutor;
private final ShellInterface mShellInterface;
private final Lazy<Optional<CentralSurfaces>> mCentralSurfacesOptionalLazy;
@@ -218,7 +219,7 @@ public class OverviewProxyService implements CallbackController<OverviewProxyLis
// If scene framework is enabled, set the scene container window to
// visible and let the touch "slip" into that window.
- if (mFeatureFlags.isEnabled(Flags.SCENE_CONTAINER)) {
+ if (mSceneContainerFlags.isEnabled()) {
mSceneInteractor.get().setVisible(true, "swipe down on launcher");
} else {
centralSurfaces.onInputFocusTransfer(
@@ -229,7 +230,7 @@ public class OverviewProxyService implements CallbackController<OverviewProxyLis
if (action == ACTION_UP || action == ACTION_CANCEL) {
mInputFocusTransferStarted = false;
- if (!mFeatureFlags.isEnabled(Flags.SCENE_CONTAINER)) {
+ if (!mSceneContainerFlags.isEnabled()) {
float velocity = (event.getY() - mInputFocusTransferStartY)
/ (event.getEventTime() - mInputFocusTransferStartMillis);
centralSurfaces.onInputFocusTransfer(mInputFocusTransferStarted,
@@ -582,6 +583,7 @@ public class OverviewProxyService implements CallbackController<OverviewProxyLis
KeyguardUnlockAnimationController sysuiUnlockAnimationController,
AssistUtils assistUtils,
FeatureFlags featureFlags,
+ SceneContainerFlags sceneContainerFlags,
DumpManager dumpManager,
Optional<UnfoldTransitionProgressForwarder> unfoldTransitionProgressForwarder
) {
@@ -592,6 +594,7 @@ public class OverviewProxyService implements CallbackController<OverviewProxyLis
mContext = context;
mFeatureFlags = featureFlags;
+ mSceneContainerFlags = sceneContainerFlags;
mMainExecutor = mainExecutor;
mShellInterface = shellInterface;
mCentralSurfacesOptionalLazy = centralSurfacesOptionalLazy;
diff --git a/packages/SystemUI/src/com/android/systemui/scene/EmptySceneModule.kt b/packages/SystemUI/src/com/android/systemui/scene/EmptySceneModule.kt
new file mode 100644
index 000000000000..efb9375a21f0
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/scene/EmptySceneModule.kt
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.scene
+
+import com.android.systemui.scene.shared.model.Scene
+import dagger.Module
+import dagger.Provides
+import dagger.multibindings.ElementsIntoSet
+
+@Module
+object EmptySceneModule {
+
+ @Provides
+ @ElementsIntoSet
+ fun emptySceneSet(): Set<Scene> {
+ return emptySet()
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/scene/KeyguardlessSceneContainerFrameworkModule.kt b/packages/SystemUI/src/com/android/systemui/scene/KeyguardlessSceneContainerFrameworkModule.kt
new file mode 100644
index 000000000000..fcbe9a6675ab
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/scene/KeyguardlessSceneContainerFrameworkModule.kt
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.scene
+
+import com.android.systemui.scene.shared.flag.SceneContainerFlagsModule
+import com.android.systemui.scene.shared.model.SceneContainerConfig
+import com.android.systemui.scene.shared.model.SceneKey
+import dagger.Module
+import dagger.Provides
+
+/** Scene framework Dagger module suitable for variants that want to exclude "keyguard" scenes. */
+@Module(
+ includes =
+ [
+ EmptySceneModule::class,
+ GoneSceneModule::class,
+ QuickSettingsSceneModule::class,
+ SceneContainerFlagsModule::class,
+ ShadeSceneModule::class,
+ ],
+)
+object KeyguardlessSceneContainerFrameworkModule {
+
+ // TODO(b/298234162): provide a SceneContainerStartable without lockscreen and bouncer.
+
+ @Provides
+ fun containerConfig(): SceneContainerConfig {
+ return SceneContainerConfig(
+ // Note that this list is in z-order. The first one is the bottom-most and the
+ // last one is top-most.
+ sceneKeys =
+ listOf(
+ SceneKey.Gone,
+ SceneKey.Shade,
+ SceneKey.QuickSettings,
+ ),
+ initialSceneKey = SceneKey.Gone,
+ )
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/scene/SceneContainerFrameworkModule.kt b/packages/SystemUI/src/com/android/systemui/scene/SceneContainerFrameworkModule.kt
index 714795109454..b36ec3274083 100644
--- a/packages/SystemUI/src/com/android/systemui/scene/SceneContainerFrameworkModule.kt
+++ b/packages/SystemUI/src/com/android/systemui/scene/SceneContainerFrameworkModule.kt
@@ -16,19 +16,62 @@
package com.android.systemui.scene
-import com.android.systemui.keyguard.ui.view.LockscreenSceneModule
-import com.android.systemui.scene.domain.startable.SceneContainerStartableModule
-import com.android.systemui.scene.shared.model.SceneContainerConfigModule
-import com.android.systemui.scene.ui.composable.SceneModule
+import com.android.systemui.CoreStartable
+import com.android.systemui.scene.domain.interactor.WindowRootViewVisibilityInteractor
+import com.android.systemui.scene.domain.startable.SceneContainerStartable
+import com.android.systemui.scene.shared.flag.SceneContainerFlagsModule
+import com.android.systemui.scene.shared.model.SceneContainerConfig
+import com.android.systemui.scene.shared.model.SceneKey
+import dagger.Binds
import dagger.Module
+import dagger.Provides
+import dagger.multibindings.ClassKey
+import dagger.multibindings.IntoMap
+/** Scene framework Dagger module suitable for AOSP. */
@Module(
includes =
[
+ BouncerSceneModule::class,
+ EmptySceneModule::class,
+ GoneSceneModule::class,
LockscreenSceneModule::class,
- SceneContainerConfigModule::class,
- SceneContainerStartableModule::class,
- SceneModule::class,
+ QuickSettingsSceneModule::class,
+ SceneContainerFlagsModule::class,
+ ShadeSceneModule::class,
],
)
-object SceneContainerFrameworkModule
+interface SceneContainerFrameworkModule {
+
+ @Binds
+ @IntoMap
+ @ClassKey(SceneContainerStartable::class)
+ fun containerStartable(impl: SceneContainerStartable): CoreStartable
+
+ @Binds
+ @IntoMap
+ @ClassKey(WindowRootViewVisibilityInteractor::class)
+ fun bindWindowRootViewVisibilityInteractor(
+ impl: WindowRootViewVisibilityInteractor
+ ): CoreStartable
+
+ companion object {
+
+ @Provides
+ fun containerConfig(): SceneContainerConfig {
+ return SceneContainerConfig(
+ // Note that this list is in z-order. The first one is the bottom-most and the
+ // last one is top-most.
+ sceneKeys =
+ listOf(
+ SceneKey.Gone,
+ SceneKey.Lockscreen,
+ SceneKey.Bouncer,
+ SceneKey.Shade,
+ SceneKey.QuickSettings,
+ ),
+ initialSceneKey = SceneKey.Lockscreen,
+ )
+ }
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/scene/shared/model/SceneContainerConfigModule.kt b/packages/SystemUI/src/com/android/systemui/scene/ShadelessSceneContainerFrameworkModule.kt
index f74005b03816..c10e51b68ba2 100644
--- a/packages/SystemUI/src/com/android/systemui/scene/shared/model/SceneContainerConfigModule.kt
+++ b/packages/SystemUI/src/com/android/systemui/scene/ShadelessSceneContainerFrameworkModule.kt
@@ -1,5 +1,5 @@
/*
- * Copyright 2023 The Android Open Source Project
+ * Copyright (C) 2023 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -14,27 +14,39 @@
* limitations under the License.
*/
-package com.android.systemui.scene.shared.model
+package com.android.systemui.scene
+import com.android.systemui.scene.shared.flag.SceneContainerFlagsModule
+import com.android.systemui.scene.shared.model.SceneContainerConfig
+import com.android.systemui.scene.shared.model.SceneKey
import dagger.Module
import dagger.Provides
-@Module
-object SceneContainerConfigModule {
+/** Scene framework Dagger module suitable for variants that want to exclude "shade" scenes. */
+@Module(
+ includes =
+ [
+ BouncerSceneModule::class,
+ EmptySceneModule::class,
+ GoneSceneModule::class,
+ LockscreenSceneModule::class,
+ SceneContainerFlagsModule::class,
+ ],
+)
+object ShadelessSceneContainerFrameworkModule {
+
+ // TODO(b/298229861): provide a version of SceneContainerStartable without shade and qs.
@Provides
fun containerConfig(): SceneContainerConfig {
return SceneContainerConfig(
// Note that this list is in z-order. The first one is the bottom-most and the
- // last
- // one is top-most.
+ // last one is top-most.
sceneKeys =
listOf(
SceneKey.Gone,
SceneKey.Lockscreen,
SceneKey.Bouncer,
- SceneKey.Shade,
- SceneKey.QuickSettings,
),
initialSceneKey = SceneKey.Lockscreen,
)
diff --git a/packages/SystemUI/src/com/android/systemui/scene/domain/startable/SceneContainerStartable.kt b/packages/SystemUI/src/com/android/systemui/scene/domain/startable/SceneContainerStartable.kt
index 7f77acc1789a..722d3661d0ae 100644
--- a/packages/SystemUI/src/com/android/systemui/scene/domain/startable/SceneContainerStartable.kt
+++ b/packages/SystemUI/src/com/android/systemui/scene/domain/startable/SceneContainerStartable.kt
@@ -26,13 +26,12 @@ import com.android.systemui.classifier.FalsingCollectorActual
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Application
import com.android.systemui.dagger.qualifiers.DisplayId
-import com.android.systemui.flags.FeatureFlags
-import com.android.systemui.flags.Flags
import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor
import com.android.systemui.keyguard.shared.model.WakefulnessState
import com.android.systemui.model.SysUiState
import com.android.systemui.model.updateFlags
import com.android.systemui.scene.domain.interactor.SceneInteractor
+import com.android.systemui.scene.shared.flag.SceneContainerFlags
import com.android.systemui.scene.shared.logger.SceneLogger
import com.android.systemui.scene.shared.model.ObservableTransitionState
import com.android.systemui.scene.shared.model.SceneKey
@@ -66,7 +65,7 @@ constructor(
private val sceneInteractor: SceneInteractor,
private val authenticationInteractor: AuthenticationInteractor,
private val keyguardInteractor: KeyguardInteractor,
- private val featureFlags: FeatureFlags,
+ private val flags: SceneContainerFlags,
private val sysUiState: SysUiState,
@DisplayId private val displayId: Int,
private val sceneLogger: SceneLogger,
@@ -74,14 +73,17 @@ constructor(
) : CoreStartable {
override fun start() {
- if (featureFlags.isEnabled(Flags.SCENE_CONTAINER)) {
+ if (flags.isEnabled()) {
sceneLogger.logFrameworkEnabled(isEnabled = true)
hydrateVisibility()
automaticallySwitchScenes()
hydrateSystemUiState()
collectFalsingSignals()
} else {
- sceneLogger.logFrameworkEnabled(isEnabled = false)
+ sceneLogger.logFrameworkEnabled(
+ isEnabled = false,
+ reason = flags.requirementDescription(),
+ )
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/scene/shared/flag/SceneContainerFlags.kt b/packages/SystemUI/src/com/android/systemui/scene/shared/flag/SceneContainerFlags.kt
new file mode 100644
index 000000000000..83fb723eda82
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/scene/shared/flag/SceneContainerFlags.kt
@@ -0,0 +1,136 @@
+/*
+ * Copyright 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.scene.shared.flag
+
+import androidx.annotation.VisibleForTesting
+import com.android.systemui.compose.ComposeFacade
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.flags.FeatureFlagsClassic
+import com.android.systemui.flags.Flag
+import com.android.systemui.flags.Flags
+import com.android.systemui.flags.ReleasedFlag
+import com.android.systemui.flags.ResourceBooleanFlag
+import com.android.systemui.flags.UnreleasedFlag
+import dagger.Module
+import dagger.Provides
+import dagger.assisted.Assisted
+import dagger.assisted.AssistedFactory
+import dagger.assisted.AssistedInject
+
+/**
+ * Defines interface for classes that can check whether the scene container framework feature is
+ * enabled.
+ */
+interface SceneContainerFlags {
+
+ /** Returns `true` if the Scene Container Framework is enabled; `false` otherwise. */
+ fun isEnabled(): Boolean
+
+ /** Returns a developer-readable string that describes the current requirement list. */
+ fun requirementDescription(): String
+}
+
+class SceneContainerFlagsImpl
+@AssistedInject
+constructor(
+ private val featureFlags: FeatureFlagsClassic,
+ @Assisted private val isComposeAvailable: Boolean,
+) : SceneContainerFlags {
+
+ companion object {
+ @VisibleForTesting
+ val flags: List<Flag<Boolean>> =
+ listOf(
+ Flags.SCENE_CONTAINER,
+ Flags.MIGRATE_SPLIT_KEYGUARD_BOTTOM_AREA,
+ Flags.MIGRATE_LOCK_ICON,
+ Flags.MIGRATE_NSSL,
+ Flags.MIGRATE_KEYGUARD_STATUS_VIEW,
+ )
+ }
+
+ /** The list of requirements, all must be met for the feature to be enabled. */
+ private val requirements =
+ flags.map { FlagMustBeEnabled(it) } +
+ listOf(ComposeMustBeAvailable(), CompileTimeFlagMustBeEnabled())
+
+ override fun isEnabled(): Boolean {
+ return requirements.all { it.isMet() }
+ }
+
+ override fun requirementDescription(): String {
+ return buildString {
+ requirements.forEach { requirement ->
+ append('\n')
+ append(if (requirement.isMet()) " [MET]" else "[NOT MET]")
+ append(" ${requirement.name}")
+ }
+ }
+ }
+
+ private interface Requirement {
+ val name: String
+
+ fun isMet(): Boolean
+ }
+
+ private inner class ComposeMustBeAvailable : Requirement {
+ override val name = "Jetpack Compose must be available"
+
+ override fun isMet(): Boolean {
+ return isComposeAvailable
+ }
+ }
+
+ private inner class CompileTimeFlagMustBeEnabled : Requirement {
+ override val name = "Flags.SCENE_CONTAINER_ENABLED must be enabled in code"
+
+ override fun isMet(): Boolean {
+ return Flags.SCENE_CONTAINER_ENABLED
+ }
+ }
+
+ private inner class FlagMustBeEnabled<FlagType : Flag<*>>(
+ private val flag: FlagType,
+ ) : Requirement {
+ override val name = "Flag ${flag.name} must be enabled"
+
+ override fun isMet(): Boolean {
+ return when (flag) {
+ is ResourceBooleanFlag -> featureFlags.isEnabled(flag)
+ is ReleasedFlag -> featureFlags.isEnabled(flag)
+ is UnreleasedFlag -> featureFlags.isEnabled(flag)
+ else -> error("Unsupported flag type ${flag.javaClass}")
+ }
+ }
+ }
+
+ @AssistedFactory
+ interface Factory {
+ fun create(isComposeAvailable: Boolean): SceneContainerFlagsImpl
+ }
+}
+
+@Module
+object SceneContainerFlagsModule {
+
+ @Provides
+ @SysUISingleton
+ fun impl(factory: SceneContainerFlagsImpl.Factory): SceneContainerFlags {
+ return factory.create(ComposeFacade.isComposeAvailable())
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/scene/shared/logger/SceneLogger.kt b/packages/SystemUI/src/com/android/systemui/scene/shared/logger/SceneLogger.kt
index 62136dcd8e1d..c2c2e04990c2 100644
--- a/packages/SystemUI/src/com/android/systemui/scene/shared/logger/SceneLogger.kt
+++ b/packages/SystemUI/src/com/android/systemui/scene/shared/logger/SceneLogger.kt
@@ -24,16 +24,21 @@ import javax.inject.Inject
class SceneLogger @Inject constructor(@SceneFrameworkLog private val logBuffer: LogBuffer) {
- fun logFrameworkEnabled(isEnabled: Boolean) {
+ fun logFrameworkEnabled(isEnabled: Boolean, reason: String? = null) {
fun asWord(isEnabled: Boolean): String {
return if (isEnabled) "enabled" else "disabled"
}
logBuffer.log(
tag = TAG,
- level = LogLevel.INFO,
- messageInitializer = { bool1 = isEnabled },
- messagePrinter = { "Scene framework is ${asWord(bool1)}" }
+ level = if (isEnabled) LogLevel.INFO else LogLevel.WARNING,
+ messageInitializer = {
+ bool1 = isEnabled
+ str1 = reason
+ },
+ messagePrinter = {
+ "Scene framework is ${asWord(bool1)}${if (str1 != null) " $str1" else ""}"
+ }
)
}
diff --git a/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java b/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java
index 8db7abf7347f..c1999043743c 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java
@@ -163,6 +163,7 @@ import com.android.systemui.plugins.FalsingManager.FalsingTapListener;
import com.android.systemui.plugins.qs.QS;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.plugins.statusbar.StatusBarStateController.StateListener;
+import com.android.systemui.shade.data.repository.ShadeRepository;
import com.android.systemui.shade.transition.ShadeTransitionController;
import com.android.systemui.shared.system.InteractionJankMonitorWrapper;
import com.android.systemui.shared.system.QuickStepContract;
@@ -350,6 +351,7 @@ public final class NotificationPanelViewController implements ShadeSurface, Dump
private final Interpolator mBounceInterpolator;
private final NotificationShadeWindowController mNotificationShadeWindowController;
private final ShadeExpansionStateManager mShadeExpansionStateManager;
+ private final ShadeRepository mShadeRepository;
private final FalsingTapListener mFalsingTapListener = this::falsingAdditionalTapRequired;
private final AccessibilityDelegate mAccessibilityDelegate = new ShadeAccessibilityDelegate();
private final NotificationGutsManager mGutsManager;
@@ -710,7 +712,8 @@ public final class NotificationPanelViewController implements ShadeSurface, Dump
VibratorHelper vibratorHelper,
LatencyTracker latencyTracker,
PowerManager powerManager,
- AccessibilityManager accessibilityManager, @DisplayId int displayId,
+ AccessibilityManager accessibilityManager,
+ @DisplayId int displayId,
KeyguardUpdateMonitor keyguardUpdateMonitor,
MetricsLogger metricsLogger,
ShadeLogger shadeLogger,
@@ -746,6 +749,7 @@ public final class NotificationPanelViewController implements ShadeSurface, Dump
ScreenOffAnimationController screenOffAnimationController,
LockscreenGestureLogger lockscreenGestureLogger,
ShadeExpansionStateManager shadeExpansionStateManager,
+ ShadeRepository shadeRepository,
Optional<SysUIUnfoldComponent> unfoldComponent,
SysUiState sysUiState,
Provider<KeyguardBottomAreaViewController> keyguardBottomAreaViewControllerProvider,
@@ -788,6 +792,7 @@ public final class NotificationPanelViewController implements ShadeSurface, Dump
mStatusBarKeyguardViewManager = statusBarKeyguardViewManager;
mLockscreenGestureLogger = lockscreenGestureLogger;
mShadeExpansionStateManager = shadeExpansionStateManager;
+ mShadeRepository = shadeRepository;
mShadeLog = shadeLogger;
mGutsManager = gutsManager;
mDreamingToLockscreenTransitionViewModel = dreamingToLockscreenTransitionViewModel;
@@ -3952,6 +3957,7 @@ public final class NotificationPanelViewController implements ShadeSurface, Dump
}
mExpandedFraction = Math.min(1f,
maxPanelHeight == 0 ? 0 : mExpandedHeight / maxPanelHeight);
+ mShadeRepository.setLegacyShadeExpansion(mExpandedFraction);
mQsController.setShadeExpansion(mExpandedHeight, mExpandedFraction);
mExpansionDragDownAmountPx = h;
mAmbientState.setExpansionFraction(mExpandedFraction);
diff --git a/packages/SystemUI/src/com/android/systemui/shade/ShadeViewProviderModule.kt b/packages/SystemUI/src/com/android/systemui/shade/ShadeViewProviderModule.kt
index 6585fcb1ae53..3f7512a25732 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/ShadeViewProviderModule.kt
+++ b/packages/SystemUI/src/com/android/systemui/shade/ShadeViewProviderModule.kt
@@ -26,13 +26,13 @@ import com.android.systemui.R
import com.android.systemui.battery.BatteryMeterView
import com.android.systemui.battery.BatteryMeterViewController
import com.android.systemui.biometrics.AuthRippleView
-import com.android.systemui.compose.ComposeFacade
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Main
import com.android.systemui.flags.FeatureFlags
import com.android.systemui.flags.Flags
import com.android.systemui.keyguard.ui.view.KeyguardRootView
import com.android.systemui.privacy.OngoingPrivacyChip
+import com.android.systemui.scene.shared.flag.SceneContainerFlags
import com.android.systemui.scene.shared.model.Scene
import com.android.systemui.scene.shared.model.SceneContainerConfig
import com.android.systemui.scene.ui.view.SceneWindowRootView
@@ -70,15 +70,13 @@ abstract class ShadeViewProviderModule {
@SysUISingleton
fun providesWindowRootView(
layoutInflater: LayoutInflater,
- featureFlags: FeatureFlags,
+ sceneContainerFlags: SceneContainerFlags,
viewModelProvider: Provider<SceneContainerViewModel>,
containerConfigProvider: Provider<SceneContainerConfig>,
scenesProvider: Provider<Set<@JvmSuppressWildcards Scene>>,
layoutInsetController: NotificationInsetsController,
): WindowRootView {
- return if (
- featureFlags.isEnabled(Flags.SCENE_CONTAINER) && ComposeFacade.isComposeAvailable()
- ) {
+ return if (sceneContainerFlags.isEnabled()) {
val sceneWindowRootView =
layoutInflater.inflate(R.layout.scene_window_root, null) as SceneWindowRootView
sceneWindowRootView.init(
@@ -102,9 +100,9 @@ abstract class ShadeViewProviderModule {
@SysUISingleton
fun providesNotificationShadeWindowView(
root: WindowRootView,
- featureFlags: FeatureFlags,
+ sceneContainerFlags: SceneContainerFlags,
): NotificationShadeWindowView {
- if (featureFlags.isEnabled(Flags.SCENE_CONTAINER)) {
+ if (sceneContainerFlags.isEnabled()) {
return root.requireViewById(R.id.legacy_window_root)
}
return root as NotificationShadeWindowView?
diff --git a/packages/SystemUI/src/com/android/systemui/shade/data/repository/ShadeRepository.kt b/packages/SystemUI/src/com/android/systemui/shade/data/repository/ShadeRepository.kt
index 5a8be1e328f6..509921fd38e1 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/data/repository/ShadeRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/shade/data/repository/ShadeRepository.kt
@@ -34,21 +34,48 @@ interface ShadeRepository {
/** ShadeModel information regarding shade expansion events */
val shadeModel: Flow<ShadeModel>
- /** Amount qs has expanded. Quick Settings can be expanded without the full shade expansion. */
+ /**
+ * Amount qs has expanded, [0-1]. 0 means fully collapsed, 1 means fully expanded. Quick
+ * Settings can be expanded without the full shade expansion.
+ */
val qsExpansion: StateFlow<Float>
- /** The amount the shade has expanded */
- val shadeExpansion: StateFlow<Float>
+ /**
+ * The amount the lockscreen shade has dragged down by the user, [0-1]. 0 means fully collapsed,
+ * 1 means fully expanded.
+ */
+ val lockscreenShadeExpansion: StateFlow<Float>
+
+ /**
+ * NotificationPanelViewController.mExpandedFraction as a StateFlow. This nominally represents
+ * the amount the shade has expanded 0-1 like many other flows in this repo, but there are cases
+ * where its value will be 1 and no shade will be rendered, e.g. whenever the keyguard is
+ * visible and when quick settings is expanded. The confusing nature and impending deletion of
+ * this makes it unsuitable for future development, so usage is discouraged.
+ */
+ @Deprecated("Use ShadeInteractor.shadeExpansion instead")
+ val legacyShadeExpansion: StateFlow<Float>
/** Amount shade has expanded with regard to the UDFPS location */
val udfpsTransitionToFullShadeProgress: StateFlow<Float>
/** The amount QS has expanded without notifications */
fun setQsExpansion(qsExpansion: Float)
+
fun setUdfpsTransitionToFullShadeProgress(progress: Float)
- /** The amount the shade has expanded, [0-1]. 0 means fully collapsed, 1 means fully expanded */
- fun setShadeExpansion(expansion: Float)
+ /**
+ * Set the amount the shade has dragged down by the user, [0-1]. 0 means fully collapsed, 1
+ * means fully expanded.
+ */
+ fun setLockscreenShadeExpansion(lockscreenShadeExpansion: Float)
+
+ /**
+ * Set the legacy expansion value. This should only be called whenever the value of
+ * NotificationPanelViewController.mExpandedFraction changes or in tests.
+ */
+ @Deprecated("Should only be called by NPVC and tests")
+ fun setLegacyShadeExpansion(expandedFraction: Float)
}
/** Business logic for shade interactions */
@@ -84,18 +111,29 @@ constructor(shadeExpansionStateManager: ShadeExpansionStateManager) : ShadeRepos
private val _qsExpansion = MutableStateFlow(0f)
override val qsExpansion: StateFlow<Float> = _qsExpansion.asStateFlow()
- private val _shadeExpansion = MutableStateFlow(0f)
- override val shadeExpansion: StateFlow<Float> = _shadeExpansion.asStateFlow()
+ private val _lockscreenShadeExpansion = MutableStateFlow(0f)
+ override val lockscreenShadeExpansion: StateFlow<Float> =
+ _lockscreenShadeExpansion.asStateFlow()
private var _udfpsTransitionToFullShadeProgress = MutableStateFlow(0f)
override val udfpsTransitionToFullShadeProgress: StateFlow<Float> =
_udfpsTransitionToFullShadeProgress.asStateFlow()
+
+ private val _legacyShadeExpansion = MutableStateFlow(0f)
+ @Deprecated("Use ShadeInteractor.shadeExpansion instead")
+ override val legacyShadeExpansion: StateFlow<Float> = _legacyShadeExpansion.asStateFlow()
+
override fun setQsExpansion(qsExpansion: Float) {
_qsExpansion.value = qsExpansion
}
- override fun setShadeExpansion(expansion: Float) {
- _shadeExpansion.value = expansion
+ @Deprecated("Should only be called by NPVC and tests")
+ override fun setLegacyShadeExpansion(expandedFraction: Float) {
+ _legacyShadeExpansion.value = expandedFraction
+ }
+
+ override fun setLockscreenShadeExpansion(lockscreenShadeExpansion: Float) {
+ _lockscreenShadeExpansion.value = lockscreenShadeExpansion
}
override fun setUdfpsTransitionToFullShadeProgress(progress: Float) {
diff --git a/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeInteractor.kt b/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeInteractor.kt
index 288d32e58c7c..fd63b89d1199 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeInteractor.kt
@@ -22,6 +22,7 @@ import com.android.systemui.keyguard.data.repository.KeyguardRepository
import com.android.systemui.keyguard.shared.model.StatusBarState
import com.android.systemui.shade.data.repository.ShadeRepository
import com.android.systemui.statusbar.disableflags.data.repository.DisableFlagsRepository
+import com.android.systemui.statusbar.notification.stack.domain.interactor.SharedNotificationContainerInteractor
import com.android.systemui.statusbar.pipeline.mobile.data.repository.UserSetupRepository
import com.android.systemui.statusbar.policy.DeviceProvisionedController
import com.android.systemui.user.domain.interactor.UserInteractor
@@ -31,6 +32,7 @@ import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.combine
+import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.stateIn
@@ -45,6 +47,7 @@ constructor(
userSetupRepository: UserSetupRepository,
deviceProvisionedController: DeviceProvisionedController,
userInteractor: UserInteractor,
+ sharedNotificationContainerInteractor: SharedNotificationContainerInteractor,
repository: ShadeRepository,
) {
/** Emits true if the shade is currently allowed and false otherwise. */
@@ -53,16 +56,31 @@ constructor(
.map { it.isShadeEnabled() }
.stateIn(scope, SharingStarted.Eagerly, initialValue = false)
+ /**
+ * Whether split shade, the combined notifications and quick settings shade used for large
+ * screens, is enabled.
+ */
+ val splitShadeEnabled: Flow<Boolean> =
+ sharedNotificationContainerInteractor.configurationBasedDimensions
+ .map { dimens -> dimens.useSplitShade }
+ .distinctUntilChanged()
+
/** The amount [0-1] that the shade has been opened */
val shadeExpansion: Flow<Float> =
- combine(repository.shadeExpansion, keyguardRepository.statusBarState) {
- shadeExpansion,
- statusBarState ->
- // This is required, as shadeExpansion gets reset to 0f even with the shade open
- if (statusBarState == StatusBarState.SHADE_LOCKED) {
- 1f
- } else {
- shadeExpansion
+ combine(
+ repository.lockscreenShadeExpansion,
+ keyguardRepository.statusBarState,
+ repository.legacyShadeExpansion,
+ repository.qsExpansion,
+ splitShadeEnabled
+ ) { dragDownAmount, statusBarState, legacyShadeExpansion, qsExpansion, splitShadeEnabled ->
+ when (statusBarState) {
+ // legacyShadeExpansion is 1 instead of 0 when QS is expanded
+ StatusBarState.SHADE ->
+ if (!splitShadeEnabled && qsExpansion > 0f) 0f else legacyShadeExpansion
+ StatusBarState.KEYGUARD -> dragDownAmount
+ // This is required, as shadeExpansion gets reset to 0f even with the shade open
+ StatusBarState.SHADE_LOCKED -> 1f
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/LockscreenShadeTransitionController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/LockscreenShadeTransitionController.kt
index f004982413e8..73bbbca09fe8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/LockscreenShadeTransitionController.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/LockscreenShadeTransitionController.kt
@@ -447,7 +447,7 @@ class LockscreenShadeTransitionController @Inject constructor(
if (!nsslController.isInLockedDownShade() || field == 0f || forceApplyAmount) {
fractionToShade =
MathUtils.saturate(dragDownAmount / notificationShelfTransitionDistance)
- shadeRepository.setShadeExpansion(fractionToShade)
+ shadeRepository.setLockscreenShadeExpansion(fractionToShade)
nsslController.setTransitionToFullShadeAmount(fractionToShade)
qsTransitionController.dragDownAmount = value
@@ -857,12 +857,12 @@ class DragDownHelper(
MotionEvent.ACTION_MOVE -> {
val h = y - initialTouchY
// Adjust the touch slop if another gesture may be being performed.
- val touchSlop = if (event.classification
- == MotionEvent.CLASSIFICATION_AMBIGUOUS_GESTURE) {
- touchSlop * slopMultiplier
- } else {
- touchSlop
- }
+ val touchSlop =
+ if (event.classification == MotionEvent.CLASSIFICATION_AMBIGUOUS_GESTURE) {
+ touchSlop * slopMultiplier
+ } else {
+ touchSlop
+ }
if (h > touchSlop && h > Math.abs(x - initialTouchX)) {
isDraggingDown = true
captureStartingChild(initialTouchX, initialTouchY)
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/core/StatusBarInitializer.kt b/packages/SystemUI/src/com/android/systemui/statusbar/core/StatusBarInitializer.kt
index 2ad71e7d989d..80274bde6ce2 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/core/StatusBarInitializer.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/core/StatusBarInitializer.kt
@@ -27,6 +27,7 @@ import com.android.systemui.statusbar.phone.fragment.dagger.StatusBarFragmentCom
import com.android.systemui.statusbar.window.StatusBarWindowController
import java.lang.IllegalStateException
import javax.inject.Inject
+import javax.inject.Provider
/**
* Responsible for creating the status bar window and initializing the root components of that
@@ -35,6 +36,7 @@ import javax.inject.Inject
@SysUISingleton
class StatusBarInitializer @Inject constructor(
private val windowController: StatusBarWindowController,
+ private val collapsedStatusBarFragmentProvider: Provider<CollapsedStatusBarFragment>,
private val creationListeners: Set<@JvmSuppressWildcards OnStatusBarViewInitializedListener>,
) {
@@ -43,11 +45,9 @@ class StatusBarInitializer @Inject constructor(
/**
* Creates the status bar window and root views, and initializes the component.
*
- * TODO(b/277762009): Inject StatusBarFragmentCreator and make this class a CoreStartable.
+ * TODO(b/277764509): Initialize the status bar via [CoreStartable#start].
*/
- fun initializeStatusBar(
- statusBarFragmentCreator: () -> CollapsedStatusBarFragment,
- ) {
+ fun initializeStatusBar() {
windowController.fragmentHostManager.addTagListener(
CollapsedStatusBarFragment.TAG,
object : FragmentHostManager.FragmentListener {
@@ -67,11 +67,14 @@ class StatusBarInitializer @Inject constructor(
override fun onFragmentViewDestroyed(tag: String?, fragment: Fragment?) {
// nop
}
- }).fragmentManager
+ }
+ ).fragmentManager
.beginTransaction()
- .replace(R.id.status_bar_container,
- statusBarFragmentCreator.invoke(),
- CollapsedStatusBarFragment.TAG)
+ .replace(
+ R.id.status_bar_container,
+ collapsedStatusBarFragmentProvider.get(),
+ CollapsedStatusBarFragment.TAG
+ )
.commit()
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/events/SystemStatusAnimationSchedulerImpl.kt b/packages/SystemUI/src/com/android/systemui/statusbar/events/SystemStatusAnimationSchedulerImpl.kt
index f40f57099110..a3bc00248362 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/events/SystemStatusAnimationSchedulerImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/events/SystemStatusAnimationSchedulerImpl.kt
@@ -132,8 +132,9 @@ constructor(
override fun onStatusEvent(event: StatusEvent) {
Assert.isMainThread()
- // Ignore any updates until the system is up and running
- if (isTooEarly() || !isImmersiveIndicatorEnabled()) {
+ // Ignore any updates until the system is up and running. However, for important events that
+ // request to be force visible (like privacy), ignore whether it's too early.
+ if ((isTooEarly() && !event.forceVisible) || !isImmersiveIndicatorEnabled()) {
return
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/events/SystemStatusAnimationSchedulerLegacyImpl.kt b/packages/SystemUI/src/com/android/systemui/statusbar/events/SystemStatusAnimationSchedulerLegacyImpl.kt
index 5fa83ef5d454..6b5a548b0afe 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/events/SystemStatusAnimationSchedulerLegacyImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/events/SystemStatusAnimationSchedulerLegacyImpl.kt
@@ -93,8 +93,9 @@ constructor(
@SystemAnimationState override fun getAnimationState() = animationState
override fun onStatusEvent(event: StatusEvent) {
- // Ignore any updates until the system is up and running
- if (isTooEarly() || !isImmersiveIndicatorEnabled()) {
+ // Ignore any updates until the system is up and running. However, for important events that
+ // request to be force visible (like privacy), ignore whether it's too early.
+ if ((isTooEarly() && !event.forceVisible) || !isImmersiveIndicatorEnabled()) {
return
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/ConversationNotifications.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/ConversationNotifications.kt
index d24896148095..6e3b15da4423 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/ConversationNotifications.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/ConversationNotifications.kt
@@ -34,6 +34,7 @@ import com.android.systemui.statusbar.notification.collection.inflation.BindEven
import com.android.systemui.statusbar.notification.collection.notifcollection.CommonNotifCollection
import com.android.systemui.statusbar.notification.collection.notifcollection.NotifCollectionListener
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow
+import com.android.systemui.statusbar.notification.row.NotificationContentInflaterLogger
import com.android.systemui.statusbar.notification.row.NotificationContentView
import com.android.systemui.statusbar.notification.stack.StackStateAnimator
import com.android.systemui.statusbar.policy.HeadsUpManager
@@ -47,7 +48,11 @@ class ConversationNotificationProcessor @Inject constructor(
private val launcherApps: LauncherApps,
private val conversationNotificationManager: ConversationNotificationManager
) {
- fun processNotification(entry: NotificationEntry, recoveredBuilder: Notification.Builder) {
+ fun processNotification(
+ entry: NotificationEntry,
+ recoveredBuilder: Notification.Builder,
+ logger: NotificationContentInflaterLogger
+ ) {
val messagingStyle = recoveredBuilder.style as? Notification.MessagingStyle ?: return
messagingStyle.conversationType =
if (entry.ranking.channel.isImportantConversation)
@@ -55,6 +60,7 @@ class ConversationNotificationProcessor @Inject constructor(
else
Notification.MessagingStyle.CONVERSATION_TYPE_NORMAL
entry.ranking.conversationShortcutInfo?.let { shortcutInfo ->
+ logger.logAsyncTaskProgress(entry, "getting shortcut icon")
messagingStyle.shortcutIcon = launcherApps.getShortcutIcon(shortcutInfo)
shortcutInfo.label?.let { label ->
messagingStyle.conversationTitle = label
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifInflaterImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifInflaterImpl.java
index d1aa01bb2125..98109f940289 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifInflaterImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifInflaterImpl.java
@@ -36,12 +36,14 @@ import javax.inject.Inject;
public class NotifInflaterImpl implements NotifInflater {
private final NotifInflationErrorManager mNotifErrorManager;
+ private final NotifInflaterLogger mLogger;
private NotificationRowBinderImpl mNotificationRowBinder;
@Inject
- public NotifInflaterImpl(NotifInflationErrorManager errorManager) {
+ public NotifInflaterImpl(NotifInflationErrorManager errorManager, NotifInflaterLogger logger) {
mNotifErrorManager = errorManager;
+ mLogger = logger;
}
/**
@@ -51,12 +53,6 @@ public class NotifInflaterImpl implements NotifInflater {
mNotificationRowBinder = rowBinder;
}
- @Override
- public void rebindViews(@NonNull NotificationEntry entry, @NonNull Params params,
- @NonNull InflationCallback callback) {
- inflateViews(entry, params, callback);
- }
-
/**
* Called to inflate the views of an entry. Views are not considered inflated until all of its
* views are bound.
@@ -64,23 +60,43 @@ public class NotifInflaterImpl implements NotifInflater {
@Override
public void inflateViews(@NonNull NotificationEntry entry, @NonNull Params params,
@NonNull InflationCallback callback) {
+ mLogger.logInflatingViews(entry, params);
+ inflateViewsImpl(entry, params, callback);
+ mLogger.logInflatedViews(entry);
+ }
+ @Override
+ public void rebindViews(@NonNull NotificationEntry entry, @NonNull Params params,
+ @NonNull InflationCallback callback) {
+ mLogger.logRebindingViews(entry, params);
+ inflateViewsImpl(entry, params, callback);
+ mLogger.logReboundViews(entry);
+ }
+
+ private void inflateViewsImpl(@NonNull NotificationEntry entry, @NonNull Params params,
+ @NonNull InflationCallback callback) {
try {
requireBinder().inflateViews(
entry,
params,
wrapInflationCallback(callback));
} catch (InflationException e) {
+ mLogger.logInflationException(entry, e);
mNotifErrorManager.setInflationError(entry, e);
}
}
@Override
public boolean abortInflation(NotificationEntry entry) {
- return entry.abortTask();
+ final boolean abortedTask = entry.abortTask();
+ if (abortedTask) {
+ mLogger.logAbortInflationAbortedTask(entry);
+ }
+ return abortedTask;
}
@Override
public void releaseViews(@NonNull NotificationEntry entry) {
+ mLogger.logReleasingViews(entry);
requireBinder().releaseViews(entry);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifInflaterLogger.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifInflaterLogger.kt
new file mode 100644
index 000000000000..366c7d329662
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifInflaterLogger.kt
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.notification.collection
+
+import com.android.systemui.log.LogBuffer
+import com.android.systemui.log.core.LogLevel
+import com.android.systemui.log.dagger.NotifInflationLog
+import com.android.systemui.statusbar.notification.InflationException
+import com.android.systemui.statusbar.notification.collection.inflation.NotifInflater.Params
+import com.android.systemui.statusbar.notification.logKey
+import javax.inject.Inject
+
+class NotifInflaterLogger @Inject constructor(@NotifInflationLog private val buffer: LogBuffer) {
+ fun logInflatingViews(entry: NotificationEntry, params: Params) {
+ buffer.log(
+ TAG,
+ LogLevel.DEBUG,
+ {
+ str1 = entry.logKey
+ str2 = params.reason
+ },
+ { "inflating views for $str1: $str2" }
+ )
+ }
+
+ fun logInflatedViews(entry: NotificationEntry) {
+ buffer.log(TAG, LogLevel.DEBUG, { str1 = entry.logKey }, { "inflated views for $str1" })
+ }
+
+ fun logRebindingViews(entry: NotificationEntry, params: Params) {
+ buffer.log(
+ TAG,
+ LogLevel.DEBUG,
+ {
+ str1 = entry.logKey
+ str2 = params.reason
+ },
+ { "rebinding views for $str1: $str2" }
+ )
+ }
+
+ fun logReboundViews(entry: NotificationEntry) {
+ buffer.log(TAG, LogLevel.DEBUG, { str1 = entry.logKey }, { "rebound views for $str1" })
+ }
+
+ fun logInflationException(entry: NotificationEntry, exc: InflationException) {
+ buffer.log(
+ TAG,
+ LogLevel.WARNING,
+ {
+ str1 = entry.logKey
+ str2 = exc.stackTraceToString()
+ },
+ { "exception inflating views for $str1: $str2" }
+ )
+ }
+
+ fun logAbortInflationAbortedTask(entry: NotificationEntry) {
+ buffer.log(
+ TAG,
+ LogLevel.DEBUG,
+ { str1 = entry.logKey },
+ { "aborted task to abort inflation for $str1" }
+ )
+ }
+
+ fun logReleasingViews(entry: NotificationEntry) {
+ buffer.log(TAG, LogLevel.DEBUG, { str1 = entry.logKey }, { "aborting inflation for $str1" })
+ }
+}
+
+private const val TAG = "NotifInflater"
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/StackCoordinator.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/StackCoordinator.kt
index 5c2f9a8d28ec..62a0d138fd05 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/StackCoordinator.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/StackCoordinator.kt
@@ -39,10 +39,7 @@ class StackCoordinator @Inject internal constructor(
override fun attach(pipeline: NotifPipeline) {
pipeline.addOnAfterRenderListListener(::onAfterRenderList)
- // TODO(b/282865576): This has an issue where it makes changes to some groups without
- // notifying listeners. To be fixed in QPR, but for now let's comment it out to avoid the
- // group expansion bug.
- // groupExpansionManagerImpl.attach(pipeline)
+ groupExpansionManagerImpl.attach(pipeline)
}
fun onAfterRenderList(entries: List<ListEntry>, controller: NotifStackController) =
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/NotificationRowBinderImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/NotificationRowBinderImpl.java
index 9ecf50ee4f8c..e20614178885 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/NotificationRowBinderImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/NotificationRowBinderImpl.java
@@ -67,6 +67,7 @@ public class NotificationRowBinderImpl implements NotificationRowBinder {
private final ExpandableNotificationRowComponent.Builder
mExpandableNotificationRowComponentBuilder;
private final IconManager mIconManager;
+ private final NotificationRowBinderLogger mLogger;
private NotificationPresenter mPresenter;
private NotificationListContainer mListContainer;
@@ -84,6 +85,7 @@ public class NotificationRowBinderImpl implements NotificationRowBinder {
Provider<RowInflaterTask> rowInflaterTaskProvider,
ExpandableNotificationRowComponent.Builder expandableNotificationRowComponentBuilder,
IconManager iconManager,
+ NotificationRowBinderLogger logger,
FeatureFlags featureFlags) {
mContext = context;
mNotifBindPipeline = notifBindPipeline;
@@ -94,6 +96,7 @@ public class NotificationRowBinderImpl implements NotificationRowBinder {
mRowInflaterTaskProvider = rowInflaterTaskProvider;
mExpandableNotificationRowComponentBuilder = expandableNotificationRowComponentBuilder;
mIconManager = iconManager;
+ mLogger = logger;
mFeatureFlags = featureFlags;
}
@@ -124,15 +127,19 @@ public class NotificationRowBinderImpl implements NotificationRowBinder {
ViewGroup parent = mListContainer.getViewParentForNotification(entry);
if (entry.rowExists()) {
+ mLogger.logUpdatingRow(entry, params);
mIconManager.updateIcons(entry);
ExpandableNotificationRow row = entry.getRow();
row.reset();
updateRow(entry, row);
inflateContentViews(entry, params, row, callback);
} else {
+ mLogger.logCreatingRow(entry, params);
mIconManager.createIcons(entry);
+ mLogger.logInflatingRow(entry);
mRowInflaterTaskProvider.get().inflate(mContext, parent, entry,
row -> {
+ mLogger.logInflatedRow(entry);
// Setup the controller for the view.
ExpandableNotificationRowComponent component =
mExpandableNotificationRowComponentBuilder
@@ -154,8 +161,10 @@ public class NotificationRowBinderImpl implements NotificationRowBinder {
@Override
public void releaseViews(NotificationEntry entry) {
if (!entry.rowExists()) {
+ mLogger.logNotReleasingViewsRowDoesntExist(entry);
return;
}
+ mLogger.logReleasingViews(entry);
final RowContentBindParams params = mRowContentBindStage.getStageParams(entry);
params.markContentViewsFreeable(FLAG_CONTENT_VIEW_CONTRACTED);
params.markContentViewsFreeable(FLAG_CONTENT_VIEW_EXPANDED);
@@ -220,7 +229,9 @@ public class NotificationRowBinderImpl implements NotificationRowBinder {
}
params.rebindAllContentViews();
+ mLogger.logRequestingRebind(entry, inflaterParams);
mRowContentBindStage.requestRebind(entry, en -> {
+ mLogger.logRebindComplete(entry);
row.setUsesIncreasedCollapsedHeight(useIncreasedCollapsedHeight);
row.setIsLowPriority(isLowPriority);
if (inflationCallback != null) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/NotificationRowBinderLogger.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/NotificationRowBinderLogger.kt
new file mode 100644
index 000000000000..7eafc59019d4
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/NotificationRowBinderLogger.kt
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.notification.collection.inflation
+
+import com.android.systemui.log.LogBuffer
+import com.android.systemui.log.core.LogLevel
+import com.android.systemui.log.dagger.NotifInflationLog
+import com.android.systemui.statusbar.notification.collection.NotificationEntry
+import com.android.systemui.statusbar.notification.collection.inflation.NotifInflater.Params
+import com.android.systemui.statusbar.notification.logKey
+import javax.inject.Inject
+
+class NotificationRowBinderLogger
+@Inject
+constructor(@NotifInflationLog private val buffer: LogBuffer) {
+ fun logCreatingRow(entry: NotificationEntry, params: Params) {
+ buffer.log(
+ TAG,
+ LogLevel.DEBUG,
+ {
+ str1 = entry.logKey
+ str2 = params.reason
+ },
+ { "creating row for $str1: $str2" }
+ )
+ }
+
+ fun logInflatingRow(entry: NotificationEntry) {
+ buffer.log(TAG, LogLevel.DEBUG, { str1 = entry.logKey }, { "inflating row for $str1" })
+ }
+
+ fun logInflatedRow(entry: NotificationEntry) {
+ buffer.log(TAG, LogLevel.DEBUG, { str1 = entry.logKey }, { "inflated row for $str1" })
+ }
+
+ fun logUpdatingRow(entry: NotificationEntry, params: Params) {
+ buffer.log(
+ TAG,
+ LogLevel.DEBUG,
+ {
+ str1 = entry.logKey
+ str2 = params.reason
+ },
+ { "updating row for $str1: $str2" }
+ )
+ }
+
+ fun logReleasingViews(entry: NotificationEntry) {
+ buffer.log(TAG, LogLevel.DEBUG, { str1 = entry.logKey }, { "releasing views for $str1" })
+ }
+
+ fun logNotReleasingViewsRowDoesntExist(entry: NotificationEntry) {
+ buffer.log(
+ TAG,
+ LogLevel.DEBUG,
+ { str1 = entry.logKey },
+ { "not releasing views for $str1: row doesn't exist" }
+ )
+ }
+
+ fun logRequestingRebind(entry: NotificationEntry, params: Params) {
+ buffer.log(
+ TAG,
+ LogLevel.DEBUG,
+ {
+ str1 = entry.key
+ str2 = params.reason
+ },
+ { "requesting rebind for $str1: $str2" }
+ )
+ }
+
+ fun logRebindComplete(entry: NotificationEntry) {
+ buffer.log(TAG, LogLevel.DEBUG, { str1 = entry.key }, { "rebind complete for $str1" })
+ }
+}
+
+private const val TAG = "NotificationRowBinder"
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/GroupExpansionManagerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/GroupExpansionManagerImpl.java
index 46af03a438f5..eb31bd3a95fe 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/GroupExpansionManagerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/GroupExpansionManagerImpl.java
@@ -67,18 +67,29 @@ public class GroupExpansionManagerImpl implements GroupExpansionManager, Dumpabl
* Cleanup entries from mExpandedGroups that no longer exist in the pipeline.
*/
private final OnBeforeRenderListListener mNotifTracker = (entries) -> {
+ if (mExpandedGroups.isEmpty()) {
+ return; // nothing to do
+ }
+
final Set<NotificationEntry> renderingSummaries = new HashSet<>();
for (ListEntry entry : entries) {
if (entry instanceof GroupEntry) {
renderingSummaries.add(entry.getRepresentativeEntry());
}
}
- mExpandedGroups.removeIf(expandedGroup -> !renderingSummaries.contains(expandedGroup));
+
+ // If a group is in mExpandedGroups but not in the pipeline entries, collapse it.
+ final var groupsToRemove = setDifference(mExpandedGroups, renderingSummaries);
+ for (NotificationEntry entry : groupsToRemove) {
+ setGroupExpanded(entry, false);
+ }
};
public void attach(NotifPipeline pipeline) {
- mDumpManager.registerDumpable(this);
- pipeline.addOnBeforeRenderListListener(mNotifTracker);
+ if (mFeatureFlags.isEnabled(Flags.NOTIFICATION_GROUP_EXPANSION_CHANGE)) {
+ mDumpManager.registerDumpable(this);
+ pipeline.addOnBeforeRenderListListener(mNotifTracker);
+ }
}
@Override
@@ -134,4 +145,27 @@ public class GroupExpansionManagerImpl implements GroupExpansionManager, Dumpabl
listener.onGroupExpansionChange(entry.getRow(), expanded);
}
}
+
+ /**
+ * Utility method to compute the difference between two sets of NotificationEntry. Unfortunately
+ * {@code Sets.difference} from Guava is not available in this codebase.
+ */
+ @NonNull
+ private Set<NotificationEntry> setDifference(Set<NotificationEntry> set1,
+ Set<NotificationEntry> set2) {
+ if (set1 == null || set1.isEmpty()) {
+ return new HashSet<>();
+ }
+ if (set2 == null || set2.isEmpty()) {
+ return new HashSet<>(set1);
+ }
+
+ final Set<NotificationEntry> difference = new HashSet<>();
+ for (NotificationEntry e : set1) {
+ if (!set2.contains(e)) {
+ difference.add(e);
+ }
+ }
+ return difference;
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/GroupMembershipManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/GroupMembershipManager.java
index b9c8f7223740..c33e8ab8cdd4 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/GroupMembershipManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/GroupMembershipManager.java
@@ -16,6 +16,7 @@
package com.android.systemui.statusbar.notification.collection.render;
+import android.annotation.NonNull;
import android.annotation.Nullable;
import com.android.systemui.statusbar.notification.collection.ListEntry;
@@ -31,13 +32,14 @@ public interface GroupMembershipManager {
* @return whether a given notification is a top level entry or is the summary in a group which
* has children
*/
- boolean isGroupSummary(NotificationEntry entry);
+ boolean isGroupSummary(@NonNull NotificationEntry entry);
/**
* Get the summary of a specified status bar notification. For an isolated notification this
* returns itself.
*/
- NotificationEntry getGroupSummary(NotificationEntry entry);
+ @Nullable
+ NotificationEntry getGroupSummary(@NonNull NotificationEntry entry);
/**
* Similar to {@link #getGroupSummary(NotificationEntry)} but doesn't get the visual summary
@@ -46,19 +48,20 @@ public interface GroupMembershipManager {
* TODO: remove this when migrating to the new pipeline, this is taken care of in the
* dismissal logic built into NotifCollection
*/
- default NotificationEntry getLogicalGroupSummary(NotificationEntry entry) {
+ @Nullable
+ default NotificationEntry getLogicalGroupSummary(@NonNull NotificationEntry entry) {
return getGroupSummary(entry);
}
/**
* @return whether a given notification is a child in a group
*/
- boolean isChildInGroup(NotificationEntry entry);
+ boolean isChildInGroup(@NonNull NotificationEntry entry);
/**
* Whether this is the only child in a group
*/
- boolean isOnlyChildInGroup(NotificationEntry entry);
+ boolean isOnlyChildInGroup(@NonNull NotificationEntry entry);
/**
* Get the children that are in the summary's group, not including those isolated.
@@ -67,5 +70,5 @@ public interface GroupMembershipManager {
* @return list of the children
*/
@Nullable
- List<NotificationEntry> getChildren(ListEntry summary);
+ List<NotificationEntry> getChildren(@NonNull ListEntry summary);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/GroupMembershipManagerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/GroupMembershipManagerImpl.java
index e784ec62c8e6..a6b855f9b838 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/GroupMembershipManagerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/GroupMembershipManagerImpl.java
@@ -18,40 +18,65 @@ package com.android.systemui.statusbar.notification.collection.render;
import static com.android.systemui.statusbar.notification.collection.GroupEntry.ROOT_ENTRY;
+import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
+import com.android.systemui.dagger.SysUISingleton;
+import com.android.systemui.flags.FeatureFlags;
+import com.android.systemui.flags.Flags;
import com.android.systemui.statusbar.notification.collection.GroupEntry;
import com.android.systemui.statusbar.notification.collection.ListEntry;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import java.util.List;
+import javax.inject.Inject;
+
/**
* ShadeListBuilder groups notifications from system server. This manager translates
* ShadeListBuilder's method of grouping to be used within SystemUI.
*/
+@SysUISingleton
public class GroupMembershipManagerImpl implements GroupMembershipManager {
+ FeatureFlags mFeatureFlags;
+
+ @Inject
+ public GroupMembershipManagerImpl(FeatureFlags featureFlags) {
+ mFeatureFlags = featureFlags;
+ }
+
@Override
- public boolean isGroupSummary(NotificationEntry entry) {
+ public boolean isGroupSummary(@NonNull NotificationEntry entry) {
return getGroupSummary(entry) == entry;
}
+ @Nullable
@Override
- public NotificationEntry getGroupSummary(NotificationEntry entry) {
- if (isEntryTopLevel(entry) || entry.getParent() == null) {
- return null;
+ public NotificationEntry getGroupSummary(@NonNull NotificationEntry entry) {
+ if (mFeatureFlags.isEnabled(Flags.NOTIFICATION_GROUP_EXPANSION_CHANGE)) {
+ if (!isChildInGroup(entry)) {
+ return entry.getRepresentativeEntry();
+ }
+ } else {
+ if (isEntryTopLevel(entry) || entry.getParent() == null) {
+ return null;
+ }
}
return entry.getParent().getRepresentativeEntry();
}
@Override
- public boolean isChildInGroup(NotificationEntry entry) {
- return !isEntryTopLevel(entry);
+ public boolean isChildInGroup(@NonNull NotificationEntry entry) {
+ if (mFeatureFlags.isEnabled(Flags.NOTIFICATION_GROUP_EXPANSION_CHANGE)) {
+ return !isEntryTopLevel(entry) && entry.getParent() != null;
+ } else {
+ return !isEntryTopLevel(entry);
+ }
}
@Override
- public boolean isOnlyChildInGroup(NotificationEntry entry) {
+ public boolean isOnlyChildInGroup(@NonNull NotificationEntry entry) {
if (entry.getParent() == null) {
return false;
}
@@ -61,20 +86,24 @@ public class GroupMembershipManagerImpl implements GroupMembershipManager {
@Nullable
@Override
- public List<NotificationEntry> getChildren(ListEntry entry) {
+ public List<NotificationEntry> getChildren(@NonNull ListEntry entry) {
if (entry instanceof GroupEntry) {
return ((GroupEntry) entry).getChildren();
}
- if (isGroupSummary(entry.getRepresentativeEntry())) {
+ NotificationEntry representativeEntry = entry.getRepresentativeEntry();
+ if (representativeEntry != null && isGroupSummary(representativeEntry)) {
// maybe we were actually passed the summary
- return entry.getRepresentativeEntry().getParent().getChildren();
+ GroupEntry parent = representativeEntry.getParent();
+ if (parent != null) {
+ return parent.getChildren();
+ }
}
return null;
}
- private boolean isEntryTopLevel(NotificationEntry entry) {
+ private boolean isEntryTopLevel(@NonNull NotificationEntry entry) {
return entry.getParent() == ROOT_ENTRY;
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/dagger/NotificationsModule.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/dagger/NotificationsModule.java
index 09be41b56a10..5664a2af7c0e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/dagger/NotificationsModule.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/dagger/NotificationsModule.java
@@ -167,11 +167,8 @@ public interface NotificationsModule {
}
/** Provides an instance of {@link GroupMembershipManager} */
- @SysUISingleton
- @Provides
- static GroupMembershipManager provideGroupMembershipManager() {
- return new GroupMembershipManagerImpl();
- }
+ @Binds
+ GroupMembershipManager provideGroupMembershipManager(GroupMembershipManagerImpl impl);
/** Provides an instance of {@link GroupExpansionManager} */
@Binds
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/logging/NotificationLogger.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/logging/NotificationLogger.java
index d2034d7a8564..8d2a63e9b3fa 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/logging/NotificationLogger.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/logging/NotificationLogger.java
@@ -276,14 +276,16 @@ public class NotificationLogger implements StateListener, CoreStartable {
}
}
- @GuardedBy("mDozingLock")
public void startNotificationLogging() {
if (!mLogging) {
mLogging = true;
if (DEBUG) {
Log.i(TAG, "startNotificationLogging");
}
- boolean lockscreen = mLockscreen != null && mLockscreen;
+ boolean lockscreen;
+ synchronized (mDozingLock) {
+ lockscreen = mLockscreen != null && mLockscreen;
+ }
mNotificationPanelLogger.logPanelShown(lockscreen, getVisibleNotifications());
mListContainer.setChildLocationsChangedListener(this::onChildLocationsChanged);
// Sometimes, the transition from lockscreenOrShadeVisible=false ->
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentInflater.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentInflater.java
index 86f545dc190e..f805183d52aa 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentInflater.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentInflater.java
@@ -80,6 +80,7 @@ public class NotificationContentInflater implements NotificationRowContentBinder
private final Executor mBgExecutor;
private final SmartReplyStateInflater mSmartReplyStateInflater;
private final NotifLayoutInflaterFactory.Provider mNotifLayoutInflaterFactoryProvider;
+ private final NotificationContentInflaterLogger mLogger;
@Inject
NotificationContentInflater(
@@ -89,7 +90,8 @@ public class NotificationContentInflater implements NotificationRowContentBinder
MediaFeatureFlag mediaFeatureFlag,
@Background Executor bgExecutor,
SmartReplyStateInflater smartRepliesInflater,
- NotifLayoutInflaterFactory.Provider notifLayoutInflaterFactoryProvider) {
+ NotifLayoutInflaterFactory.Provider notifLayoutInflaterFactoryProvider,
+ NotificationContentInflaterLogger logger) {
mRemoteViewCache = remoteViewCache;
mRemoteInputManager = remoteInputManager;
mConversationProcessor = conversationProcessor;
@@ -97,6 +99,7 @@ public class NotificationContentInflater implements NotificationRowContentBinder
mBgExecutor = bgExecutor;
mSmartReplyStateInflater = smartRepliesInflater;
mNotifLayoutInflaterFactoryProvider = notifLayoutInflaterFactoryProvider;
+ mLogger = logger;
}
@Override
@@ -111,9 +114,12 @@ public class NotificationContentInflater implements NotificationRowContentBinder
// We don't want to reinflate anything for removed notifications. Otherwise views might
// be readded to the stack, leading to leaks. This may happen with low-priority groups
// where the removal of already removed children can lead to a reinflation.
+ mLogger.logNotBindingRowWasRemoved(entry);
return;
}
+ mLogger.logBinding(entry, contentToBind);
+
StatusBarNotification sbn = entry.getSbn();
// To check if the notification has inline image and preload inline image if necessary.
@@ -141,7 +147,8 @@ public class NotificationContentInflater implements NotificationRowContentBinder
mRemoteInputManager.getRemoteViewsOnClickHandler(),
mIsMediaInQS,
mSmartReplyStateInflater,
- mNotifLayoutInflaterFactoryProvider);
+ mNotifLayoutInflaterFactoryProvider,
+ mLogger);
if (mInflateSynchronously) {
task.onPostExecute(task.doInBackground());
} else {
@@ -166,12 +173,11 @@ public class NotificationContentInflater implements NotificationRowContentBinder
bindParams.usesIncreasedHeadsUpHeight,
packageContext,
row,
- mNotifLayoutInflaterFactoryProvider);
+ mNotifLayoutInflaterFactoryProvider,
+ mLogger);
- result = inflateSmartReplyViews(result, reInflateFlags, entry,
- row.getContext(), packageContext,
- row.getExistingSmartReplyState(),
- smartRepliesInflater);
+ result = inflateSmartReplyViews(result, reInflateFlags, entry, row.getContext(),
+ packageContext, row.getExistingSmartReplyState(), smartRepliesInflater, mLogger);
apply(
mBgExecutor,
@@ -182,15 +188,20 @@ public class NotificationContentInflater implements NotificationRowContentBinder
entry,
row,
mRemoteInputManager.getRemoteViewsOnClickHandler(),
- null);
+ null /* callback */,
+ mLogger);
return result;
}
@Override
- public void cancelBind(
+ public boolean cancelBind(
@NonNull NotificationEntry entry,
@NonNull ExpandableNotificationRow row) {
- entry.abortTask();
+ final boolean abortedTask = entry.abortTask();
+ if (abortedTask) {
+ mLogger.logCancelBindAbortedTask(entry);
+ }
+ return abortedTask;
}
@Override
@@ -198,6 +209,7 @@ public class NotificationContentInflater implements NotificationRowContentBinder
@NonNull NotificationEntry entry,
@NonNull ExpandableNotificationRow row,
@InflationFlag int contentToUnbind) {
+ mLogger.logUnbinding(entry, contentToUnbind);
int curFlag = 1;
while (contentToUnbind != 0) {
if ((contentToUnbind & curFlag) != 0) {
@@ -279,7 +291,8 @@ public class NotificationContentInflater implements NotificationRowContentBinder
Context context,
Context packageContext,
InflatedSmartReplyState previousSmartReplyState,
- SmartReplyStateInflater inflater) {
+ SmartReplyStateInflater inflater,
+ NotificationContentInflaterLogger logger) {
boolean inflateContracted = (reInflateFlags & FLAG_CONTENT_VIEW_CONTRACTED) != 0
&& result.newContentView != null;
boolean inflateExpanded = (reInflateFlags & FLAG_CONTENT_VIEW_EXPANDED) != 0
@@ -287,14 +300,17 @@ public class NotificationContentInflater implements NotificationRowContentBinder
boolean inflateHeadsUp = (reInflateFlags & FLAG_CONTENT_VIEW_HEADS_UP) != 0
&& result.newHeadsUpView != null;
if (inflateContracted || inflateExpanded || inflateHeadsUp) {
+ logger.logAsyncTaskProgress(entry, "inflating contracted smart reply state");
result.inflatedSmartReplyState = inflater.inflateSmartReplyState(entry);
}
if (inflateExpanded) {
+ logger.logAsyncTaskProgress(entry, "inflating expanded smart reply state");
result.expandedInflatedSmartReplies = inflater.inflateSmartReplyViewHolder(
context, packageContext, entry, previousSmartReplyState,
result.inflatedSmartReplyState);
}
if (inflateHeadsUp) {
+ logger.logAsyncTaskProgress(entry, "inflating heads up smart reply state");
result.headsUpInflatedSmartReplies = inflater.inflateSmartReplyViewHolder(
context, packageContext, entry, previousSmartReplyState,
result.inflatedSmartReplyState);
@@ -306,22 +322,28 @@ public class NotificationContentInflater implements NotificationRowContentBinder
Notification.Builder builder, boolean isLowPriority, boolean usesIncreasedHeight,
boolean usesIncreasedHeadsUpHeight, Context packageContext,
ExpandableNotificationRow row,
- NotifLayoutInflaterFactory.Provider notifLayoutInflaterFactoryProvider) {
+ NotifLayoutInflaterFactory.Provider notifLayoutInflaterFactoryProvider,
+ NotificationContentInflaterLogger logger) {
InflationProgress result = new InflationProgress();
+ final NotificationEntry entryForLogging = row.getEntry();
if ((reInflateFlags & FLAG_CONTENT_VIEW_CONTRACTED) != 0) {
+ logger.logAsyncTaskProgress(entryForLogging, "creating contracted remote view");
result.newContentView = createContentView(builder, isLowPriority, usesIncreasedHeight);
}
if ((reInflateFlags & FLAG_CONTENT_VIEW_EXPANDED) != 0) {
+ logger.logAsyncTaskProgress(entryForLogging, "creating expanded remote view");
result.newExpandedView = createExpandedView(builder, isLowPriority);
}
if ((reInflateFlags & FLAG_CONTENT_VIEW_HEADS_UP) != 0) {
+ logger.logAsyncTaskProgress(entryForLogging, "creating heads up remote view");
result.newHeadsUpView = builder.createHeadsUpContentView(usesIncreasedHeadsUpHeight);
}
if ((reInflateFlags & FLAG_CONTENT_VIEW_PUBLIC) != 0) {
+ logger.logAsyncTaskProgress(entryForLogging, "creating public remote view");
result.newPublicView = builder.makePublicContentView(isLowPriority);
}
setNotifsViewsInflaterFactory(result, row, notifLayoutInflaterFactoryProvider);
@@ -361,7 +383,8 @@ public class NotificationContentInflater implements NotificationRowContentBinder
NotificationEntry entry,
ExpandableNotificationRow row,
RemoteViews.InteractionHandler remoteViewClickHandler,
- @Nullable InflationCallback callback) {
+ @Nullable InflationCallback callback,
+ NotificationContentInflaterLogger logger) {
NotificationContentView privateLayout = row.getPrivateLayout();
NotificationContentView publicLayout = row.getPublicLayout();
final HashMap<Integer, CancellationSignal> runningInflations = new HashMap<>();
@@ -374,6 +397,7 @@ public class NotificationContentInflater implements NotificationRowContentBinder
ApplyCallback applyCallback = new ApplyCallback() {
@Override
public void setResultView(View v) {
+ logger.logAsyncTaskProgress(entry, "contracted view applied");
result.inflatedContentView = v;
}
@Override
@@ -381,12 +405,13 @@ public class NotificationContentInflater implements NotificationRowContentBinder
return result.newContentView;
}
};
+ logger.logAsyncTaskProgress(entry, "applying contracted view");
applyRemoteView(bgExecutor, inflateSynchronously, result, reInflateFlags, flag,
remoteViewCache, entry, row, isNewView, remoteViewClickHandler, callback,
privateLayout, privateLayout.getContractedChild(),
privateLayout.getVisibleWrapper(
NotificationContentView.VISIBLE_TYPE_CONTRACTED),
- runningInflations, applyCallback);
+ runningInflations, applyCallback, logger);
}
flag = FLAG_CONTENT_VIEW_EXPANDED;
@@ -398,6 +423,7 @@ public class NotificationContentInflater implements NotificationRowContentBinder
ApplyCallback applyCallback = new ApplyCallback() {
@Override
public void setResultView(View v) {
+ logger.logAsyncTaskProgress(entry, "expanded view applied");
result.inflatedExpandedView = v;
}
@@ -406,12 +432,13 @@ public class NotificationContentInflater implements NotificationRowContentBinder
return result.newExpandedView;
}
};
+ logger.logAsyncTaskProgress(entry, "applying expanded view");
applyRemoteView(bgExecutor, inflateSynchronously, result, reInflateFlags, flag,
remoteViewCache, entry, row, isNewView, remoteViewClickHandler,
callback, privateLayout, privateLayout.getExpandedChild(),
privateLayout.getVisibleWrapper(
NotificationContentView.VISIBLE_TYPE_EXPANDED), runningInflations,
- applyCallback);
+ applyCallback, logger);
}
}
@@ -424,6 +451,7 @@ public class NotificationContentInflater implements NotificationRowContentBinder
ApplyCallback applyCallback = new ApplyCallback() {
@Override
public void setResultView(View v) {
+ logger.logAsyncTaskProgress(entry, "heads up view applied");
result.inflatedHeadsUpView = v;
}
@@ -432,12 +460,13 @@ public class NotificationContentInflater implements NotificationRowContentBinder
return result.newHeadsUpView;
}
};
+ logger.logAsyncTaskProgress(entry, "applying heads up view");
applyRemoteView(bgExecutor, inflateSynchronously, result, reInflateFlags, flag,
remoteViewCache, entry, row, isNewView, remoteViewClickHandler,
callback, privateLayout, privateLayout.getHeadsUpChild(),
privateLayout.getVisibleWrapper(
VISIBLE_TYPE_HEADSUP), runningInflations,
- applyCallback);
+ applyCallback, logger);
}
}
@@ -449,6 +478,7 @@ public class NotificationContentInflater implements NotificationRowContentBinder
ApplyCallback applyCallback = new ApplyCallback() {
@Override
public void setResultView(View v) {
+ logger.logAsyncTaskProgress(entry, "public view applied");
result.inflatedPublicView = v;
}
@@ -457,19 +487,23 @@ public class NotificationContentInflater implements NotificationRowContentBinder
return result.newPublicView;
}
};
+ logger.logAsyncTaskProgress(entry, "applying public view");
applyRemoteView(bgExecutor, inflateSynchronously, result, reInflateFlags, flag,
remoteViewCache, entry, row, isNewView, remoteViewClickHandler, callback,
publicLayout, publicLayout.getContractedChild(),
publicLayout.getVisibleWrapper(NotificationContentView.VISIBLE_TYPE_CONTRACTED),
- runningInflations, applyCallback);
+ runningInflations, applyCallback, logger);
}
// Let's try to finish, maybe nobody is even inflating anything
finishIfDone(result, reInflateFlags, remoteViewCache, runningInflations, callback, entry,
- row);
+ row, logger);
CancellationSignal cancellationSignal = new CancellationSignal();
cancellationSignal.setOnCancelListener(
- () -> runningInflations.values().forEach(CancellationSignal::cancel));
+ () -> {
+ logger.logAsyncTaskProgress(entry, "apply cancelled");
+ runningInflations.values().forEach(CancellationSignal::cancel);
+ });
return cancellationSignal;
}
@@ -491,7 +525,8 @@ public class NotificationContentInflater implements NotificationRowContentBinder
View existingView,
NotificationViewWrapper existingWrapper,
final HashMap<Integer, CancellationSignal> runningInflations,
- ApplyCallback applyCallback) {
+ ApplyCallback applyCallback,
+ NotificationContentInflaterLogger logger) {
RemoteViews newContentView = applyCallback.getRemoteView();
if (inflateSynchronously) {
try {
@@ -511,7 +546,8 @@ public class NotificationContentInflater implements NotificationRowContentBinder
existingWrapper.onReinflated();
}
} catch (Exception e) {
- handleInflationError(runningInflations, e, row.getEntry(), callback);
+ handleInflationError(runningInflations, e, row.getEntry(), callback, logger,
+ "applying view synchronously");
// Add a running inflation to make sure we don't trigger callbacks.
// Safe to do because only happens in tests.
runningInflations.put(inflationId, new CancellationSignal());
@@ -532,7 +568,7 @@ public class NotificationContentInflater implements NotificationRowContentBinder
String invalidReason = isValidView(v, entry, row.getResources());
if (invalidReason != null) {
handleInflationError(runningInflations, new InflationException(invalidReason),
- row.getEntry(), callback);
+ row.getEntry(), callback, logger, "applied invalid view");
runningInflations.remove(inflationId);
return;
}
@@ -543,7 +579,7 @@ public class NotificationContentInflater implements NotificationRowContentBinder
}
runningInflations.remove(inflationId);
finishIfDone(result, reInflateFlags, remoteViewCache, runningInflations,
- callback, entry, row);
+ callback, entry, row, logger);
}
@Override
@@ -569,7 +605,7 @@ public class NotificationContentInflater implements NotificationRowContentBinder
} catch (Exception anotherException) {
runningInflations.remove(inflationId);
handleInflationError(runningInflations, e, row.getEntry(),
- callback);
+ callback, logger, "applying view");
}
}
};
@@ -653,8 +689,10 @@ public class NotificationContentInflater implements NotificationRowContentBinder
private static void handleInflationError(
HashMap<Integer, CancellationSignal> runningInflations, Exception e,
- NotificationEntry notification, @Nullable InflationCallback callback) {
+ NotificationEntry notification, @Nullable InflationCallback callback,
+ NotificationContentInflaterLogger logger, String logContext) {
Assert.isMainThread();
+ logger.logAsyncTaskException(notification, logContext, e);
runningInflations.values().forEach(CancellationSignal::cancel);
if (callback != null) {
callback.handleInflationException(notification, e);
@@ -670,11 +708,12 @@ public class NotificationContentInflater implements NotificationRowContentBinder
@InflationFlag int reInflateFlags, NotifRemoteViewCache remoteViewCache,
HashMap<Integer, CancellationSignal> runningInflations,
@Nullable InflationCallback endListener, NotificationEntry entry,
- ExpandableNotificationRow row) {
+ ExpandableNotificationRow row, NotificationContentInflaterLogger logger) {
Assert.isMainThread();
NotificationContentView privateLayout = row.getPrivateLayout();
NotificationContentView publicLayout = row.getPublicLayout();
if (runningInflations.isEmpty()) {
+ logger.logAsyncTaskProgress(entry, "finishing");
boolean setRepliesAndActions = true;
if ((reInflateFlags & FLAG_CONTENT_VIEW_CONTRACTED) != 0) {
if (result.inflatedContentView != null) {
@@ -828,6 +867,7 @@ public class NotificationContentInflater implements NotificationRowContentBinder
private final boolean mIsMediaInQS;
private final SmartReplyStateInflater mSmartRepliesInflater;
private final NotifLayoutInflaterFactory.Provider mNotifLayoutInflaterFactoryProvider;
+ private final NotificationContentInflaterLogger mLogger;
private AsyncInflationTask(
Executor bgExecutor,
@@ -844,7 +884,8 @@ public class NotificationContentInflater implements NotificationRowContentBinder
RemoteViews.InteractionHandler remoteViewClickHandler,
boolean isMediaFlagEnabled,
SmartReplyStateInflater smartRepliesInflater,
- NotifLayoutInflaterFactory.Provider notifLayoutInflaterFactoryProvider) {
+ NotifLayoutInflaterFactory.Provider notifLayoutInflaterFactoryProvider,
+ NotificationContentInflaterLogger logger) {
mEntry = entry;
mRow = row;
mBgExecutor = bgExecutor;
@@ -861,6 +902,7 @@ public class NotificationContentInflater implements NotificationRowContentBinder
mConversationProcessor = conversationProcessor;
mIsMediaInQS = isMediaFlagEnabled;
mNotifLayoutInflaterFactoryProvider = notifLayoutInflaterFactoryProvider;
+ mLogger = logger;
entry.setInflationTask(this);
}
@@ -900,13 +942,16 @@ public class NotificationContentInflater implements NotificationRowContentBinder
packageContext = new RtlEnabledContext(packageContext);
}
if (mEntry.getRanking().isConversation()) {
- mConversationProcessor.processNotification(mEntry, recoveredBuilder);
+ mConversationProcessor.processNotification(mEntry, recoveredBuilder, mLogger);
}
InflationProgress inflationProgress = createRemoteViews(mReInflateFlags,
recoveredBuilder, mIsLowPriority, mUsesIncreasedHeight,
mUsesIncreasedHeadsUpHeight, packageContext, mRow,
- mNotifLayoutInflaterFactoryProvider);
+ mNotifLayoutInflaterFactoryProvider, mLogger);
+ mLogger.logAsyncTaskProgress(mEntry,
+ "getting existing smart reply state (on wrong thread!)");
InflatedSmartReplyState previousSmartReplyState = mRow.getExistingSmartReplyState();
+ mLogger.logAsyncTaskProgress(mEntry, "inflating smart reply views");
InflationProgress result = inflateSmartReplyViews(
inflationProgress,
mReInflateFlags,
@@ -914,14 +959,20 @@ public class NotificationContentInflater implements NotificationRowContentBinder
mContext,
packageContext,
previousSmartReplyState,
- mSmartRepliesInflater);
+ mSmartRepliesInflater,
+ mLogger);
+ mLogger.logAsyncTaskProgress(mEntry,
+ "getting row image resolver (on wrong thread!)");
+ final NotificationInlineImageResolver imageResolver = mRow.getImageResolver();
// wait for image resolver to finish preloading
- mRow.getImageResolver().waitForPreloadedImages(IMG_PRELOAD_TIMEOUT_MS);
+ mLogger.logAsyncTaskProgress(mEntry, "waiting for preloaded images");
+ imageResolver.waitForPreloadedImages(IMG_PRELOAD_TIMEOUT_MS);
return result;
} catch (Exception e) {
mError = e;
+ mLogger.logAsyncTaskException(mEntry, "inflating", e);
return null;
}
}
@@ -929,6 +980,7 @@ public class NotificationContentInflater implements NotificationRowContentBinder
@Override
protected void onPostExecute(InflationProgress result) {
if (mError == null) {
+ // Logged in detail in apply.
mCancellationSignal = apply(
mBgExecutor,
mInflateSynchronously,
@@ -938,7 +990,8 @@ public class NotificationContentInflater implements NotificationRowContentBinder
mEntry,
mRow,
mRemoteViewClickHandler,
- this);
+ this /* callback */,
+ mLogger);
} else {
handleError(mError);
}
@@ -961,10 +1014,13 @@ public class NotificationContentInflater implements NotificationRowContentBinder
@Override
public void abort() {
+ mLogger.logAsyncTaskProgress(mEntry, "cancelling inflate");
cancel(true /* mayInterruptIfRunning */);
if (mCancellationSignal != null) {
+ mLogger.logAsyncTaskProgress(mEntry, "cancelling apply");
mCancellationSignal.cancel();
}
+ mLogger.logAsyncTaskProgress(mEntry, "aborted");
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentInflaterLogger.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentInflaterLogger.kt
new file mode 100644
index 000000000000..4f5455dc455f
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentInflaterLogger.kt
@@ -0,0 +1,129 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.notification.row
+
+import com.android.systemui.log.LogBuffer
+import com.android.systemui.log.core.LogLevel
+import com.android.systemui.log.dagger.NotifInflationLog
+import com.android.systemui.statusbar.notification.collection.NotificationEntry
+import com.android.systemui.statusbar.notification.logKey
+import com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.FLAG_CONTENT_VIEW_ALL
+import com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.FLAG_CONTENT_VIEW_CONTRACTED
+import com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.FLAG_CONTENT_VIEW_EXPANDED
+import com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.FLAG_CONTENT_VIEW_HEADS_UP
+import com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.FLAG_CONTENT_VIEW_PUBLIC
+import com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.InflationFlag
+import javax.inject.Inject
+
+class NotificationContentInflaterLogger
+@Inject
+constructor(@NotifInflationLog private val buffer: LogBuffer) {
+ fun logNotBindingRowWasRemoved(entry: NotificationEntry) {
+ buffer.log(
+ TAG,
+ LogLevel.INFO,
+ { str1 = entry.logKey },
+ { "not inflating $str1: row was removed" }
+ )
+ }
+
+ fun logBinding(entry: NotificationEntry, @InflationFlag flag: Int) {
+ buffer.log(
+ TAG,
+ LogLevel.DEBUG,
+ {
+ str1 = entry.logKey
+ int1 = flag
+ },
+ { "binding views ${flagToString(int1)} for $str1" }
+ )
+ }
+
+ fun logCancelBindAbortedTask(entry: NotificationEntry) {
+ buffer.log(
+ TAG,
+ LogLevel.INFO,
+ { str1 = entry.logKey },
+ { "aborted task to cancel binding $str1" }
+ )
+ }
+
+ fun logUnbinding(entry: NotificationEntry, @InflationFlag flag: Int) {
+ buffer.log(
+ TAG,
+ LogLevel.DEBUG,
+ {
+ str1 = entry.logKey
+ int1 = flag
+ },
+ { "unbinding views ${flagToString(int1)} for $str1" }
+ )
+ }
+
+ fun logAsyncTaskProgress(entry: NotificationEntry, progress: String) {
+ buffer.log(
+ TAG,
+ LogLevel.DEBUG,
+ {
+ str1 = entry.logKey
+ str2 = progress
+ },
+ { "async task for $str1: $str2" }
+ )
+ }
+
+ fun logAsyncTaskException(entry: NotificationEntry, logContext: String, exception: Throwable) {
+ buffer.log(
+ TAG,
+ LogLevel.DEBUG,
+ {
+ str1 = entry.logKey
+ str2 = logContext
+ str3 = exception.stackTraceToString()
+ },
+ { "async task for $str1 got exception $str2: $str3" }
+ )
+ }
+
+ companion object {
+ fun flagToString(@InflationFlag flag: Int): String {
+ if (flag == 0) {
+ return "NONE"
+ }
+ if (flag == FLAG_CONTENT_VIEW_ALL) {
+ return "ALL"
+ }
+
+ var l = mutableListOf<String>()
+ if (flag and FLAG_CONTENT_VIEW_CONTRACTED != 0) {
+ l.add("CONTRACTED")
+ }
+ if (flag and FLAG_CONTENT_VIEW_EXPANDED != 0) {
+ l.add("EXPANDED")
+ }
+ if (flag and FLAG_CONTENT_VIEW_HEADS_UP != 0) {
+ l.add("HEADS_UP")
+ }
+ if (flag and FLAG_CONTENT_VIEW_PUBLIC != 0) {
+ l.add("PUBLIC")
+ }
+ return l.joinToString("|")
+ }
+ }
+}
+
+private const val TAG = "NotificationContentInflater"
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationRowContentBinder.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationRowContentBinder.java
index a9f83c8b9e6b..d7b7aa210257 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationRowContentBinder.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationRowContentBinder.java
@@ -54,8 +54,9 @@ public interface NotificationRowContentBinder {
*
* @param entry notification
* @param row notification row to cancel bind on
+ * @return true if an on-going bind operation was cancelled
*/
- void cancelBind(
+ boolean cancelBind(
@NonNull NotificationEntry entry,
@NonNull ExpandableNotificationRow row);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/RowContentBindStage.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/RowContentBindStage.java
index 81cf14646465..b70da00ad517 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/RowContentBindStage.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/RowContentBindStage.java
@@ -57,7 +57,7 @@ public class RowContentBindStage extends BindStage<RowContentBindParams> {
@NonNull StageCallback callback) {
RowContentBindParams params = getStageParams(entry);
- mLogger.logStageParams(entry, params);
+ mLogger.logExecutingStage(entry, params);
// Resolve content to bind/unbind.
@InflationFlag int inflationFlags = params.getContentViews();
@@ -96,7 +96,10 @@ public class RowContentBindStage extends BindStage<RowContentBindParams> {
protected void abortStage(
@NonNull NotificationEntry entry,
@NonNull ExpandableNotificationRow row) {
- mBinder.cancelBind(entry, row);
+ final boolean cancelledBind = mBinder.cancelBind(entry, row);
+ if (cancelledBind) {
+ mLogger.logAbortStageCancelledBind(entry);
+ }
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/RowContentBindStageLogger.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/RowContentBindStageLogger.kt
index 02627fd8f975..1b961cfbb34c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/RowContentBindStageLogger.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/RowContentBindStageLogger.kt
@@ -16,22 +16,30 @@
package com.android.systemui.statusbar.notification.row
-import com.android.systemui.log.dagger.NotificationLog
import com.android.systemui.log.LogBuffer
import com.android.systemui.log.core.LogLevel.INFO
+import com.android.systemui.log.dagger.NotifInflationLog
import com.android.systemui.statusbar.notification.collection.NotificationEntry
import com.android.systemui.statusbar.notification.logKey
import javax.inject.Inject
class RowContentBindStageLogger @Inject constructor(
- @NotificationLog private val buffer: LogBuffer
+ @NotifInflationLog private val buffer: LogBuffer
) {
- fun logStageParams(entry: NotificationEntry, stageParams: RowContentBindParams) {
+ fun logExecutingStage(entry: NotificationEntry, stageParams: RowContentBindParams) {
buffer.log(TAG, INFO, {
str1 = entry.logKey
str2 = stageParams.toString()
}, {
- "Invalidated notif $str1 with params: $str2"
+ "executing bind stage for $str1 with params $str2"
+ })
+ }
+
+ fun logAbortStageCancelledBind(entry: NotificationEntry) {
+ buffer.log(TAG, INFO, {
+ str1 = entry.logKey
+ }, {
+ "cancelled bind to abort stage for $str1"
})
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfaces.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfaces.java
index 0ff1a9561748..67c0c94d6544 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfaces.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfaces.java
@@ -44,7 +44,6 @@ import com.android.systemui.navigationbar.NavigationBarView;
import com.android.systemui.plugins.ActivityStarter.OnDismissAction;
import com.android.systemui.qs.QSPanelController;
import com.android.systemui.shared.system.RemoteAnimationRunnerCompat;
-import com.android.systemui.statusbar.NotificationPresenter;
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
import com.android.systemui.util.Compile;
@@ -183,8 +182,6 @@ public interface CentralSurfaces extends Dumpable, LifecycleOwner {
return contextForUser.getPackageManager();
}
- void start();
-
boolean updateIsKeyguard();
boolean updateIsKeyguard(boolean forceStateChange);
@@ -200,8 +197,6 @@ public interface CentralSurfaces extends Dumpable, LifecycleOwner {
void onKeyguardViewManagerStatesUpdated();
- NotificationPresenter getPresenter();
-
/**
* Used to dispatch initial touch events before crossing the threshold to pull down the
* notification shade. After that, since the launcher window is set to slippery, input
@@ -220,8 +215,6 @@ public interface CentralSurfaces extends Dumpable, LifecycleOwner {
/** */
boolean getCommandQueuePanelsEnabled();
- BiometricUnlockController getBiometricUnlockController();
-
void showWirelessChargingAnimation(int batteryLevel);
void checkBarModes();
@@ -230,9 +223,6 @@ public interface CentralSurfaces extends Dumpable, LifecycleOwner {
void setInteracting(int barWindow, boolean interacting);
- @Override
- void dump(PrintWriter pwOriginal, String[] args);
-
/** @deprecated Use {@link DisplayMetricsRepository} instead. */
@Deprecated
float getDisplayWidth();
@@ -281,8 +271,6 @@ public interface CentralSurfaces extends Dumpable, LifecycleOwner {
void setBouncerShowing(boolean bouncerShowing);
- int getWakefulnessState();
-
boolean isScreenFullyOff();
void showScreenPinningRequest(int taskId, boolean allowCancel);
@@ -323,8 +311,6 @@ public interface CentralSurfaces extends Dumpable, LifecycleOwner {
boolean isBouncerShowingOverDream();
- boolean isKeyguardSecure();
-
void updateNotificationPanelTouchState();
int getRotation();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesEmptyImpl.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesEmptyImpl.kt
index 37038a357479..98ba6d91413f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesEmptyImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesEmptyImpl.kt
@@ -23,9 +23,7 @@ import com.android.systemui.animation.ActivityLaunchAnimator
import com.android.systemui.navigationbar.NavigationBarView
import com.android.systemui.plugins.ActivityStarter.OnDismissAction
import com.android.systemui.qs.QSPanelController
-import com.android.systemui.statusbar.NotificationPresenter
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow
-import java.io.PrintWriter
/**
* Empty implementation of [CentralSurfaces] for variants only need to override portions of the
@@ -41,15 +39,12 @@ abstract class CentralSurfacesEmptyImpl : CentralSurfaces {
override fun getKeyguardMessageArea(): AuthKeyguardMessageArea? = null
override fun isLaunchingActivityOverLockscreen() = false
override fun onKeyguardViewManagerStatesUpdated() {}
- override fun getPresenter(): NotificationPresenter? = null
override fun onInputFocusTransfer(start: Boolean, cancel: Boolean, velocity: Float) {}
override fun getCommandQueuePanelsEnabled() = false
- override fun getBiometricUnlockController(): BiometricUnlockController? = null
override fun showWirelessChargingAnimation(batteryLevel: Int) {}
override fun checkBarModes() {}
override fun updateBubblesVisibility() {}
override fun setInteracting(barWindow: Int, interacting: Boolean) {}
- override fun dump(pwOriginal: PrintWriter, args: Array<String>) {}
override fun getDisplayWidth() = 0f
override fun getDisplayHeight() = 0f
override fun showKeyguard() {}
@@ -77,7 +72,6 @@ abstract class CentralSurfacesEmptyImpl : CentralSurfaces {
override fun showPinningEnterExitToast(entering: Boolean) {}
override fun showPinningEscapeToast() {}
override fun setBouncerShowing(bouncerShowing: Boolean) {}
- override fun getWakefulnessState() = 0
override fun isScreenFullyOff() = false
override fun showScreenPinningRequest(taskId: Int, allowCancel: Boolean) {}
override fun getEmergencyActionIntent(): Intent? = null
@@ -95,7 +89,6 @@ abstract class CentralSurfacesEmptyImpl : CentralSurfaces {
override fun isBouncerShowing() = false
override fun isBouncerShowingScrimmed() = false
override fun isBouncerShowingOverDream() = false
- override fun isKeyguardSecure() = false
override fun updateNotificationPanelTouchState() {}
override fun getRotation() = 0
override fun setBarStateForTest(state: Int) {}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java
index 8cdf7d8a100d..0277a36c91ad 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java
@@ -222,9 +222,7 @@ import com.android.systemui.statusbar.notification.row.NotificationGutsManager;
import com.android.systemui.statusbar.notification.stack.NotificationListContainer;
import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout;
import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayoutController;
-import com.android.systemui.statusbar.phone.dagger.CentralSurfacesComponent;
import com.android.systemui.statusbar.phone.dagger.StatusBarPhoneModule;
-import com.android.systemui.statusbar.phone.fragment.CollapsedStatusBarFragment;
import com.android.systemui.statusbar.phone.ongoingcall.OngoingCallController;
import com.android.systemui.statusbar.policy.BatteryController;
import com.android.systemui.statusbar.policy.BrightnessMirrorController;
@@ -454,7 +452,6 @@ public class CentralSurfacesImpl implements CoreStartable, CentralSurfaces {
mNotificationShadeWindowViewControllerLazy;
private final DozeParameters mDozeParameters;
private final Lazy<BiometricUnlockController> mBiometricUnlockControllerLazy;
- private final CentralSurfacesComponent.Factory mCentralSurfacesComponentFactory;
private final PluginManager mPluginManager;
private final ShadeController mShadeController;
private final WindowRootViewVisibilityInteractor mWindowRootViewVisibilityInteractor;
@@ -500,8 +497,6 @@ public class CentralSurfacesImpl implements CoreStartable, CentralSurfaces {
private final Provider<FingerprintManager> mFingerprintManager;
private final ActivityStarter mActivityStarter;
- private CentralSurfacesComponent mCentralSurfacesComponent;
-
/** @see android.view.WindowInsetsController#setSystemBarsAppearance(int, int) */
private @Appearance int mAppearance;
@@ -702,7 +697,6 @@ public class CentralSurfacesImpl implements CoreStartable, CentralSurfaces {
DozeScrimController dozeScrimController,
VolumeComponent volumeComponent,
CommandQueue commandQueue,
- CentralSurfacesComponent.Factory centralSurfacesComponentFactory,
Lazy<CentralSurfacesCommandQueueCallbacks> commandQueueCallbacksLazy,
PluginManager pluginManager,
ShadeController shadeController,
@@ -813,7 +807,6 @@ public class CentralSurfacesImpl implements CoreStartable, CentralSurfaces {
mNotificationShadeDepthControllerLazy = notificationShadeDepthControllerLazy;
mVolumeComponent = volumeComponent;
mCommandQueue = commandQueue;
- mCentralSurfacesComponentFactory = centralSurfacesComponentFactory;
mCommandQueueCallbacksLazy = commandQueueCallbacksLazy;
mPluginManager = pluginManager;
mShadeController = shadeController;
@@ -1193,10 +1186,15 @@ public class CentralSurfacesImpl implements CoreStartable, CentralSurfaces {
updateResources();
updateTheme();
- inflateStatusBarWindow();
+ setUpShade();
getNotificationShadeWindowView().setOnTouchListener(getStatusBarWindowTouchListener());
mWallpaperController.setRootView(getNotificationShadeWindowView());
+ mDemoModeController.addCallback(mDemoModeCallback);
+
+ mCommandQueueCallbacks = mCommandQueueCallbacksLazy.get();
+ mCommandQueue.addCallback(mCommandQueueCallbacks);
+
// TODO: Deal with the ugliness that comes from having some of the status bar broken out
// into fragments, but the rest here, it leaves some awkward lifecycle and whatnot.
if (!mFeatureFlags.isEnabled(Flags.NOTIFICATION_SHELF_REFACTOR)) {
@@ -1227,8 +1225,7 @@ public class CentralSurfacesImpl implements CoreStartable, CentralSurfaces {
setBouncerShowingForStatusBarComponents(mBouncerShowing);
checkBarModes();
});
- mStatusBarInitializer.initializeStatusBar(
- mCentralSurfacesComponent::createCollapsedStatusBarFragment);
+ mStatusBarInitializer.initializeStatusBar();
mStatusBarTouchableRegionManager.setup(this, getNotificationShadeWindowView());
@@ -1551,15 +1548,7 @@ public class CentralSurfacesImpl implements CoreStartable, CentralSurfaces {
};
}
- private void inflateStatusBarWindow() {
- if (mCentralSurfacesComponent != null) {
- Log.e(TAG, "CentralSurfacesComponent being recreated; this is unexpected.");
- }
- mCentralSurfacesComponent = mCentralSurfacesComponentFactory.create();
- mFragmentService.addFragmentInstantiationProvider(
- CollapsedStatusBarFragment.class,
- mCentralSurfacesComponent::createCollapsedStatusBarFragment);
-
+ private void setUpShade() {
// Ideally, NotificationShadeWindowController could automatically fetch the window root view
// in #attach or a CoreStartable.start method or something similar. But for now, to avoid
// regressions, we'll continue standing up the root view in CentralSurfaces.
@@ -1568,12 +1557,6 @@ public class CentralSurfacesImpl implements CoreStartable, CentralSurfaces {
mShadeController.setNotificationShadeWindowViewController(
getNotificationShadeWindowViewController());
mBackActionInteractor.setup(mQsController, mShadeSurface);
-
- // Listen for demo mode changes
- mDemoModeController.addCallback(mDemoModeCallback);
-
- mCommandQueueCallbacks = mCommandQueueCallbacksLazy.get();
- mCommandQueue.addCallback(mCommandQueueCallbacks);
}
protected NotificationShadeWindowViewController getNotificationShadeWindowViewController() {
@@ -1666,11 +1649,6 @@ public class CentralSurfacesImpl implements CoreStartable, CentralSurfaces {
logStateToEventlog();
}
- @Override
- public NotificationPresenter getPresenter() {
- return mPresenter;
- }
-
@VisibleForTesting
@Override
public void setBarStateForTest(int state) {
@@ -1745,11 +1723,6 @@ public class CentralSurfacesImpl implements CoreStartable, CentralSurfaces {
}
@Override
- public BiometricUnlockController getBiometricUnlockController() {
- return mBiometricUnlockController;
- }
-
- @Override
public void showTransientUnchecked() {
if (!mTransientShown) {
mTransientShown = true;
@@ -2503,7 +2476,7 @@ public class CentralSurfacesImpl implements CoreStartable, CentralSurfaces {
mStatusBarKeyguardViewManager.reset(true);
} else if (mState == StatusBarState.KEYGUARD
&& !mStatusBarKeyguardViewManager.primaryBouncerIsOrWillBeShowing()
- && isKeyguardSecure()) {
+ && mStatusBarKeyguardViewManager.isSecure()) {
mStatusBarKeyguardViewManager.showBouncer(true /* scrimmed */);
}
}
@@ -2842,11 +2815,6 @@ public class CentralSurfacesImpl implements CoreStartable, CentralSurfaces {
}
};
- @Override
- public int getWakefulnessState() {
- return mWakefulnessLifecycle.getWakefulness();
- }
-
/**
* @return true if the screen is currently fully off, i.e. has finished turning off and has
* since not started turning on.
@@ -2912,7 +2880,7 @@ public class CentralSurfacesImpl implements CoreStartable, CentralSurfaces {
if (mDevicePolicyManager.getCameraDisabled(null,
mLockscreenUserManager.getCurrentUserId())) {
return false;
- } else if (isKeyguardShowing() && isKeyguardSecure()) {
+ } else if (isKeyguardShowing() && mStatusBarKeyguardViewManager.isSecure()) {
// Check if the admin has disabled the camera specifically for the keyguard
return (mDevicePolicyManager.getKeyguardDisabledFeatures(null,
mLockscreenUserManager.getCurrentUserId())
@@ -3215,11 +3183,6 @@ public class CentralSurfacesImpl implements CoreStartable, CentralSurfaces {
return mBouncerShowingOverDream;
}
- @Override
- public boolean isKeyguardSecure() {
- return mStatusBarKeyguardViewManager.isSecure();
- }
-
// End Extra BaseStatusBarMethods.
boolean isTransientShown() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewController.kt
index cc41bf843565..23b0ee0ec9bc 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewController.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewController.kt
@@ -27,6 +27,7 @@ import com.android.systemui.Gefingerpoken
import com.android.systemui.R
import com.android.systemui.flags.FeatureFlags
import com.android.systemui.flags.Flags
+import com.android.systemui.scene.shared.flag.SceneContainerFlags
import com.android.systemui.scene.ui.view.WindowRootView
import com.android.systemui.shade.ShadeController
import com.android.systemui.shade.ShadeLogger
@@ -48,8 +49,9 @@ import javax.inject.Provider
private const val TAG = "PhoneStatusBarViewController"
-/** Controller for [PhoneStatusBarView]. */
-class PhoneStatusBarViewController private constructor(
+/** Controller for [PhoneStatusBarView]. */
+class PhoneStatusBarViewController
+private constructor(
view: PhoneStatusBarView,
@Named(UNFOLD_STATUS_BAR) private val progressProvider: ScopedUnfoldTransitionProgressProvider?,
private val centralSurfaces: CentralSurfaces,
@@ -61,42 +63,42 @@ class PhoneStatusBarViewController private constructor(
private val moveFromCenterAnimationController: StatusBarMoveFromCenterAnimationController?,
private val userChipViewModel: StatusBarUserChipViewModel,
private val viewUtil: ViewUtil,
- private val featureFlags: FeatureFlags,
+ private val sceneContainerFlags: SceneContainerFlags,
private val configurationController: ConfigurationController,
private val statusOverlayHoverListenerFactory: StatusOverlayHoverListenerFactory,
) : ViewController<PhoneStatusBarView>(view) {
private lateinit var statusContainer: View
- private val configurationListener = object : ConfigurationController.ConfigurationListener {
- override fun onConfigChanged(newConfig: Configuration?) {
- mView.updateResources()
+ private val configurationListener =
+ object : ConfigurationController.ConfigurationListener {
+ override fun onConfigChanged(newConfig: Configuration?) {
+ mView.updateResources()
+ }
}
- }
override fun onViewAttached() {
statusContainer = mView.requireViewById(R.id.system_icons)
statusContainer.setOnHoverListener(
- statusOverlayHoverListenerFactory.createDarkAwareListener(statusContainer))
+ statusOverlayHoverListenerFactory.createDarkAwareListener(statusContainer)
+ )
if (moveFromCenterAnimationController == null) return
val statusBarLeftSide: View =
- mView.requireViewById(R.id.status_bar_start_side_except_heads_up)
+ mView.requireViewById(R.id.status_bar_start_side_except_heads_up)
val systemIconArea: ViewGroup = mView.requireViewById(R.id.status_bar_end_side_content)
- val viewsToAnimate = arrayOf(
- statusBarLeftSide,
- systemIconArea
- )
+ val viewsToAnimate = arrayOf(statusBarLeftSide, systemIconArea)
- mView.viewTreeObserver.addOnPreDrawListener(object :
- ViewTreeObserver.OnPreDrawListener {
- override fun onPreDraw(): Boolean {
- moveFromCenterAnimationController.onViewsReady(viewsToAnimate)
- mView.viewTreeObserver.removeOnPreDrawListener(this)
- return true
+ mView.viewTreeObserver.addOnPreDrawListener(
+ object : ViewTreeObserver.OnPreDrawListener {
+ override fun onPreDraw(): Boolean {
+ moveFromCenterAnimationController.onViewsReady(viewsToAnimate)
+ mView.viewTreeObserver.removeOnPreDrawListener(this)
+ return true
+ }
}
- })
+ )
mView.addOnLayoutChangeListener { _, left, _, right, _, oldLeft, _, oldRight, _ ->
val widthChanged = right - left != oldRight - oldLeft
@@ -121,8 +123,7 @@ class PhoneStatusBarViewController private constructor(
mView.init(userChipViewModel)
}
- override fun onInit() {
- }
+ override fun onInit() {}
fun setImportantForAccessibility(mode: Int) {
mView.importantForAccessibility = mode
@@ -151,10 +152,11 @@ class PhoneStatusBarViewController private constructor(
fun onTouch(event: MotionEvent) {
if (statusBarWindowStateController.windowIsShowing()) {
val upOrCancel =
- event.action == MotionEvent.ACTION_UP ||
- event.action == MotionEvent.ACTION_CANCEL
- centralSurfaces.setInteracting(WINDOW_STATUS_BAR,
- !upOrCancel || shadeController.isExpandedVisible)
+ event.action == MotionEvent.ACTION_UP || event.action == MotionEvent.ACTION_CANCEL
+ centralSurfaces.setInteracting(
+ WINDOW_STATUS_BAR,
+ !upOrCancel || shadeController.isExpandedVisible
+ )
}
}
@@ -171,15 +173,20 @@ class PhoneStatusBarViewController private constructor(
// panel view.
if (!centralSurfaces.commandQueuePanelsEnabled) {
if (event.action == MotionEvent.ACTION_DOWN) {
- Log.v(TAG, String.format("onTouchForwardedFromStatusBar: panel disabled, " +
- "ignoring touch at (${event.x.toInt()},${event.y.toInt()})"))
+ Log.v(
+ TAG,
+ String.format(
+ "onTouchForwardedFromStatusBar: panel disabled, " +
+ "ignoring touch at (${event.x.toInt()},${event.y.toInt()})"
+ )
+ )
}
return false
}
// If scene framework is enabled, route the touch to it and
// ignore the rest of the gesture.
- if (featureFlags.isEnabled(Flags.SCENE_CONTAINER)) {
+ if (sceneContainerFlags.isEnabled()) {
windowRootView.get().dispatchTouchEvent(event)
return true
}
@@ -188,12 +195,13 @@ class PhoneStatusBarViewController private constructor(
// If the view that would receive the touch is disabled, just have status
// bar eat the gesture.
if (!shadeViewController.isViewEnabled) {
- shadeLogger.logMotionEvent(event,
- "onTouchForwardedFromStatusBar: panel view disabled")
+ shadeLogger.logMotionEvent(
+ event,
+ "onTouchForwardedFromStatusBar: panel view disabled"
+ )
return true
}
- if (shadeViewController.isFullyCollapsed &&
- event.y < 1f) {
+ if (shadeViewController.isFullyCollapsed && event.y < 1f) {
// b/235889526 Eat events on the top edge of the phone when collapsed
shadeLogger.logMotionEvent(event, "top edge touch ignored")
return true
@@ -218,9 +226,7 @@ class PhoneStatusBarViewController private constructor(
else -> super.getViewCenter(view, outPoint)
}
- /**
- * Returns start or end (based on [isStart]) center point of the view
- */
+ /** Returns start or end (based on [isStart]) center point of the view */
private fun getViewEdgeCenter(view: View, outPoint: Point, isStart: Boolean) {
val isRtl = view.resources.configuration.layoutDirection == View.LAYOUT_DIRECTION_RTL
val isLeftEdge = isRtl xor isStart
@@ -236,11 +242,14 @@ class PhoneStatusBarViewController private constructor(
}
}
- class Factory @Inject constructor(
+ class Factory
+ @Inject
+ constructor(
private val unfoldComponent: Optional<SysUIUnfoldComponent>,
@Named(UNFOLD_STATUS_BAR)
private val progressProvider: Optional<ScopedUnfoldTransitionProgressProvider>,
private val featureFlags: FeatureFlags,
+ private val sceneContainerFlags: SceneContainerFlags,
private val userChipViewModel: StatusBarUserChipViewModel,
private val centralSurfaces: CentralSurfaces,
private val statusBarWindowStateController: StatusBarWindowStateController,
@@ -252,9 +261,7 @@ class PhoneStatusBarViewController private constructor(
private val configurationController: ConfigurationController,
private val statusOverlayHoverListenerFactory: StatusOverlayHoverListenerFactory,
) {
- fun create(
- view: PhoneStatusBarView
- ): PhoneStatusBarViewController {
+ fun create(view: PhoneStatusBarView): PhoneStatusBarViewController {
val statusBarMoveFromCenterAnimationController =
if (featureFlags.isEnabled(Flags.ENABLE_UNFOLD_STATUS_BAR_ANIMATIONS)) {
unfoldComponent.getOrNull()?.getStatusBarMoveFromCenterAnimationController()
@@ -274,10 +281,10 @@ class PhoneStatusBarViewController private constructor(
statusBarMoveFromCenterAnimationController,
userChipViewModel,
viewUtil,
- featureFlags,
+ sceneContainerFlags,
configurationController,
statusOverlayHoverListenerFactory,
)
}
}
-} \ No newline at end of file
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
index b0f8276e460d..40432eee95bb 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
@@ -1480,7 +1480,7 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, Dump
public void setScrimBehindChangeRunnable(Runnable changeRunnable) {
// TODO: remove this. This is necessary because of an order-of-operations limitation.
- // The fix is to move more of these class into @CentralSurfacesScope
+ // The fix is to move more of these class into @SysUISingleton.
if (mScrimBehind == null) {
mScrimBehindChangeRunnable = changeRunnable;
} else {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarTouchableRegionManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarTouchableRegionManager.java
index fa9b9d2c571a..5773612d55c7 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarTouchableRegionManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarTouchableRegionManager.java
@@ -34,9 +34,8 @@ import com.android.systemui.Dumpable;
import com.android.systemui.R;
import com.android.systemui.ScreenDecorations;
import com.android.systemui.dagger.SysUISingleton;
-import com.android.systemui.flags.FeatureFlags;
-import com.android.systemui.flags.Flags;
import com.android.systemui.scene.domain.interactor.SceneInteractor;
+import com.android.systemui.scene.shared.flag.SceneContainerFlags;
import com.android.systemui.shade.ShadeExpansionStateManager;
import com.android.systemui.statusbar.NotificationShadeWindowController;
import com.android.systemui.statusbar.policy.ConfigurationController;
@@ -85,7 +84,7 @@ public final class StatusBarTouchableRegionManager implements Dumpable {
ShadeExpansionStateManager shadeExpansionStateManager,
Provider<SceneInteractor> sceneInteractor,
Provider<JavaAdapter> javaAdapter,
- FeatureFlags featureFlags,
+ SceneContainerFlags sceneContainerFlags,
UnlockedScreenOffAnimationController unlockedScreenOffAnimationController
) {
mContext = context;
@@ -123,7 +122,7 @@ public final class StatusBarTouchableRegionManager implements Dumpable {
mUnlockedScreenOffAnimationController = unlockedScreenOffAnimationController;
shadeExpansionStateManager.addFullExpansionListener(this::onShadeExpansionFullyChanged);
- if (featureFlags.isEnabled(Flags.SCENE_CONTAINER)) {
+ if (sceneContainerFlags.isEnabled()) {
javaAdapter.get().alwaysCollectFlow(
sceneInteractor.get().isVisible(),
this::onShadeExpansionFullyChanged);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/UnlockedScreenOffAnimationController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/UnlockedScreenOffAnimationController.kt
index 37f032b464b7..2c15e27b8148 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/UnlockedScreenOffAnimationController.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/UnlockedScreenOffAnimationController.kt
@@ -125,6 +125,7 @@ class UnlockedScreenOffAnimationController @Inject constructor(
// FrameCallback used to delay starting the light reveal animation until the next frame
private val startLightRevealCallback = TraceUtils.namedRunnable("startLightReveal") {
+ lightRevealAnimationPlaying = true
lightRevealAnimator.start()
}
@@ -268,7 +269,6 @@ class UnlockedScreenOffAnimationController @Inject constructor(
decidedToAnimateGoingToSleep = true
shouldAnimateInKeyguard = true
- lightRevealAnimationPlaying = true
// Start the animation on the next frame. startAnimation() is called after
// PhoneWindowManager makes a binder call to System UI on
@@ -283,7 +283,8 @@ class UnlockedScreenOffAnimationController @Inject constructor(
// dispatched, a race condition could make it possible for this callback to be run
// as the device is waking up. That results in the AOD UI being shown while we wake
// up, with unpredictable consequences.
- if (!powerManager.isInteractive(Display.DEFAULT_DISPLAY)) {
+ if (!powerManager.isInteractive(Display.DEFAULT_DISPLAY) &&
+ shouldAnimateInKeyguard) {
aodUiAnimationPlaying = true
// Show AOD. That'll cause the KeyguardVisibilityHelper to call
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/CentralSurfacesComponent.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/CentralSurfacesComponent.java
deleted file mode 100644
index 1a04b913f3e6..000000000000
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/CentralSurfacesComponent.java
+++ /dev/null
@@ -1,76 +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.statusbar.phone.dagger;
-
-import static com.android.systemui.statusbar.phone.dagger.StatusBarViewModule.STATUS_BAR_FRAGMENT;
-
-import static java.lang.annotation.RetentionPolicy.RUNTIME;
-
-import com.android.systemui.shade.ShadeHeaderController;
-import com.android.systemui.statusbar.phone.CentralSurfacesImpl;
-import com.android.systemui.statusbar.phone.fragment.CollapsedStatusBarFragment;
-
-import dagger.Subcomponent;
-
-import java.lang.annotation.Documented;
-import java.lang.annotation.Retention;
-
-import javax.inject.Named;
-import javax.inject.Scope;
-
-/**
- * Dagger subcomponent for classes (semi-)related to the status bar. The component is created once
- * inside {@link CentralSurfacesImpl} and never re-created.
- *
- * TODO(b/197137564): This should likely be re-factored a bit. It includes classes that aren't
- * directly related to status bar functionality, like multiple notification classes. And, the fact
- * that it has many getter methods indicates that we need to access many of these classes from
- * outside the component. Should more items be moved *into* this component to avoid so many getters?
- */
-@Subcomponent(modules = {
- StatusBarViewModule.class,
-})
-@CentralSurfacesComponent.CentralSurfacesScope
-public interface CentralSurfacesComponent {
- /**
- * Builder for {@link CentralSurfacesComponent}.
- */
- @Subcomponent.Factory
- interface Factory {
- CentralSurfacesComponent create();
- }
-
- /**
- * Scope annotation for singleton items within the CentralSurfacesComponent.
- */
- @Documented
- @Retention(RUNTIME)
- @Scope
- @interface CentralSurfacesScope {}
-
- /**
- * Creates a {@link ShadeHeaderController}.
- */
- ShadeHeaderController getLargeScreenShadeHeaderController();
-
- /**
- * Creates a new {@link CollapsedStatusBarFragment} each time it's called. See
- * {@link StatusBarViewModule#createCollapsedStatusBarFragment}.
- */
- @Named(STATUS_BAR_FRAGMENT)
- CollapsedStatusBarFragment createCollapsedStatusBarFragment();
-}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarViewModule.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarViewModule.java
deleted file mode 100644
index ebdde78e4ea4..000000000000
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarViewModule.java
+++ /dev/null
@@ -1,127 +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.statusbar.phone.dagger;
-
-import com.android.keyguard.KeyguardUpdateMonitor;
-import com.android.systemui.dagger.qualifiers.Main;
-import com.android.systemui.dump.DumpManager;
-import com.android.systemui.flags.FeatureFlags;
-import com.android.systemui.plugins.statusbar.StatusBarStateController;
-import com.android.systemui.shade.ShadeExpansionStateManager;
-import com.android.systemui.shade.ShadeViewController;
-import com.android.systemui.statusbar.CommandQueue;
-import com.android.systemui.statusbar.OperatorNameViewController;
-import com.android.systemui.statusbar.events.SystemStatusAnimationScheduler;
-import com.android.systemui.statusbar.phone.NotificationIconAreaController;
-import com.android.systemui.statusbar.phone.StatusBarHideIconsForBouncerManager;
-import com.android.systemui.statusbar.phone.StatusBarIconController;
-import com.android.systemui.statusbar.phone.StatusBarLocationPublisher;
-import com.android.systemui.statusbar.phone.fragment.CollapsedStatusBarFragment;
-import com.android.systemui.statusbar.phone.fragment.CollapsedStatusBarFragmentLogger;
-import com.android.systemui.statusbar.phone.fragment.dagger.StatusBarFragmentComponent;
-import com.android.systemui.statusbar.phone.ongoingcall.OngoingCallController;
-import com.android.systemui.statusbar.pipeline.shared.ui.binder.CollapsedStatusBarViewBinder;
-import com.android.systemui.statusbar.pipeline.shared.ui.viewmodel.CollapsedStatusBarViewModel;
-import com.android.systemui.statusbar.policy.KeyguardStateController;
-import com.android.systemui.statusbar.window.StatusBarWindowStateController;
-import com.android.systemui.util.CarrierConfigTracker;
-import com.android.systemui.util.settings.SecureSettings;
-
-import dagger.Module;
-import dagger.Provides;
-
-import java.util.concurrent.Executor;
-
-import javax.inject.Named;
-
-/**
- * A module for {@link CentralSurfacesComponent.CentralSurfacesScope} components.
- *
- * @deprecated CentralSurfacesScope will be removed shortly (b/277762009). Classes should be
- * annotated with @SysUISingleton instead.
- */
-@Module(subcomponents = StatusBarFragmentComponent.class)
-@Deprecated
-public abstract class StatusBarViewModule {
-
- public static final String STATUS_BAR_FRAGMENT = "status_bar_fragment";
-
- /**
- * Creates a new {@link CollapsedStatusBarFragment}.
- *
- * **IMPORTANT**: This method intentionally does not have
- * {@link CentralSurfacesComponent.CentralSurfacesScope}, which means a new fragment *will* be
- * created each time this method is called. This is intentional because we need fragments to
- * re-created in certain lifecycle scenarios.
- *
- * This provider is {@link Named} such that it does not conflict with the provider inside of
- * {@link StatusBarFragmentComponent}.
- */
- @Provides
- @Named(STATUS_BAR_FRAGMENT)
- public static CollapsedStatusBarFragment createCollapsedStatusBarFragment(
- StatusBarFragmentComponent.Factory statusBarFragmentComponentFactory,
- OngoingCallController ongoingCallController,
- SystemStatusAnimationScheduler animationScheduler,
- StatusBarLocationPublisher locationPublisher,
- NotificationIconAreaController notificationIconAreaController,
- ShadeExpansionStateManager shadeExpansionStateManager,
- FeatureFlags featureFlags,
- StatusBarIconController statusBarIconController,
- StatusBarIconController.DarkIconManager.Factory darkIconManagerFactory,
- CollapsedStatusBarViewModel collapsedStatusBarViewModel,
- CollapsedStatusBarViewBinder collapsedStatusBarViewBinder,
- StatusBarHideIconsForBouncerManager statusBarHideIconsForBouncerManager,
- KeyguardStateController keyguardStateController,
- ShadeViewController shadeViewController,
- StatusBarStateController statusBarStateController,
- CommandQueue commandQueue,
- CarrierConfigTracker carrierConfigTracker,
- CollapsedStatusBarFragmentLogger collapsedStatusBarFragmentLogger,
- OperatorNameViewController.Factory operatorNameViewControllerFactory,
- SecureSettings secureSettings,
- @Main Executor mainExecutor,
- DumpManager dumpManager,
- StatusBarWindowStateController statusBarWindowStateController,
- KeyguardUpdateMonitor keyguardUpdateMonitor
- ) {
- return new CollapsedStatusBarFragment(statusBarFragmentComponentFactory,
- ongoingCallController,
- animationScheduler,
- locationPublisher,
- notificationIconAreaController,
- shadeExpansionStateManager,
- featureFlags,
- statusBarIconController,
- darkIconManagerFactory,
- collapsedStatusBarViewModel,
- collapsedStatusBarViewBinder,
- statusBarHideIconsForBouncerManager,
- keyguardStateController,
- shadeViewController,
- statusBarStateController,
- commandQueue,
- carrierConfigTracker,
- collapsedStatusBarFragmentLogger,
- operatorNameViewControllerFactory,
- secureSettings,
- mainExecutor,
- dumpManager,
- statusBarWindowStateController,
- keyguardUpdateMonitor);
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragment.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragment.java
index 2efdf8a0b181..66f0f597ea6e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragment.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragment.java
@@ -29,7 +29,6 @@ import android.util.SparseArray;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
-import android.view.ViewStub;
import android.widget.LinearLayout;
import androidx.annotation.VisibleForTesting;
@@ -85,6 +84,8 @@ import java.util.Map;
import java.util.Set;
import java.util.concurrent.Executor;
+import javax.inject.Inject;
+
/**
* Contains the collapsed status bar and handles hiding/showing based on disable flags
* and keyguard state. Also manages lifecycle to make sure the views it contains are being
@@ -203,7 +204,7 @@ public class CollapsedStatusBarFragment extends Fragment implements CommandQueue
mTransitionFromLockscreenToDreamStarted = false;
};
- @SuppressLint("ValidFragment")
+ @Inject
public CollapsedStatusBarFragment(
StatusBarFragmentComponent.Factory statusBarFragmentComponentFactory,
OngoingCallController ongoingCallController,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragmentStartable.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragmentStartable.kt
new file mode 100644
index 000000000000..55af0e3d65a3
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragmentStartable.kt
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.phone.fragment
+
+import com.android.systemui.CoreStartable
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.fragments.FragmentService
+import com.android.systemui.qs.QSFragmentStartable
+import com.android.systemui.statusbar.phone.fragment.dagger.StatusBarFragmentComponent
+import dagger.Binds
+import dagger.Module
+import dagger.multibindings.ClassKey
+import dagger.multibindings.IntoMap
+import javax.inject.Inject
+import javax.inject.Provider
+
+/**
+ * Provides [FragmentService] with a way to automatically inflate [CollapsedStatusBarFragment],
+ * similar to [QSFragmentStartable].
+ */
+@SysUISingleton
+class CollapsedStatusBarFragmentStartable
+@Inject
+constructor(
+ private val fragmentService: FragmentService,
+ private val collapsedstatusBarFragmentProvider: Provider<CollapsedStatusBarFragment>
+) : CoreStartable {
+ override fun start() {
+ fragmentService.addFragmentInstantiationProvider(
+ CollapsedStatusBarFragment::class.java,
+ collapsedstatusBarFragmentProvider,
+ )
+ }
+}
+
+@Module(subcomponents = [StatusBarFragmentComponent::class])
+interface CollapsedStatusBarFragmentStartableModule {
+ @Binds
+ @IntoMap
+ @ClassKey(CollapsedStatusBarFragmentStartable::class)
+ fun bindsCollapsedStatusBarFragmentStartable(
+ startable: CollapsedStatusBarFragmentStartable
+ ): CoreStartable
+}
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/ClockEventControllerTest.kt b/packages/SystemUI/tests/src/com/android/keyguard/ClockEventControllerTest.kt
index c91313ad09b5..6afa5256523c 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/ClockEventControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/keyguard/ClockEventControllerTest.kt
@@ -126,12 +126,14 @@ class ClockEventControllerTest : SysuiTestCase() {
withDeps.featureFlags.apply {
set(Flags.REGION_SAMPLING, false)
set(Flags.DOZING_MIGRATION_1, false)
+ set(Flags.FACE_AUTH_REFACTOR, false)
}
underTest =
ClockEventController(
withDeps.keyguardInteractor,
KeyguardTransitionInteractorFactory.create(
scope = TestScope().backgroundScope,
+ featureFlags = withDeps.featureFlags,
)
.keyguardTransitionInteractor,
broadcastDispatcher,
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerControllerTest.kt b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerControllerTest.kt
index 6bff4ce4aad9..5da919b22afe 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerControllerTest.kt
@@ -191,7 +191,6 @@ class KeyguardSecurityContainerControllerTest : SysuiTestCase() {
featureFlags = FakeFeatureFlags()
featureFlags.set(Flags.REVAMPED_BOUNCER_MESSAGES, true)
- featureFlags.set(Flags.SCENE_CONTAINER, false)
featureFlags.set(Flags.BOUNCER_USER_SWITCHER, false)
featureFlags.set(Flags.KEYGUARD_WM_STATE_REFACTOR, false)
@@ -244,6 +243,7 @@ class KeyguardSecurityContainerControllerTest : SysuiTestCase() {
falsingManager,
userSwitcherController,
featureFlags,
+ sceneTestUtils.sceneContainerFlags,
globalSettings,
sessionTracker,
Optional.of(sideFpsController),
@@ -622,51 +622,6 @@ class KeyguardSecurityContainerControllerTest : SysuiTestCase() {
configurationListenerArgumentCaptor.value.onUiModeChanged()
verify(view).reloadColors()
}
- @Test
- fun onOrientationChanged_landscapeKeyguardFlagDisabled_blockReinflate() {
- featureFlags.set(Flags.LOCKSCREEN_ENABLE_LANDSCAPE, false)
-
- // Run onOrientationChanged
- val configurationListenerArgumentCaptor =
- ArgumentCaptor.forClass(ConfigurationController.ConfigurationListener::class.java)
- underTest.onViewAttached()
- verify(configurationController).addCallback(configurationListenerArgumentCaptor.capture())
- clearInvocations(viewFlipperController)
- configurationListenerArgumentCaptor.value.onOrientationChanged(
- Configuration.ORIENTATION_LANDSCAPE
- )
- // Verify view is reinflated when flag is on
- verify(viewFlipperController, never()).clearViews()
- verify(viewFlipperController, never())
- .asynchronouslyInflateView(
- eq(SecurityMode.PIN),
- any(),
- onViewInflatedCallbackArgumentCaptor.capture()
- )
- }
-
- @Test
- fun onOrientationChanged_landscapeKeyguardFlagEnabled_doesReinflate() {
- featureFlags.set(Flags.LOCKSCREEN_ENABLE_LANDSCAPE, true)
-
- // Run onOrientationChanged
- val configurationListenerArgumentCaptor =
- ArgumentCaptor.forClass(ConfigurationController.ConfigurationListener::class.java)
- underTest.onViewAttached()
- verify(configurationController).addCallback(configurationListenerArgumentCaptor.capture())
- clearInvocations(viewFlipperController)
- configurationListenerArgumentCaptor.value.onOrientationChanged(
- Configuration.ORIENTATION_LANDSCAPE
- )
- // Verify view is reinflated when flag is on
- verify(viewFlipperController).clearViews()
- verify(viewFlipperController)
- .asynchronouslyInflateView(
- eq(SecurityMode.PIN),
- any(),
- onViewInflatedCallbackArgumentCaptor.capture()
- )
- }
@Test
fun hasDismissActions() {
@@ -802,8 +757,6 @@ class KeyguardSecurityContainerControllerTest : SysuiTestCase() {
@Test
fun dismissesKeyguard_whenSceneChangesToGone() =
sceneTestUtils.testScope.runTest {
- featureFlags.set(Flags.SCENE_CONTAINER, true)
-
// Upon init, we have never dismisses the keyguard.
underTest.onInit()
runCurrent()
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityViewFlipperControllerTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityViewFlipperControllerTest.java
index 68c2f59722ad..19bc8186eee5 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityViewFlipperControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityViewFlipperControllerTest.java
@@ -140,11 +140,6 @@ public class KeyguardSecurityViewFlipperControllerTest extends SysuiTestCase {
@Test
public void asynchronouslyInflateView_setNeedsInput() {
- when(mKeyguardSecurityViewControllerFactory.create(
- any(), any(SecurityMode.class),
- any(KeyguardSecurityCallback.class)))
- .thenReturn(mKeyguardInputViewController);
-
ArgumentCaptor<AsyncLayoutInflater.OnInflateFinishedListener> argumentCaptor =
ArgumentCaptor.forClass(AsyncLayoutInflater.OnInflateFinishedListener.class);
mKeyguardSecurityViewFlipperController.asynchronouslyInflateView(SecurityMode.PIN,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/appops/AppOpsControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/appops/AppOpsControllerTest.java
index b100336b602f..f9830b124827 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/appops/AppOpsControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/appops/AppOpsControllerTest.java
@@ -71,6 +71,7 @@ import org.mockito.MockitoAnnotations;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
+import java.util.Map;
@SmallTest
@RunWith(AndroidTestingRunner.class)
@@ -163,6 +164,204 @@ public class AppOpsControllerTest extends SysuiTestCase {
}
@Test
+ public void startListening_fetchesCurrentActive_none() {
+ when(mAppOpsManager.getPackagesForOps(AppOpsControllerImpl.OPS))
+ .thenReturn(List.of());
+
+ mController.setListening(true);
+
+ assertThat(mController.getActiveAppOps()).isEmpty();
+ }
+
+ /** Regression test for b/294104969. */
+ @Test
+ public void startListening_fetchesCurrentActive_oneActive() {
+ AppOpsManager.PackageOps packageOps = createPackageOp(
+ "package.test",
+ /* packageUid= */ 2,
+ AppOpsManager.OPSTR_FINE_LOCATION,
+ /* isRunning= */ true);
+ when(mAppOpsManager.getPackagesForOps(AppOpsControllerImpl.OPS))
+ .thenReturn(List.of(packageOps));
+
+ // WHEN we start listening
+ mController.setListening(true);
+
+ // THEN the active list has the op
+ List<AppOpItem> list = mController.getActiveAppOps();
+ assertEquals(1, list.size());
+ AppOpItem first = list.get(0);
+ assertThat(first.getPackageName()).isEqualTo("package.test");
+ assertThat(first.getUid()).isEqualTo(2);
+ assertThat(first.getCode()).isEqualTo(AppOpsManager.OP_FINE_LOCATION);
+ }
+
+ @Test
+ public void startListening_fetchesCurrentActive_multiplePackages() {
+ AppOpsManager.PackageOps packageOps1 = createPackageOp(
+ "package.one",
+ /* packageUid= */ 1,
+ AppOpsManager.OPSTR_FINE_LOCATION,
+ /* isRunning= */ true);
+ AppOpsManager.PackageOps packageOps2 = createPackageOp(
+ "package.two",
+ /* packageUid= */ 2,
+ AppOpsManager.OPSTR_FINE_LOCATION,
+ /* isRunning= */ false);
+ AppOpsManager.PackageOps packageOps3 = createPackageOp(
+ "package.three",
+ /* packageUid= */ 3,
+ AppOpsManager.OPSTR_FINE_LOCATION,
+ /* isRunning= */ true);
+ when(mAppOpsManager.getPackagesForOps(AppOpsControllerImpl.OPS))
+ .thenReturn(List.of(packageOps1, packageOps2, packageOps3));
+
+ // WHEN we start listening
+ mController.setListening(true);
+
+ // THEN the active list has the ops
+ List<AppOpItem> list = mController.getActiveAppOps();
+ assertEquals(2, list.size());
+
+ AppOpItem item0 = list.get(0);
+ assertThat(item0.getPackageName()).isEqualTo("package.one");
+ assertThat(item0.getUid()).isEqualTo(1);
+ assertThat(item0.getCode()).isEqualTo(AppOpsManager.OP_FINE_LOCATION);
+
+ AppOpItem item1 = list.get(1);
+ assertThat(item1.getPackageName()).isEqualTo("package.three");
+ assertThat(item1.getUid()).isEqualTo(3);
+ assertThat(item1.getCode()).isEqualTo(AppOpsManager.OP_FINE_LOCATION);
+ }
+
+ @Test
+ public void startListening_fetchesCurrentActive_multipleEntries() {
+ AppOpsManager.PackageOps packageOps = mock(AppOpsManager.PackageOps.class);
+ when(packageOps.getUid()).thenReturn(1);
+ when(packageOps.getPackageName()).thenReturn("package.one");
+
+ // Entry 1
+ AppOpsManager.OpEntry entry1 = mock(AppOpsManager.OpEntry.class);
+ when(entry1.getOpStr()).thenReturn(AppOpsManager.OPSTR_PHONE_CALL_MICROPHONE);
+ AppOpsManager.AttributedOpEntry attributed1 = mock(AppOpsManager.AttributedOpEntry.class);
+ when(attributed1.isRunning()).thenReturn(true);
+ when(entry1.getAttributedOpEntries()).thenReturn(Map.of("tag", attributed1));
+ // Entry 2
+ AppOpsManager.OpEntry entry2 = mock(AppOpsManager.OpEntry.class);
+ when(entry2.getOpStr()).thenReturn(AppOpsManager.OPSTR_CAMERA);
+ AppOpsManager.AttributedOpEntry attributed2 = mock(AppOpsManager.AttributedOpEntry.class);
+ when(attributed2.isRunning()).thenReturn(true);
+ when(entry2.getAttributedOpEntries()).thenReturn(Map.of("tag", attributed2));
+ // Entry 3
+ AppOpsManager.OpEntry entry3 = mock(AppOpsManager.OpEntry.class);
+ when(entry3.getOpStr()).thenReturn(AppOpsManager.OPSTR_FINE_LOCATION);
+ AppOpsManager.AttributedOpEntry attributed3 = mock(AppOpsManager.AttributedOpEntry.class);
+ when(attributed3.isRunning()).thenReturn(false);
+ when(entry3.getAttributedOpEntries()).thenReturn(Map.of("tag", attributed3));
+
+ when(packageOps.getOps()).thenReturn(List.of(entry1, entry2, entry3));
+ when(mAppOpsManager.getPackagesForOps(AppOpsControllerImpl.OPS))
+ .thenReturn(List.of(packageOps));
+
+ // WHEN we start listening
+ mController.setListening(true);
+
+ // THEN the active list has the ops
+ List<AppOpItem> list = mController.getActiveAppOps();
+ assertEquals(2, list.size());
+
+ AppOpItem first = list.get(0);
+ assertThat(first.getPackageName()).isEqualTo("package.one");
+ assertThat(first.getUid()).isEqualTo(1);
+ assertThat(first.getCode()).isEqualTo(AppOpsManager.OP_PHONE_CALL_MICROPHONE);
+
+ AppOpItem second = list.get(1);
+ assertThat(second.getPackageName()).isEqualTo("package.one");
+ assertThat(second.getUid()).isEqualTo(1);
+ assertThat(second.getCode()).isEqualTo(AppOpsManager.OP_CAMERA);
+ }
+
+ @Test
+ public void startListening_fetchesCurrentActive_multipleAttributes() {
+ AppOpsManager.PackageOps packageOps = mock(AppOpsManager.PackageOps.class);
+ when(packageOps.getUid()).thenReturn(1);
+ when(packageOps.getPackageName()).thenReturn("package.one");
+ AppOpsManager.OpEntry entry = mock(AppOpsManager.OpEntry.class);
+ when(entry.getOpStr()).thenReturn(AppOpsManager.OPSTR_RECORD_AUDIO);
+
+ AppOpsManager.AttributedOpEntry attributed1 = mock(AppOpsManager.AttributedOpEntry.class);
+ when(attributed1.isRunning()).thenReturn(false);
+ AppOpsManager.AttributedOpEntry attributed2 = mock(AppOpsManager.AttributedOpEntry.class);
+ when(attributed2.isRunning()).thenReturn(true);
+ AppOpsManager.AttributedOpEntry attributed3 = mock(AppOpsManager.AttributedOpEntry.class);
+ when(attributed3.isRunning()).thenReturn(true);
+ when(entry.getAttributedOpEntries()).thenReturn(
+ Map.of("attr1", attributed1, "attr2", attributed2, "attr3", attributed3));
+
+ when(packageOps.getOps()).thenReturn(List.of(entry));
+ when(mAppOpsManager.getPackagesForOps(AppOpsControllerImpl.OPS))
+ .thenReturn(List.of(packageOps));
+
+ // WHEN we start listening
+ mController.setListening(true);
+
+ // THEN the active list has the ops
+ List<AppOpItem> list = mController.getActiveAppOps();
+ // Multiple attributes get merged into one entry in the active ops
+ assertEquals(1, list.size());
+
+ AppOpItem first = list.get(0);
+ assertThat(first.getPackageName()).isEqualTo("package.one");
+ assertThat(first.getUid()).isEqualTo(1);
+ assertThat(first.getCode()).isEqualTo(AppOpsManager.OP_RECORD_AUDIO);
+ }
+
+ /** Regression test for b/294104969. */
+ @Test
+ public void addCallback_existingCallbacksNotifiedOfCurrentActive() {
+ AppOpsManager.PackageOps packageOps1 = createPackageOp(
+ "package.one",
+ /* packageUid= */ 1,
+ AppOpsManager.OPSTR_FINE_LOCATION,
+ /* isRunning= */ true);
+ AppOpsManager.PackageOps packageOps2 = createPackageOp(
+ "package.two",
+ /* packageUid= */ 2,
+ AppOpsManager.OPSTR_RECORD_AUDIO,
+ /* isRunning= */ true);
+ AppOpsManager.PackageOps packageOps3 = createPackageOp(
+ "package.three",
+ /* packageUid= */ 3,
+ AppOpsManager.OPSTR_PHONE_CALL_MICROPHONE,
+ /* isRunning= */ true);
+ when(mAppOpsManager.getPackagesForOps(AppOpsControllerImpl.OPS))
+ .thenReturn(List.of(packageOps1, packageOps2, packageOps3));
+
+ // WHEN we start listening
+ mController.addCallback(
+ new int[]{AppOpsManager.OP_RECORD_AUDIO, AppOpsManager.OP_FINE_LOCATION},
+ mCallback);
+ mTestableLooper.processAllMessages();
+
+ // THEN the callback is notified of the current active ops it cares about
+ verify(mCallback).onActiveStateChanged(
+ AppOpsManager.OP_FINE_LOCATION,
+ /* uid= */ 1,
+ "package.one",
+ true);
+ verify(mCallback).onActiveStateChanged(
+ AppOpsManager.OP_RECORD_AUDIO,
+ /* uid= */ 2,
+ "package.two",
+ true);
+ verify(mCallback, never()).onActiveStateChanged(
+ AppOpsManager.OP_PHONE_CALL_MICROPHONE,
+ /* uid= */ 3,
+ "package.three",
+ true);
+ }
+
+ @Test
public void addCallback_includedCode() {
mController.addCallback(
new int[]{AppOpsManager.OP_RECORD_AUDIO, AppOpsManager.OP_FINE_LOCATION},
@@ -772,6 +971,22 @@ public class AppOpsControllerTest extends SysuiTestCase {
assertFalse(list.get(1).isDisabled());
}
+ private AppOpsManager.PackageOps createPackageOp(
+ String packageName, int packageUid, String opStr, boolean isRunning) {
+ AppOpsManager.PackageOps packageOps = mock(AppOpsManager.PackageOps.class);
+ when(packageOps.getPackageName()).thenReturn(packageName);
+ when(packageOps.getUid()).thenReturn(packageUid);
+ AppOpsManager.OpEntry entry = mock(AppOpsManager.OpEntry.class);
+ when(entry.getOpStr()).thenReturn(opStr);
+ AppOpsManager.AttributedOpEntry attributed = mock(AppOpsManager.AttributedOpEntry.class);
+ when(attributed.isRunning()).thenReturn(isRunning);
+
+ when(packageOps.getOps()).thenReturn(Collections.singletonList(entry));
+ when(entry.getAttributedOpEntries()).thenReturn(Map.of("tag", attributed));
+
+ return packageOps;
+ }
+
private class TestHandler extends AppOpsControllerImpl.H {
TestHandler(Looper looper) {
mController.super(looper);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerTest.java
index e56b5c7406b6..e01b5afefe0a 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerTest.java
@@ -106,7 +106,6 @@ import com.android.systemui.statusbar.phone.SystemUIDialogManager;
import com.android.systemui.statusbar.phone.UnlockedScreenOffAnimationController;
import com.android.systemui.statusbar.policy.ConfigurationController;
import com.android.systemui.statusbar.policy.KeyguardStateController;
-import com.android.systemui.util.concurrency.Execution;
import com.android.systemui.util.concurrency.FakeExecution;
import com.android.systemui.util.concurrency.FakeExecutor;
import com.android.systemui.util.settings.SecureSettings;
@@ -252,7 +251,9 @@ public class UdfpsControllerTest extends SysuiTestCase {
@Before
public void setUp() {
- Execution execution = new FakeExecution();
+ mContext.getOrCreateTestableResources()
+ .addOverride(com.android.internal.R.bool.config_ignoreUdfpsVote, false);
+
mUdfpsUtils = new UdfpsUtils();
when(mLayoutInflater.inflate(R.layout.udfps_view, null, false))
diff --git a/packages/SystemUI/tests/src/com/android/systemui/communal/data/repository/CommunalWidgetRepositoryImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/communal/data/repository/CommunalWidgetRepositoryImplTest.kt
index 3df9cbb29e4a..7fa828fbfadd 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/communal/data/repository/CommunalWidgetRepositoryImplTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/communal/data/repository/CommunalWidgetRepositoryImplTest.kt
@@ -9,6 +9,7 @@ import android.os.UserHandle
import android.os.UserManager
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
+import com.android.systemui.RoboPilotTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.broadcast.BroadcastDispatcher
import com.android.systemui.coroutines.collectLastValue
@@ -39,6 +40,7 @@ import org.mockito.MockitoAnnotations
@OptIn(ExperimentalCoroutinesApi::class)
@SmallTest
+@RoboPilotTest
@RunWith(AndroidJUnit4::class)
class CommunalWidgetRepositoryImplTest : SysuiTestCase() {
@Mock private lateinit var appWidgetManager: AppWidgetManager
diff --git a/packages/SystemUI/tests/src/com/android/systemui/communal/ui/view/layout/blueprints/DefaultCommunalBlueprintTest.kt b/packages/SystemUI/tests/src/com/android/systemui/communal/ui/view/layout/blueprints/DefaultCommunalBlueprintTest.kt
index 4ad9549d1d4a..09cb9291f6b2 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/communal/ui/view/layout/blueprints/DefaultCommunalBlueprintTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/communal/ui/view/layout/blueprints/DefaultCommunalBlueprintTest.kt
@@ -1,10 +1,11 @@
package com.android.systemui.communal.ui.view.layout.blueprints
-import android.testing.AndroidTestingRunner
import android.testing.TestableLooper
import androidx.constraintlayout.widget.ConstraintLayout
import androidx.constraintlayout.widget.ConstraintSet
+import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
+import com.android.systemui.RoboPilotTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.communal.ui.view.layout.sections.DefaultCommunalWidgetSection
import org.junit.Before
@@ -14,7 +15,8 @@ import org.mockito.Mock
import org.mockito.Mockito.verify
import org.mockito.MockitoAnnotations
-@RunWith(AndroidTestingRunner::class)
+@RoboPilotTest
+@RunWith(AndroidJUnit4::class)
@TestableLooper.RunWithLooper(setAsMainLooper = true)
@SmallTest
class DefaultCommunalBlueprintTest : SysuiTestCase() {
@@ -31,7 +33,7 @@ class DefaultCommunalBlueprintTest : SysuiTestCase() {
@Test
fun addView() {
val constraintLayout = ConstraintLayout(context, null)
- blueprint.addViews(constraintLayout)
+ blueprint.addViews(null, constraintLayout)
verify(widgetSection).addViews(constraintLayout)
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/controls/dagger/ControlsComponentTest.kt b/packages/SystemUI/tests/src/com/android/systemui/controls/dagger/ControlsComponentTest.kt
index 0b27bc9c7dbd..54f66dc957d9 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/controls/dagger/ControlsComponentTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/controls/dagger/ControlsComponentTest.kt
@@ -29,7 +29,6 @@ import com.android.systemui.controls.settings.FakeControlsSettingsRepository
import com.android.systemui.controls.ui.ControlsUiController
import com.android.systemui.settings.UserTracker
import com.android.systemui.statusbar.policy.KeyguardStateController
-import dagger.Lazy
import java.util.Optional
import org.junit.Assert.assertEquals
import org.junit.Assert.assertFalse
@@ -173,10 +172,9 @@ class ControlsComponentTest : SysuiTestCase() {
private fun setupComponent(enabled: Boolean): ControlsComponent {
return ControlsComponent(
enabled,
- mContext,
- Lazy { controller },
- Lazy { uiController },
- Lazy { listingController },
+ { controller },
+ { uiController },
+ { listingController },
lockPatternUtils,
keyguardStateController,
userTracker,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/controls/ui/TemperatureControlBehaviorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/controls/ui/TemperatureControlBehaviorTest.kt
new file mode 100644
index 000000000000..588e34d3111d
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/controls/ui/TemperatureControlBehaviorTest.kt
@@ -0,0 +1,98 @@
+package com.android.systemui.controls.ui
+
+import android.app.PendingIntent
+import android.content.ComponentName
+import android.content.Intent
+import android.graphics.drawable.Icon
+import android.service.controls.Control
+import android.service.controls.DeviceTypes
+import android.service.controls.templates.TemperatureControlTemplate
+import android.service.controls.templates.ThumbnailTemplate
+import android.view.LayoutInflater
+import android.view.ViewGroup
+import androidx.test.filters.SmallTest
+import com.android.systemui.R
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.controls.ControlsMetricsLogger
+import com.android.systemui.controls.controller.ControlInfo
+import com.android.systemui.controls.controller.ControlsController
+import com.android.systemui.util.concurrency.FakeExecutor
+import com.android.systemui.util.time.FakeSystemClock
+import org.junit.Before
+import org.junit.Test
+import org.mockito.Mock
+import org.mockito.MockitoAnnotations
+
+@SmallTest
+class TemperatureControlBehaviorTest : SysuiTestCase() {
+
+ @Mock lateinit var controlsMetricsLogger: ControlsMetricsLogger
+ @Mock lateinit var controlActionCoordinator: ControlActionCoordinator
+ @Mock lateinit var controlsController: ControlsController
+
+ private val fakeSystemClock = FakeSystemClock()
+ private val underTest = TemperatureControlBehavior()
+
+ private lateinit var viewHolder: ControlViewHolder
+
+ @Before
+ fun setup() {
+ MockitoAnnotations.initMocks(this)
+
+ viewHolder =
+ ControlViewHolder(
+ LayoutInflater.from(mContext).inflate(R.layout.controls_base_item, null, false)
+ as ViewGroup,
+ controlsController,
+ FakeExecutor(fakeSystemClock),
+ FakeExecutor(fakeSystemClock),
+ controlActionCoordinator,
+ controlsMetricsLogger,
+ 0,
+ 0,
+ )
+ }
+
+ @Test
+ fun testBehaviourSupportsThumbnailSubBehaviour() {
+ val controlWithState =
+ ControlWithState(
+ ComponentName("test.pkg", "TestClass"),
+ ControlInfo(
+ "test_id",
+ "test title",
+ "test subtitle",
+ DeviceTypes.TYPE_AC_UNIT,
+ ),
+ Control.StatefulBuilder(
+ "",
+ PendingIntent.getActivity(
+ context,
+ 0,
+ Intent(),
+ PendingIntent.FLAG_IMMUTABLE,
+ ),
+ )
+ .setControlTemplate(
+ TemperatureControlTemplate(
+ "test id",
+ ThumbnailTemplate(
+ "test id",
+ false,
+ Icon.createWithContentUri(""),
+ "test description",
+ ),
+ 0,
+ 0,
+ 0
+ )
+ )
+ .setStatus(Control.STATUS_OK)
+ .build()
+ )
+ viewHolder.bindData(controlWithState, false)
+ underTest.initialize(viewHolder)
+
+ underTest.bind(controlWithState, 0) // no crash
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/display/data/repository/DisplayRepositoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/display/data/repository/DisplayRepositoryTest.kt
index db7c003ee545..4bd380e927c7 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/display/data/repository/DisplayRepositoryTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/display/data/repository/DisplayRepositoryTest.kt
@@ -52,6 +52,7 @@ class DisplayRepositoryTest : SysuiTestCase() {
private val displayManager = mock<DisplayManager>()
private val displayListener = kotlinArgumentCaptor<DisplayManager.DisplayListener>()
+ private val connectedDisplayListener = kotlinArgumentCaptor<DisplayManager.DisplayListener>()
private val testHandler = FakeHandler(Looper.getMainLooper())
private val testScope = TestScope(UnconfinedTestDispatcher())
@@ -114,7 +115,7 @@ class DisplayRepositoryTest : SysuiTestCase() {
// Let's make sure it has *NOT* been unregistered, as there is still a subscriber.
setDisplays(1)
- displayListener.value.onDisplayAdded(1)
+ sendOnDisplayAdded(1)
assertThat(firstSubscriber?.ids()).containsExactly(1)
}
@@ -127,7 +128,7 @@ class DisplayRepositoryTest : SysuiTestCase() {
val value by latestDisplayFlowValue()
setDisplays(1)
- displayListener.value.onDisplayAdded(1)
+ sendOnDisplayAdded(1)
assertThat(value?.ids()).containsExactly(1)
}
@@ -138,13 +139,13 @@ class DisplayRepositoryTest : SysuiTestCase() {
val value by latestDisplayFlowValue()
setDisplays(1, 2, 3, 4)
- displayListener.value.onDisplayAdded(1)
- displayListener.value.onDisplayAdded(2)
- displayListener.value.onDisplayAdded(3)
- displayListener.value.onDisplayAdded(4)
+ sendOnDisplayAdded(1)
+ sendOnDisplayAdded(2)
+ sendOnDisplayAdded(3)
+ sendOnDisplayAdded(4)
setDisplays(1, 2, 3)
- displayListener.value.onDisplayRemoved(4)
+ sendOnDisplayRemoved(4)
assertThat(value?.ids()).containsExactly(1, 2, 3)
}
@@ -155,10 +156,10 @@ class DisplayRepositoryTest : SysuiTestCase() {
val value by latestDisplayFlowValue()
setDisplays(1, 2, 3, 4)
- displayListener.value.onDisplayAdded(1)
- displayListener.value.onDisplayAdded(2)
- displayListener.value.onDisplayAdded(3)
- displayListener.value.onDisplayAdded(4)
+ sendOnDisplayAdded(1)
+ sendOnDisplayAdded(2)
+ sendOnDisplayAdded(3)
+ sendOnDisplayAdded(4)
displayListener.value.onDisplayChanged(4)
@@ -168,22 +169,22 @@ class DisplayRepositoryTest : SysuiTestCase() {
@Test
fun onDisplayConnected_pendingDisplayReceived() =
testScope.runTest {
- val pendingDisplay by latestPendingDisplayFlowValue()
+ val pendingDisplay by lastPendingDisplay()
- displayListener.value.onDisplayConnected(1)
+ sendOnDisplayConnected(1)
- assertThat(pendingDisplay).isEqualTo(1)
+ assertThat(pendingDisplay!!.id).isEqualTo(1)
}
@Test
fun onDisplayDisconnected_pendingDisplayNull() =
testScope.runTest {
- val pendingDisplay by latestPendingDisplayFlowValue()
- displayListener.value.onDisplayConnected(1)
+ val pendingDisplay by lastPendingDisplay()
+ sendOnDisplayConnected(1)
assertThat(pendingDisplay).isNotNull()
- displayListener.value.onDisplayDisconnected(1)
+ sendOnDisplayDisconnected(1)
assertThat(pendingDisplay).isNull()
}
@@ -191,24 +192,162 @@ class DisplayRepositoryTest : SysuiTestCase() {
@Test
fun onDisplayDisconnected_unknownDisplay_doesNotSendNull() =
testScope.runTest {
- val pendingDisplay by latestPendingDisplayFlowValue()
- displayListener.value.onDisplayConnected(1)
+ val pendingDisplay by lastPendingDisplay()
+ sendOnDisplayConnected(1)
assertThat(pendingDisplay).isNotNull()
- displayListener.value.onDisplayDisconnected(2)
+ sendOnDisplayDisconnected(2)
assertThat(pendingDisplay).isNotNull()
}
@Test
- fun onDisplayConnected_multipleTimes_sendsOnlyTheLastOne() =
+ fun onDisplayConnected_multipleTimes_sendsOnlyTheMaximum() =
testScope.runTest {
- val pendingDisplay by latestPendingDisplayFlowValue()
- displayListener.value.onDisplayConnected(1)
- displayListener.value.onDisplayConnected(2)
+ val pendingDisplay by lastPendingDisplay()
- assertThat(pendingDisplay).isEqualTo(2)
+ sendOnDisplayConnected(1)
+ sendOnDisplayConnected(2)
+
+ assertThat(pendingDisplay!!.id).isEqualTo(2)
+ }
+
+ @Test
+ fun onPendingDisplay_enable_displayEnabled() =
+ testScope.runTest {
+ val pendingDisplay by lastPendingDisplay()
+
+ sendOnDisplayConnected(1)
+ pendingDisplay!!.enable()
+
+ verify(displayManager).enableConnectedDisplay(eq(1))
+ }
+
+ @Test
+ fun onPendingDisplay_enableBySysui_disabledBySomeoneElse_pendingDisplayStillIgnored() =
+ testScope.runTest {
+ val pendingDisplay by lastPendingDisplay()
+
+ sendOnDisplayConnected(1)
+ pendingDisplay!!.enable()
+ // to mock the display being really enabled:
+ sendOnDisplayAdded(1)
+
+ // Simulate the display being disabled by someone else. Now, sysui will have it in the
+ // "pending displays" list again, but it should be ignored.
+ sendOnDisplayRemoved(1)
+
+ assertThat(pendingDisplay).isNull()
+ }
+
+ @Test
+ fun onPendingDisplay_ignoredBySysui_enabledDisabledBySomeoneElse_pendingDisplayStillIgnored() =
+ testScope.runTest {
+ val pendingDisplay by lastPendingDisplay()
+
+ sendOnDisplayConnected(1)
+ pendingDisplay!!.ignore()
+
+ // to mock the display being enabled and disabled by someone else:
+ sendOnDisplayAdded(1)
+ sendOnDisplayRemoved(1)
+
+ // Sysui already decided to ignore it, so the pending display should be null.
+ assertThat(pendingDisplay).isNull()
+ }
+
+ @Test
+ fun onPendingDisplay_disable_displayDisabled() =
+ testScope.runTest {
+ val pendingDisplay by lastPendingDisplay()
+
+ sendOnDisplayConnected(1)
+ pendingDisplay!!.disable()
+
+ verify(displayManager).disableConnectedDisplay(eq(1))
+ }
+
+ @Test
+ fun onPendingDisplay_ignore_pendingDisplayNull() =
+ testScope.runTest {
+ val pendingDisplay by lastPendingDisplay()
+ sendOnDisplayConnected(1)
+
+ pendingDisplay!!.ignore()
+
+ assertThat(pendingDisplay).isNull()
+ verify(displayManager, never()).disableConnectedDisplay(eq(1))
+ verify(displayManager, never()).enableConnectedDisplay(eq(1))
+ }
+
+ @Test
+ fun onPendingDisplay_enabled_pendingDisplayNull() =
+ testScope.runTest {
+ val pendingDisplay by lastPendingDisplay()
+
+ sendOnDisplayConnected(1)
+ assertThat(pendingDisplay).isNotNull()
+
+ setDisplays(1)
+ sendOnDisplayAdded(1)
+
+ assertThat(pendingDisplay).isNull()
+ }
+
+ @Test
+ fun onPendingDisplay_multipleConnected_oneEnabled_pendingDisplayNotNull() =
+ testScope.runTest {
+ val pendingDisplay by lastPendingDisplay()
+
+ sendOnDisplayConnected(1)
+ sendOnDisplayConnected(2)
+
+ assertThat(pendingDisplay).isNotNull()
+
+ setDisplays(1)
+ sendOnDisplayAdded(1)
+
+ assertThat(pendingDisplay).isNotNull()
+ assertThat(pendingDisplay!!.id).isEqualTo(2)
+
+ setDisplays(1, 2)
+ sendOnDisplayAdded(2)
+
+ assertThat(pendingDisplay).isNull()
+ }
+
+ @Test
+ fun pendingDisplay_connectedDisconnectedAndReconnected_expectedPendingDisplayState() =
+ testScope.runTest {
+ val pendingDisplay by lastPendingDisplay()
+
+ // Plug the cable
+ sendOnDisplayConnected(1)
+
+ // Enable it
+ assertThat(pendingDisplay).isNotNull()
+ pendingDisplay!!.enable()
+
+ // Enabled
+ verify(displayManager).enableConnectedDisplay(1)
+ setDisplays(1)
+ sendOnDisplayAdded(1)
+
+ // No more pending displays
+ assertThat(pendingDisplay).isNull()
+
+ // Let's disconnect the cable
+ setDisplays()
+ sendOnDisplayRemoved(1)
+ sendOnDisplayDisconnected(1)
+
+ assertThat(pendingDisplay).isNull()
+
+ // Let's reconnect it
+ sendOnDisplayConnected(1)
+
+ assertThat(pendingDisplay).isNotNull()
}
private fun Iterable<Display>.ids(): List<Int> = map { it.displayId }
@@ -216,28 +355,47 @@ class DisplayRepositoryTest : SysuiTestCase() {
// Wrapper to capture the displayListener.
private fun TestScope.latestDisplayFlowValue(): FlowValue<Set<Display>?> {
val flowValue = collectLastValue(displayRepository.displays)
+ captureAddedRemovedListener()
+ return flowValue
+ }
+
+ private fun TestScope.lastPendingDisplay(): FlowValue<DisplayRepository.PendingDisplay?> {
+ val flowValue = collectLastValue(displayRepository.pendingDisplay)
+ captureAddedRemovedListener()
verify(displayManager)
.registerDisplayListener(
- displayListener.capture(),
+ connectedDisplayListener.capture(),
eq(testHandler),
- eq(
- DisplayManager.EVENT_FLAG_DISPLAY_ADDED or
- DisplayManager.EVENT_FLAG_DISPLAY_CHANGED or
- DisplayManager.EVENT_FLAG_DISPLAY_REMOVED
- )
+ eq(DisplayManager.EVENT_FLAG_DISPLAY_CONNECTION_CHANGED)
)
return flowValue
}
- private fun TestScope.latestPendingDisplayFlowValue(): FlowValue<Int?> {
- val flowValue = collectLastValue(displayRepository.pendingDisplayId)
+ private fun captureAddedRemovedListener() {
verify(displayManager)
.registerDisplayListener(
displayListener.capture(),
eq(testHandler),
- eq(DisplayManager.EVENT_FLAG_DISPLAY_CONNECTION_CHANGED)
+ eq(
+ DisplayManager.EVENT_FLAG_DISPLAY_ADDED or
+ DisplayManager.EVENT_FLAG_DISPLAY_CHANGED or
+ DisplayManager.EVENT_FLAG_DISPLAY_REMOVED
+ )
)
- return flowValue
+ }
+ private fun sendOnDisplayAdded(id: Int) {
+ displayListener.value.onDisplayAdded(id)
+ }
+ private fun sendOnDisplayRemoved(id: Int) {
+ displayListener.value.onDisplayRemoved(id)
+ }
+
+ private fun sendOnDisplayDisconnected(id: Int) {
+ connectedDisplayListener.value.onDisplayDisconnected(id)
+ }
+
+ private fun sendOnDisplayConnected(id: Int) {
+ connectedDisplayListener.value.onDisplayConnected(id)
}
private fun setDisplays(displays: List<Display>) {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/display/domain/interactor/ConnectedDisplayInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/display/domain/interactor/ConnectedDisplayInteractorTest.kt
index 50617a16ce0b..26ee09412687 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/display/domain/interactor/ConnectedDisplayInteractorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/display/domain/interactor/ConnectedDisplayInteractorTest.kt
@@ -16,7 +16,6 @@
package com.android.systemui.display.domain.interactor
-import android.hardware.display.DisplayManager
import android.testing.AndroidTestingRunner
import android.testing.TestableLooper
import android.view.Display
@@ -27,12 +26,11 @@ import com.android.systemui.SysuiTestCase
import com.android.systemui.coroutines.FlowValue
import com.android.systemui.coroutines.collectLastValue
import com.android.systemui.display.data.repository.FakeDisplayRepository
+import com.android.systemui.display.data.repository.createPendingDisplay
import com.android.systemui.display.data.repository.display
import com.android.systemui.display.domain.interactor.ConnectedDisplayInteractor.PendingDisplay
import com.android.systemui.display.domain.interactor.ConnectedDisplayInteractor.State
import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository
-import com.android.systemui.util.mockito.eq
-import com.android.systemui.util.mockito.mock
import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.test.TestScope
@@ -41,7 +39,6 @@ import kotlinx.coroutines.test.runTest
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
-import org.mockito.Mockito
@RunWith(AndroidTestingRunner::class)
@TestableLooper.RunWithLooper
@@ -49,20 +46,15 @@ import org.mockito.Mockito
@SmallTest
class ConnectedDisplayInteractorTest : SysuiTestCase() {
- private val displayManager = mock<DisplayManager>()
private val fakeDisplayRepository = FakeDisplayRepository()
private val fakeKeyguardRepository = FakeKeyguardRepository()
private val connectedDisplayStateProvider: ConnectedDisplayInteractor =
- ConnectedDisplayInteractorImpl(
- displayManager,
- fakeKeyguardRepository,
- fakeDisplayRepository
- )
+ ConnectedDisplayInteractorImpl(fakeKeyguardRepository, fakeDisplayRepository)
private val testScope = TestScope(UnconfinedTestDispatcher())
@Before
fun setup() {
- fakeKeyguardRepository.setKeyguardUnlocked(true)
+ fakeKeyguardRepository.setKeyguardShowing(false)
}
@Test
@@ -148,7 +140,7 @@ class ConnectedDisplayInteractorTest : SysuiTestCase() {
fun pendingDisplay_propagated() =
testScope.runTest {
val value by lastPendingDisplay()
- val pendingDisplayId = 4
+ val pendingDisplayId = createPendingDisplay()
fakeDisplayRepository.emit(pendingDisplayId)
@@ -156,51 +148,29 @@ class ConnectedDisplayInteractorTest : SysuiTestCase() {
}
@Test
- fun onPendingDisplay_enable_displayEnabled() =
+ fun onPendingDisplay_keyguardShowing_returnsPendingDisplay() =
testScope.runTest {
+ fakeKeyguardRepository.setKeyguardShowing(true)
val pendingDisplay by lastPendingDisplay()
- fakeDisplayRepository.emit(1)
- pendingDisplay!!.enable()
-
- Mockito.verify(displayManager).enableConnectedDisplay(eq(1))
- }
-
- @Test
- fun onPendingDisplay_disable_displayDisabled() =
- testScope.runTest {
- val pendingDisplay by lastPendingDisplay()
-
- fakeDisplayRepository.emit(1)
- pendingDisplay!!.disable()
-
- Mockito.verify(displayManager).disableConnectedDisplay(eq(1))
- }
-
- @Test
- fun onPendingDisplay_keyguardUnlocked_returnsPendingDisplay() =
- testScope.runTest {
- fakeKeyguardRepository.setKeyguardUnlocked(false)
- val pendingDisplay by lastPendingDisplay()
-
- fakeDisplayRepository.emit(1)
+ fakeDisplayRepository.emit(createPendingDisplay())
assertThat(pendingDisplay).isNull()
- fakeKeyguardRepository.setKeyguardUnlocked(true)
+ fakeKeyguardRepository.setKeyguardShowing(false)
assertThat(pendingDisplay).isNotNull()
}
@Test
- fun onPendingDisplay_keyguardLocked_returnsNull() =
+ fun onPendingDisplay_keyguardShowing_returnsNull() =
testScope.runTest {
- fakeKeyguardRepository.setKeyguardUnlocked(true)
+ fakeKeyguardRepository.setKeyguardShowing(false)
val pendingDisplay by lastPendingDisplay()
- fakeDisplayRepository.emit(1)
+ fakeDisplayRepository.emit(createPendingDisplay())
assertThat(pendingDisplay).isNotNull()
- fakeKeyguardRepository.setKeyguardUnlocked(false)
+ fakeKeyguardRepository.setKeyguardShowing(true)
assertThat(pendingDisplay).isNull()
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/display/ui/view/MirroringConfirmationDialogTest.kt b/packages/SystemUI/tests/src/com/android/systemui/display/ui/view/MirroringConfirmationDialogTest.kt
index 705964736a49..46f758216aae 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/display/ui/view/MirroringConfirmationDialogTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/display/ui/view/MirroringConfirmationDialogTest.kt
@@ -68,6 +68,28 @@ class MirroringConfirmationDialogTest : SysuiTestCase() {
verify(onStartMirroringCallback, never()).onClick(any())
}
+ @Test
+ fun onCancel_afterEnablingMirroring_cancelCallbackNotCalled() {
+ dialog.show()
+ dialog.requireViewById<View>(R.id.enable_display).callOnClick()
+
+ dialog.cancel()
+
+ verify(onCancelCallback, never()).onClick(any())
+ verify(onStartMirroringCallback).onClick(any())
+ }
+
+ @Test
+ fun onDismiss_afterEnablingMirroring_cancelCallbackNotCalled() {
+ dialog.show()
+ dialog.requireViewById<View>(R.id.enable_display).callOnClick()
+
+ dialog.dismiss()
+
+ verify(onCancelCallback, never()).onClick(any())
+ verify(onStartMirroringCallback).onClick(any())
+ }
+
@After
fun teardown() {
if (::dialog.isInitialized) {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayAnimationsControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayAnimationsControllerTest.kt
index 57307fc84b1c..781ad6b10b70 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayAnimationsControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayAnimationsControllerTest.kt
@@ -3,9 +3,10 @@ package com.android.systemui.dreams
import android.animation.Animator
import android.animation.AnimatorSet
import android.animation.ValueAnimator
-import android.testing.AndroidTestingRunner
import android.view.View
+import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
+import com.android.systemui.RoboPilotTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.complication.ComplicationHostViewController
import com.android.systemui.keyguard.ui.viewmodel.DreamingToLockscreenTransitionViewModel
@@ -29,8 +30,9 @@ import org.mockito.Mockito.times
import org.mockito.Mockito.verify
import org.mockito.MockitoAnnotations
+@RoboPilotTest
@SmallTest
-@RunWith(AndroidTestingRunner::class)
+@RunWith(AndroidJUnit4::class)
class DreamOverlayAnimationsControllerTest : SysuiTestCase() {
companion object {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayCallbackControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayCallbackControllerTest.kt
index 9f534ef14f54..21192fa11da3 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayCallbackControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayCallbackControllerTest.kt
@@ -15,8 +15,9 @@
*/
package com.android.systemui.dreams
-import android.testing.AndroidTestingRunner
+import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
+import com.android.systemui.RoboPilotTest
import com.android.systemui.SysuiTestCase
import com.google.common.truth.Truth.assertThat
import org.junit.Before
@@ -29,8 +30,9 @@ import org.mockito.Mockito.times
import org.mockito.Mockito.verify
import org.mockito.MockitoAnnotations
+@RoboPilotTest
@SmallTest
-@RunWith(AndroidTestingRunner::class)
+@RunWith(AndroidJUnit4::class)
class DreamOverlayCallbackControllerTest : SysuiTestCase() {
@Mock private lateinit var callback: DreamOverlayCallbackController.Callback
diff --git a/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayContainerViewControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayContainerViewControllerTest.java
index 8786520ccf0e..7c36642f5417 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayContainerViewControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayContainerViewControllerTest.java
@@ -28,21 +28,22 @@ import static org.mockito.Mockito.when;
import android.content.res.Resources;
import android.graphics.Region;
import android.os.Handler;
-import android.testing.AndroidTestingRunner;
import android.view.AttachedSurfaceControl;
import android.view.ViewGroup;
import android.view.ViewRootImpl;
import android.view.ViewTreeObserver;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.filters.SmallTest;
import com.android.dream.lowlight.LowLightTransitionCoordinator;
import com.android.keyguard.BouncerPanelExpansionCalculator;
+import com.android.systemui.RoboPilotTest;
import com.android.systemui.SysuiTestCase;
-import com.android.systemui.complication.ComplicationHostViewController;
-import com.android.systemui.dreams.touch.scrim.BouncerlessScrimController;
import com.android.systemui.bouncer.domain.interactor.PrimaryBouncerCallbackInteractor;
import com.android.systemui.bouncer.domain.interactor.PrimaryBouncerCallbackInteractor.PrimaryBouncerExpansionCallback;
+import com.android.systemui.complication.ComplicationHostViewController;
+import com.android.systemui.dreams.touch.scrim.BouncerlessScrimController;
import com.android.systemui.statusbar.BlurUtils;
import org.junit.Before;
@@ -52,8 +53,9 @@ import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
+@RoboPilotTest
@SmallTest
-@RunWith(AndroidTestingRunner.class)
+@RunWith(AndroidJUnit4.class)
public class DreamOverlayContainerViewControllerTest extends SysuiTestCase {
private static final int MAX_BURN_IN_OFFSET = 20;
private static final long BURN_IN_PROTECTION_UPDATE_INTERVAL = 10;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayNotificationCountProviderTest.java b/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayNotificationCountProviderTest.java
index 25d4c472dc63..be7638ef31e6 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayNotificationCountProviderTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayNotificationCountProviderTest.java
@@ -22,10 +22,11 @@ import static org.mockito.Mockito.when;
import android.service.notification.NotificationListenerService;
import android.service.notification.StatusBarNotification;
-import android.testing.AndroidTestingRunner;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.filters.SmallTest;
+import com.android.systemui.RoboPilotTest;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.statusbar.NotificationListener;
import com.android.systemui.statusbar.NotificationListener.NotificationHandler;
@@ -37,8 +38,9 @@ import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
+@RoboPilotTest
@SmallTest
-@RunWith(AndroidTestingRunner.class)
+@RunWith(AndroidJUnit4.class)
public class DreamOverlayNotificationCountProviderTest extends SysuiTestCase {
@Mock
NotificationListener mNotificationListener;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayServiceTest.java b/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayServiceTest.java
index d99f0da494fd..8379f73402cf 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayServiceTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayServiceTest.java
@@ -37,7 +37,6 @@ import android.service.dreams.IDreamOverlay;
import android.service.dreams.IDreamOverlayCallback;
import android.service.dreams.IDreamOverlayClient;
import android.service.dreams.IDreamOverlayClientCallback;
-import android.testing.AndroidTestingRunner;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;
@@ -45,10 +44,12 @@ import android.view.WindowManagerImpl;
import androidx.lifecycle.Lifecycle;
import androidx.lifecycle.LifecycleRegistry;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.filters.SmallTest;
import com.android.internal.logging.UiEventLogger;
import com.android.keyguard.KeyguardUpdateMonitor;
+import com.android.systemui.RoboPilotTest;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.complication.ComplicationLayoutEngine;
import com.android.systemui.dreams.complication.HideComplicationTouchHandler;
@@ -71,8 +72,9 @@ import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
+@RoboPilotTest
@SmallTest
-@RunWith(AndroidTestingRunner.class)
+@RunWith(AndroidJUnit4.class)
public class DreamOverlayServiceTest extends SysuiTestCase {
private static final ComponentName LOW_LIGHT_COMPONENT = new ComponentName("package",
"lowlight");
diff --git a/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayStateControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayStateControllerTest.java
index 44a78ac3bc96..2ef227c245c3 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayStateControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayStateControllerTest.java
@@ -26,10 +26,10 @@ import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
-import android.testing.AndroidTestingRunner;
-
+import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.filters.SmallTest;
+import com.android.systemui.RoboPilotTest;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.complication.Complication;
import com.android.systemui.flags.FeatureFlags;
@@ -48,8 +48,9 @@ import org.mockito.MockitoAnnotations;
import java.util.Collection;
+@RoboPilotTest
@SmallTest
-@RunWith(AndroidTestingRunner.class)
+@RunWith(AndroidJUnit4.class)
public class DreamOverlayStateControllerTest extends SysuiTestCase {
@Mock
DreamOverlayStateController.Callback mCallback;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayStatusBarItemsProviderTest.java b/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayStatusBarItemsProviderTest.java
index a78886f8d504..12cb332c7cc5 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayStatusBarItemsProviderTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayStatusBarItemsProviderTest.java
@@ -21,10 +21,10 @@ import static org.mockito.Mockito.never;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
-import android.testing.AndroidTestingRunner;
-
+import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.filters.SmallTest;
+import com.android.systemui.RoboPilotTest;
import com.android.systemui.SysuiTestCase;
import org.junit.Before;
@@ -36,8 +36,9 @@ import org.mockito.MockitoAnnotations;
import java.util.List;
import java.util.concurrent.Executor;
+@RoboPilotTest
@SmallTest
-@RunWith(AndroidTestingRunner.class)
+@RunWith(AndroidJUnit4.class)
public class DreamOverlayStatusBarItemsProviderTest extends SysuiTestCase {
@Mock
DreamOverlayStatusBarItemsProvider.Callback mCallback;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayStatusBarViewControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayStatusBarViewControllerTest.java
index 4e74f451932b..af2dab599a66 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayStatusBarViewControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayStatusBarViewControllerTest.java
@@ -41,12 +41,13 @@ import android.net.Network;
import android.net.NetworkCapabilities;
import android.net.NetworkRequest;
import android.provider.Settings;
-import android.testing.AndroidTestingRunner;
import android.view.View;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.filters.SmallTest;
import com.android.systemui.R;
+import com.android.systemui.RoboPilotTest;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.log.LogBuffer;
import com.android.systemui.log.core.FakeLogBuffer;
@@ -71,8 +72,9 @@ import java.util.List;
import java.util.Optional;
import java.util.concurrent.Executor;
+@RoboPilotTest
@SmallTest
-@RunWith(AndroidTestingRunner.class)
+@RunWith(AndroidJUnit4.class)
public class DreamOverlayStatusBarViewControllerTest extends SysuiTestCase {
private static final String NOTIFICATION_INDICATOR_FORMATTER_STRING =
"{count, plural, =1 {# notification} other {# notifications}}";
@@ -92,8 +94,6 @@ public class DreamOverlayStatusBarViewControllerTest extends SysuiTestCase {
@Mock
AlarmManager mAlarmManager;
@Mock
- AlarmManager.AlarmClockInfo mAlarmClockInfo;
- @Mock
NextAlarmController mNextAlarmController;
@Mock
DateFormatUtil mDateFormatUtil;
@@ -203,8 +203,9 @@ public class DreamOverlayStatusBarViewControllerTest extends SysuiTestCase {
@Test
public void testOnViewAttachedShowsAlarmIconWhenAlarmExists() {
- when(mAlarmClockInfo.getTriggerTime()).thenReturn(1L);
- when(mAlarmManager.getNextAlarmClock(anyInt())).thenReturn(mAlarmClockInfo);
+ final AlarmManager.AlarmClockInfo alarmClockInfo =
+ new AlarmManager.AlarmClockInfo(1L, null);
+ when(mAlarmManager.getNextAlarmClock(anyInt())).thenReturn(alarmClockInfo);
mController.onViewAttached();
verify(mView).showIcon(
eq(DreamOverlayStatusBarView.STATUS_ICON_ALARM_SET), eq(true), any());
diff --git a/packages/SystemUI/tests/src/com/android/systemui/dreams/complication/HideComplicationTouchHandlerTest.java b/packages/SystemUI/tests/src/com/android/systemui/dreams/complication/HideComplicationTouchHandlerTest.java
index eed4dbcb7773..d32788df30be 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/dreams/complication/HideComplicationTouchHandlerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/dreams/complication/HideComplicationTouchHandlerTest.java
@@ -23,13 +23,14 @@ import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.os.Handler;
-import android.testing.AndroidTestingRunner;
import android.view.MotionEvent;
import android.view.View;
import androidx.concurrent.futures.CallbackToFutureAdapter;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.filters.SmallTest;
+import com.android.systemui.RoboPilotTest;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.complication.Complication;
import com.android.systemui.dreams.DreamOverlayStateController;
@@ -48,8 +49,9 @@ import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
+@RoboPilotTest
@SmallTest
-@RunWith(AndroidTestingRunner.class)
+@RunWith(AndroidJUnit4.class)
public class HideComplicationTouchHandlerTest extends SysuiTestCase {
private static final int RESTORE_TIMEOUT = 1000;
private static final int HIDE_DELAY = 500;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/dreams/conditions/AssistantAttentionConditionTest.java b/packages/SystemUI/tests/src/com/android/systemui/dreams/conditions/AssistantAttentionConditionTest.java
index 6a178895839b..4a7700fe1ca2 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/dreams/conditions/AssistantAttentionConditionTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/dreams/conditions/AssistantAttentionConditionTest.java
@@ -23,10 +23,10 @@ import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
-import android.testing.AndroidTestingRunner;
-
+import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.filters.SmallTest;
+import com.android.systemui.RoboPilotTest;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.assist.AssistManager;
import com.android.systemui.assist.AssistManager.VisualQueryAttentionListener;
@@ -41,8 +41,9 @@ import org.mockito.MockitoAnnotations;
import kotlinx.coroutines.CoroutineScope;
+@RoboPilotTest
@SmallTest
-@RunWith(AndroidTestingRunner.class)
+@RunWith(AndroidJUnit4.class)
public class AssistantAttentionConditionTest extends SysuiTestCase {
@Mock
Condition.Callback mCallback;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/dreams/conditions/DreamConditionTest.java b/packages/SystemUI/tests/src/com/android/systemui/dreams/conditions/DreamConditionTest.java
index 68c79652ac00..cd2efded7e85 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/dreams/conditions/DreamConditionTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/dreams/conditions/DreamConditionTest.java
@@ -25,12 +25,13 @@ import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.app.DreamManager;
-import android.testing.AndroidTestingRunner;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.filters.SmallTest;
import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.keyguard.KeyguardUpdateMonitorCallback;
+import com.android.systemui.RoboPilotTest;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.shared.condition.Condition;
@@ -43,8 +44,9 @@ import org.mockito.MockitoAnnotations;
import kotlinx.coroutines.CoroutineScope;
+@RoboPilotTest
@SmallTest
-@RunWith(AndroidTestingRunner.class)
+@RunWith(AndroidJUnit4.class)
public class DreamConditionTest extends SysuiTestCase {
@Mock
Condition.Callback mCallback;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/dreams/touch/BouncerSwipeTouchHandlerTest.java b/packages/SystemUI/tests/src/com/android/systemui/dreams/touch/BouncerSwipeTouchHandlerTest.java
index 3f9b198ee17d..90076fd21520 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/dreams/touch/BouncerSwipeTouchHandlerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/dreams/touch/BouncerSwipeTouchHandlerTest.java
@@ -31,16 +31,17 @@ import android.animation.ValueAnimator;
import android.content.pm.UserInfo;
import android.graphics.Rect;
import android.graphics.Region;
-import android.testing.AndroidTestingRunner;
import android.view.GestureDetector;
import android.view.GestureDetector.OnGestureListener;
import android.view.MotionEvent;
import android.view.VelocityTracker;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.filters.SmallTest;
import com.android.internal.logging.UiEventLogger;
import com.android.internal.widget.LockPatternUtils;
+import com.android.systemui.RoboPilotTest;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.bouncer.shared.constants.KeyguardBouncerConstants;
import com.android.systemui.dreams.touch.scrim.ScrimController;
@@ -56,6 +57,7 @@ import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
+import org.mockito.Captor;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
@@ -63,8 +65,9 @@ import org.mockito.MockitoAnnotations;
import java.util.Collections;
import java.util.Optional;
+@RoboPilotTest
@SmallTest
-@RunWith(AndroidTestingRunner.class)
+@RunWith(AndroidJUnit4.class)
public class BouncerSwipeTouchHandlerTest extends SysuiTestCase {
@Mock
CentralSurfaces mCentralSurfaces;
@@ -107,6 +110,12 @@ public class BouncerSwipeTouchHandlerTest extends SysuiTestCase {
@Mock
LockPatternUtils mLockPatternUtils;
+ @Mock
+ Region mRegion;
+
+ @Captor
+ ArgumentCaptor<Rect> mRectCaptor;
+
FakeUserTracker mUserTracker;
private static final float TOUCH_REGION = .3f;
@@ -153,10 +162,10 @@ public class BouncerSwipeTouchHandlerTest extends SysuiTestCase {
*/
@Test
public void testSessionStart() {
- final Region region = Region.obtain();
- mTouchHandler.getTouchInitiationRegion(SCREEN_BOUNDS, region);
+ mTouchHandler.getTouchInitiationRegion(SCREEN_BOUNDS, mRegion);
- final Rect bounds = region.getBounds();
+ verify(mRegion).op(mRectCaptor.capture(), eq(Region.Op.UNION));
+ final Rect bounds = mRectCaptor.getValue();
final Rect expected = new Rect();
diff --git a/packages/SystemUI/tests/src/com/android/systemui/dreams/touch/ShadeTouchHandlerTest.java b/packages/SystemUI/tests/src/com/android/systemui/dreams/touch/ShadeTouchHandlerTest.java
index 2b9821406fea..ff6d97d3b380 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/dreams/touch/ShadeTouchHandlerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/dreams/touch/ShadeTouchHandlerTest.java
@@ -21,12 +21,13 @@ import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
-import android.testing.AndroidTestingRunner;
import android.view.GestureDetector;
import android.view.MotionEvent;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.filters.SmallTest;
+import com.android.systemui.RoboPilotTest;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.shade.ShadeViewController;
import com.android.systemui.shared.system.InputChannelCompat;
@@ -42,8 +43,9 @@ import org.mockito.MockitoAnnotations;
import java.util.Optional;
+@RoboPilotTest
@SmallTest
-@RunWith(AndroidTestingRunner.class)
+@RunWith(AndroidJUnit4.class)
public class ShadeTouchHandlerTest extends SysuiTestCase {
@Mock
CentralSurfaces mCentralSurfaces;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/dreams/touch/scrim/BouncerlessScrimControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/dreams/touch/scrim/BouncerlessScrimControllerTest.java
index 79c535aea2d0..da393818c6f7 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/dreams/touch/scrim/BouncerlessScrimControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/dreams/touch/scrim/BouncerlessScrimControllerTest.java
@@ -22,10 +22,11 @@ import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.verify;
import android.os.PowerManager;
-import android.testing.AndroidTestingRunner;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.filters.SmallTest;
+import com.android.systemui.RoboPilotTest;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.shade.ShadeExpansionChangeEvent;
import com.android.systemui.util.concurrency.FakeExecutor;
@@ -37,8 +38,9 @@ import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
+@RoboPilotTest
@SmallTest
-@RunWith(AndroidTestingRunner.class)
+@RunWith(AndroidJUnit4.class)
public class BouncerlessScrimControllerTest extends SysuiTestCase {
@Mock
BouncerlessScrimController.Callback mCallback;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/dreams/touch/scrim/ScrimManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/dreams/touch/scrim/ScrimManagerTest.java
index ac9822db85d6..81f6fe3e24d3 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/dreams/touch/scrim/ScrimManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/dreams/touch/scrim/ScrimManagerTest.java
@@ -22,10 +22,10 @@ import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
-import android.testing.AndroidTestingRunner;
-
+import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.filters.SmallTest;
+import com.android.systemui.RoboPilotTest;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.statusbar.policy.KeyguardStateController;
import com.android.systemui.util.concurrency.FakeExecutor;
@@ -38,8 +38,9 @@ import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
+@RoboPilotTest
@SmallTest
-@RunWith(AndroidTestingRunner.class)
+@RunWith(AndroidJUnit4.class)
public class ScrimManagerTest extends SysuiTestCase {
@Mock
ScrimController mBouncerlessScrimController;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/CustomizationProviderTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/CustomizationProviderTest.kt
index 36822e6a4e24..f62137c62c65 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/CustomizationProviderTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/CustomizationProviderTest.kt
@@ -63,6 +63,7 @@ import com.android.systemui.util.mockito.whenever
import com.android.systemui.util.settings.FakeSettings
import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.test.TestScope
import kotlinx.coroutines.test.UnconfinedTestDispatcher
import kotlinx.coroutines.test.runTest
@@ -180,6 +181,10 @@ class CustomizationProviderTest : SysuiTestCase() {
keyguardInteractor =
KeyguardInteractorFactory.create(
featureFlags = featureFlags,
+ sceneInteractor =
+ mock {
+ whenever(transitioningTo).thenReturn(MutableStateFlow(null))
+ },
)
.keyguardInteractor,
lockPatternUtils = lockPatternUtils,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractorTest.kt
index 972af4a8a172..14cdf2f58a7d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractorTest.kt
@@ -15,6 +15,8 @@
*
*/
+@file:OptIn(ExperimentalCoroutinesApi::class)
+
package com.android.systemui.keyguard.domain.interactor
import android.app.StatusBarManager
@@ -30,8 +32,15 @@ import com.android.systemui.flags.Flags.FACE_AUTH_REFACTOR
import com.android.systemui.keyguard.data.repository.FakeCommandQueue
import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository
import com.android.systemui.keyguard.shared.model.CameraLaunchSourceModel
+import com.android.systemui.scene.SceneTestUtils
+import com.android.systemui.scene.domain.interactor.SceneInteractor
+import com.android.systemui.scene.shared.model.ObservableTransitionState
+import com.android.systemui.scene.shared.model.SceneKey
import com.android.systemui.shade.data.repository.FakeShadeRepository
import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.flow.MutableStateFlow
+import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.flow.onCompletion
import kotlinx.coroutines.test.TestScope
import kotlinx.coroutines.test.runCurrent
@@ -54,25 +63,33 @@ class KeyguardInteractorTest : SysuiTestCase() {
private lateinit var bouncerRepository: FakeKeyguardBouncerRepository
private lateinit var configurationRepository: FakeConfigurationRepository
private lateinit var shadeRepository: FakeShadeRepository
+ private lateinit var sceneInteractor: SceneInteractor
+ private lateinit var transitionState: MutableStateFlow<ObservableTransitionState>
@Before
fun setUp() {
MockitoAnnotations.initMocks(this)
featureFlags = FakeFeatureFlags().apply { set(FACE_AUTH_REFACTOR, true) }
commandQueue = FakeCommandQueue()
- testScope = TestScope()
- repository = FakeKeyguardRepository()
+ val sceneTestUtils = SceneTestUtils(this)
+ testScope = sceneTestUtils.testScope
+ repository = sceneTestUtils.keyguardRepository
bouncerRepository = FakeKeyguardBouncerRepository()
configurationRepository = FakeConfigurationRepository()
shadeRepository = FakeShadeRepository()
+ sceneInteractor = sceneTestUtils.sceneInteractor()
+ transitionState = MutableStateFlow(ObservableTransitionState.Idle(SceneKey.Gone))
+ sceneInteractor.setTransitionState(transitionState)
underTest =
KeyguardInteractor(
- repository,
- commandQueue,
- featureFlags,
- bouncerRepository,
- configurationRepository,
- shadeRepository,
+ repository = repository,
+ commandQueue = commandQueue,
+ featureFlags = featureFlags,
+ sceneContainerFlags = sceneTestUtils.sceneContainerFlags,
+ bouncerRepository = bouncerRepository,
+ configurationRepository = configurationRepository,
+ shadeRepository = shadeRepository,
+ sceneInteractorProvider = { sceneInteractor },
)
}
@@ -180,4 +197,28 @@ class KeyguardInteractorTest : SysuiTestCase() {
assertThat(secureCameraActive()).isFalse()
}
+
+ @Test
+ fun animationDozingTransitions() =
+ testScope.runTest {
+ val isAnimate by collectLastValue(underTest.animateDozingTransitions)
+
+ underTest.setAnimateDozingTransitions(true)
+ runCurrent()
+ assertThat(isAnimate).isTrue()
+
+ underTest.setAnimateDozingTransitions(false)
+ runCurrent()
+ assertThat(isAnimate).isFalse()
+
+ underTest.setAnimateDozingTransitions(true)
+ transitionState.value =
+ ObservableTransitionState.Transition(
+ fromScene = SceneKey.Gone,
+ toScene = SceneKey.Lockscreen,
+ progress = flowOf(0f),
+ )
+ runCurrent()
+ assertThat(isAnimate).isFalse()
+ }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/OccludingAppDeviceEntryInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/OccludingAppDeviceEntryInteractorTest.kt
index f24ea6c0216f..bdcb9abba745 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/OccludingAppDeviceEntryInteractorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/OccludingAppDeviceEntryInteractorTest.kt
@@ -52,6 +52,7 @@ import com.android.systemui.util.mockito.whenever
import com.android.systemui.util.time.FakeSystemClock
import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.test.TestScope
import kotlinx.coroutines.test.runCurrent
import kotlinx.coroutines.test.runTest
@@ -121,6 +122,8 @@ class OccludingAppDeviceEntryInteractorTest : SysuiTestCase() {
repository = keyguardRepository,
bouncerRepository = bouncerRepository,
configurationRepository = configurationRepository,
+ sceneInteractor =
+ mock { whenever(transitioningTo).thenReturn(MutableStateFlow(null)) },
)
.keyguardInteractor,
PrimaryBouncerInteractor(
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/view/layout/blueprints/DefaultKeyguardBlueprintTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/view/layout/blueprints/DefaultKeyguardBlueprintTest.kt
index 3b4eab2a5fe1..bf57ecb41091 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/view/layout/blueprints/DefaultKeyguardBlueprintTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/view/layout/blueprints/DefaultKeyguardBlueprintTest.kt
@@ -25,6 +25,7 @@ import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.flags.FakeFeatureFlags
import com.android.systemui.flags.Flags
+import com.android.systemui.keyguard.shared.model.KeyguardBlueprint
import com.android.systemui.keyguard.ui.view.KeyguardRootView
import com.android.systemui.keyguard.ui.view.layout.sections.DefaultAmbientIndicationAreaSection
import com.android.systemui.keyguard.ui.view.layout.sections.DefaultIndicationAreaSection
@@ -34,10 +35,12 @@ import com.android.systemui.keyguard.ui.view.layout.sections.DefaultSettingsPopu
import com.android.systemui.keyguard.ui.view.layout.sections.DefaultShortcutsSection
import com.android.systemui.keyguard.ui.view.layout.sections.DefaultStatusViewSection
import com.android.systemui.keyguard.ui.view.layout.sections.SplitShadeGuidelines
+import com.android.systemui.util.mockito.whenever
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.Mock
+import org.mockito.Mockito.mock
import org.mockito.Mockito.never
import org.mockito.Mockito.verify
import org.mockito.MockitoAnnotations
@@ -81,7 +84,7 @@ class DefaultKeyguardBlueprintTest : SysuiTestCase() {
@Test
fun addViews() {
val constraintLayout = ConstraintLayout(context, null)
- underTest.addViews(constraintLayout)
+ underTest.addViews(null, constraintLayout)
underTest.sections.forEach { verify(it, never()).addViews(constraintLayout) }
}
@@ -89,11 +92,35 @@ class DefaultKeyguardBlueprintTest : SysuiTestCase() {
fun addViews_lazyInflateFlagOn() {
featureFlags.set(Flags.LAZY_INFLATE_KEYGUARD, true)
val constraintLayout = ConstraintLayout(context, null)
- underTest.addViews(constraintLayout)
+ underTest.addViews(null, constraintLayout)
underTest.sections.forEach { verify(it).addViews(constraintLayout) }
}
@Test
+ fun addViews_withPrevBlueprint() {
+ val prevBlueprint = mock(KeyguardBlueprint::class.java)
+ whenever(prevBlueprint.sections)
+ .thenReturn(underTest.sections.minus(defaultLockIconSection))
+ featureFlags.set(Flags.LAZY_INFLATE_KEYGUARD, true)
+ val constraintLayout = ConstraintLayout(context, null)
+ underTest.addViews(prevBlueprint, constraintLayout)
+ underTest.sections.minus(defaultLockIconSection).forEach {
+ verify(it, never()).addViews(constraintLayout)
+ }
+
+ verify(defaultLockIconSection).addViews(constraintLayout)
+ }
+
+ @Test
+ fun addViews_withNextBlueprint() {
+ val nextBlueprint = mock(KeyguardBlueprint::class.java)
+ whenever(nextBlueprint.sections).thenReturn(setOf())
+ val constraintLayout = ConstraintLayout(context, null)
+ underTest.removeViews(nextBlueprint, constraintLayout)
+ underTest.sections.forEach { verify(it).removeViews(constraintLayout) }
+ }
+
+ @Test
fun applyConstraints() {
val cs = ConstraintSet()
underTest.applyConstraints(cs)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultIndicationAreaSectionTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultIndicationAreaSectionTest.kt
index 798b23e4a074..4e31af22f771 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultIndicationAreaSectionTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultIndicationAreaSectionTest.kt
@@ -18,14 +18,17 @@
package com.android.systemui.keyguard.ui.view.layout.sections
import android.view.ViewGroup
+import androidx.constraintlayout.widget.ConstraintLayout
import androidx.constraintlayout.widget.ConstraintSet
import androidx.test.filters.SmallTest
import com.android.systemui.R
import com.android.systemui.SysuiTestCase
import com.android.systemui.flags.FeatureFlags
+import com.android.systemui.flags.Flags
import com.android.systemui.keyguard.ui.viewmodel.KeyguardIndicationAreaViewModel
import com.android.systemui.keyguard.ui.viewmodel.KeyguardRootViewModel
import com.android.systemui.statusbar.KeyguardIndicationController
+import com.android.systemui.util.mockito.whenever
import com.google.common.truth.Truth.assertThat
import org.junit.Before
import org.junit.Test
@@ -58,7 +61,23 @@ class DefaultIndicationAreaSectionTest : SysuiTestCase() {
}
@Test
- fun apply() {
+ fun addViewsConditionally() {
+ whenever(featureFlags.isEnabled(Flags.MIGRATE_SPLIT_KEYGUARD_BOTTOM_AREA)).thenReturn(true)
+ val constraintLayout = ConstraintLayout(context, null)
+ underTest.addViews(constraintLayout)
+ assertThat(constraintLayout.childCount).isGreaterThan(0)
+ }
+
+ @Test
+ fun addViewsConditionally_migrateFlagOff() {
+ whenever(featureFlags.isEnabled(Flags.MIGRATE_SPLIT_KEYGUARD_BOTTOM_AREA)).thenReturn(false)
+ val constraintLayout = ConstraintLayout(context, null)
+ underTest.addViews(constraintLayout)
+ assertThat(constraintLayout.childCount).isEqualTo(0)
+ }
+
+ @Test
+ fun applyConstraints() {
val cs = ConstraintSet()
underTest.applyConstraints(cs)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultLockIconSectionTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultLockIconSectionTest.kt
index 1192a8017dc4..1c3b5e616ddf 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultLockIconSectionTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultLockIconSectionTest.kt
@@ -19,6 +19,7 @@ package com.android.systemui.keyguard.ui.view.layout.sections
import android.graphics.Point
import android.view.WindowManager
+import androidx.constraintlayout.widget.ConstraintLayout
import androidx.constraintlayout.widget.ConstraintSet
import androidx.test.filters.SmallTest
import com.android.keyguard.KeyguardUpdateMonitor
@@ -27,7 +28,9 @@ import com.android.systemui.R
import com.android.systemui.SysuiTestCase
import com.android.systemui.biometrics.AuthController
import com.android.systemui.flags.FeatureFlags
+import com.android.systemui.flags.Flags
import com.android.systemui.shade.NotificationPanelView
+import com.android.systemui.util.mockito.whenever
import com.google.common.truth.Truth.assertThat
import org.junit.Before
import org.junit.Test
@@ -64,7 +67,23 @@ class DefaultLockIconSectionTest : SysuiTestCase() {
}
@Test
- fun apply() {
+ fun addViewsConditionally() {
+ whenever(featureFlags.isEnabled(Flags.MIGRATE_LOCK_ICON)).thenReturn(true)
+ val constraintLayout = ConstraintLayout(context, null)
+ underTest.addViews(constraintLayout)
+ assertThat(constraintLayout.childCount).isGreaterThan(0)
+ }
+
+ @Test
+ fun addViewsConditionally_migrateFlagOff() {
+ whenever(featureFlags.isEnabled(Flags.MIGRATE_LOCK_ICON)).thenReturn(false)
+ val constraintLayout = ConstraintLayout(context, null)
+ underTest.addViews(constraintLayout)
+ assertThat(constraintLayout.childCount).isEqualTo(0)
+ }
+
+ @Test
+ fun applyConstraints() {
val cs = ConstraintSet()
underTest.applyConstraints(cs)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardQuickAffordancesCombinedViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardQuickAffordancesCombinedViewModelTest.kt
index 3576ec9601e3..b935e1d3c65a 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardQuickAffordancesCombinedViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardQuickAffordancesCombinedViewModelTest.kt
@@ -57,11 +57,12 @@ import com.android.systemui.util.mockito.mock
import com.android.systemui.util.mockito.whenever
import com.android.systemui.util.settings.FakeSettings
import com.google.common.truth.Truth
+import kotlin.math.max
+import kotlin.math.min
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.test.StandardTestDispatcher
import kotlinx.coroutines.test.TestScope
import kotlinx.coroutines.test.runTest
-import org.junit.Assert.*
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
@@ -70,8 +71,6 @@ import org.mockito.ArgumentMatchers
import org.mockito.Mock
import org.mockito.Mockito
import org.mockito.MockitoAnnotations
-import kotlin.math.max
-import kotlin.math.min
@SmallTest
@RunWith(JUnit4::class)
@@ -105,9 +104,11 @@ class KeyguardQuickAffordancesCombinedViewModelTest : SysuiTestCase() {
overrideResource(
R.array.config_keyguardQuickAffordanceDefaults,
arrayOf(
- KeyguardQuickAffordanceSlots.SLOT_ID_BOTTOM_START + ":" +
+ KeyguardQuickAffordanceSlots.SLOT_ID_BOTTOM_START +
+ ":" +
BuiltInKeyguardQuickAffordanceKeys.HOME_CONTROLS,
- KeyguardQuickAffordanceSlots.SLOT_ID_BOTTOM_END + ":" +
+ KeyguardQuickAffordanceSlots.SLOT_ID_BOTTOM_END +
+ ":" +
BuiltInKeyguardQuickAffordanceKeys.QUICK_ACCESS_WALLET
)
)
@@ -144,16 +145,16 @@ class KeyguardQuickAffordancesCombinedViewModelTest : SysuiTestCase() {
KeyguardQuickAffordanceLocalUserSelectionManager(
context = context,
userFileManager =
- mock<UserFileManager>().apply {
- whenever(
- getSharedPreferences(
- ArgumentMatchers.anyString(),
- ArgumentMatchers.anyInt(),
- ArgumentMatchers.anyInt(),
- )
- )
- .thenReturn(FakeSharedPreferences())
- },
+ mock<UserFileManager>().apply {
+ whenever(
+ getSharedPreferences(
+ ArgumentMatchers.anyString(),
+ ArgumentMatchers.anyInt(),
+ ArgumentMatchers.anyInt(),
+ )
+ )
+ .thenReturn(FakeSharedPreferences())
+ },
userTracker = userTracker,
broadcastDispatcher = fakeBroadcastDispatcher,
)
@@ -172,42 +173,43 @@ class KeyguardQuickAffordancesCombinedViewModelTest : SysuiTestCase() {
remoteUserSelectionManager = remoteUserSelectionManager,
userTracker = userTracker,
legacySettingSyncer =
- KeyguardQuickAffordanceLegacySettingSyncer(
- scope = testScope.backgroundScope,
- backgroundDispatcher = testDispatcher,
- secureSettings = FakeSettings(),
- selectionsManager = localUserSelectionManager,
- ),
+ KeyguardQuickAffordanceLegacySettingSyncer(
+ scope = testScope.backgroundScope,
+ backgroundDispatcher = testDispatcher,
+ secureSettings = FakeSettings(),
+ selectionsManager = localUserSelectionManager,
+ ),
configs =
- setOf(
- homeControlsQuickAffordanceConfig,
- quickAccessWalletAffordanceConfig,
- qrCodeScannerAffordanceConfig,
- ),
+ setOf(
+ homeControlsQuickAffordanceConfig,
+ quickAccessWalletAffordanceConfig,
+ qrCodeScannerAffordanceConfig,
+ ),
dumpManager = mock(),
userHandle = UserHandle.SYSTEM,
)
- underTest = KeyguardQuickAffordancesCombinedViewModel(
- quickAffordanceInteractor =
- KeyguardQuickAffordanceInteractor(
- keyguardInteractor = keyguardInteractor,
- lockPatternUtils = lockPatternUtils,
- keyguardStateController = keyguardStateController,
- userTracker = userTracker,
- activityStarter = activityStarter,
- featureFlags = featureFlags,
- repository = { quickAffordanceRepository },
- launchAnimator = launchAnimator,
- logger = logger,
- devicePolicyManager = devicePolicyManager,
- dockManager = dockManager,
- biometricSettingsRepository = biometricSettingsRepository,
- backgroundDispatcher = testDispatcher,
- appContext = mContext,
- ),
- keyguardInteractor = keyguardInteractor
- )
+ underTest =
+ KeyguardQuickAffordancesCombinedViewModel(
+ quickAffordanceInteractor =
+ KeyguardQuickAffordanceInteractor(
+ keyguardInteractor = keyguardInteractor,
+ lockPatternUtils = lockPatternUtils,
+ keyguardStateController = keyguardStateController,
+ userTracker = userTracker,
+ activityStarter = activityStarter,
+ featureFlags = featureFlags,
+ repository = { quickAffordanceRepository },
+ launchAnimator = launchAnimator,
+ logger = logger,
+ devicePolicyManager = devicePolicyManager,
+ dockManager = dockManager,
+ biometricSettingsRepository = biometricSettingsRepository,
+ backgroundDispatcher = testDispatcher,
+ appContext = mContext,
+ ),
+ keyguardInteractor = keyguardInteractor
+ )
}
@Test
@@ -242,9 +244,8 @@ class KeyguardQuickAffordancesCombinedViewModelTest : SysuiTestCase() {
@Test
fun startButton_hiddenWhenDevicePolicyDisablesAllKeyguardFeatures() =
testScope.runTest {
- whenever(
- devicePolicyManager.getKeyguardDisabledFeatures(null, userTracker.userId)
- ).thenReturn(DevicePolicyManager.KEYGUARD_DISABLE_FEATURES_ALL)
+ whenever(devicePolicyManager.getKeyguardDisabledFeatures(null, userTracker.userId))
+ .thenReturn(DevicePolicyManager.KEYGUARD_DISABLE_FEATURES_ALL)
repository.setKeyguardShowing(true)
val latest by collectLastValue(underTest.startButton)
@@ -267,10 +268,10 @@ class KeyguardQuickAffordancesCombinedViewModelTest : SysuiTestCase() {
assertQuickAffordanceViewModel(
viewModel = latest,
testConfig =
- TestConfig(
- isVisible = false,
- slotId = KeyguardQuickAffordancePosition.BOTTOM_START.toSlotId(),
- ),
+ TestConfig(
+ isVisible = false,
+ slotId = KeyguardQuickAffordancePosition.BOTTOM_START.toSlotId(),
+ ),
configKey = configKey,
)
}
@@ -278,9 +279,7 @@ class KeyguardQuickAffordancesCombinedViewModelTest : SysuiTestCase() {
@Test
fun startButton_inPreviewMode_visibleEvenWhenKeyguardNotShowing() =
testScope.runTest {
- underTest.onPreviewSlotSelected(
- KeyguardQuickAffordanceSlots.SLOT_ID_BOTTOM_START
- )
+ underTest.onPreviewSlotSelected(KeyguardQuickAffordanceSlots.SLOT_ID_BOTTOM_START)
underTest.enablePreviewMode(KeyguardQuickAffordanceSlots.SLOT_ID_BOTTOM_START, true)
repository.setKeyguardShowing(false)
@@ -291,30 +290,30 @@ class KeyguardQuickAffordancesCombinedViewModelTest : SysuiTestCase() {
setUpQuickAffordanceModel(
position = KeyguardQuickAffordancePosition.BOTTOM_START,
testConfig =
+ TestConfig(
+ isVisible = true,
+ isClickable = true,
+ isActivated = true,
+ icon = icon,
+ canShowWhileLocked = false,
+ intent = Intent("action"),
+ slotId = KeyguardQuickAffordancePosition.BOTTOM_START.toSlotId(),
+ ),
+ )
+
+ assertQuickAffordanceViewModel(
+ viewModel = latest(),
+ testConfig =
TestConfig(
isVisible = true,
- isClickable = true,
- isActivated = true,
+ isClickable = false,
+ isActivated = false,
icon = icon,
canShowWhileLocked = false,
intent = Intent("action"),
+ isSelected = true,
slotId = KeyguardQuickAffordancePosition.BOTTOM_START.toSlotId(),
),
- )
-
- assertQuickAffordanceViewModel(
- viewModel = latest(),
- testConfig =
- TestConfig(
- isVisible = true,
- isClickable = false,
- isActivated = false,
- icon = icon,
- canShowWhileLocked = false,
- intent = Intent("action"),
- isSelected = true,
- slotId = KeyguardQuickAffordancePosition.BOTTOM_START.toSlotId(),
- ),
configKey = configKey,
)
Truth.assertThat(latest()?.isSelected).isTrue()
@@ -323,9 +322,7 @@ class KeyguardQuickAffordancesCombinedViewModelTest : SysuiTestCase() {
@Test
fun endButton_inHiglightedPreviewMode_dimmedWhenOtherIsSelected() =
testScope.runTest {
- underTest.onPreviewSlotSelected(
- KeyguardQuickAffordanceSlots.SLOT_ID_BOTTOM_START
- )
+ underTest.onPreviewSlotSelected(KeyguardQuickAffordanceSlots.SLOT_ID_BOTTOM_START)
underTest.enablePreviewMode(KeyguardQuickAffordanceSlots.SLOT_ID_BOTTOM_START, true)
repository.setKeyguardShowing(false)
@@ -335,20 +332,6 @@ class KeyguardQuickAffordancesCombinedViewModelTest : SysuiTestCase() {
setUpQuickAffordanceModel(
position = KeyguardQuickAffordancePosition.BOTTOM_START,
testConfig =
- TestConfig(
- isVisible = true,
- isClickable = true,
- isActivated = true,
- icon = icon,
- canShowWhileLocked = false,
- intent = Intent("action"),
- slotId = KeyguardQuickAffordancePosition.BOTTOM_START.toSlotId(),
- ),
- )
- val configKey =
- setUpQuickAffordanceModel(
- position = KeyguardQuickAffordancePosition.BOTTOM_END,
- testConfig =
TestConfig(
isVisible = true,
isClickable = true,
@@ -356,23 +339,37 @@ class KeyguardQuickAffordancesCombinedViewModelTest : SysuiTestCase() {
icon = icon,
canShowWhileLocked = false,
intent = Intent("action"),
- slotId = KeyguardQuickAffordancePosition.BOTTOM_END.toSlotId(),
+ slotId = KeyguardQuickAffordancePosition.BOTTOM_START.toSlotId(),
),
+ )
+ val configKey =
+ setUpQuickAffordanceModel(
+ position = KeyguardQuickAffordancePosition.BOTTOM_END,
+ testConfig =
+ TestConfig(
+ isVisible = true,
+ isClickable = true,
+ isActivated = true,
+ icon = icon,
+ canShowWhileLocked = false,
+ intent = Intent("action"),
+ slotId = KeyguardQuickAffordancePosition.BOTTOM_END.toSlotId(),
+ ),
)
assertQuickAffordanceViewModel(
viewModel = endButton(),
testConfig =
- TestConfig(
- isVisible = true,
- isClickable = false,
- isActivated = false,
- icon = icon,
- canShowWhileLocked = false,
- intent = Intent("action"),
- isDimmed = true,
- slotId = KeyguardQuickAffordancePosition.BOTTOM_END.toSlotId(),
- ),
+ TestConfig(
+ isVisible = true,
+ isClickable = false,
+ isActivated = false,
+ icon = icon,
+ canShowWhileLocked = false,
+ intent = Intent("action"),
+ isDimmed = true,
+ slotId = KeyguardQuickAffordancePosition.BOTTOM_END.toSlotId(),
+ ),
configKey = configKey,
)
}
@@ -390,7 +387,7 @@ class KeyguardQuickAffordancesCombinedViewModelTest : SysuiTestCase() {
icon = mock(),
canShowWhileLocked = false,
intent =
- null, // This will cause it to tell the system that the click was handled.
+ null, // This will cause it to tell the system that the click was handled.
slotId = KeyguardQuickAffordancePosition.BOTTOM_END.toSlotId(),
)
val configKey =
@@ -610,10 +607,10 @@ class KeyguardQuickAffordancesCombinedViewModelTest : SysuiTestCase() {
KeyguardQuickAffordanceConfig.LockScreenState.Visible(
icon = testConfig.icon ?: error("Icon is unexpectedly null!"),
activationState =
- when (testConfig.isActivated) {
- true -> ActivationState.Active
- false -> ActivationState.Inactive
- }
+ when (testConfig.isActivated) {
+ true -> ActivationState.Active
+ false -> ActivationState.Inactive
+ }
)
} else {
KeyguardQuickAffordanceConfig.LockScreenState.Hidden
@@ -644,9 +641,7 @@ class KeyguardQuickAffordancesCombinedViewModelTest : SysuiTestCase() {
)
)
if (testConfig.intent != null) {
- Truth.assertThat(
- Mockito.mockingDetails(activityStarter).invocations
- ).hasSize(1)
+ Truth.assertThat(Mockito.mockingDetails(activityStarter).invocations).hasSize(1)
} else {
Mockito.verifyZeroInteractions(activityStarter)
}
@@ -670,4 +665,4 @@ class KeyguardQuickAffordancesCombinedViewModelTest : SysuiTestCase() {
check(!isVisible || icon != null) { "Must supply non-null icon if visible!" }
}
}
-} \ No newline at end of file
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/MediaCarouselScrollHandlerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/MediaCarouselScrollHandlerTest.kt
new file mode 100644
index 000000000000..49f536e26ce6
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/MediaCarouselScrollHandlerTest.kt
@@ -0,0 +1,127 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.media.controls.ui
+
+import android.testing.AndroidTestingRunner
+import android.testing.TestableLooper
+import android.view.MotionEvent
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.media.controls.util.MediaUiEventLogger
+import com.android.systemui.plugins.FalsingManager
+import com.android.systemui.qs.PageIndicator
+import com.android.systemui.util.concurrency.FakeExecutor
+import com.android.systemui.util.mockito.eq
+import com.android.systemui.util.mockito.whenever
+import com.android.systemui.util.time.FakeSystemClock
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.Mock
+import org.mockito.Mockito.anyInt
+import org.mockito.Mockito.verify
+import org.mockito.MockitoAnnotations
+
+@SmallTest
+@TestableLooper.RunWithLooper(setAsMainLooper = true)
+@RunWith(AndroidTestingRunner::class)
+class MediaCarouselScrollHandlerTest : SysuiTestCase() {
+
+ private val carouselWidth = 1038
+ private val motionEventUp = MotionEvent.obtain(0, 0, MotionEvent.ACTION_UP, 0f, 0f, 0)
+
+ @Mock lateinit var mediaCarousel: MediaScrollView
+ @Mock lateinit var pageIndicator: PageIndicator
+ @Mock lateinit var dismissCallback: () -> Unit
+ @Mock lateinit var translationChangedListener: () -> Unit
+ @Mock lateinit var seekBarUpdateListener: (visibleToUser: Boolean) -> Unit
+ @Mock lateinit var closeGuts: (immediate: Boolean) -> Unit
+ @Mock lateinit var falsingManager: FalsingManager
+ @Mock lateinit var logSmartspaceImpression: (Boolean) -> Unit
+ @Mock lateinit var logger: MediaUiEventLogger
+
+ lateinit var executor: FakeExecutor
+ private val clock = FakeSystemClock()
+
+ private lateinit var mediaCarouselScrollHandler: MediaCarouselScrollHandler
+
+ @Before
+ fun setup() {
+ MockitoAnnotations.initMocks(this)
+ executor = FakeExecutor(clock)
+ mediaCarouselScrollHandler =
+ MediaCarouselScrollHandler(
+ mediaCarousel,
+ pageIndicator,
+ executor,
+ dismissCallback,
+ translationChangedListener,
+ seekBarUpdateListener,
+ closeGuts,
+ falsingManager,
+ logSmartspaceImpression,
+ logger
+ )
+ mediaCarouselScrollHandler.playerWidthPlusPadding = carouselWidth
+
+ whenever(mediaCarousel.touchListener).thenReturn(mediaCarouselScrollHandler.touchListener)
+ }
+
+ @Test
+ fun testCarouselScroll_shortScroll() {
+ whenever(mediaCarousel.isLayoutRtl).thenReturn(false)
+ whenever(mediaCarousel.relativeScrollX).thenReturn(300)
+
+ mediaCarousel.touchListener?.onTouchEvent(motionEventUp)
+ executor.runAllReady()
+
+ verify(mediaCarousel).smoothScrollTo(eq(0), anyInt())
+ }
+
+ @Test
+ fun testCarouselScroll_shortScroll_isRTL() {
+ whenever(mediaCarousel.isLayoutRtl).thenReturn(true)
+ whenever(mediaCarousel.relativeScrollX).thenReturn(300)
+
+ mediaCarousel.touchListener?.onTouchEvent(motionEventUp)
+ executor.runAllReady()
+
+ verify(mediaCarousel).smoothScrollTo(eq(carouselWidth), anyInt())
+ }
+
+ @Test
+ fun testCarouselScroll_longScroll() {
+ whenever(mediaCarousel.isLayoutRtl).thenReturn(false)
+ whenever(mediaCarousel.relativeScrollX).thenReturn(600)
+
+ mediaCarousel.touchListener?.onTouchEvent(motionEventUp)
+ executor.runAllReady()
+
+ verify(mediaCarousel).smoothScrollTo(eq(carouselWidth), anyInt())
+ }
+
+ @Test
+ fun testCarouselScroll_longScroll_isRTL() {
+ whenever(mediaCarousel.isLayoutRtl).thenReturn(true)
+ whenever(mediaCarousel.relativeScrollX).thenReturn(600)
+
+ mediaCarousel.touchListener?.onTouchEvent(motionEventUp)
+ executor.runAllReady()
+
+ verify(mediaCarousel).smoothScrollTo(eq(0), anyInt())
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/recents/OverviewProxyServiceTest.kt b/packages/SystemUI/tests/src/com/android/systemui/recents/OverviewProxyServiceTest.kt
index ef07fab70bb0..e353a53af752 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/recents/OverviewProxyServiceTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/recents/OverviewProxyServiceTest.kt
@@ -36,6 +36,7 @@ import com.android.systemui.model.SysUiState
import com.android.systemui.navigationbar.NavigationBarController
import com.android.systemui.navigationbar.NavigationModeController
import com.android.systemui.recents.OverviewProxyService.ACTION_QUICKSTEP
+import com.android.systemui.scene.shared.flag.FakeSceneContainerFlags
import com.android.systemui.settings.FakeDisplayTracker
import com.android.systemui.settings.UserTracker
import com.android.systemui.shade.ShadeViewController
@@ -146,6 +147,7 @@ class OverviewProxyServiceTest : SysuiTestCase() {
sysuiUnlockAnimationController,
assistUtils,
featureFlags,
+ FakeSceneContainerFlags(),
dumpManager,
unfoldTransitionProgressForwarder
)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/scene/SceneFrameworkIntegrationTest.kt b/packages/SystemUI/tests/src/com/android/systemui/scene/SceneFrameworkIntegrationTest.kt
index 6006cd42424a..2f26a53afe7c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/scene/SceneFrameworkIntegrationTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/scene/SceneFrameworkIntegrationTest.kt
@@ -25,8 +25,6 @@ import com.android.systemui.authentication.domain.model.AuthenticationMethodMode
import com.android.systemui.authentication.domain.model.AuthenticationMethodModel
import com.android.systemui.bouncer.ui.viewmodel.PinBouncerViewModel
import com.android.systemui.coroutines.collectLastValue
-import com.android.systemui.flags.FakeFeatureFlags
-import com.android.systemui.flags.Flags
import com.android.systemui.keyguard.shared.model.WakefulnessState
import com.android.systemui.keyguard.ui.viewmodel.KeyguardLongPressViewModel
import com.android.systemui.keyguard.ui.viewmodel.LockscreenSceneViewModel
@@ -140,8 +138,6 @@ class SceneFrameworkIntegrationTest : SysuiTestCase() {
@Before
fun setUp() {
- val featureFlags = FakeFeatureFlags().apply { set(Flags.SCENE_CONTAINER, true) }
-
authenticationRepository.setUnlocked(false)
val displayTracker = FakeDisplayTracker(context)
@@ -152,7 +148,7 @@ class SceneFrameworkIntegrationTest : SysuiTestCase() {
sceneInteractor = sceneInteractor,
authenticationInteractor = authenticationInteractor,
keyguardInteractor = keyguardInteractor,
- featureFlags = featureFlags,
+ flags = utils.sceneContainerFlags,
sysUiState = sysUiState,
displayId = displayTracker.defaultDisplayId,
sceneLogger = mock(),
diff --git a/packages/SystemUI/tests/src/com/android/systemui/scene/domain/startable/SceneContainerStartableTest.kt b/packages/SystemUI/tests/src/com/android/systemui/scene/domain/startable/SceneContainerStartableTest.kt
index 771c3e330e8a..145629a65f68 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/scene/domain/startable/SceneContainerStartableTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/scene/domain/startable/SceneContainerStartableTest.kt
@@ -42,6 +42,7 @@ import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.test.runCurrent
import kotlinx.coroutines.test.runTest
+import org.junit.Assume.assumeTrue
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runners.JUnit4
@@ -57,7 +58,7 @@ class SceneContainerStartableTest : SysuiTestCase() {
private val utils = SceneTestUtils(this)
private val testScope = utils.testScope
private val sceneInteractor = utils.sceneInteractor()
- private val featureFlags = utils.featureFlags
+ private val sceneContainerFlags = utils.sceneContainerFlags
private val authenticationRepository = utils.authenticationRepository()
private val authenticationInteractor =
utils.authenticationInteractor(
@@ -78,7 +79,7 @@ class SceneContainerStartableTest : SysuiTestCase() {
sceneInteractor = sceneInteractor,
authenticationInteractor = authenticationInteractor,
keyguardInteractor = keyguardInteractor,
- featureFlags = featureFlags,
+ flags = sceneContainerFlags,
sysUiState = sysUiState,
displayId = Display.DEFAULT_DISPLAY,
sceneLogger = mock(),
@@ -516,7 +517,8 @@ class SceneContainerStartableTest : SysuiTestCase() {
initialSceneKey: SceneKey? = null,
authenticationMethod: AuthenticationMethodModel? = null,
): MutableStateFlow<ObservableTransitionState> {
- featureFlags.set(Flags.SCENE_CONTAINER, true)
+ assumeTrue(Flags.SCENE_CONTAINER_ENABLED)
+ sceneContainerFlags.enabled = true
authenticationRepository.setUnlocked(isDeviceUnlocked)
keyguardRepository.setBypassEnabled(isBypassEnabled)
val transitionStateFlow =
diff --git a/packages/SystemUI/tests/src/com/android/systemui/scene/shared/flag/SceneContainerFlagsTest.kt b/packages/SystemUI/tests/src/com/android/systemui/scene/shared/flag/SceneContainerFlagsTest.kt
new file mode 100644
index 000000000000..17ee3a1cc906
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/scene/shared/flag/SceneContainerFlagsTest.kt
@@ -0,0 +1,96 @@
+/*
+ * Copyright 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.scene.shared.flag
+
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.flags.FakeFeatureFlagsClassic
+import com.android.systemui.flags.Flags
+import com.android.systemui.flags.ReleasedFlag
+import com.android.systemui.flags.ResourceBooleanFlag
+import com.android.systemui.flags.UnreleasedFlag
+import com.google.common.truth.Truth.assertThat
+import org.junit.Assume.assumeTrue
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.Parameterized
+
+@SmallTest
+@RunWith(Parameterized::class)
+internal class SceneContainerFlagsTest(
+ private val testCase: TestCase,
+) : SysuiTestCase() {
+
+ private lateinit var underTest: SceneContainerFlags
+
+ @Before
+ fun setUp() {
+ val featureFlags =
+ FakeFeatureFlagsClassic().apply {
+ SceneContainerFlagsImpl.flags.forEach { flag ->
+ when (flag) {
+ is ResourceBooleanFlag -> set(flag, testCase.areAllFlagsSet)
+ is ReleasedFlag -> set(flag, testCase.areAllFlagsSet)
+ is UnreleasedFlag -> set(flag, testCase.areAllFlagsSet)
+ else -> error("Unsupported flag type ${flag.javaClass}")
+ }
+ }
+ }
+ underTest = SceneContainerFlagsImpl(featureFlags, testCase.isComposeAvailable)
+ }
+
+ @Test
+ fun isEnabled() {
+ assumeTrue(Flags.SCENE_CONTAINER_ENABLED)
+ assertThat(underTest.isEnabled()).isEqualTo(testCase.expectedEnabled)
+ }
+
+ internal data class TestCase(
+ val isComposeAvailable: Boolean,
+ val areAllFlagsSet: Boolean,
+ val expectedEnabled: Boolean,
+ ) {
+ override fun toString(): String {
+ return """
+ (compose=$isComposeAvailable + flags=$areAllFlagsSet) -> expected=$expectedEnabled
+ """
+ .trimIndent()
+ }
+ }
+
+ companion object {
+ @Parameterized.Parameters(name = "{0}")
+ @JvmStatic
+ fun testCases() = buildList {
+ repeat(4) { combination ->
+ val isComposeAvailable = combination and 0b100 != 0
+ val areAllFlagsSet = combination and 0b001 != 0
+
+ val expectedEnabled = isComposeAvailable && areAllFlagsSet
+
+ add(
+ TestCase(
+ isComposeAvailable = isComposeAvailable,
+ areAllFlagsSet = areAllFlagsSet,
+ expectedEnabled = expectedEnabled,
+ )
+ )
+ }
+ }
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/screenshot/ScreenshotPolicyImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/screenshot/ScreenshotPolicyImplTest.kt
index ee61f5736263..587da2d5d677 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/screenshot/ScreenshotPolicyImplTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/screenshot/ScreenshotPolicyImplTest.kt
@@ -140,7 +140,7 @@ class ScreenshotPolicyImplTest : SysuiTestCase() {
private val pipTask = RootTaskInfo().apply {
configuration.windowConfiguration.apply {
windowingMode = WINDOWING_MODE_PINNED
- bounds = Rect(628, 1885, 1038, 2295)
+ setBounds(Rect(628, 1885, 1038, 2295))
activityType = ACTIVITY_TYPE_STANDARD
}
displayId = DISPLAY_ID
@@ -164,7 +164,7 @@ class ScreenshotPolicyImplTest : SysuiTestCase() {
private val fullScreenWorkProfileTask = RootTaskInfo().apply {
configuration.windowConfiguration.apply {
windowingMode = WINDOWING_MODE_FULLSCREEN
- bounds = Rect(0, 0, 1080, 2400)
+ setBounds(Rect(0, 0, 1080, 2400))
activityType = ACTIVITY_TYPE_STANDARD
}
displayId = DISPLAY_ID
@@ -188,7 +188,7 @@ class ScreenshotPolicyImplTest : SysuiTestCase() {
private val launcherTask = RootTaskInfo().apply {
configuration.windowConfiguration.apply {
windowingMode = WINDOWING_MODE_FULLSCREEN
- bounds = Rect(0, 0, 1080, 2400)
+ setBounds(Rect(0, 0, 1080, 2400))
activityType = ACTIVITY_TYPE_HOME
}
displayId = DISPLAY_ID
@@ -212,7 +212,7 @@ class ScreenshotPolicyImplTest : SysuiTestCase() {
private val emptyTask = RootTaskInfo().apply {
configuration.windowConfiguration.apply {
windowingMode = WINDOWING_MODE_FULLSCREEN
- bounds = Rect(0, 0, 1080, 2400)
+ setBounds(Rect(0, 0, 1080, 2400))
activityType = ACTIVITY_TYPE_UNDEFINED
}
displayId = DISPLAY_ID
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelViewControllerBaseTest.java b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelViewControllerBaseTest.java
index c573ac638032..1c9ec27c6a1b 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelViewControllerBaseTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelViewControllerBaseTest.java
@@ -626,6 +626,7 @@ public class NotificationPanelViewControllerBaseTest extends SysuiTestCase {
mScreenOffAnimationController,
mLockscreenGestureLogger,
mShadeExpansionStateManager,
+ mShadeRepository,
mSysUIUnfoldComponent,
mSysUiState,
() -> mKeyguardBottomAreaViewController,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/QuickSettingsControllerBaseTest.java b/packages/SystemUI/tests/src/com/android/systemui/shade/QuickSettingsControllerBaseTest.java
index ab0ae05b0e83..e42a7a6f50d7 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/shade/QuickSettingsControllerBaseTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/shade/QuickSettingsControllerBaseTest.java
@@ -37,6 +37,7 @@ import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.keyguard.TestScopeProvider;
import com.android.systemui.R;
import com.android.systemui.SysuiTestCase;
+import com.android.systemui.common.ui.data.repository.FakeConfigurationRepository;
import com.android.systemui.dump.DumpManager;
import com.android.systemui.flags.FeatureFlags;
import com.android.systemui.fragments.FragmentHostManager;
@@ -61,6 +62,7 @@ import com.android.systemui.statusbar.SysuiStatusBarStateController;
import com.android.systemui.statusbar.disableflags.data.repository.FakeDisableFlagsRepository;
import com.android.systemui.statusbar.notification.stack.AmbientState;
import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayoutController;
+import com.android.systemui.statusbar.notification.stack.domain.interactor.SharedNotificationContainerInteractor;
import com.android.systemui.statusbar.phone.KeyguardBottomAreaView;
import com.android.systemui.statusbar.phone.KeyguardBypassController;
import com.android.systemui.statusbar.phone.KeyguardStatusBarView;
@@ -174,6 +176,9 @@ public class QuickSettingsControllerBaseTest extends SysuiTestCase {
new FakeUserSetupRepository(),
mDeviceProvisionedController,
mUserInteractor,
+ new SharedNotificationContainerInteractor(
+ new FakeConfigurationRepository(),
+ mContext),
mShadeRepository
);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/data/repository/ShadeInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/shade/data/repository/ShadeInteractorTest.kt
index e6e7482bdaf9..41ea5b747e06 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/shade/data/repository/ShadeInteractorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/shade/data/repository/ShadeInteractorTest.kt
@@ -25,7 +25,9 @@ import android.os.UserManager
import androidx.test.filters.SmallTest
import com.android.internal.logging.UiEventLogger
import com.android.keyguard.KeyguardUpdateMonitor
+import com.android.systemui.R
import com.android.systemui.SysuiTestCase
+import com.android.systemui.common.ui.data.repository.FakeConfigurationRepository
import com.android.systemui.coroutines.collectLastValue
import com.android.systemui.flags.FakeFeatureFlags
import com.android.systemui.flags.Flags
@@ -36,6 +38,7 @@ import com.android.systemui.plugins.ActivityStarter
import com.android.systemui.shade.domain.interactor.ShadeInteractor
import com.android.systemui.statusbar.disableflags.data.model.DisableFlagsModel
import com.android.systemui.statusbar.disableflags.data.repository.FakeDisableFlagsRepository
+import com.android.systemui.statusbar.notification.stack.domain.interactor.SharedNotificationContainerInteractor
import com.android.systemui.statusbar.pipeline.mobile.data.repository.FakeUserSetupRepository
import com.android.systemui.statusbar.policy.DeviceProvisionedController
import com.android.systemui.telephony.data.repository.FakeTelephonyRepository
@@ -52,6 +55,7 @@ import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.runBlocking
import kotlinx.coroutines.test.StandardTestDispatcher
import kotlinx.coroutines.test.TestScope
+import kotlinx.coroutines.test.runCurrent
import kotlinx.coroutines.test.runTest
import org.junit.Before
import org.junit.Test
@@ -71,6 +75,12 @@ class ShadeInteractorTest : SysuiTestCase() {
private val disableFlagsRepository = FakeDisableFlagsRepository()
private val keyguardRepository = FakeKeyguardRepository()
private val shadeRepository = FakeShadeRepository()
+ private val configurationRepository = FakeConfigurationRepository()
+ private val sharedNotificationContainerInteractor =
+ SharedNotificationContainerInteractor(
+ configurationRepository,
+ mContext,
+ )
@Mock private lateinit var manager: UserManager
@Mock private lateinit var headlessSystemUserMode: HeadlessSystemUserMode
@@ -145,6 +155,7 @@ class ShadeInteractorTest : SysuiTestCase() {
userSetupRepository,
deviceProvisionedController,
userInteractor,
+ sharedNotificationContainerInteractor,
shadeRepository,
)
}
@@ -363,7 +374,7 @@ class ShadeInteractorTest : SysuiTestCase() {
val actual by collectLastValue(underTest.shadeExpansion)
keyguardRepository.setStatusBarState(StatusBarState.SHADE_LOCKED)
- shadeRepository.setShadeExpansion(0.5f)
+ shadeRepository.setLockscreenShadeExpansion(0.5f)
assertThat(actual).isEqualTo(1f)
}
@@ -375,10 +386,52 @@ class ShadeInteractorTest : SysuiTestCase() {
keyguardRepository.setStatusBarState(StatusBarState.KEYGUARD)
- shadeRepository.setShadeExpansion(0.5f)
+ shadeRepository.setLockscreenShadeExpansion(0.5f)
assertThat(actual).isEqualTo(0.5f)
- shadeRepository.setShadeExpansion(0.8f)
+ shadeRepository.setLockscreenShadeExpansion(0.8f)
assertThat(actual).isEqualTo(0.8f)
}
+
+ fun shadeExpansionWhenInSplitShadeAndQsExpanded() =
+ testScope.runTest {
+ val actual by collectLastValue(underTest.shadeExpansion)
+
+ // WHEN split shade is enabled and QS is expanded
+ keyguardRepository.setStatusBarState(StatusBarState.SHADE)
+ overrideResource(R.bool.config_use_split_notification_shade, true)
+ configurationRepository.onAnyConfigurationChange()
+ runCurrent()
+ shadeRepository.setQsExpansion(.5f)
+ shadeRepository.setLegacyShadeExpansion(.7f)
+
+ // THEN legacy shade expansion is passed through
+ assertThat(actual).isEqualTo(.7f)
+ }
+
+ fun shadeExpansionWhenNotInSplitShadeAndQsExpanded() =
+ testScope.runTest {
+ val actual by collectLastValue(underTest.shadeExpansion)
+
+ // WHEN split shade is not enabled and QS is expanded
+ keyguardRepository.setStatusBarState(StatusBarState.SHADE)
+ shadeRepository.setQsExpansion(.5f)
+ shadeRepository.setLegacyShadeExpansion(1f)
+
+ // THEN shade expansion is zero
+ assertThat(actual).isEqualTo(0f)
+ }
+
+ fun shadeExpansionWhenNotInSplitShadeAndQsCollapsed() =
+ testScope.runTest {
+ val actual by collectLastValue(underTest.shadeExpansion)
+
+ // WHEN split shade is not enabled and QS is expanded
+ keyguardRepository.setStatusBarState(StatusBarState.SHADE)
+ shadeRepository.setQsExpansion(0f)
+ shadeRepository.setLegacyShadeExpansion(.6f)
+
+ // THEN shade expansion is zero
+ assertThat(actual).isEqualTo(.6f)
+ }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/data/repository/ShadeRepositoryImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/shade/data/repository/ShadeRepositoryImplTest.kt
index fdaea2220de9..e086712308b6 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/shade/data/repository/ShadeRepositoryImplTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/shade/data/repository/ShadeRepositoryImplTest.kt
@@ -121,18 +121,33 @@ class ShadeRepositoryImplTest : SysuiTestCase() {
}
@Test
- fun updateShadeExpansion() =
+ fun updateDragDownAmount() =
testScope.runTest {
- assertThat(underTest.shadeExpansion.value).isEqualTo(0f)
+ assertThat(underTest.lockscreenShadeExpansion.value).isEqualTo(0f)
- underTest.setShadeExpansion(.5f)
- assertThat(underTest.shadeExpansion.value).isEqualTo(.5f)
+ underTest.setLockscreenShadeExpansion(.5f)
+ assertThat(underTest.lockscreenShadeExpansion.value).isEqualTo(.5f)
- underTest.setShadeExpansion(.82f)
- assertThat(underTest.shadeExpansion.value).isEqualTo(.82f)
+ underTest.setLockscreenShadeExpansion(.82f)
+ assertThat(underTest.lockscreenShadeExpansion.value).isEqualTo(.82f)
- underTest.setShadeExpansion(1f)
- assertThat(underTest.shadeExpansion.value).isEqualTo(1f)
+ underTest.setLockscreenShadeExpansion(1f)
+ assertThat(underTest.lockscreenShadeExpansion.value).isEqualTo(1f)
+ }
+
+ @Test
+ fun updateLegacyShadeExpansion() =
+ testScope.runTest {
+ assertThat(underTest.legacyShadeExpansion.value).isEqualTo(0f)
+
+ underTest.setLegacyShadeExpansion(.5f)
+ assertThat(underTest.legacyShadeExpansion.value).isEqualTo(.5f)
+
+ underTest.setLegacyShadeExpansion(.82f)
+ assertThat(underTest.legacyShadeExpansion.value).isEqualTo(.82f)
+
+ underTest.setLegacyShadeExpansion(1f)
+ assertThat(underTest.legacyShadeExpansion.value).isEqualTo(1f)
}
@Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/LockscreenShadeTransitionControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/LockscreenShadeTransitionControllerTest.kt
index 51e72c615372..6f7588097c70 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/LockscreenShadeTransitionControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/LockscreenShadeTransitionControllerTest.kt
@@ -10,6 +10,7 @@ import com.android.systemui.R
import com.android.systemui.SysuiTestCase
import com.android.systemui.classifier.FalsingCollector
import com.android.systemui.classifier.FalsingCollectorFake
+import com.android.systemui.common.ui.data.repository.FakeConfigurationRepository
import com.android.systemui.dump.DumpManager
import com.android.systemui.keyguard.WakefulnessLifecycle
import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository
@@ -29,6 +30,7 @@ import com.android.systemui.statusbar.notification.row.NotificationTestHelper
import com.android.systemui.statusbar.notification.stack.AmbientState
import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout
import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayoutController
+import com.android.systemui.statusbar.notification.stack.domain.interactor.SharedNotificationContainerInteractor
import com.android.systemui.statusbar.phone.CentralSurfaces
import com.android.systemui.statusbar.phone.KeyguardBypassController
import com.android.systemui.statusbar.phone.LSShadeTransitionLogger
@@ -102,6 +104,11 @@ class LockscreenShadeTransitionControllerTest : SysuiTestCase() {
@Mock lateinit var transitionControllerCallback: LockscreenShadeTransitionController.Callback
private val disableFlagsRepository = FakeDisableFlagsRepository()
private val keyguardRepository = FakeKeyguardRepository()
+ private val configurationRepository = FakeConfigurationRepository()
+ private val sharedNotificationContainerInteractor = SharedNotificationContainerInteractor(
+ configurationRepository,
+ mContext,
+ )
private val shadeInteractor =
ShadeInteractor(
testScope.backgroundScope,
@@ -110,6 +117,7 @@ class LockscreenShadeTransitionControllerTest : SysuiTestCase() {
userSetupRepository = FakeUserSetupRepository(),
deviceProvisionedController = mock(),
userInteractor = mock(),
+ sharedNotificationContainerInteractor,
repository = FakeShadeRepository(),
)
private val powerInteractor =
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/events/SystemStatusAnimationSchedulerImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/events/SystemStatusAnimationSchedulerImplTest.kt
index 6be2fa586f00..4fcccf887e58 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/events/SystemStatusAnimationSchedulerImplTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/events/SystemStatusAnimationSchedulerImplTest.kt
@@ -93,9 +93,6 @@ class SystemStatusAnimationSchedulerImplTest : SysuiTestCase() {
fakeFeatureFlags
)
- // ensure that isTooEarly() check in SystemStatusAnimationScheduler does not return true
- systemClock.advanceTime(Process.getStartUptimeMillis() + MIN_UPTIME)
-
// StatusBarContentInsetProvider is mocked. Ensure that it returns some mocked values.
whenever(statusBarContentInsetProvider.getStatusBarContentInsetsForCurrentRotation())
.thenReturn(android.util.Pair(10, 10))
@@ -156,6 +153,21 @@ class SystemStatusAnimationSchedulerImplTest : SysuiTestCase() {
assertEquals(0f, batteryChip.view.alpha)
}
+ /** Regression test for b/294104969. */
+ @Test
+ fun testPrivacyStatusEvent_beforeSystemUptime_stillDisplayed() = runTest {
+ initializeSystemStatusAnimationScheduler(testScope = this, advancePastMinUptime = false)
+
+ // WHEN the uptime hasn't quite passed the minimum required uptime...
+ systemClock.setUptimeMillis(Process.getStartUptimeMillis() + MIN_UPTIME / 2)
+
+ // BUT the event is a privacy event
+ createAndScheduleFakePrivacyEvent()
+
+ // THEN the privacy event still happens
+ assertEquals(ANIMATION_QUEUED, systemStatusAnimationScheduler.getAnimationState())
+ }
+
@Test
fun testPrivacyStatusEvent_standardAnimationLifecycle() = runTest {
// Instantiate class under test with TestScope from runTest
@@ -568,7 +580,10 @@ class SystemStatusAnimationSchedulerImplTest : SysuiTestCase() {
return batteryChip
}
- private fun initializeSystemStatusAnimationScheduler(testScope: TestScope) {
+ private fun initializeSystemStatusAnimationScheduler(
+ testScope: TestScope,
+ advancePastMinUptime: Boolean = true,
+ ) {
systemStatusAnimationScheduler =
SystemStatusAnimationSchedulerImpl(
systemEventCoordinator,
@@ -581,5 +596,10 @@ class SystemStatusAnimationSchedulerImplTest : SysuiTestCase() {
)
// add a mock listener
systemStatusAnimationScheduler.addCallback(listener)
+
+ if (advancePastMinUptime) {
+ // ensure that isTooEarly() check in SystemStatusAnimationScheduler does not return true
+ systemClock.advanceTime(Process.getStartUptimeMillis() + MIN_UPTIME)
+ }
}
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/ConversationCoordinatorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/ConversationCoordinatorTest.kt
index 55ea31571dfe..65697b736cbd 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/ConversationCoordinatorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/ConversationCoordinatorTest.kt
@@ -24,6 +24,7 @@ import android.testing.AndroidTestingRunner
import android.testing.TestableLooper
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
+import com.android.systemui.flags.FakeFeatureFlagsClassic
import com.android.systemui.statusbar.notification.collection.GroupEntry
import com.android.systemui.statusbar.notification.collection.GroupEntryBuilder
import com.android.systemui.statusbar.notification.collection.NotifPipeline
@@ -77,13 +78,18 @@ class ConversationCoordinatorTest : SysuiTestCase() {
private lateinit var coordinator: ConversationCoordinator
+ private val featureFlags = FakeFeatureFlagsClassic()
+
@Before
fun setUp() {
MockitoAnnotations.initMocks(this)
coordinator = ConversationCoordinator(
peopleNotificationIdentifier,
conversationIconManager,
- HighPriorityProvider(peopleNotificationIdentifier, GroupMembershipManagerImpl()),
+ HighPriorityProvider(
+ peopleNotificationIdentifier,
+ GroupMembershipManagerImpl(featureFlags)
+ ),
headerController
)
whenever(channel.isImportantConversation).thenReturn(true)
@@ -182,7 +188,7 @@ class ConversationCoordinatorTest : SysuiTestCase() {
}
@Test
- fun testInAlertingPeopleSectionWhenThereIsAnImportantChild(){
+ fun testInAlertingPeopleSectionWhenThereIsAnImportantChild() {
// GIVEN
val altChildA = NotificationEntryBuilder().setTag("A")
.setImportance(IMPORTANCE_DEFAULT).build()
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/render/GroupExpansionManagerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/render/GroupExpansionManagerTest.kt
index 4a94dc819a9e..ac2aec6e0c86 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/render/GroupExpansionManagerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/render/GroupExpansionManagerTest.kt
@@ -19,13 +19,23 @@ package com.android.systemui.statusbar.notification.collection.render
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.dump.DumpManager
-import com.android.systemui.flags.FakeFeatureFlags
+import com.android.systemui.flags.FakeFeatureFlagsClassic
import com.android.systemui.flags.Flags
+import com.android.systemui.statusbar.notification.collection.GroupEntryBuilder
+import com.android.systemui.statusbar.notification.collection.ListEntry
+import com.android.systemui.statusbar.notification.collection.NotifPipeline
import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder
+import com.android.systemui.statusbar.notification.collection.listbuilder.OnBeforeRenderListListener
+import com.android.systemui.statusbar.notification.collection.render.GroupExpansionManager.OnGroupExpansionChangeListener
+import com.android.systemui.util.mockito.any
import com.android.systemui.util.mockito.mock
-import org.junit.Assert
+import com.android.systemui.util.mockito.withArgCaptor
+import com.google.common.truth.Truth.assertThat
import org.junit.Before
import org.junit.Test
+import org.mockito.Mockito.never
+import org.mockito.Mockito.verify
+import org.mockito.Mockito.verifyNoMoreInteractions
import org.mockito.Mockito.`when` as whenever
@SmallTest
@@ -34,15 +44,45 @@ class GroupExpansionManagerTest : SysuiTestCase() {
private val dumpManager: DumpManager = mock()
private val groupMembershipManager: GroupMembershipManager = mock()
- private val featureFlags = FakeFeatureFlags()
+ private val featureFlags = FakeFeatureFlagsClassic()
- private val entry1 = NotificationEntryBuilder().build()
- private val entry2 = NotificationEntryBuilder().build()
+ private val pipeline: NotifPipeline = mock()
+ private lateinit var beforeRenderListListener: OnBeforeRenderListListener
+
+ private val summary1 = notificationEntry("foo", 1)
+ private val summary2 = notificationEntry("bar", 1)
+ private val entries =
+ listOf<ListEntry>(
+ GroupEntryBuilder()
+ .setSummary(summary1)
+ .setChildren(
+ listOf(
+ notificationEntry("foo", 2),
+ notificationEntry("foo", 3),
+ notificationEntry("foo", 4)
+ )
+ )
+ .build(),
+ GroupEntryBuilder()
+ .setSummary(summary2)
+ .setChildren(
+ listOf(
+ notificationEntry("bar", 2),
+ notificationEntry("bar", 3),
+ notificationEntry("bar", 4)
+ )
+ )
+ .build(),
+ notificationEntry("baz", 1)
+ )
+
+ private fun notificationEntry(pkg: String, id: Int) =
+ NotificationEntryBuilder().setPkg(pkg).setId(id).build().apply { row = mock() }
@Before
fun setUp() {
- whenever(groupMembershipManager.getGroupSummary(entry1)).thenReturn(entry1)
- whenever(groupMembershipManager.getGroupSummary(entry2)).thenReturn(entry2)
+ whenever(groupMembershipManager.getGroupSummary(summary1)).thenReturn(summary1)
+ whenever(groupMembershipManager.getGroupSummary(summary2)).thenReturn(summary2)
gem = GroupExpansionManagerImpl(dumpManager, groupMembershipManager, featureFlags)
}
@@ -54,16 +94,16 @@ class GroupExpansionManagerTest : SysuiTestCase() {
var listenerCalledCount = 0
gem.registerGroupExpansionChangeListener { _, _ -> listenerCalledCount++ }
- gem.setGroupExpanded(entry1, false)
- Assert.assertEquals(0, listenerCalledCount)
- gem.setGroupExpanded(entry1, true)
- Assert.assertEquals(1, listenerCalledCount)
- gem.setGroupExpanded(entry2, true)
- Assert.assertEquals(2, listenerCalledCount)
- gem.setGroupExpanded(entry1, true)
- Assert.assertEquals(2, listenerCalledCount)
- gem.setGroupExpanded(entry2, false)
- Assert.assertEquals(3, listenerCalledCount)
+ gem.setGroupExpanded(summary1, false)
+ assertThat(listenerCalledCount).isEqualTo(0)
+ gem.setGroupExpanded(summary1, true)
+ assertThat(listenerCalledCount).isEqualTo(1)
+ gem.setGroupExpanded(summary2, true)
+ assertThat(listenerCalledCount).isEqualTo(2)
+ gem.setGroupExpanded(summary1, true)
+ assertThat(listenerCalledCount).isEqualTo(2)
+ gem.setGroupExpanded(summary2, false)
+ assertThat(listenerCalledCount).isEqualTo(3)
}
@Test
@@ -73,15 +113,39 @@ class GroupExpansionManagerTest : SysuiTestCase() {
var listenerCalledCount = 0
gem.registerGroupExpansionChangeListener { _, _ -> listenerCalledCount++ }
- gem.setGroupExpanded(entry1, false)
- Assert.assertEquals(1, listenerCalledCount)
- gem.setGroupExpanded(entry1, true)
- Assert.assertEquals(2, listenerCalledCount)
- gem.setGroupExpanded(entry2, true)
- Assert.assertEquals(3, listenerCalledCount)
- gem.setGroupExpanded(entry1, true)
- Assert.assertEquals(4, listenerCalledCount)
- gem.setGroupExpanded(entry2, false)
- Assert.assertEquals(5, listenerCalledCount)
+ gem.setGroupExpanded(summary1, false)
+ assertThat(listenerCalledCount).isEqualTo(1)
+ gem.setGroupExpanded(summary1, true)
+ assertThat(listenerCalledCount).isEqualTo(2)
+ gem.setGroupExpanded(summary2, true)
+ assertThat(listenerCalledCount).isEqualTo(3)
+ gem.setGroupExpanded(summary1, true)
+ assertThat(listenerCalledCount).isEqualTo(4)
+ gem.setGroupExpanded(summary2, false)
+ assertThat(listenerCalledCount).isEqualTo(5)
+ }
+
+ @Test
+ fun testSyncWithPipeline() {
+ featureFlags.set(Flags.NOTIFICATION_GROUP_EXPANSION_CHANGE, true)
+ gem.attach(pipeline)
+ beforeRenderListListener = withArgCaptor {
+ verify(pipeline).addOnBeforeRenderListListener(capture())
+ }
+
+ val listener: OnGroupExpansionChangeListener = mock()
+ gem.registerGroupExpansionChangeListener(listener)
+
+ beforeRenderListListener.onBeforeRenderList(entries)
+ verify(listener, never()).onGroupExpansionChange(any(), any())
+
+ // Expand one of the groups.
+ gem.setGroupExpanded(summary1, true)
+ verify(listener).onGroupExpansionChange(summary1.row, true)
+
+ // Empty the pipeline list and verify that the group is no longer expanded.
+ beforeRenderListListener.onBeforeRenderList(emptyList())
+ verify(listener).onGroupExpansionChange(summary1.row, false)
+ verifyNoMoreInteractions(listener)
}
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/render/GroupMembershipManagerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/render/GroupMembershipManagerTest.kt
new file mode 100644
index 000000000000..37ec0e09f841
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/render/GroupMembershipManagerTest.kt
@@ -0,0 +1,106 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.notification.collection.render
+
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.flags.FakeFeatureFlagsClassic
+import com.android.systemui.flags.Flags
+import com.android.systemui.statusbar.notification.collection.GroupEntry
+import com.android.systemui.statusbar.notification.collection.GroupEntryBuilder
+import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder
+import com.google.common.truth.Truth.assertThat
+import org.junit.Before
+import org.junit.Test
+
+@SmallTest
+class GroupMembershipManagerTest : SysuiTestCase() {
+ private lateinit var gmm: GroupMembershipManagerImpl
+
+ private val featureFlags = FakeFeatureFlagsClassic()
+
+ @Before
+ fun setUp() {
+ gmm = GroupMembershipManagerImpl(featureFlags)
+ }
+
+ @Test
+ fun testIsChildInGroup_topLevel() {
+ featureFlags.set(Flags.NOTIFICATION_GROUP_EXPANSION_CHANGE, false)
+ val topLevelEntry = NotificationEntryBuilder().setParent(GroupEntry.ROOT_ENTRY).build()
+ assertThat(gmm.isChildInGroup(topLevelEntry)).isFalse()
+ }
+
+ @Test
+ fun testIsChildInGroup_noParent_old() {
+ featureFlags.set(Flags.NOTIFICATION_GROUP_EXPANSION_CHANGE, false)
+ val noParentEntry = NotificationEntryBuilder().setParent(null).build()
+ assertThat(gmm.isChildInGroup(noParentEntry)).isTrue()
+ }
+
+ @Test
+ fun testIsChildInGroup_noParent_new() {
+ featureFlags.set(Flags.NOTIFICATION_GROUP_EXPANSION_CHANGE, true)
+ val noParentEntry = NotificationEntryBuilder().setParent(null).build()
+ assertThat(gmm.isChildInGroup(noParentEntry)).isFalse()
+ }
+
+ @Test
+ fun testIsChildInGroup_child() {
+ featureFlags.set(Flags.NOTIFICATION_GROUP_EXPANSION_CHANGE, false)
+ val childEntry = NotificationEntryBuilder().build()
+ assertThat(gmm.isChildInGroup(childEntry)).isTrue()
+ }
+
+ @Test
+ fun testIsGroupSummary() {
+ featureFlags.set(Flags.NOTIFICATION_GROUP_EXPANSION_CHANGE, true)
+ val entry = NotificationEntryBuilder().setGroupSummary(mContext, true).build()
+ assertThat(gmm.isGroupSummary(entry)).isTrue()
+ }
+
+ @Test
+ fun testGetGroupSummary() {
+ featureFlags.set(Flags.NOTIFICATION_GROUP_EXPANSION_CHANGE, true)
+
+ val summary =
+ NotificationEntryBuilder()
+ .setGroup(mContext, "group")
+ .setGroupSummary(mContext, true)
+ .build()
+ val groupEntry =
+ GroupEntryBuilder().setParent(GroupEntry.ROOT_ENTRY).setSummary(summary).build()
+ val entry =
+ NotificationEntryBuilder().setGroup(mContext, "group").setParent(groupEntry).build()
+
+ assertThat(gmm.getGroupSummary(entry)).isEqualTo(summary)
+ }
+
+ @Test
+ fun testGetGroupSummary_isSummary_old() {
+ featureFlags.set(Flags.NOTIFICATION_GROUP_EXPANSION_CHANGE, false)
+ val entry = NotificationEntryBuilder().setGroupSummary(mContext, true).build()
+ assertThat(gmm.getGroupSummary(entry)).isNull()
+ }
+
+ @Test
+ fun testGetGroupSummary_isSummary_new() {
+ featureFlags.set(Flags.NOTIFICATION_GROUP_EXPANSION_CHANGE, true)
+ val entry = NotificationEntryBuilder().setGroupSummary(mContext, true).build()
+ assertThat(gmm.getGroupSummary(entry)).isEqualTo(entry)
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationContentInflaterTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationContentInflaterTest.java
index ea87c808debd..e52cb572f289 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationContentInflaterTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationContentInflaterTest.java
@@ -135,7 +135,8 @@ public class NotificationContentInflaterTest extends SysuiTestCase {
mock(MediaFeatureFlag.class),
mock(Executor.class),
mSmartReplyStateInflater,
- mNotifLayoutInflaterFactoryProvider);
+ mNotifLayoutInflaterFactoryProvider,
+ mock(NotificationContentInflaterLogger.class));
}
@Test
@@ -258,7 +259,8 @@ public class NotificationContentInflaterTest extends SysuiTestCase {
return new AsyncFailRemoteView(mContext.getPackageName(),
R.layout.custom_view_dark);
}
- });
+ },
+ mock(NotificationContentInflaterLogger.class));
assertTrue(countDownLatch.await(500, TimeUnit.MILLISECONDS));
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationTestHelper.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationTestHelper.java
index 9dfcb3f75eb1..638694038a6a 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationTestHelper.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationTestHelper.java
@@ -174,7 +174,8 @@ public class NotificationTestHelper {
mock(MediaFeatureFlag.class),
mock(Executor.class),
new MockSmartReplyInflater(),
- mock(NotifLayoutInflaterFactory.Provider.class));
+ mock(NotifLayoutInflaterFactory.Provider.class),
+ mock(NotificationContentInflaterLogger.class));
contentBinder.setInflateSynchronously(true);
mBindStage = new RowContentBindStage(contentBinder,
mock(NotifInflationErrorManager.class),
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/SharedNotificationContainerViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/SharedNotificationContainerViewModelTest.kt
index 55b52dc21434..75fb22dfddd0 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/SharedNotificationContainerViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/SharedNotificationContainerViewModelTest.kt
@@ -30,6 +30,7 @@ import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor
import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor
import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractorFactory
import com.android.systemui.keyguard.shared.model.KeyguardState
+import com.android.systemui.keyguard.shared.model.StatusBarState
import com.android.systemui.keyguard.shared.model.TransitionState
import com.android.systemui.keyguard.shared.model.TransitionStep
import com.android.systemui.shade.data.repository.FakeShadeRepository
@@ -97,7 +98,11 @@ class SharedNotificationContainerViewModelTest : SysuiTestCase() {
keyguardTransitionInteractor = it.keyguardTransitionInteractor
keyguardTransitionRepository = it.repository
}
-
+ sharedNotificationContainerInteractor =
+ SharedNotificationContainerInteractor(
+ configurationRepository,
+ mContext,
+ )
shadeInteractor =
ShadeInteractor(
testScope.backgroundScope,
@@ -106,14 +111,9 @@ class SharedNotificationContainerViewModelTest : SysuiTestCase() {
userSetupRepository,
deviceProvisionedController,
userInteractor,
+ sharedNotificationContainerInteractor,
shadeRepository,
)
-
- sharedNotificationContainerInteractor =
- SharedNotificationContainerInteractor(
- configurationRepository,
- mContext,
- )
underTest =
SharedNotificationContainerViewModel(
sharedNotificationContainerInteractor,
@@ -228,7 +228,7 @@ class SharedNotificationContainerViewModelTest : SysuiTestCase() {
val isOnLockscreenWithoutShade by collectLastValue(underTest.isOnLockscreenWithoutShade)
// First on AOD
- shadeRepository.setShadeExpansion(0f)
+ shadeRepository.setLockscreenShadeExpansion(0f)
shadeRepository.setQsExpansion(0f)
keyguardTransitionRepository.sendTransitionStep(
TransitionStep(
@@ -242,19 +242,19 @@ class SharedNotificationContainerViewModelTest : SysuiTestCase() {
showLockscreen()
// While state is LOCKSCREEN, validate variations of both shade and qs expansion
- shadeRepository.setShadeExpansion(0.1f)
+ shadeRepository.setLockscreenShadeExpansion(0.1f)
shadeRepository.setQsExpansion(0f)
assertThat(isOnLockscreenWithoutShade).isFalse()
- shadeRepository.setShadeExpansion(0.1f)
+ shadeRepository.setLockscreenShadeExpansion(0.1f)
shadeRepository.setQsExpansion(0.1f)
assertThat(isOnLockscreenWithoutShade).isFalse()
- shadeRepository.setShadeExpansion(0f)
+ shadeRepository.setLockscreenShadeExpansion(0f)
shadeRepository.setQsExpansion(0.1f)
assertThat(isOnLockscreenWithoutShade).isFalse()
- shadeRepository.setShadeExpansion(0f)
+ shadeRepository.setLockscreenShadeExpansion(0f)
shadeRepository.setQsExpansion(0f)
assertThat(isOnLockscreenWithoutShade).isTrue()
}
@@ -366,8 +366,9 @@ class SharedNotificationContainerViewModelTest : SysuiTestCase() {
}
private suspend fun showLockscreen() {
- shadeRepository.setShadeExpansion(0f)
+ shadeRepository.setLockscreenShadeExpansion(0f)
shadeRepository.setQsExpansion(0f)
+ keyguardRepository.setStatusBarState(StatusBarState.KEYGUARD)
keyguardTransitionRepository.sendTransitionStep(
TransitionStep(
to = KeyguardState.LOCKSCREEN,
@@ -377,8 +378,9 @@ class SharedNotificationContainerViewModelTest : SysuiTestCase() {
}
private suspend fun showLockscreenWithShadeExpanded() {
- shadeRepository.setShadeExpansion(1f)
+ shadeRepository.setLockscreenShadeExpansion(1f)
shadeRepository.setQsExpansion(0f)
+ keyguardRepository.setStatusBarState(StatusBarState.SHADE_LOCKED)
keyguardTransitionRepository.sendTransitionStep(
TransitionStep(
to = KeyguardState.LOCKSCREEN,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CentralSurfacesImplTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CentralSurfacesImplTest.java
index 5a1450f1c57b..4e3690f1d124 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CentralSurfacesImplTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CentralSurfacesImplTest.java
@@ -162,7 +162,7 @@ import com.android.systemui.statusbar.notification.interruption.NotificationInte
import com.android.systemui.statusbar.notification.row.NotificationGutsManager;
import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout;
import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayoutController;
-import com.android.systemui.statusbar.phone.dagger.CentralSurfacesComponent;
+import com.android.systemui.statusbar.phone.fragment.CollapsedStatusBarFragment;
import com.android.systemui.statusbar.phone.ongoingcall.OngoingCallController;
import com.android.systemui.statusbar.policy.BatteryController;
import com.android.systemui.statusbar.policy.ConfigurationController;
@@ -195,6 +195,8 @@ import java.io.ByteArrayOutputStream;
import java.io.PrintWriter;
import java.util.Optional;
+import javax.inject.Provider;
+
@SmallTest
@RunWith(AndroidTestingRunner.class)
@RunWithLooper(setAsMainLooper = true)
@@ -259,6 +261,7 @@ public class CentralSurfacesImplTest extends SysuiTestCase {
@Mock private DynamicPrivacyController mDynamicPrivacyController;
@Mock private AutoHideController mAutoHideController;
@Mock private StatusBarWindowController mStatusBarWindowController;
+ @Mock private Provider<CollapsedStatusBarFragment> mCollapsedStatusBarFragmentProvider;
@Mock private StatusBarWindowStateController mStatusBarWindowStateController;
@Mock private UserSwitcherController mUserSwitcherController;
@Mock private Bubbles mBubbles;
@@ -277,8 +280,6 @@ public class CentralSurfacesImplTest extends SysuiTestCase {
@Mock private ViewMediatorCallback mKeyguardVieMediatorCallback;
@Mock private VolumeComponent mVolumeComponent;
@Mock private CommandQueue mCommandQueue;
- @Mock private CentralSurfacesComponent.Factory mStatusBarComponentFactory;
- @Mock private CentralSurfacesComponent mCentralSurfacesComponent;
@Mock private CentralSurfacesCommandQueueCallbacks mCentralSurfacesCommandQueueCallbacks;
@Mock private PluginManager mPluginManager;
@Mock private ViewMediatorCallback mViewMediatorCallback;
@@ -405,7 +406,6 @@ public class CentralSurfacesImplTest extends SysuiTestCase {
when(mNotificationShadeWindowViewControllerLazy.get())
.thenReturn(mNotificationShadeWindowViewController);
- when(mStatusBarComponentFactory.create()).thenReturn(mCentralSurfacesComponent);
doAnswer(invocation -> {
((Runnable) invocation.getArgument(0)).run();
return null;
@@ -443,7 +443,10 @@ public class CentralSurfacesImplTest extends SysuiTestCase {
mock(FragmentService.class),
mLightBarController,
mAutoHideController,
- new StatusBarInitializer(mStatusBarWindowController, emptySet()),
+ new StatusBarInitializer(
+ mStatusBarWindowController,
+ mCollapsedStatusBarFragmentProvider,
+ emptySet()),
mStatusBarWindowController,
mStatusBarWindowStateController,
mKeyguardUpdateMonitor,
@@ -504,7 +507,6 @@ public class CentralSurfacesImplTest extends SysuiTestCase {
mDozeScrimController,
mVolumeComponent,
mCommandQueue,
- mStatusBarComponentFactory,
() -> mCentralSurfacesCommandQueueCallbacks,
mPluginManager,
mShadeController,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewControllerTest.kt
index 4c3c3f9d8da5..4349d738b0f3 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewControllerTest.kt
@@ -31,6 +31,7 @@ import com.android.systemui.R
import com.android.systemui.SysuiTestCase
import com.android.systemui.flags.FeatureFlags
import com.android.systemui.flags.Flags
+import com.android.systemui.scene.shared.flag.FakeSceneContainerFlags
import com.android.systemui.scene.ui.view.WindowRootView
import com.android.systemui.shade.ShadeControllerImpl
import com.android.systemui.shade.ShadeLogger
@@ -47,6 +48,8 @@ import com.android.systemui.util.mockito.argumentCaptor
import com.android.systemui.util.mockito.whenever
import com.android.systemui.util.view.ViewUtil
import com.google.common.truth.Truth.assertThat
+import java.util.Optional
+import javax.inject.Provider
import org.junit.Before
import org.junit.Test
import org.mockito.ArgumentCaptor
@@ -57,40 +60,24 @@ import org.mockito.Mockito.spy
import org.mockito.Mockito.verify
import org.mockito.Mockito.`when`
import org.mockito.MockitoAnnotations
-import java.util.Optional
-import javax.inject.Provider
@SmallTest
class PhoneStatusBarViewControllerTest : SysuiTestCase() {
- @Mock
- private lateinit var shadeViewController: ShadeViewController
- @Mock
- private lateinit var featureFlags: FeatureFlags
- @Mock
- private lateinit var moveFromCenterAnimation: StatusBarMoveFromCenterAnimationController
- @Mock
- private lateinit var sysuiUnfoldComponent: SysUIUnfoldComponent
- @Mock
- private lateinit var progressProvider: ScopedUnfoldTransitionProgressProvider
- @Mock
- private lateinit var configurationController: ConfigurationController
- @Mock
- private lateinit var mStatusOverlayHoverListenerFactory: StatusOverlayHoverListenerFactory
- @Mock
- private lateinit var userChipViewModel: StatusBarUserChipViewModel
- @Mock
- private lateinit var centralSurfacesImpl: CentralSurfacesImpl
- @Mock
- private lateinit var commandQueue: CommandQueue
- @Mock
- private lateinit var shadeControllerImpl: ShadeControllerImpl
- @Mock
- private lateinit var windowRootView: Provider<WindowRootView>
- @Mock
- private lateinit var shadeLogger: ShadeLogger
- @Mock
- private lateinit var viewUtil: ViewUtil
+ @Mock private lateinit var shadeViewController: ShadeViewController
+ @Mock private lateinit var featureFlags: FeatureFlags
+ @Mock private lateinit var moveFromCenterAnimation: StatusBarMoveFromCenterAnimationController
+ @Mock private lateinit var sysuiUnfoldComponent: SysUIUnfoldComponent
+ @Mock private lateinit var progressProvider: ScopedUnfoldTransitionProgressProvider
+ @Mock private lateinit var configurationController: ConfigurationController
+ @Mock private lateinit var mStatusOverlayHoverListenerFactory: StatusOverlayHoverListenerFactory
+ @Mock private lateinit var userChipViewModel: StatusBarUserChipViewModel
+ @Mock private lateinit var centralSurfacesImpl: CentralSurfacesImpl
+ @Mock private lateinit var commandQueue: CommandQueue
+ @Mock private lateinit var shadeControllerImpl: ShadeControllerImpl
+ @Mock private lateinit var windowRootView: Provider<WindowRootView>
+ @Mock private lateinit var shadeLogger: ShadeLogger
+ @Mock private lateinit var viewUtil: ViewUtil
private lateinit var statusBarWindowStateController: StatusBarWindowStateController
private lateinit var view: PhoneStatusBarView
@@ -109,16 +96,16 @@ class PhoneStatusBarViewControllerTest : SysuiTestCase() {
// create the view and controller on main thread as it requires main looper
InstrumentationRegistry.getInstrumentation().runOnMainSync {
val parent = FrameLayout(mContext) // add parent to keep layout params
- view = LayoutInflater.from(mContext)
- .inflate(R.layout.status_bar, parent, false) as PhoneStatusBarView
+ view =
+ LayoutInflater.from(mContext).inflate(R.layout.status_bar, parent, false)
+ as PhoneStatusBarView
controller = createAndInitController(view)
}
}
@Test
fun onViewAttachedAndDrawn_moveFromCenterAnimationEnabled_moveFromCenterAnimationInitialized() {
- whenever(featureFlags.isEnabled(Flags.ENABLE_UNFOLD_STATUS_BAR_ANIMATIONS))
- .thenReturn(true)
+ whenever(featureFlags.isEnabled(Flags.ENABLE_UNFOLD_STATUS_BAR_ANIMATIONS)).thenReturn(true)
val view = createViewMock()
val argumentCaptor = ArgumentCaptor.forClass(OnPreDrawListener::class.java)
unfoldConfig.isEnabled = true
@@ -136,7 +123,7 @@ class PhoneStatusBarViewControllerTest : SysuiTestCase() {
@Test
fun onViewAttachedAndDrawn_statusBarAnimationDisabled_animationNotInitialized() {
whenever(featureFlags.isEnabled(Flags.ENABLE_UNFOLD_STATUS_BAR_ANIMATIONS))
- .thenReturn(false)
+ .thenReturn(false)
val view = createViewMock()
unfoldConfig.isEnabled = true
// create the controller on main thread as it requires main looper
@@ -150,8 +137,8 @@ class PhoneStatusBarViewControllerTest : SysuiTestCase() {
@Test
fun handleTouchEventFromStatusBar_panelsNotEnabled_returnsFalseAndNoViewEvent() {
`when`(centralSurfacesImpl.commandQueuePanelsEnabled).thenReturn(false)
- val returnVal = view.onTouchEvent(
- MotionEvent.obtain(0L, 0L, MotionEvent.ACTION_DOWN, 0f, 0f, 0))
+ val returnVal =
+ view.onTouchEvent(MotionEvent.obtain(0L, 0L, MotionEvent.ACTION_DOWN, 0f, 0f, 0))
assertThat(returnVal).isFalse()
verify(shadeViewController, never()).handleExternalTouch(any())
}
@@ -160,8 +147,8 @@ class PhoneStatusBarViewControllerTest : SysuiTestCase() {
fun handleTouchEventFromStatusBar_viewNotEnabled_returnsTrueAndNoViewEvent() {
`when`(centralSurfacesImpl.commandQueuePanelsEnabled).thenReturn(true)
`when`(shadeViewController.isViewEnabled).thenReturn(false)
- val returnVal = view.onTouchEvent(
- MotionEvent.obtain(0L, 0L, MotionEvent.ACTION_DOWN, 0f, 0f, 0))
+ val returnVal =
+ view.onTouchEvent(MotionEvent.obtain(0L, 0L, MotionEvent.ACTION_DOWN, 0f, 0f, 0))
assertThat(returnVal).isTrue()
verify(shadeViewController, never()).handleExternalTouch(any())
}
@@ -245,22 +232,23 @@ class PhoneStatusBarViewControllerTest : SysuiTestCase() {
private fun createAndInitController(view: PhoneStatusBarView): PhoneStatusBarViewController {
return PhoneStatusBarViewController.Factory(
- Optional.of(sysuiUnfoldComponent),
- Optional.of(progressProvider),
- featureFlags,
- userChipViewModel,
- centralSurfacesImpl,
- statusBarWindowStateController,
- shadeControllerImpl,
- shadeViewController,
- windowRootView,
- shadeLogger,
- viewUtil,
- configurationController,
- mStatusOverlayHoverListenerFactory
- ).create(view).also {
- it.init()
- }
+ Optional.of(sysuiUnfoldComponent),
+ Optional.of(progressProvider),
+ featureFlags,
+ FakeSceneContainerFlags(),
+ userChipViewModel,
+ centralSurfacesImpl,
+ statusBarWindowStateController,
+ shadeControllerImpl,
+ shadeViewController,
+ windowRootView,
+ shadeLogger,
+ viewUtil,
+ configurationController,
+ mStatusOverlayHoverListenerFactory
+ )
+ .create(view)
+ .also { it.init() }
}
private class UnfoldConfig : UnfoldTransitionConfig {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/UnlockedScreenOffAnimationControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/UnlockedScreenOffAnimationControllerTest.kt
index e76f26d8128e..e6f8c4861a94 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/UnlockedScreenOffAnimationControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/UnlockedScreenOffAnimationControllerTest.kt
@@ -134,6 +134,22 @@ class UnlockedScreenOffAnimationControllerTest : SysuiTestCase() {
verify(shadeViewController, times(1)).showAodUi()
}
+ @Test
+ fun testAodUiShowNotInvokedIfWakingUp() {
+ `when`(dozeParameters.canControlUnlockedScreenOff()).thenReturn(true)
+ `when`(powerManager.isInteractive).thenReturn(false)
+
+ val callbackCaptor = ArgumentCaptor.forClass(Runnable::class.java)
+ controller.startAnimation()
+ controller.onStartedWakingUp()
+
+ verify(handler).postDelayed(callbackCaptor.capture(), anyLong())
+
+ callbackCaptor.value.run()
+
+ verify(shadeViewController, never()).showAodUi()
+ }
+
/**
* The AOD UI is shown during the screen off animation, after a delay to allow the light reveal
* animation to start. If the device is woken up during the screen off, we should *never* do
diff --git a/packages/SystemUI/tests/src/com/android/systemui/volume/VolumeDialogImplTest.java b/packages/SystemUI/tests/src/com/android/systemui/volume/VolumeDialogImplTest.java
index 525624547528..65cac6efad1c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/volume/VolumeDialogImplTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/volume/VolumeDialogImplTest.java
@@ -84,7 +84,7 @@ import java.util.function.Predicate;
@SmallTest
@RunWith(AndroidTestingRunner.class)
-@TestableLooper.RunWithLooper
+@TestableLooper.RunWithLooper(setAsMainLooper = true)
public class VolumeDialogImplTest extends SysuiTestCase {
VolumeDialogImpl mDialog;
View mActiveRinger;
@@ -141,6 +141,7 @@ public class VolumeDialogImplTest extends SysuiTestCase {
getContext().addMockSystemService(KeyguardManager.class, mKeyguard);
mTestableLooper = TestableLooper.get(this);
+ allowTestableLooperAsMainThread();
when(mPostureController.getDevicePosture())
.thenReturn(DevicePostureController.DEVICE_POSTURE_CLOSED);
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/SysuiTestCase.java b/packages/SystemUI/tests/utils/src/com/android/systemui/SysuiTestCase.java
index 28b7d4171df1..aa88a46d670c 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/SysuiTestCase.java
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/SysuiTestCase.java
@@ -166,7 +166,9 @@ public abstract class SysuiTestCase {
}
disallowTestableLooperAsMainThread();
mContext.cleanUpReceivers(this.getClass().getSimpleName());
- mFakeBroadcastDispatcher.cleanUpReceivers(this.getClass().getSimpleName());
+ if (mFakeBroadcastDispatcher != null) {
+ mFakeBroadcastDispatcher.cleanUpReceivers(this.getClass().getSimpleName());
+ }
}
@AfterClass
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/display/data/repository/FakeDisplayRepository.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/display/data/repository/FakeDisplayRepository.kt
index 6f51d1b60822..2ac625d68bfe 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/display/data/repository/FakeDisplayRepository.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/display/data/repository/FakeDisplayRepository.kt
@@ -30,20 +30,24 @@ fun display(type: Int, flags: Int = 0, id: Int = 0): Display {
}
}
+/** Creates a mock [DisplayRepository.PendingDisplay]. */
+fun createPendingDisplay(id: Int = 0): DisplayRepository.PendingDisplay =
+ mock<DisplayRepository.PendingDisplay> { whenever(this.id).thenReturn(id) }
+
/** Fake [DisplayRepository] implementation for testing. */
class FakeDisplayRepository : DisplayRepository {
private val flow = MutableSharedFlow<Set<Display>>()
- private val pendingDisplayFlow = MutableSharedFlow<Int?>()
+ private val pendingDisplayFlow = MutableSharedFlow<DisplayRepository.PendingDisplay?>()
/** Emits [value] as [displays] flow value. */
suspend fun emit(value: Set<Display>) = flow.emit(value)
- /** Emits [value] as [pendingDisplayId] flow value. */
- suspend fun emit(value: Int?) = pendingDisplayFlow.emit(value)
+ /** Emits [value] as [pendingDisplay] flow value. */
+ suspend fun emit(value: DisplayRepository.PendingDisplay?) = pendingDisplayFlow.emit(value)
override val displays: Flow<Set<Display>>
get() = flow
- override val pendingDisplayId: Flow<Int?>
+ override val pendingDisplay: Flow<DisplayRepository.PendingDisplay?>
get() = pendingDisplayFlow
}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractorFactory.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractorFactory.kt
index 8c1ef1deb0da..2e3bb2b545d8 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractorFactory.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractorFactory.kt
@@ -23,7 +23,11 @@ import com.android.systemui.flags.FakeFeatureFlags
import com.android.systemui.flags.Flags
import com.android.systemui.keyguard.data.repository.FakeCommandQueue
import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository
+import com.android.systemui.scene.domain.interactor.SceneInteractor
+import com.android.systemui.scene.shared.flag.FakeSceneContainerFlags
+import com.android.systemui.scene.shared.flag.SceneContainerFlags
import com.android.systemui.shade.data.repository.FakeShadeRepository
+import com.android.systemui.util.mockito.mock
/**
* Simply put, I got tired of adding a constructor argument and then having to tweak dozens of
@@ -35,16 +39,19 @@ object KeyguardInteractorFactory {
@JvmStatic
fun create(
featureFlags: FakeFeatureFlags = createFakeFeatureFlags(),
+ sceneContainerFlags: SceneContainerFlags = FakeSceneContainerFlags(),
repository: FakeKeyguardRepository = FakeKeyguardRepository(),
commandQueue: FakeCommandQueue = FakeCommandQueue(),
bouncerRepository: FakeKeyguardBouncerRepository = FakeKeyguardBouncerRepository(),
configurationRepository: FakeConfigurationRepository = FakeConfigurationRepository(),
shadeRepository: FakeShadeRepository = FakeShadeRepository(),
+ sceneInteractor: SceneInteractor = mock(),
): WithDependencies {
return WithDependencies(
repository = repository,
commandQueue = commandQueue,
featureFlags = featureFlags,
+ sceneContainerFlags = sceneContainerFlags,
bouncerRepository = bouncerRepository,
configurationRepository = configurationRepository,
shadeRepository = shadeRepository,
@@ -52,9 +59,11 @@ object KeyguardInteractorFactory {
repository = repository,
commandQueue = commandQueue,
featureFlags = featureFlags,
+ sceneContainerFlags = sceneContainerFlags,
bouncerRepository = bouncerRepository,
configurationRepository = configurationRepository,
shadeRepository = shadeRepository,
+ sceneInteractorProvider = { sceneInteractor },
)
)
}
@@ -68,6 +77,7 @@ object KeyguardInteractorFactory {
val repository: FakeKeyguardRepository,
val commandQueue: FakeCommandQueue,
val featureFlags: FakeFeatureFlags,
+ val sceneContainerFlags: SceneContainerFlags,
val bouncerRepository: FakeKeyguardBouncerRepository,
val configurationRepository: FakeConfigurationRepository,
val shadeRepository: FakeShadeRepository,
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionInteractorFactory.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionInteractorFactory.kt
index 05c63b6cea72..5cf656ceedaa 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionInteractorFactory.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionInteractorFactory.kt
@@ -16,6 +16,8 @@
package com.android.systemui.keyguard.domain.interactor
+import com.android.systemui.flags.FakeFeatureFlags
+import com.android.systemui.flags.FakeFeatureFlagsClassic
import com.android.systemui.keyguard.data.repository.FakeKeyguardTransitionRepository
import com.android.systemui.util.mockito.mock
import dagger.Lazy
@@ -31,8 +33,9 @@ object KeyguardTransitionInteractorFactory {
fun create(
scope: CoroutineScope,
repository: FakeKeyguardTransitionRepository = FakeKeyguardTransitionRepository(),
+ featureFlags: FakeFeatureFlags = FakeFeatureFlagsClassic(),
keyguardInteractor: KeyguardInteractor =
- KeyguardInteractorFactory.create().keyguardInteractor,
+ KeyguardInteractorFactory.create(featureFlags = featureFlags).keyguardInteractor,
fromLockscreenTransitionInteractor: Lazy<FromLockscreenTransitionInteractor> = Lazy {
mock<FromLockscreenTransitionInteractor>()
},
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/scene/SceneTestUtils.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/scene/SceneTestUtils.kt
index f7db44e9618a..9dea0a0c26d5 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/scene/SceneTestUtils.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/scene/SceneTestUtils.kt
@@ -31,7 +31,7 @@ import com.android.systemui.classifier.FalsingCollector
import com.android.systemui.classifier.FalsingCollectorFake
import com.android.systemui.classifier.domain.interactor.FalsingInteractor
import com.android.systemui.common.ui.data.repository.FakeConfigurationRepository
-import com.android.systemui.flags.FakeFeatureFlags
+import com.android.systemui.flags.FakeFeatureFlagsClassic
import com.android.systemui.flags.Flags
import com.android.systemui.keyguard.data.repository.FakeCommandQueue
import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository
@@ -43,6 +43,7 @@ import com.android.systemui.keyguard.shared.model.WakefulnessState
import com.android.systemui.power.data.repository.FakePowerRepository
import com.android.systemui.scene.data.repository.SceneContainerRepository
import com.android.systemui.scene.domain.interactor.SceneInteractor
+import com.android.systemui.scene.shared.flag.FakeSceneContainerFlags
import com.android.systemui.scene.shared.model.SceneContainerConfig
import com.android.systemui.scene.shared.model.SceneKey
import com.android.systemui.shade.data.repository.FakeShadeRepository
@@ -67,11 +68,8 @@ class SceneTestUtils(
) {
val testDispatcher = StandardTestDispatcher()
val testScope = TestScope(testDispatcher)
- val featureFlags =
- FakeFeatureFlags().apply {
- set(Flags.SCENE_CONTAINER, true)
- set(Flags.FACE_AUTH_REFACTOR, false)
- }
+ val featureFlags = FakeFeatureFlagsClassic().apply { set(Flags.FACE_AUTH_REFACTOR, false) }
+ val sceneContainerFlags = FakeSceneContainerFlags().apply { enabled = true }
private val userRepository: UserRepository by lazy {
FakeUserRepository().apply {
val users = listOf(UserInfo(/* id= */ 0, "name", /* flags= */ 0))
@@ -164,9 +162,11 @@ class SceneTestUtils(
repository = repository,
commandQueue = FakeCommandQueue(),
featureFlags = featureFlags,
+ sceneContainerFlags = sceneContainerFlags,
bouncerRepository = FakeKeyguardBouncerRepository(),
configurationRepository = FakeConfigurationRepository(),
shadeRepository = FakeShadeRepository(),
+ sceneInteractorProvider = { sceneInteractor() },
)
}
@@ -180,7 +180,7 @@ class SceneTestUtils(
repository = BouncerRepository(),
authenticationInteractor = authenticationInteractor,
sceneInteractor = sceneInteractor,
- featureFlags = featureFlags,
+ flags = sceneContainerFlags,
falsingInteractor = falsingInteractor(),
)
}
@@ -194,7 +194,7 @@ class SceneTestUtils(
applicationScope = applicationScope(),
bouncerInteractor = bouncerInteractor,
authenticationInteractor = authenticationInteractor,
- featureFlags = featureFlags,
+ flags = sceneContainerFlags,
)
}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/scene/shared/flag/FakeSceneContainerFlags.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/scene/shared/flag/FakeSceneContainerFlags.kt
new file mode 100644
index 000000000000..01a1ecea9997
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/scene/shared/flag/FakeSceneContainerFlags.kt
@@ -0,0 +1,30 @@
+/*
+ * Copyright 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.scene.shared.flag
+
+class FakeSceneContainerFlags(
+ var enabled: Boolean = false,
+) : SceneContainerFlags {
+
+ override fun isEnabled(): Boolean {
+ return enabled
+ }
+
+ override fun requirementDescription(): String {
+ return ""
+ }
+}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/shade/data/repository/FakeShadeRepository.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/shade/data/repository/FakeShadeRepository.kt
index ccddca2d6611..08152a3c49cd 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/shade/data/repository/FakeShadeRepository.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/shade/data/repository/FakeShadeRepository.kt
@@ -33,8 +33,12 @@ class FakeShadeRepository : ShadeRepository {
private val _udfpsTransitionToFullShadeProgress = MutableStateFlow(0f)
override val udfpsTransitionToFullShadeProgress = _udfpsTransitionToFullShadeProgress
- private val _shadeExpansion = MutableStateFlow(0f)
- override val shadeExpansion = _shadeExpansion
+ private val _lockscreenShadeExpansion = MutableStateFlow(0f)
+ override val lockscreenShadeExpansion = _lockscreenShadeExpansion
+
+ private val _legacyShadeExpansion = MutableStateFlow(0f)
+ @Deprecated("Use ShadeInteractor instead")
+ override val legacyShadeExpansion = _legacyShadeExpansion
fun setShadeModel(model: ShadeModel) {
_shadeModel.value = model
@@ -48,7 +52,12 @@ class FakeShadeRepository : ShadeRepository {
_udfpsTransitionToFullShadeProgress.value = progress
}
- override fun setShadeExpansion(expansion: Float) {
- _shadeExpansion.value = expansion
+ override fun setLockscreenShadeExpansion(lockscreenShadeExpansion: Float) {
+ _lockscreenShadeExpansion.value = lockscreenShadeExpansion
+ }
+
+ @Deprecated("Should only be called by NPVC and tests")
+ override fun setLegacyShadeExpansion(expandedFraction: Float) {
+ _legacyShadeExpansion.value = expandedFraction
}
}
diff --git a/packages/WallpaperBackup/Android.bp b/packages/WallpaperBackup/Android.bp
index 8acc5089f8bd..155dc1a68295 100644
--- a/packages/WallpaperBackup/Android.bp
+++ b/packages/WallpaperBackup/Android.bp
@@ -27,9 +27,6 @@ android_app {
name: "WallpaperBackup",
defaults: ["platform_app_defaults"],
srcs: ["src/**/*.java"],
- optimize: {
- proguard_flags_files: ["proguard.flags"],
- },
platform_apis: true,
certificate: "platform",
privileged: false,
diff --git a/packages/WallpaperBackup/proguard.flags b/packages/WallpaperBackup/proguard.flags
deleted file mode 100644
index 247e6efb10ef..000000000000
--- a/packages/WallpaperBackup/proguard.flags
+++ /dev/null
@@ -1 +0,0 @@
--keep class com.android.wallpaperbackup.WallpaperBackupAgent
diff --git a/services/autofill/Android.bp b/services/autofill/Android.bp
index eb23f2f9b435..d43a219e6205 100644
--- a/services/autofill/Android.bp
+++ b/services/autofill/Android.bp
@@ -19,4 +19,19 @@ java_library_static {
defaults: ["platform_service_defaults"],
srcs: [":services.autofill-sources"],
libs: ["services.core"],
+ static_libs: ["autofill_flags_java_lib"],
+}
+
+aconfig_declarations {
+ name: "autofill_flags",
+ package: "android.service.autofill",
+ srcs: [
+ "bugfixes.aconfig",
+ "features.aconfig",
+ ],
+}
+
+java_aconfig_library {
+ name: "autofill_flags_java_lib",
+ aconfig_declarations: "autofill_flags",
}
diff --git a/services/autofill/bugfixes.aconfig b/services/autofill/bugfixes.aconfig
new file mode 100644
index 000000000000..ef237546378e
--- /dev/null
+++ b/services/autofill/bugfixes.aconfig
@@ -0,0 +1,8 @@
+package: "android.service.autofill"
+
+flag {
+ name: "test"
+ namespace: "autofill"
+ description: "Test flag "
+ bug: "297380045"
+} \ No newline at end of file
diff --git a/services/autofill/features.aconfig b/services/autofill/features.aconfig
new file mode 100644
index 000000000000..1e44de61bdd7
--- /dev/null
+++ b/services/autofill/features.aconfig
@@ -0,0 +1 @@
+package: "android.service.autofill" \ No newline at end of file
diff --git a/services/autofill/java/com/android/server/autofill/AutofillManagerServiceShellCommand.java b/services/autofill/java/com/android/server/autofill/AutofillManagerServiceShellCommand.java
index c66fb81f51c6..39756dfee7bf 100644
--- a/services/autofill/java/com/android/server/autofill/AutofillManagerServiceShellCommand.java
+++ b/services/autofill/java/com/android/server/autofill/AutofillManagerServiceShellCommand.java
@@ -26,11 +26,14 @@ import android.os.RemoteCallback;
import android.os.ShellCommand;
import android.os.UserHandle;
import android.service.autofill.AutofillFieldClassificationService.Scores;
+import android.service.autofill.Flags;
import android.view.autofill.AutofillManager;
import com.android.internal.os.IResultReceiver;
import java.io.PrintWriter;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
@@ -60,6 +63,8 @@ public final class AutofillManagerServiceShellCommand extends ShellCommand {
return requestGet(pw);
case "set":
return requestSet(pw);
+ case "flags":
+ return requestFlags(pw);
default:
return handleDefaultCommands(cmd);
}
@@ -67,7 +72,7 @@ public final class AutofillManagerServiceShellCommand extends ShellCommand {
@Override
public void onHelp() {
- try (final PrintWriter pw = getOutPrintWriter();) {
+ try (final PrintWriter pw = getOutPrintWriter(); ) {
pw.println("AutoFill Service (autofill) commands:");
pw.println(" help");
pw.println(" Prints this help text.");
@@ -109,21 +114,24 @@ public final class AutofillManagerServiceShellCommand extends ShellCommand {
pw.println(" Sets whether binding to services provided by instant apps is allowed");
pw.println("");
pw.println(" set temporary-augmented-service USER_ID [COMPONENT_NAME DURATION]");
- pw.println(" Temporarily (for DURATION ms) changes the augmented autofill service "
- + "implementation.");
+ pw.println(
+ " Temporarily (for DURATION ms) changes the augmented autofill service "
+ + "implementation.");
pw.println(" To reset, call with just the USER_ID argument.");
pw.println("");
pw.println(" set default-augmented-service-enabled USER_ID [true|false]");
pw.println(" Enable / disable the default augmented autofill service for the user.");
pw.println("");
pw.println(" set temporary-detection-service USER_ID [COMPONENT_NAME DURATION]");
- pw.println(" Temporarily (for DURATION ms) changes the autofill detection service "
- + "implementation.");
+ pw.println(
+ " Temporarily (for DURATION ms) changes the autofill detection service "
+ + "implementation.");
pw.println(" To reset, call with [COMPONENT_NAME 0].");
pw.println("");
pw.println(" get default-augmented-service-enabled USER_ID");
- pw.println(" Checks whether the default augmented autofill service is enabled for "
- + "the user.");
+ pw.println(
+ " Checks whether the default augmented autofill service is enabled for "
+ + "the user.");
pw.println("");
pw.println(" list sessions [--user USER_ID]");
pw.println(" Lists all pending sessions.");
@@ -134,7 +142,34 @@ public final class AutofillManagerServiceShellCommand extends ShellCommand {
pw.println(" reset");
pw.println(" Resets all pending sessions and cached service connections.");
pw.println("");
+ pw.println(" flags");
+ pw.println(" Prints out all autofill related flags.");
+ pw.println("");
+ }
+ }
+
+ private int requestFlags(PrintWriter pw) {
+
+ if (Flags.test()) {
+ pw.println("Hello Flag World!");
+ pw.println("");
+ }
+
+ try {
+ Method[] flagMethods = Flags.class.getMethods();
+ // For some reason, unreferenced flags do not show up here
+ // Maybe compiler optomized them out of bytecode?
+ for (Method method : flagMethods) {
+ if (Modifier.isPublic(method.getModifiers())) {
+ pw.println(method.getName() + ": " + method.invoke(null));
+ }
+ }
+ } catch (Exception ex) {
+ pw.println(ex);
+ return -1;
}
+
+ return 0;
}
private int requestGet(PrintWriter pw) {
diff --git a/services/companion/java/com/android/server/companion/virtual/CameraAccessController.java b/services/companion/java/com/android/server/companion/virtual/CameraAccessController.java
index 66755688fb19..ce4067cf3786 100644
--- a/services/companion/java/com/android/server/companion/virtual/CameraAccessController.java
+++ b/services/companion/java/com/android/server/companion/virtual/CameraAccessController.java
@@ -19,6 +19,7 @@ package com.android.server.companion.virtual;
import static android.hardware.camera2.CameraInjectionSession.InjectionStatusCallback.ERROR_INJECTION_UNSUPPORTED;
import android.annotation.NonNull;
+import android.annotation.RequiresPermission;
import android.annotation.UserIdInt;
import android.content.Context;
import android.content.pm.ApplicationInfo;
@@ -146,6 +147,7 @@ class CameraAccessController extends CameraManager.AvailabilityCallback implemen
*
* @param runningUids uids of the application running on the virtual display
*/
+ @RequiresPermission(android.Manifest.permission.CAMERA_INJECT_EXTERNAL_CAMERA)
public void blockCameraAccessIfNeeded(Set<Integer> runningUids) {
synchronized (mLock) {
for (int i = 0; i < mAppsToBlockOnVirtualDevice.size(); i++) {
@@ -181,6 +183,7 @@ class CameraAccessController extends CameraManager.AvailabilityCallback implemen
}
@Override
+ @RequiresPermission(android.Manifest.permission.CAMERA_INJECT_EXTERNAL_CAMERA)
public void onCameraOpened(@NonNull String cameraId, @NonNull String packageName) {
synchronized (mLock) {
InjectionSessionData data = mPackageToSessionData.get(packageName);
@@ -243,6 +246,7 @@ class CameraAccessController extends CameraManager.AvailabilityCallback implemen
/**
* Turns on blocking for a particular camera and package.
*/
+ @RequiresPermission(android.Manifest.permission.CAMERA_INJECT_EXTERNAL_CAMERA)
private void startBlocking(String packageName, String cameraId) {
try {
Slog.d(
diff --git a/services/companion/java/com/android/server/companion/virtual/GenericWindowPolicyController.java b/services/companion/java/com/android/server/companion/virtual/GenericWindowPolicyController.java
index 34033e225b80..b07a0bb57678 100644
--- a/services/companion/java/com/android/server/companion/virtual/GenericWindowPolicyController.java
+++ b/services/companion/java/com/android/server/companion/virtual/GenericWindowPolicyController.java
@@ -17,6 +17,7 @@
package com.android.server.companion.virtual;
import static android.content.pm.ActivityInfo.FLAG_CAN_DISPLAY_ON_REMOTE_DEVICES;
+import static android.view.Display.DEFAULT_DISPLAY;
import static android.view.WindowManager.LayoutParams.FLAG_SECURE;
import static android.view.WindowManager.LayoutParams.SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS;
@@ -26,8 +27,6 @@ import android.annotation.UserIdInt;
import android.app.WindowConfiguration;
import android.app.compat.CompatChanges;
import android.companion.virtual.VirtualDeviceManager.ActivityListener;
-import android.companion.virtual.VirtualDeviceParams;
-import android.companion.virtual.VirtualDeviceParams.ActivityPolicy;
import android.compat.annotation.ChangeId;
import android.compat.annotation.EnabledSince;
import android.content.ComponentName;
@@ -46,7 +45,6 @@ import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.app.BlockedAppStreamingActivity;
-import java.util.List;
import java.util.Set;
@@ -108,18 +106,14 @@ public class GenericWindowPolicyController extends DisplayWindowPolicyController
public static final long ALLOW_SECURE_ACTIVITY_DISPLAY_ON_REMOTE_DEVICE = 201712607L;
@NonNull
private final ArraySet<UserHandle> mAllowedUsers;
- @Nullable
- private final ArraySet<ComponentName> mAllowedCrossTaskNavigations;
- @Nullable
- private final ArraySet<ComponentName> mBlockedCrossTaskNavigations;
- @Nullable
- private final ArraySet<ComponentName> mAllowedActivities;
- @Nullable
- private final ArraySet<ComponentName> mBlockedActivities;
+ private final boolean mActivityLaunchAllowedByDefault;
+ @NonNull
+ private final ArraySet<ComponentName> mActivityPolicyExceptions;
+ private final boolean mCrossTaskNavigationAllowedByDefault;
+ @NonNull
+ private final ArraySet<ComponentName> mCrossTaskNavigationExceptions;
private final Object mGenericWindowPolicyControllerLock = new Object();
- @ActivityPolicy
- private final int mDefaultActivityPolicy;
- private final ActivityBlockedCallback mActivityBlockedCallback;
+ @Nullable private final ActivityBlockedCallback mActivityBlockedCallback;
private int mDisplayId = Display.INVALID_DISPLAY;
@NonNull
@@ -134,9 +128,10 @@ public class GenericWindowPolicyController extends DisplayWindowPolicyController
private final ArraySet<RunningAppsChangedListener> mRunningAppsChangedListeners =
new ArraySet<>();
@Nullable private final SecureWindowCallback mSecureWindowCallback;
- @Nullable private final Set<String> mDisplayCategories;
+ @NonNull private final Set<String> mDisplayCategories;
- private final boolean mShowTasksInHostDeviceRecents;
+ @GuardedBy("mGenericWindowPolicyControllerLock")
+ private boolean mShowTasksInHostDeviceRecents;
/**
* Creates a window policy controller that is generic to the different use cases of virtual
@@ -145,18 +140,14 @@ public class GenericWindowPolicyController extends DisplayWindowPolicyController
* @param windowFlags The window flags that this controller is interested in.
* @param systemWindowFlags The system window flags that this controller is interested in.
* @param allowedUsers The set of users that are allowed to stream in this display.
- * @param allowedCrossTaskNavigations The set of components explicitly allowed to navigate
- * across tasks on this device.
- * @param blockedCrossTaskNavigations The set of components explicitly blocked from
- * navigating across tasks on this device.
- * @param allowedActivities The set of activities explicitly allowed to stream on this device.
- * Used only if the {@code activityPolicy} is
- * {@link VirtualDeviceParams#ACTIVITY_POLICY_DEFAULT_BLOCKED}.
- * @param blockedActivities The set of activities explicitly blocked from streaming on this
- * device. Used only if the {@code activityPolicy} is
- * {@link VirtualDeviceParams#ACTIVITY_POLICY_DEFAULT_ALLOWED}
- * @param defaultActivityPolicy Whether activities are default allowed to be displayed or
- * blocked.
+ * @param activityLaunchAllowedByDefault Whether activities are default allowed to be launched
+ * or blocked.
+ * @param activityPolicyExceptions The set of activities explicitly exempt from the default
+ * activity policy.
+ * @param crossTaskNavigationAllowedByDefault Whether cross task navigations are allowed by
+ * default or not.
+ * @param crossTaskNavigationExceptions The set of components explicitly exempt from the default
+ * navigation policy.
* @param activityListener Activity listener to listen for activity changes.
* @param activityBlockedCallback Callback that is called when an activity is blocked from
* launching.
@@ -168,25 +159,23 @@ public class GenericWindowPolicyController extends DisplayWindowPolicyController
*/
public GenericWindowPolicyController(int windowFlags, int systemWindowFlags,
@NonNull ArraySet<UserHandle> allowedUsers,
- @NonNull Set<ComponentName> allowedCrossTaskNavigations,
- @NonNull Set<ComponentName> blockedCrossTaskNavigations,
- @NonNull Set<ComponentName> allowedActivities,
- @NonNull Set<ComponentName> blockedActivities,
- @ActivityPolicy int defaultActivityPolicy,
- @NonNull ActivityListener activityListener,
- @NonNull PipBlockedCallback pipBlockedCallback,
- @NonNull ActivityBlockedCallback activityBlockedCallback,
- @NonNull SecureWindowCallback secureWindowCallback,
- @NonNull IntentListenerCallback intentListenerCallback,
+ boolean activityLaunchAllowedByDefault,
+ @NonNull Set<ComponentName> activityPolicyExceptions,
+ boolean crossTaskNavigationAllowedByDefault,
+ @NonNull Set<ComponentName> crossTaskNavigationExceptions,
+ @Nullable ActivityListener activityListener,
+ @Nullable PipBlockedCallback pipBlockedCallback,
+ @Nullable ActivityBlockedCallback activityBlockedCallback,
+ @Nullable SecureWindowCallback secureWindowCallback,
+ @Nullable IntentListenerCallback intentListenerCallback,
@NonNull Set<String> displayCategories,
boolean showTasksInHostDeviceRecents) {
super();
mAllowedUsers = allowedUsers;
- mAllowedCrossTaskNavigations = new ArraySet<>(allowedCrossTaskNavigations);
- mBlockedCrossTaskNavigations = new ArraySet<>(blockedCrossTaskNavigations);
- mAllowedActivities = new ArraySet<>(allowedActivities);
- mBlockedActivities = new ArraySet<>(blockedActivities);
- mDefaultActivityPolicy = defaultActivityPolicy;
+ mActivityLaunchAllowedByDefault = activityLaunchAllowedByDefault;
+ mActivityPolicyExceptions = new ArraySet<>(activityPolicyExceptions);
+ mCrossTaskNavigationAllowedByDefault = crossTaskNavigationAllowedByDefault;
+ mCrossTaskNavigationExceptions = new ArraySet<>(crossTaskNavigationExceptions);
mActivityBlockedCallback = activityBlockedCallback;
setInterestedWindowFlags(windowFlags, systemWindowFlags);
mActivityListener = activityListener;
@@ -204,6 +193,15 @@ public class GenericWindowPolicyController extends DisplayWindowPolicyController
mDisplayId = displayId;
}
+ /**
+ * Set whether to show activities in recents on the host device.
+ */
+ public void setShowInHostDeviceRecents(boolean showInHostDeviceRecents) {
+ synchronized (mGenericWindowPolicyControllerLock) {
+ mShowTasksInHostDeviceRecents = showInHostDeviceRecents;
+ }
+ }
+
/** Register a listener for running applications changes. */
public void registerRunningAppsChangedListener(@NonNull RunningAppsChangedListener listener) {
synchronized (mGenericWindowPolicyControllerLock) {
@@ -219,28 +217,39 @@ public class GenericWindowPolicyController extends DisplayWindowPolicyController
}
@Override
- public boolean canContainActivities(@NonNull List<ActivityInfo> activities,
- @WindowConfiguration.WindowingMode int windowingMode) {
- if (!isWindowingModeSupported(windowingMode)) {
+ public boolean canActivityBeLaunched(@NonNull ActivityInfo activityInfo,
+ @Nullable Intent intent, @WindowConfiguration.WindowingMode int windowingMode,
+ int launchingFromDisplayId, boolean isNewTask) {
+ if (!canContainActivity(activityInfo, windowingMode, launchingFromDisplayId, isNewTask)) {
+ if (mActivityBlockedCallback != null) {
+ mActivityBlockedCallback.onActivityBlocked(mDisplayId, activityInfo);
+ }
return false;
}
- // Can't display all the activities if any of them don't want to be displayed.
- final int activityCount = activities.size();
- for (int i = 0; i < activityCount; i++) {
- final ActivityInfo aInfo = activities.get(i);
- if (!canContainActivity(aInfo, /* windowFlags= */ 0, /* systemWindowFlags= */ 0)) {
- mActivityBlockedCallback.onActivityBlocked(mDisplayId, aInfo);
- return false;
- }
+ if (mIntentListenerCallback != null && intent != null
+ && mIntentListenerCallback.shouldInterceptIntent(intent)) {
+ Slog.d(TAG, "Virtual device intercepting intent");
+ return false;
}
return true;
}
@Override
- public boolean canActivityBeLaunched(ActivityInfo activityInfo,
- Intent intent, @WindowConfiguration.WindowingMode int windowingMode,
- int launchingFromDisplayId, boolean isNewTask) {
+ public boolean canContainActivity(@NonNull ActivityInfo activityInfo,
+ @WindowConfiguration.WindowingMode int windowingMode, int launchingFromDisplayId,
+ boolean isNewTask) {
if (!isWindowingModeSupported(windowingMode)) {
+ Slog.d(TAG, "Virtual device doesn't support windowing mode " + windowingMode);
+ return false;
+ }
+ if ((activityInfo.flags & FLAG_CAN_DISPLAY_ON_REMOTE_DEVICES) == 0) {
+ Slog.d(TAG, "Virtual device requires android:canDisplayOnRemoteDevices=true");
+ return false;
+ }
+ final UserHandle activityUser =
+ UserHandle.getUserHandleForUid(activityInfo.applicationInfo.uid);
+ if (!mAllowedUsers.contains(activityUser)) {
+ Slog.d(TAG, "Virtual device launch disallowed from user " + activityUser);
return false;
}
@@ -249,54 +258,54 @@ public class GenericWindowPolicyController extends DisplayWindowPolicyController
// The error dialog alerting users that streaming is blocked is always allowed.
return true;
}
-
- if (!canContainActivity(activityInfo, /* windowFlags= */ 0, /* systemWindowFlags= */ 0)) {
- mActivityBlockedCallback.onActivityBlocked(mDisplayId, activityInfo);
+ if (!activityMatchesDisplayCategory(activityInfo)) {
+ Slog.d(TAG, "The activity's required display category '"
+ + activityInfo.requiredDisplayCategory
+ + "' not found on virtual display with the following categories: "
+ + mDisplayCategories);
return false;
}
-
- if (launchingFromDisplayId == Display.DEFAULT_DISPLAY) {
- return true;
- }
- if (isNewTask && !mBlockedCrossTaskNavigations.isEmpty()
- && mBlockedCrossTaskNavigations.contains(activityComponent)) {
- Slog.d(TAG, "Virtual device blocking cross task navigation of " + activityComponent);
- mActivityBlockedCallback.onActivityBlocked(mDisplayId, activityInfo);
+ if (!isAllowedByPolicy(mActivityLaunchAllowedByDefault, mActivityPolicyExceptions,
+ activityComponent)) {
+ Slog.d(TAG, "Virtual device launch disallowed by policy: " + activityComponent);
return false;
}
- if (isNewTask && !mAllowedCrossTaskNavigations.isEmpty()
- && !mAllowedCrossTaskNavigations.contains(activityComponent)) {
- Slog.d(TAG, "Virtual device not allowing cross task navigation of "
+ if (isNewTask && launchingFromDisplayId != DEFAULT_DISPLAY
+ && !isAllowedByPolicy(mCrossTaskNavigationAllowedByDefault,
+ mCrossTaskNavigationExceptions, activityComponent)) {
+ Slog.d(TAG, "Virtual device cross task navigation disallowed by policy: "
+ activityComponent);
- mActivityBlockedCallback.onActivityBlocked(mDisplayId, activityInfo);
- return false;
- }
-
- if (mIntentListenerCallback != null && intent != null
- && mIntentListenerCallback.shouldInterceptIntent(intent)) {
- Slog.d(TAG, "Virtual device has intercepted intent");
return false;
}
return true;
}
-
@Override
+ @SuppressWarnings("AndroidFrameworkRequiresPermission")
public boolean keepActivityOnWindowFlagsChanged(ActivityInfo activityInfo, int windowFlags,
int systemWindowFlags) {
// The callback is fired only when windowFlags are changed. To let VirtualDevice owner
// aware that the virtual display has a secure window on top.
- if ((windowFlags & FLAG_SECURE) != 0) {
+ if ((windowFlags & FLAG_SECURE) != 0 && mSecureWindowCallback != null) {
// Post callback on the main thread, so it doesn't block activity launching.
mHandler.post(() -> mSecureWindowCallback.onSecureWindowShown(mDisplayId,
activityInfo.applicationInfo.uid));
}
- if (!canContainActivity(activityInfo, windowFlags, systemWindowFlags)) {
- mActivityBlockedCallback.onActivityBlocked(mDisplayId, activityInfo);
- return false;
+ if (!CompatChanges.isChangeEnabled(ALLOW_SECURE_ACTIVITY_DISPLAY_ON_REMOTE_DEVICE,
+ activityInfo.packageName,
+ UserHandle.getUserHandleForUid(activityInfo.applicationInfo.uid))) {
+ // TODO(b/201712607): Add checks for the apps that use SurfaceView#setSecure.
+ if ((windowFlags & FLAG_SECURE) != 0
+ || (systemWindowFlags & SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS) != 0) {
+ if (mActivityBlockedCallback != null) {
+ mActivityBlockedCallback.onActivityBlocked(mDisplayId, activityInfo);
+ }
+ return false;
+ }
}
+
return true;
}
@@ -335,7 +344,9 @@ public class GenericWindowPolicyController extends DisplayWindowPolicyController
@Override
public boolean canShowTasksInHostDeviceRecents() {
- return mShowTasksInHostDeviceRecents;
+ synchronized (mGenericWindowPolicyControllerLock) {
+ return mShowTasksInHostDeviceRecents;
+ }
}
@Override
@@ -343,9 +354,9 @@ public class GenericWindowPolicyController extends DisplayWindowPolicyController
if (super.isEnteringPipAllowed(uid)) {
return true;
}
- mHandler.post(() -> {
- mPipBlockedCallback.onEnteringPipBlocked(uid);
- });
+ if (mPipBlockedCallback != null) {
+ mHandler.post(() -> mPipBlockedCallback.onEnteringPipBlocked(uid));
+ }
return false;
}
@@ -365,54 +376,13 @@ public class GenericWindowPolicyController extends DisplayWindowPolicyController
}
return activityInfo.requiredDisplayCategory != null
&& mDisplayCategories.contains(activityInfo.requiredDisplayCategory);
-
}
- private boolean canContainActivity(ActivityInfo activityInfo, int windowFlags,
- int systemWindowFlags) {
- if ((activityInfo.flags & FLAG_CAN_DISPLAY_ON_REMOTE_DEVICES) == 0) {
- return false;
- }
- ComponentName activityComponent = activityInfo.getComponentName();
- if (BLOCKED_APP_STREAMING_COMPONENT.equals(activityComponent)) {
- // The error dialog alerting users that streaming is blocked is always allowed. Need to
- // run before the clauses below to ensure error dialog always shows up.
- return true;
- }
- if (!activityMatchesDisplayCategory(activityInfo)) {
- Slog.d(TAG, String.format(
- "The activity's required display category: %s is not found on virtual display"
- + " with the following categories: %s",
- activityInfo.requiredDisplayCategory, mDisplayCategories.toString()));
- return false;
- }
- final UserHandle activityUser =
- UserHandle.getUserHandleForUid(activityInfo.applicationInfo.uid);
- if (!mAllowedUsers.contains(activityUser)) {
- Slog.d(TAG, "Virtual device activity not allowed from user " + activityUser);
- return false;
- }
- if (mDefaultActivityPolicy == VirtualDeviceParams.ACTIVITY_POLICY_DEFAULT_ALLOWED
- && mBlockedActivities.contains(activityComponent)) {
- Slog.d(TAG, "Virtual device blocking launch of " + activityComponent);
- return false;
- }
- if (mDefaultActivityPolicy == VirtualDeviceParams.ACTIVITY_POLICY_DEFAULT_BLOCKED
- && !mAllowedActivities.contains(activityComponent)) {
- Slog.d(TAG, activityComponent + " is not in the allowed list.");
- return false;
- }
- if (!CompatChanges.isChangeEnabled(ALLOW_SECURE_ACTIVITY_DISPLAY_ON_REMOTE_DEVICE,
- activityInfo.packageName, activityUser)) {
- // TODO(b/201712607): Add checks for the apps that use SurfaceView#setSecure.
- if ((windowFlags & FLAG_SECURE) != 0) {
- return false;
- }
- if ((systemWindowFlags & SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS) != 0) {
- return false;
- }
- }
- return true;
+ private boolean isAllowedByPolicy(boolean allowedByDefault, ArraySet<ComponentName> exceptions,
+ ComponentName component) {
+ // Either allowed and the exceptions do not contain the component,
+ // or disallowed and the exceptions contain the component.
+ return allowedByDefault != exceptions.contains(component);
}
@VisibleForTesting
diff --git a/services/companion/java/com/android/server/companion/virtual/InputController.java b/services/companion/java/com/android/server/companion/virtual/InputController.java
index 307f7bfc1fd5..eeaa423b1aef 100644
--- a/services/companion/java/com/android/server/companion/virtual/InputController.java
+++ b/services/companion/java/com/android/server/companion/virtual/InputController.java
@@ -16,6 +16,8 @@
package com.android.server.companion.virtual;
+import static android.text.TextUtils.formatSimple;
+
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.StringDef;
@@ -350,7 +352,7 @@ class InputController {
}
private static String createPhys(@PhysType String type) {
- return String.format("virtual%s:%d", type, sNextPhysId.getAndIncrement());
+ return formatSimple("virtual%s:%d", type, sNextPhysId.getAndIncrement());
}
private void setUniqueIdAssociation(int displayId, String phys) {
diff --git a/services/companion/java/com/android/server/companion/virtual/SensorController.java b/services/companion/java/com/android/server/companion/virtual/SensorController.java
index a831401168af..e9241dddcde9 100644
--- a/services/companion/java/com/android/server/companion/virtual/SensorController.java
+++ b/services/companion/java/com/android/server/companion/virtual/SensorController.java
@@ -323,8 +323,5 @@ public class SensorController {
SensorCreationException(String message) {
super(message);
}
- SensorCreationException(String message, Exception cause) {
- super(message, cause);
- }
}
}
diff --git a/services/companion/java/com/android/server/companion/virtual/VirtualDeviceImpl.java b/services/companion/java/com/android/server/companion/virtual/VirtualDeviceImpl.java
index f23fe2a7bce4..8f765e4b79d6 100644
--- a/services/companion/java/com/android/server/companion/virtual/VirtualDeviceImpl.java
+++ b/services/companion/java/com/android/server/companion/virtual/VirtualDeviceImpl.java
@@ -19,12 +19,17 @@ package com.android.server.companion.virtual;
import static android.app.admin.DevicePolicyManager.NEARBY_STREAMING_ENABLED;
import static android.app.admin.DevicePolicyManager.NEARBY_STREAMING_NOT_CONTROLLED_BY_POLICY;
import static android.app.admin.DevicePolicyManager.NEARBY_STREAMING_SAME_MANAGED_ACCOUNT_ONLY;
+import static android.companion.virtual.VirtualDeviceParams.ACTIVITY_POLICY_DEFAULT_ALLOWED;
+import static android.companion.virtual.VirtualDeviceParams.DEVICE_POLICY_DEFAULT;
+import static android.companion.virtual.VirtualDeviceParams.NAVIGATION_POLICY_DEFAULT_ALLOWED;
+import static android.companion.virtual.VirtualDeviceParams.POLICY_TYPE_RECENTS;
import static android.view.WindowManager.LayoutParams.FLAG_SECURE;
import static android.view.WindowManager.LayoutParams.SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS;
import android.annotation.EnforcePermission;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.RequiresPermission;
import android.annotation.StringRes;
import android.annotation.UserIdInt;
import android.app.Activity;
@@ -36,11 +41,13 @@ import android.companion.virtual.IVirtualDevice;
import android.companion.virtual.IVirtualDeviceActivityListener;
import android.companion.virtual.IVirtualDeviceIntentInterceptor;
import android.companion.virtual.IVirtualDeviceSoundEffectListener;
+import android.companion.virtual.VirtualDevice;
import android.companion.virtual.VirtualDeviceManager;
import android.companion.virtual.VirtualDeviceManager.ActivityListener;
import android.companion.virtual.VirtualDeviceParams;
import android.companion.virtual.audio.IAudioConfigChangedCallback;
import android.companion.virtual.audio.IAudioRoutingCallback;
+import android.companion.virtual.flags.Flags;
import android.companion.virtual.sensor.VirtualSensor;
import android.companion.virtual.sensor.VirtualSensorEvent;
import android.content.AttributionSource;
@@ -78,12 +85,15 @@ import android.os.UserHandle;
import android.os.UserManager;
import android.util.ArrayMap;
import android.util.ArraySet;
+import android.util.IntArray;
import android.util.Slog;
import android.util.SparseArray;
+import android.util.SparseIntArray;
import android.view.Display;
import android.view.WindowManager;
import android.widget.Toast;
+
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.app.BlockedAppStreamingActivity;
@@ -93,7 +103,6 @@ import com.android.server.companion.virtual.audio.VirtualAudioController;
import java.io.FileDescriptor;
import java.io.PrintWriter;
-import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
@@ -128,8 +137,8 @@ final class VirtualDeviceImpl extends IVirtualDevice.Stub
private final int mOwnerUid;
private final VirtualDeviceLog mVirtualDeviceLog;
private final String mOwnerPackageName;
- private int mDeviceId;
- private @Nullable String mPersistentDeviceId;
+ private final int mDeviceId;
+ private @Nullable final String mPersistentDeviceId;
// Thou shall not hold the mVirtualDeviceLock over the mInputController calls.
// Holding the lock can lead to lock inversion with GlobalWindowManagerLock.
// 1. After display is created the window manager calls into VDM during construction
@@ -145,6 +154,8 @@ final class VirtualDeviceImpl extends IVirtualDevice.Stub
private final IBinder mAppToken;
private final VirtualDeviceParams mParams;
@GuardedBy("mVirtualDeviceLock")
+ private final SparseIntArray mDevicePolicies;
+ @GuardedBy("mVirtualDeviceLock")
private final SparseArray<VirtualDisplayWrapper> mVirtualDisplays = new SparseArray<>();
private final IVirtualDeviceActivityListener mActivityListener;
private final IVirtualDeviceSoundEffectListener mSoundEffectListener;
@@ -152,7 +163,7 @@ final class VirtualDeviceImpl extends IVirtualDevice.Stub
@GuardedBy("mVirtualDeviceLock")
private final Map<IBinder, IntentFilter> mIntentInterceptors = new ArrayMap<>();
@NonNull
- private Consumer<ArraySet<Integer>> mRunningAppsChangedCallback;
+ private final Consumer<ArraySet<Integer>> mRunningAppsChangedCallback;
// The default setting for showing the pointer on new displays.
@GuardedBy("mVirtualDeviceLock")
private boolean mDefaultShowPointerIcon = true;
@@ -160,6 +171,9 @@ final class VirtualDeviceImpl extends IVirtualDevice.Stub
@Nullable
private LocaleList mLocaleList = null;
+ @NonNull
+ private final VirtualDevice mPublicVirtualDeviceObject;
+
private ActivityListener createListenerAdapter() {
return new ActivityListener() {
@@ -259,6 +273,7 @@ final class VirtualDeviceImpl extends IVirtualDevice.Stub
mDeviceId = deviceId;
mAppToken = token;
mParams = params;
+ mDevicePolicies = params.getDevicePolicies();
mDisplayManager = displayManager;
if (inputController == null) {
mInputController = new InputController(
@@ -277,6 +292,9 @@ final class VirtualDeviceImpl extends IVirtualDevice.Stub
throw e.rethrowFromSystemServer();
}
mVirtualDeviceLog.logCreated(deviceId, mOwnerUid);
+
+ mPublicVirtualDeviceObject = new VirtualDevice(
+ this, getDeviceId(), getPersistentDeviceId(), mParams.getName());
}
@VisibleForTesting
@@ -306,9 +324,9 @@ final class VirtualDeviceImpl extends IVirtualDevice.Stub
return mAssociationInfo.getDisplayName();
}
- /** Returns the optional name of the device. */
- String getDeviceName() {
- return mParams.getName();
+ /** Returns the public representation of the device. */
+ VirtualDevice getPublicVirtualDeviceObject() {
+ return mPublicVirtualDeviceObject;
}
/** Returns the locale of the device. */
@@ -318,10 +336,16 @@ final class VirtualDeviceImpl extends IVirtualDevice.Stub
}
}
- /** Returns the policy specified for this policy type */
+ @Override // Binder call
public @VirtualDeviceParams.DevicePolicy int getDevicePolicy(
@VirtualDeviceParams.PolicyType int policyType) {
- return mParams.getDevicePolicy(policyType);
+ if (Flags.dynamicPolicy()) {
+ synchronized (mVirtualDeviceLock) {
+ return mDevicePolicies.get(policyType, DEVICE_POLICY_DEFAULT);
+ }
+ } else {
+ return mParams.getDevicePolicy(policyType);
+ }
}
/** Returns device-specific audio session id for playback. */
@@ -410,15 +434,13 @@ final class VirtualDeviceImpl extends IVirtualDevice.Stub
public void close() {
super.close_enforcePermission();
// Remove about-to-be-closed virtual device from the service before butchering it.
- boolean removed = mService.removeVirtualDevice(mDeviceId);
- mVirtualDeviceLog.logClosed(mDeviceId, mOwnerUid);
- mDeviceId = Context.DEVICE_ID_INVALID;
-
- // Device is already closed.
- if (!removed) {
+ if (!mService.removeVirtualDevice(mDeviceId)) {
+ // Device is already closed.
return;
}
+ mVirtualDeviceLog.logClosed(mDeviceId, mOwnerUid);
+
final long ident = Binder.clearCallingIdentity();
try {
VirtualDisplayWrapper[] virtualDisplaysToBeReleased;
@@ -460,6 +482,7 @@ final class VirtualDeviceImpl extends IVirtualDevice.Stub
}
@Override
+ @RequiresPermission(android.Manifest.permission.CAMERA_INJECT_EXTERNAL_CAMERA)
public void onRunningAppsChanged(ArraySet<Integer> runningUids) {
mCameraAccessController.blockCameraAccessIfNeeded(runningUids);
mRunningAppsChangedCallback.accept(runningUids);
@@ -507,6 +530,27 @@ final class VirtualDeviceImpl extends IVirtualDevice.Stub
@Override // Binder call
@EnforcePermission(android.Manifest.permission.CREATE_VIRTUAL_DEVICE)
+ public void setDevicePolicy(@VirtualDeviceParams.DynamicPolicyType int policyType,
+ @VirtualDeviceParams.DevicePolicy int devicePolicy) {
+ super.setDevicePolicy_enforcePermission();
+ switch (policyType) {
+ case POLICY_TYPE_RECENTS:
+ synchronized (mVirtualDeviceLock) {
+ mDevicePolicies.put(policyType, devicePolicy);
+ for (int i = 0; i < mVirtualDisplays.size(); i++) {
+ mVirtualDisplays.valueAt(i).getWindowPolicyController()
+ .setShowInHostDeviceRecents(devicePolicy == DEVICE_POLICY_DEFAULT);
+ }
+ }
+ break;
+ default:
+ throw new IllegalArgumentException("Device policy " + policyType
+ + " cannot be changed at runtime. ");
+ }
+ }
+
+ @Override // Binder call
+ @EnforcePermission(android.Manifest.permission.CREATE_VIRTUAL_DEVICE)
public void createVirtualDpad(VirtualDpadConfig config, @NonNull IBinder deviceToken) {
super.createVirtualDpad_enforcePermission();
Objects.requireNonNull(config);
@@ -718,10 +762,10 @@ final class VirtualDeviceImpl extends IVirtualDevice.Stub
try {
synchronized (mVirtualDeviceLock) {
mDefaultShowPointerIcon = showPointerIcon;
- for (int i = 0; i < mVirtualDisplays.size(); i++) {
- final int displayId = mVirtualDisplays.keyAt(i);
- mInputController.setShowPointerIcon(mDefaultShowPointerIcon, displayId);
- }
+ }
+ final int[] displayIds = getDisplayIds();
+ for (int i = 0; i < displayIds.length; ++i) {
+ mInputController.setShowPointerIcon(showPointerIcon, displayIds[i]);
}
} finally {
Binder.restoreCallingIdentity(ident);
@@ -786,6 +830,7 @@ final class VirtualDeviceImpl extends IVirtualDevice.Stub
mParams.dump(fout, " ");
fout.println(" mVirtualDisplayIds: ");
synchronized (mVirtualDeviceLock) {
+ fout.println(" mDevicePolicies: " + mDevicePolicies);
for (int i = 0; i < mVirtualDisplays.size(); i++) {
fout.println(" " + mVirtualDisplays.keyAt(i));
}
@@ -797,24 +842,31 @@ final class VirtualDeviceImpl extends IVirtualDevice.Stub
private GenericWindowPolicyController createWindowPolicyController(
@NonNull Set<String> displayCategories) {
- final GenericWindowPolicyController gwpc =
- new GenericWindowPolicyController(FLAG_SECURE,
- SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS,
- getAllowedUserHandles(),
- mParams.getAllowedCrossTaskNavigations(),
- mParams.getBlockedCrossTaskNavigations(),
- mParams.getAllowedActivities(),
- mParams.getBlockedActivities(),
- mParams.getDefaultActivityPolicy(),
- createListenerAdapter(),
- this::onEnteringPipBlocked,
- this::onActivityBlocked,
- this::onSecureWindowShown,
- this::shouldInterceptIntent,
- displayCategories,
- mParams.getDevicePolicy(
- VirtualDeviceParams.POLICY_TYPE_RECENTS)
- == VirtualDeviceParams.DEVICE_POLICY_DEFAULT);
+ final boolean activityLaunchAllowedByDefault =
+ mParams.getDefaultActivityPolicy() == ACTIVITY_POLICY_DEFAULT_ALLOWED;
+ final boolean crossTaskNavigationAllowedByDefault =
+ mParams.getDefaultNavigationPolicy() == NAVIGATION_POLICY_DEFAULT_ALLOWED;
+ final boolean showTasksInHostDeviceRecents =
+ mParams.getDevicePolicy(POLICY_TYPE_RECENTS) == DEVICE_POLICY_DEFAULT;
+
+ final GenericWindowPolicyController gwpc = new GenericWindowPolicyController(
+ FLAG_SECURE,
+ SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS,
+ getAllowedUserHandles(),
+ activityLaunchAllowedByDefault,
+ /*activityPolicyExceptions=*/activityLaunchAllowedByDefault
+ ? mParams.getBlockedActivities() : mParams.getAllowedActivities(),
+ crossTaskNavigationAllowedByDefault,
+ /*crossTaskNavigationExceptions=*/crossTaskNavigationAllowedByDefault
+ ? mParams.getBlockedCrossTaskNavigations()
+ : mParams.getAllowedCrossTaskNavigations(),
+ createListenerAdapter(),
+ this::onEnteringPipBlocked,
+ this::onActivityBlocked,
+ this::onSecureWindowShown,
+ this::shouldInterceptIntent,
+ displayCategories,
+ showTasksInHostDeviceRecents);
gwpc.registerRunningAppsChangedListener(/* listener= */ this);
return gwpc;
}
@@ -830,6 +882,7 @@ final class VirtualDeviceImpl extends IVirtualDevice.Stub
this, gwpc, packageName);
gwpc.setDisplayId(displayId);
+ boolean showPointer;
synchronized (mVirtualDeviceLock) {
if (mVirtualDisplays.contains(displayId)) {
gwpc.unregisterRunningAppsChangedListener(this);
@@ -839,11 +892,12 @@ final class VirtualDeviceImpl extends IVirtualDevice.Stub
PowerManager.WakeLock wakeLock = createAndAcquireWakeLockForDisplay(displayId);
mVirtualDisplays.put(displayId, new VirtualDisplayWrapper(callback, gwpc, wakeLock));
+ showPointer = mDefaultShowPointerIcon;
}
final long token = Binder.clearCallingIdentity();
try {
- mInputController.setShowPointerIcon(mDefaultShowPointerIcon, displayId);
+ mInputController.setShowPointerIcon(showPointer, displayId);
mInputController.setPointerAcceleration(1f, displayId);
mInputController.setDisplayEligibilityForPointerCapture(/* isEligible= */ false,
displayId);
@@ -869,6 +923,7 @@ final class VirtualDeviceImpl extends IVirtualDevice.Stub
}
}
+ @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS)
private void onActivityBlocked(int displayId, ActivityInfo activityInfo) {
Intent intent = BlockedAppStreamingActivity.createIntent(
activityInfo, mAssociationInfo.getDisplayName());
@@ -950,6 +1005,7 @@ final class VirtualDeviceImpl extends IVirtualDevice.Stub
}
}
+ @SuppressWarnings("AndroidFrameworkRequiresPermission")
private void checkVirtualInputDeviceDisplayIdAssociation(int displayId) {
if (mContext.checkCallingPermission(android.Manifest.permission.INJECT_EVENTS)
== PackageManager.PERMISSION_GRANTED) {
@@ -982,14 +1038,15 @@ final class VirtualDeviceImpl extends IVirtualDevice.Stub
return mOwnerUid;
}
- ArraySet<Integer> getDisplayIds() {
+ @Override // Binder call
+ public int[] getDisplayIds() {
synchronized (mVirtualDeviceLock) {
final int size = mVirtualDisplays.size();
- ArraySet<Integer> arraySet = new ArraySet<>(size);
+ int[] displayIds = new int[size];
for (int i = 0; i < size; i++) {
- arraySet.append(mVirtualDisplays.keyAt(i));
+ displayIds[i] = mVirtualDisplays.keyAt(i);
}
- return arraySet;
+ return displayIds;
}
}
@@ -1031,8 +1088,8 @@ final class VirtualDeviceImpl extends IVirtualDevice.Stub
*/
void showToastWhereUidIsRunning(int uid, String text, @Toast.Duration int duration,
Looper looper) {
- ArrayList<Integer> displayIdsForUid = getDisplayIdsWhereUidIsRunning(uid);
- if (displayIdsForUid.isEmpty()) {
+ IntArray displayIdsForUid = getDisplayIdsWhereUidIsRunning(uid);
+ if (displayIdsForUid.size() == 0) {
return;
}
DisplayManager displayManager = mContext.getSystemService(DisplayManager.class);
@@ -1045,8 +1102,8 @@ final class VirtualDeviceImpl extends IVirtualDevice.Stub
}
}
- private ArrayList<Integer> getDisplayIdsWhereUidIsRunning(int uid) {
- ArrayList<Integer> displayIdsForUid = new ArrayList<>();
+ private IntArray getDisplayIdsWhereUidIsRunning(int uid) {
+ IntArray displayIdsForUid = new IntArray();
synchronized (mVirtualDeviceLock) {
for (int i = 0; i < mVirtualDisplays.size(); i++) {
if (mVirtualDisplays.valueAt(i).getWindowPolicyController().containsUid(uid)) {
diff --git a/services/companion/java/com/android/server/companion/virtual/VirtualDeviceManagerService.java b/services/companion/java/com/android/server/companion/virtual/VirtualDeviceManagerService.java
index 7429fbe18a0c..cfe56e910b8a 100644
--- a/services/companion/java/com/android/server/companion/virtual/VirtualDeviceManagerService.java
+++ b/services/companion/java/com/android/server/companion/virtual/VirtualDeviceManagerService.java
@@ -23,17 +23,20 @@ import static com.android.server.wm.ActivityInterceptorCallback.VIRTUAL_DEVICE_S
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.RequiresPermission;
import android.annotation.SuppressLint;
import android.app.ActivityOptions;
import android.companion.AssociationInfo;
import android.companion.CompanionDeviceManager;
import android.companion.virtual.IVirtualDevice;
import android.companion.virtual.IVirtualDeviceActivityListener;
+import android.companion.virtual.IVirtualDeviceListener;
import android.companion.virtual.IVirtualDeviceManager;
import android.companion.virtual.IVirtualDeviceSoundEffectListener;
import android.companion.virtual.VirtualDevice;
import android.companion.virtual.VirtualDeviceManager;
import android.companion.virtual.VirtualDeviceParams;
+import android.companion.virtual.flags.Flags;
import android.companion.virtual.sensor.VirtualSensor;
import android.content.AttributionSource;
import android.content.Context;
@@ -47,6 +50,7 @@ import android.os.LocaleList;
import android.os.Looper;
import android.os.Parcel;
import android.os.Process;
+import android.os.RemoteCallbackList;
import android.os.RemoteException;
import android.os.UserHandle;
import android.util.ArraySet;
@@ -68,6 +72,7 @@ import com.android.server.wm.ActivityTaskManagerInternal;
import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Objects;
@@ -75,6 +80,7 @@ import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Consumer;
+import java.util.stream.Collectors;
@SuppressLint("LongLogTag")
@@ -95,11 +101,15 @@ public class VirtualDeviceManagerService extends SystemService {
private final CompanionDeviceManager.OnAssociationsChangedListener mCdmAssociationListener =
new CompanionDeviceManager.OnAssociationsChangedListener() {
@Override
+ @RequiresPermission(android.Manifest.permission.CREATE_VIRTUAL_DEVICE)
public void onAssociationsChanged(@NonNull List<AssociationInfo> associations) {
syncVirtualDevicesToCdmAssociations(associations);
}
};
+ private final RemoteCallbackList<IVirtualDeviceListener> mVirtualDeviceListeners =
+ new RemoteCallbackList<>();
+
/**
* Mapping from device IDs to virtual devices.
*/
@@ -222,6 +232,17 @@ public class VirtualDeviceManagerService extends SystemService {
mVirtualDevices.remove(deviceId);
}
+ if (Flags.vdmPublicApis()) {
+ mVirtualDeviceListeners.broadcast(listener -> {
+ try {
+ listener.onVirtualDeviceClosed(deviceId);
+ } catch (RemoteException e) {
+ Slog.i(TAG, "Failed to invoke onVirtualDeviceClosed listener: "
+ + e.getMessage());
+ }
+ });
+ }
+
Intent i = new Intent(VirtualDeviceManager.ACTION_VIRTUAL_DEVICE_REMOVED);
i.putExtra(VirtualDeviceManager.EXTRA_VIRTUAL_DEVICE_ID, deviceId);
i.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
@@ -240,6 +261,7 @@ public class VirtualDeviceManagerService extends SystemService {
return true;
}
+ @RequiresPermission(android.Manifest.permission.CREATE_VIRTUAL_DEVICE)
private void syncVirtualDevicesToCdmAssociations(List<AssociationInfo> associations) {
Set<VirtualDeviceImpl> virtualDevicesToRemove = new HashSet<>();
synchronized (mVirtualDeviceManagerLock) {
@@ -265,6 +287,7 @@ public class VirtualDeviceManagerService extends SystemService {
}
}
+ @RequiresPermission(android.Manifest.permission.MANAGE_COMPANION_DEVICES)
private void registerCdmAssociationListener() {
final CompanionDeviceManager cdm = getContext().getSystemService(
CompanionDeviceManager.class);
@@ -272,6 +295,7 @@ public class VirtualDeviceManagerService extends SystemService {
mCdmAssociationListener);
}
+ @RequiresPermission(android.Manifest.permission.MANAGE_COMPANION_DEVICES)
private void unregisterCdmAssociationListener() {
final CompanionDeviceManager cdm = getContext().getSystemService(
CompanionDeviceManager.class);
@@ -323,6 +347,15 @@ public class VirtualDeviceManagerService extends SystemService {
@NonNull IVirtualDeviceSoundEffectListener soundEffectListener) {
createVirtualDevice_enforcePermission();
attributionSource.enforceCallingUid();
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ if (Flags.moreLogs()) {
+ Slog.i(TAG, "Creating VirtualDevice");
+ }
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+
final int callingUid = getCallingUid();
final String packageName = attributionSource.getPackageName();
if (!PermissionUtils.validateCallingPackageName(getContext(), packageName)) {
@@ -361,6 +394,17 @@ public class VirtualDeviceManagerService extends SystemService {
}
mVirtualDevices.put(deviceId, virtualDevice);
}
+
+ if (Flags.vdmPublicApis()) {
+ mVirtualDeviceListeners.broadcast(listener -> {
+ try {
+ listener.onVirtualDeviceCreated(deviceId);
+ } catch (RemoteException e) {
+ Slog.i(TAG, "Failed to invoke onVirtualDeviceCreated listener: "
+ + e.getMessage());
+ }
+ });
+ }
return virtualDevice;
}
@@ -400,14 +444,31 @@ public class VirtualDeviceManagerService extends SystemService {
synchronized (mVirtualDeviceManagerLock) {
for (int i = 0; i < mVirtualDevices.size(); i++) {
final VirtualDeviceImpl device = mVirtualDevices.valueAt(i);
- virtualDevices.add(
- new VirtualDevice(device.getDeviceId(), device.getPersistentDeviceId(),
- device.getDeviceName()));
+ virtualDevices.add(device.getPublicVirtualDeviceObject());
}
}
return virtualDevices;
}
+ @Override // Binder call
+ public VirtualDevice getVirtualDevice(int deviceId) {
+ VirtualDeviceImpl device;
+ synchronized (mVirtualDeviceManagerLock) {
+ device = mVirtualDevices.get(deviceId);
+ }
+ return device == null ? null : device.getPublicVirtualDeviceObject();
+ }
+
+ @Override // Binder call
+ public void registerVirtualDeviceListener(IVirtualDeviceListener listener) {
+ mVirtualDeviceListeners.register(listener);
+ }
+
+ @Override // Binder call
+ public void unregisterVirtualDeviceListener(IVirtualDeviceListener listener) {
+ mVirtualDeviceListeners.unregister(listener);
+ }
+
@Override // BinderCall
@VirtualDeviceParams.DevicePolicy
public int getDevicePolicy(int deviceId, @VirtualDeviceParams.PolicyType int policyType) {
@@ -690,7 +751,9 @@ public class VirtualDeviceManagerService extends SystemService {
synchronized (mVirtualDeviceManagerLock) {
virtualDevice = mVirtualDevices.get(deviceId);
}
- return virtualDevice == null ? new ArraySet<>() : virtualDevice.getDisplayIds();
+ return virtualDevice == null ? new ArraySet<>()
+ : Arrays.stream(virtualDevice.getDisplayIds()).boxed()
+ .collect(Collectors.toCollection(ArraySet::new));
}
@Override
diff --git a/services/companion/java/com/android/server/companion/virtual/flags.aconfig b/services/companion/java/com/android/server/companion/virtual/flags.aconfig
index 4fe4c870a283..6297e91e8705 100644
--- a/services/companion/java/com/android/server/companion/virtual/flags.aconfig
+++ b/services/companion/java/com/android/server/companion/virtual/flags.aconfig
@@ -1,3 +1,5 @@
+# OLD PACKAGE, DO NOT USE: Prefer `flags.aconfig` in core/java/android/companion/virtual
+# (or other custom files) to define your flags
package: "com.android.server.companion.virtual"
flag {
diff --git a/services/core/java/android/content/pm/PackageManagerInternal.java b/services/core/java/android/content/pm/PackageManagerInternal.java
index 557e4ac843d2..838aae8a83c0 100644
--- a/services/core/java/android/content/pm/PackageManagerInternal.java
+++ b/services/core/java/android/content/pm/PackageManagerInternal.java
@@ -1409,4 +1409,10 @@ public abstract class PackageManagerInternal {
*/
public abstract boolean isPackageQuarantined(@NonNull String packageName,
@UserIdInt int userId);
+
+ /**
+ * Return a list of all historical install sessions for the given user.
+ */
+ public abstract ParceledListSlice<PackageInstaller.SessionInfo> getHistoricalSessions(
+ int userId);
}
diff --git a/services/core/java/com/android/server/LogMteState.java b/services/core/java/com/android/server/LogMteState.java
index 410dd8339b30..ec0492b19f89 100644
--- a/services/core/java/com/android/server/LogMteState.java
+++ b/services/core/java/com/android/server/LogMteState.java
@@ -16,11 +16,12 @@
package com.android.server;
+import static com.android.internal.util.ConcurrentUtils.DIRECT_EXECUTOR;
+
import android.app.StatsManager;
import android.content.Context;
import android.util.StatsEvent;
-import com.android.internal.os.BackgroundThread;
import com.android.internal.os.Zygote;
import com.android.internal.util.FrameworkStatsLog;
@@ -32,7 +33,7 @@ public class LogMteState {
.setPullAtomCallback(
FrameworkStatsLog.MTE_STATE,
null, // use default PullAtomMetadata values
- BackgroundThread.getExecutor(),
+ DIRECT_EXECUTOR,
new StatsManager.StatsPullAtomCallback() {
@Override
public int onPullAtom(int atomTag, List<StatsEvent> data) {
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index bf9cdbec7b0c..0d265a0f4c4a 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -3852,15 +3852,16 @@ public class ActivityManagerService extends IActivityManager.Stub
@Override
public void forceStopPackage(final String packageName, int userId) {
- forceStopPackage(packageName, userId, /*flags=*/ 0);
+ forceStopPackage(packageName, userId, /*flags=*/ 0, null);
}
@Override
public void forceStopPackageEvenWhenStopping(final String packageName, int userId) {
- forceStopPackage(packageName, userId, ActivityManager.FLAG_OR_STOPPED);
+ forceStopPackage(packageName, userId, ActivityManager.FLAG_OR_STOPPED, null);
}
- private void forceStopPackage(final String packageName, int userId, int userRunningFlags) {
+ private void forceStopPackage(final String packageName, int userId, int userRunningFlags,
+ String reason) {
if (checkCallingPermission(android.Manifest.permission.FORCE_STOP_PACKAGES)
!= PackageManager.PERMISSION_GRANTED) {
String msg = "Permission Denial: forceStopPackage() from pid="
@@ -3905,7 +3906,8 @@ public class ActivityManagerService extends IActivityManager.Stub
+ packageName + ": " + e);
}
if (mUserController.isUserRunning(user, userRunningFlags)) {
- forceStopPackageLocked(packageName, pkgUid, "from pid " + callingPid);
+ forceStopPackageLocked(packageName, pkgUid,
+ reason == null ? ("from pid " + callingPid) : reason);
finishForceStopPackageLocked(packageName, pkgUid);
}
}
@@ -5444,6 +5446,19 @@ public class ActivityManagerService extends IActivityManager.Stub
intent = new Intent(Intent.ACTION_MAIN);
}
try {
+ if (allowlistToken != null) {
+ final int callingUid = Binder.getCallingUid();
+ final String packageName;
+ final long token = Binder.clearCallingIdentity();
+ try {
+ packageName = AppGlobals.getPackageManager().getNameForUid(callingUid);
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ Slog.wtf(TAG, "Send a non-null allowlistToken to a non-PI target."
+ + " Calling package: " + packageName + "; intent: " + intent
+ + "; options: " + options);
+ }
target.send(code, intent, resolvedType, allowlistToken, null,
requiredPermission, options);
} catch (RemoteException e) {
@@ -14898,8 +14913,8 @@ public class ActivityManagerService extends IActivityManager.Stub
Intent.EXTRA_QUARANTINED, false);
if (suspended && quarantined && packageNames != null) {
for (int i = 0; i < packageNames.length; i++) {
- forceStopPackageLocked(packageNames[i], -1, false, true, true,
- false, false, userId, "suspended");
+ forceStopPackage(packageNames[i], userId,
+ ActivityManager.FLAG_OR_STOPPED, "quarantined");
}
}
diff --git a/services/core/java/com/android/server/am/BatteryStatsService.java b/services/core/java/com/android/server/am/BatteryStatsService.java
index 610b8af48cd1..2249607863d5 100644
--- a/services/core/java/com/android/server/am/BatteryStatsService.java
+++ b/services/core/java/com/android/server/am/BatteryStatsService.java
@@ -27,9 +27,12 @@ import static android.net.NetworkCapabilities.TRANSPORT_WIFI;
import static android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK;
import static android.os.BatteryStats.POWER_DATA_UNAVAILABLE;
+import static com.android.internal.util.ConcurrentUtils.DIRECT_EXECUTOR;
+
import android.annotation.EnforcePermission;
import android.annotation.NonNull;
import android.annotation.RequiresNoPermission;
+import android.annotation.SuppressLint;
import android.app.StatsManager;
import android.app.usage.NetworkStatsManager;
import android.bluetooth.BluetoothActivityEnergyInfo;
@@ -81,6 +84,7 @@ import android.os.health.HealthStatsParceler;
import android.os.health.HealthStatsWriter;
import android.os.health.UidHealthStats;
import android.power.PowerStatsInternal;
+import android.provider.DeviceConfig;
import android.provider.Settings;
import android.telephony.DataConnectionRealTimeInfo;
import android.telephony.ModemActivityInfo;
@@ -94,7 +98,6 @@ import android.util.StatsEvent;
import com.android.internal.R;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.app.IBatteryStats;
-import com.android.internal.os.BackgroundThread;
import com.android.internal.os.BinderCallsStats;
import com.android.internal.os.CpuScalingPolicies;
import com.android.internal.os.CpuScalingPolicyReader;
@@ -174,6 +177,7 @@ public final class BatteryStatsService extends IBatteryStats.Stub
.replaceWith("?");
private static final int MAX_LOW_POWER_STATS_SIZE = 32768;
private static final int POWER_STATS_QUERY_TIMEOUT_MILLIS = 2000;
+ private static final String MIN_CONSUMED_POWER_THRESHOLD_KEY = "min_consumed_power_threshold";
private static final String EMPTY = "Empty";
private final HandlerThread mHandlerThread;
@@ -844,15 +848,15 @@ public final class BatteryStatsService extends IBatteryStats.Stub
statsManager.setPullAtomCallback(
FrameworkStatsLog.BATTERY_USAGE_STATS_SINCE_RESET,
null, // use default PullAtomMetadata values
- BackgroundThread.getExecutor(), pullAtomCallback);
+ DIRECT_EXECUTOR, pullAtomCallback);
statsManager.setPullAtomCallback(
FrameworkStatsLog.BATTERY_USAGE_STATS_SINCE_RESET_USING_POWER_PROFILE_MODEL,
null, // use default PullAtomMetadata values
- BackgroundThread.getExecutor(), pullAtomCallback);
+ DIRECT_EXECUTOR, pullAtomCallback);
statsManager.setPullAtomCallback(
FrameworkStatsLog.BATTERY_USAGE_STATS_BEFORE_RESET,
null, // use default PullAtomMetadata values
- BackgroundThread.getExecutor(), pullAtomCallback);
+ DIRECT_EXECUTOR, pullAtomCallback);
}
/** StatsPullAtomCallback for pulling BatteryUsageStats data. */
@@ -862,12 +866,17 @@ public final class BatteryStatsService extends IBatteryStats.Stub
final BatteryUsageStats bus;
switch (atomTag) {
case FrameworkStatsLog.BATTERY_USAGE_STATS_SINCE_RESET:
+ @SuppressLint("MissingPermission")
+ final double minConsumedPowerThreshold =
+ DeviceConfig.getFloat(DeviceConfig.NAMESPACE_BATTERY_STATS,
+ MIN_CONSUMED_POWER_THRESHOLD_KEY, 0);
final BatteryUsageStatsQuery querySinceReset =
new BatteryUsageStatsQuery.Builder()
.setMaxStatsAgeMs(0)
.includeProcessStateData()
.includeVirtualUids()
.includePowerModels()
+ .setMinConsumedPowerThreshold(minConsumedPowerThreshold)
.build();
bus = getBatteryUsageStats(List.of(querySinceReset)).get(0);
break;
diff --git a/services/core/java/com/android/server/am/ContentProviderHelper.java b/services/core/java/com/android/server/am/ContentProviderHelper.java
index 9219623a031d..095d907d7df6 100644
--- a/services/core/java/com/android/server/am/ContentProviderHelper.java
+++ b/services/core/java/com/android/server/am/ContentProviderHelper.java
@@ -1975,9 +1975,10 @@ public class ContentProviderHelper {
return mProviderMap.dumpProviderProto(fd, pw, name, args);
}
- private Boolean isAuthorityRedirectedForCloneProfileCached(String auth) {
+ private boolean isAuthorityRedirectedForCloneProfileCached(String auth) {
if (mCloneProfileAuthorityRedirectionCache.containsKey(auth)) {
- return mCloneProfileAuthorityRedirectionCache.get(auth);
+ final Boolean retVal = mCloneProfileAuthorityRedirectionCache.get(auth);
+ return retVal == null ? false : retVal.booleanValue();
} else {
boolean isAuthRedirected = isAuthorityRedirectedForCloneProfile(auth);
mCloneProfileAuthorityRedirectionCache.put(auth, isAuthRedirected);
diff --git a/services/core/java/com/android/server/am/SettingsToPropertiesMapper.java b/services/core/java/com/android/server/am/SettingsToPropertiesMapper.java
index 36b8283dd3a1..bbda952970ae 100644
--- a/services/core/java/com/android/server/am/SettingsToPropertiesMapper.java
+++ b/services/core/java/com/android/server/am/SettingsToPropertiesMapper.java
@@ -117,20 +117,21 @@ public class SettingsToPropertiesMapper {
// All the aconfig flags under the listed DeviceConfig scopes will be synced to native level.
@VisibleForTesting
static final String[] sDeviceConfigAconfigScopes = new String[] {
- "core_experiments_team_internal",
- "camera_platform",
- "power",
- "vibrator",
- "haptics",
- "text",
- "arc_next",
- "test_suites",
- "hardware_backed_security_mainline",
- "threadnetwork",
- "media_solutions",
- "responsible_apis",
- "rust",
- "pixel_biometrics",
+ "biometrics_framework",
+ "core_experiments_team_internal",
+ "camera_platform",
+ "power",
+ "vibrator",
+ "haptics",
+ "text",
+ "arc_next",
+ "test_suites",
+ "hardware_backed_security_mainline",
+ "threadnetwork",
+ "media_solutions",
+ "responsible_apis",
+ "rust",
+ "pixel_biometrics",
};
private final String[] mGlobalSettings;
diff --git a/services/core/java/com/android/server/app/GameManagerService.java b/services/core/java/com/android/server/app/GameManagerService.java
index 81397b4d1e9f..905589f70dc1 100644
--- a/services/core/java/com/android/server/app/GameManagerService.java
+++ b/services/core/java/com/android/server/app/GameManagerService.java
@@ -25,6 +25,7 @@ import static com.android.internal.R.styleable.GameModeConfig_allowGameDownscali
import static com.android.internal.R.styleable.GameModeConfig_allowGameFpsOverride;
import static com.android.internal.R.styleable.GameModeConfig_supportsBatteryGameMode;
import static com.android.internal.R.styleable.GameModeConfig_supportsPerformanceGameMode;
+import static com.android.internal.util.ConcurrentUtils.DIRECT_EXECUTOR;
import android.Manifest;
import android.annotation.NonNull;
@@ -2087,17 +2088,17 @@ public final class GameManagerService extends IGameManagerService.Stub {
statsManager.setPullAtomCallback(
FrameworkStatsLog.GAME_MODE_INFO,
null, // use default PullAtomMetadata values
- BackgroundThread.getExecutor(),
+ DIRECT_EXECUTOR,
this::onPullAtom);
statsManager.setPullAtomCallback(
FrameworkStatsLog.GAME_MODE_CONFIGURATION,
null, // use default PullAtomMetadata values
- BackgroundThread.getExecutor(),
+ DIRECT_EXECUTOR,
this::onPullAtom);
statsManager.setPullAtomCallback(
FrameworkStatsLog.GAME_MODE_LISTENER,
null, // use default PullAtomMetadata values
- BackgroundThread.getExecutor(),
+ DIRECT_EXECUTOR,
this::onPullAtom);
}
diff --git a/services/core/java/com/android/server/appop/AttributedOp.java b/services/core/java/com/android/server/appop/AttributedOp.java
index dcc36bcf6149..0ded75a848ac 100644
--- a/services/core/java/com/android/server/appop/AttributedOp.java
+++ b/services/core/java/com/android/server/appop/AttributedOp.java
@@ -199,28 +199,18 @@ final class AttributedOp {
@AppOpsManager.UidState int uidState, @AppOpsManager.OpFlags int flags,
@AppOpsManager.AttributionFlags
int attributionFlags, int attributionChainId) throws RemoteException {
- started(clientId, proxyUid, proxyPackageName, proxyAttributionTag,
- uidState, flags, /*triggerCallbackIfNeeded*/ true, attributionFlags,
- attributionChainId);
- }
-
- private void started(@NonNull IBinder clientId, int proxyUid,
- @Nullable String proxyPackageName, @Nullable String proxyAttributionTag,
- @AppOpsManager.UidState int uidState, @AppOpsManager.OpFlags int flags,
- boolean triggerCallbackIfNeeded, @AppOpsManager.AttributionFlags int attributionFlags,
- int attributionChainId) throws RemoteException {
startedOrPaused(clientId, proxyUid, proxyPackageName,
- proxyAttributionTag, uidState, flags, triggerCallbackIfNeeded,
- /*triggerCallbackIfNeeded*/ true, attributionFlags, attributionChainId);
+ proxyAttributionTag, uidState, flags, /* triggeredByUidStateChange */ false,
+ /* isStarted */ true, attributionFlags, attributionChainId);
}
@SuppressWarnings("GuardedBy") // Lock is held on mAppOpsService
private void startedOrPaused(@NonNull IBinder clientId, int proxyUid,
@Nullable String proxyPackageName, @Nullable String proxyAttributionTag,
@AppOpsManager.UidState int uidState, @AppOpsManager.OpFlags int flags,
- boolean triggerCallbackIfNeeded, boolean isStarted, @AppOpsManager.AttributionFlags
+ boolean triggeredByUidStateChange, boolean isStarted, @AppOpsManager.AttributionFlags
int attributionFlags, int attributionChainId) throws RemoteException {
- if (triggerCallbackIfNeeded && !parent.isRunning() && isStarted) {
+ if (!triggeredByUidStateChange && !parent.isRunning() && isStarted) {
mAppOpsService.scheduleOpActiveChangedIfNeededLocked(parent.op, parent.uid,
parent.packageName, tag, true, attributionFlags, attributionChainId);
}
@@ -263,19 +253,27 @@ final class AttributedOp {
* @param clientId Id of the finishOp caller
*/
public void finished(@NonNull IBinder clientId) {
- finished(clientId, true);
+ finished(clientId, false);
}
- private void finished(@NonNull IBinder clientId, boolean triggerCallbackIfNeeded) {
- finishOrPause(clientId, triggerCallbackIfNeeded, false);
+ private void finished(@NonNull IBinder clientId, boolean triggeredByUidStateChange) {
+ finishOrPause(clientId, triggeredByUidStateChange, false);
}
/**
* Update state when paused or finished is called. If pausing, it records the op as
* stopping in the HistoricalRegistry, but does not delete it.
+ *
+ * @param triggeredByUidStateChange If {@code true}, then this method operates as usual, except
+ * that {@link AppOpsService#mActiveWatchers} will not be notified. This is currently only
+ * used in {@link #onUidStateChanged(int)}, for the purpose of restarting (i.e.,
+ * finishing then immediately starting again in the new uid state) the AttributedOp. In this
+ * case, the caller is responsible for guaranteeing that either the AttributedOp is started
+ * again or all {@link AppOpsService#mActiveWatchers} are notified that the AttributedOp is
+ * finished.
*/
@SuppressWarnings("GuardedBy") // Lock is held on mAppOpsService
- private void finishOrPause(@NonNull IBinder clientId, boolean triggerCallbackIfNeeded,
+ private void finishOrPause(@NonNull IBinder clientId, boolean triggeredByUidStateChange,
boolean isPausing) {
int indexOfToken = isRunning() ? mInProgressEvents.indexOfKey(clientId) : -1;
if (indexOfToken < 0) {
@@ -320,7 +318,7 @@ final class AttributedOp {
mInProgressEvents = null;
// TODO ntmyren: Also callback for single attribution tag activity changes
- if (triggerCallbackIfNeeded && !parent.isRunning()) {
+ if (!triggeredByUidStateChange && !parent.isRunning()) {
mAppOpsService.scheduleOpActiveChangedIfNeededLocked(parent.op,
parent.uid, parent.packageName, tag, false,
event.getAttributionFlags(), event.getAttributionChainId());
@@ -368,7 +366,7 @@ final class AttributedOp {
@AppOpsManager.AttributionFlags
int attributionFlags, int attributionChainId) throws RemoteException {
startedOrPaused(clientId, proxyUid, proxyPackageName, proxyAttributionTag,
- uidState, flags, true, false, attributionFlags, attributionChainId);
+ uidState, flags, false, false, attributionFlags, attributionChainId);
}
/**
@@ -386,7 +384,7 @@ final class AttributedOp {
for (int i = 0; i < mInProgressEvents.size(); i++) {
InProgressStartOpEvent event = mInProgressEvents.valueAt(i);
mPausedInProgressEvents.put(event.getClientId(), event);
- finishOrPause(event.getClientId(), true, true);
+ finishOrPause(event.getClientId(), false, true);
mAppOpsService.scheduleOpActiveChangedIfNeededLocked(parent.op, parent.uid,
parent.packageName, tag, false,
@@ -475,6 +473,8 @@ final class AttributedOp {
InProgressStartOpEvent event = events.get(binders.get(i));
if (event != null && event.getUidState() != newState) {
+ int eventAttributionFlags = event.getAttributionFlags();
+ int eventAttributionChainId = event.getAttributionChainId();
try {
// Remove all but one unfinished start count and then call finished() to
// remove start event object
@@ -482,18 +482,18 @@ final class AttributedOp {
event.mNumUnfinishedStarts = 1;
AppOpsManager.OpEventProxyInfo proxy = event.getProxy();
- finished(event.getClientId(), false);
+ finished(event.getClientId(), true);
// Call started() to add a new start event object and then add the
// previously removed unfinished start counts back
if (proxy != null) {
startedOrPaused(event.getClientId(), proxy.getUid(),
proxy.getPackageName(), proxy.getAttributionTag(), newState,
- event.getFlags(), false, isRunning,
+ event.getFlags(), true, isRunning,
event.getAttributionFlags(), event.getAttributionChainId());
} else {
startedOrPaused(event.getClientId(), Process.INVALID_UID, null, null,
- newState, event.getFlags(), false, isRunning,
+ newState, event.getFlags(), true, isRunning,
event.getAttributionFlags(), event.getAttributionChainId());
}
@@ -507,6 +507,9 @@ final class AttributedOp {
Slog.e(AppOpsService.TAG,
"Cannot switch to new uidState " + newState);
}
+ mAppOpsService.scheduleOpActiveChangedIfNeededLocked(parent.op,
+ parent.uid, parent.packageName, tag, false,
+ eventAttributionFlags, eventAttributionChainId);
}
}
}
diff --git a/services/core/java/com/android/server/appop/HistoricalRegistry.java b/services/core/java/com/android/server/appop/HistoricalRegistry.java
index bd9d057f9704..6f3526fb07e9 100644
--- a/services/core/java/com/android/server/appop/HistoricalRegistry.java
+++ b/services/core/java/com/android/server/appop/HistoricalRegistry.java
@@ -37,7 +37,6 @@ import android.app.AppOpsManager.UidState;
import android.content.ContentResolver;
import android.database.ContentObserver;
import android.net.Uri;
-import android.os.Binder;
import android.os.Build;
import android.os.Bundle;
import android.os.Debug;
@@ -46,7 +45,6 @@ import android.os.Message;
import android.os.Process;
import android.os.RemoteCallback;
import android.os.UserHandle;
-import android.provider.DeviceConfig;
import android.provider.Settings;
import android.util.ArraySet;
import android.util.LongSparseArray;
@@ -136,7 +134,6 @@ final class HistoricalRegistry {
private static final String PARAMETER_DELIMITER = ",";
private static final String PARAMETER_ASSIGNMENT = "=";
- private static final String PROPERTY_PERMISSIONS_HUB_ENABLED = "permissions_hub_enabled";
private volatile @NonNull DiscreteRegistry mDiscreteRegistry;
@@ -304,10 +301,6 @@ final class HistoricalRegistry {
void dump(String prefix, PrintWriter pw, int filterUid, @Nullable String filterPackage,
@Nullable String filterAttributionTag, int filterOp,
@HistoricalOpsRequestFilter int filter) {
- if (!isApiEnabled()) {
- return;
- }
-
synchronized (mOnDiskLock) {
synchronized (mInMemoryLock) {
pw.println();
@@ -371,11 +364,6 @@ final class HistoricalRegistry {
@OpHistoryFlags int historyFlags, @HistoricalOpsRequestFilter int filter,
long beginTimeMillis, long endTimeMillis, @OpFlags int flags,
String[] attributionExemptedPackages, @NonNull RemoteCallback callback) {
- if (!isApiEnabled()) {
- callback.sendResult(new Bundle());
- return;
- }
-
final HistoricalOps result = new HistoricalOps(beginTimeMillis, endTimeMillis);
if ((historyFlags & HISTORY_FLAG_AGGREGATE) != 0) {
@@ -409,11 +397,6 @@ final class HistoricalRegistry {
@HistoricalOpsRequestFilter int filter, long beginTimeMillis, long endTimeMillis,
@OpFlags int flags, @Nullable String[] attributionExemptPkgs,
@NonNull RemoteCallback callback) {
- if (!isApiEnabled()) {
- callback.sendResult(new Bundle());
- return;
- }
-
final long currentTimeMillis = System.currentTimeMillis();
if (endTimeMillis == Long.MAX_VALUE) {
endTimeMillis = currentTimeMillis;
@@ -807,12 +790,6 @@ final class HistoricalRegistry {
}
}
- private static boolean isApiEnabled() {
- return Binder.getCallingUid() == Process.myUid()
- || DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_PRIVACY,
- PROPERTY_PERMISSIONS_HUB_ENABLED, true);
- }
-
private static final class Persistence {
private static final boolean DEBUG = false;
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index a3245f0e717f..0aa9cc11c432 100644
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -140,6 +140,7 @@ import android.media.VolumeInfo;
import android.media.VolumePolicy;
import android.media.audiofx.AudioEffect;
import android.media.audiopolicy.AudioMix;
+import android.media.audiopolicy.AudioMixingRule;
import android.media.audiopolicy.AudioPolicy;
import android.media.audiopolicy.AudioPolicyConfig;
import android.media.audiopolicy.AudioProductStrategy;
@@ -166,6 +167,7 @@ import android.os.Process;
import android.os.RemoteCallbackList;
import android.os.RemoteException;
import android.os.ResultReceiver;
+import android.os.ServiceDebugInfo;
import android.os.ServiceManager;
import android.os.ShellCallback;
import android.os.SystemClock;
@@ -10860,6 +10862,7 @@ public class AudioService extends IAudioService.Stub
mDeviceBroker.addOrUpdateBtAudioDeviceCategoryInInventory(deviceState);
mDeviceBroker.persistAudioDeviceSettings();
+ mSpatializerHelper.refreshDevice(deviceState.getAudioDeviceAttributes());
mSoundDoseHelper.setAudioDeviceCategory(addr, internalType,
btAudioDeviceCategory == AUDIO_DEVICE_CATEGORY_HEADPHONES);
}
@@ -12048,6 +12051,49 @@ public class AudioService extends IAudioService.Stub
}
}
+ /**
+ * Update {@link AudioMixingRule}-s for already registered {@link AudioMix}-es.
+ *
+ * @param mixesToUpdate - array of already registered {@link AudioMix}-es to update.
+ * @param updatedMixingRules - array of {@link AudioMixingRule}-s corresponding to
+ * {@code mixesToUpdate} mixes. The array must be same size as
+ * {@code mixesToUpdate} and i-th {@link AudioMixingRule} must
+ * correspond to i-th {@link AudioMix} from mixesToUpdate array.
+ * @param pcb - {@link IAudioPolicyCallback} corresponding to the registered
+ * {@link AudioPolicy} all {@link AudioMix}-es for {@code mixesToUpdate}
+ * are part of.
+ * @return {@link AudioManager#SUCCESS} iff the mixing rules were updated successfully,
+ * {@link AudioManager#ERROR} otherwise.
+ */
+ @android.annotation.EnforcePermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING)
+ public int updateMixingRulesForPolicy(
+ @NonNull AudioMix[] mixesToUpdate,
+ @NonNull AudioMixingRule[] updatedMixingRules,
+ @NonNull IAudioPolicyCallback pcb) {
+ super.updateMixingRulesForPolicy_enforcePermission();
+ Objects.requireNonNull(mixesToUpdate);
+ Objects.requireNonNull(updatedMixingRules);
+ Objects.requireNonNull(pcb);
+ if (mixesToUpdate.length != updatedMixingRules.length) {
+ Log.e(TAG, "Provided list of audio mixes to update and corresponding mixing rules "
+ + "have mismatching length (mixesToUpdate.length = " + mixesToUpdate.length
+ + ", updatedMixingRules.length = " + updatedMixingRules.length + ").");
+ return AudioManager.ERROR;
+ }
+ if (DEBUG_AP) {
+ Log.d(TAG, "updateMixingRules for " + pcb.asBinder() + "with mix rules: ");
+ }
+ synchronized (mAudioPolicies) {
+ final AudioPolicyProxy app =
+ checkUpdateForPolicy(pcb, "Cannot add AudioMix in audio policy");
+ if (app == null) {
+ return AudioManager.ERROR;
+ }
+ return app.updateMixingRules(mixesToUpdate, updatedMixingRules) == AudioSystem.SUCCESS
+ ? AudioManager.SUCCESS : AudioManager.ERROR;
+ }
+ }
+
/** see AudioPolicy.setUidDeviceAffinity() */
public int setUidDeviceAffinity(IAudioPolicyCallback pcb, int uid,
@NonNull int[] deviceTypes, @NonNull String[] deviceAddresses) {
@@ -12785,6 +12831,35 @@ public class AudioService extends IAudioService.Stub
}
+ @AudioSystem.AudioSystemError int updateMixingRules(
+ @NonNull AudioMix[] mixesToUpdate,
+ @NonNull AudioMixingRule[] updatedMixingRules) {
+ Objects.requireNonNull(mixesToUpdate);
+ Objects.requireNonNull(updatedMixingRules);
+
+ if (mixesToUpdate.length != updatedMixingRules.length) {
+ Log.e(TAG, "Provided list of audio mixes to update and corresponding mixing rules "
+ + "have mismatching length (mixesToUpdate.length = " + mixesToUpdate.length
+ + ", updatedMixingRules.length = " + updatedMixingRules.length + ").");
+ return AudioSystem.BAD_VALUE;
+ }
+
+ synchronized (mMixes) {
+ try (SafeCloseable unused = ClearCallingIdentityContext.create()) {
+ int ret = mAudioSystem.updateMixingRules(mixesToUpdate, updatedMixingRules);
+ if (ret == AudioSystem.SUCCESS) {
+ for (int i = 0; i < mixesToUpdate.length; i++) {
+ AudioMix audioMixToUpdate = mixesToUpdate[i];
+ AudioMixingRule audioMixingRule = updatedMixingRules[i];
+ mMixes.stream().filter(audioMixToUpdate::equals).findAny().ifPresent(
+ mix -> mix.setAudioMixingRule(audioMixingRule));
+ }
+ }
+ return ret;
+ }
+ }
+ }
+
int setUidDeviceAffinities(int uid, @NonNull int[] types, @NonNull String[] addresses) {
final Integer Uid = new Integer(uid);
if (mUidDeviceAffinities.remove(Uid) != null) {
@@ -13077,12 +13152,25 @@ public class AudioService extends IAudioService.Stub
private static final String AUDIO_HAL_SERVICE_PREFIX = "android.hardware.audio";
- private Set<Integer> getAudioHalPids() {
+ private void getAudioAidlHalPids(HashSet<Integer> pids) {
+ try {
+ ServiceDebugInfo[] infos = ServiceManager.getServiceDebugInfo();
+ if (infos == null) return;
+ for (ServiceDebugInfo info : infos) {
+ if (info.debugPid > 0 && info.name.startsWith(AUDIO_HAL_SERVICE_PREFIX)) {
+ pids.add(info.debugPid);
+ }
+ }
+ } catch (RuntimeException e) {
+ // ignored, pid hashset does not change
+ }
+ }
+
+ private void getAudioHalHidlPids(HashSet<Integer> pids) {
try {
IServiceManager serviceManager = IServiceManager.getService();
ArrayList<IServiceManager.InstanceDebugInfo> dump =
serviceManager.debugDump();
- HashSet<Integer> pids = new HashSet<>();
for (IServiceManager.InstanceDebugInfo info : dump) {
if (info.pid != IServiceManager.PidConstant.NO_PID
&& info.interfaceName != null
@@ -13090,12 +13178,18 @@ public class AudioService extends IAudioService.Stub
pids.add(info.pid);
}
}
- return pids;
} catch (RemoteException | RuntimeException e) {
- return new HashSet<Integer>();
+ // ignored, pid hashset does not change
}
}
+ private Set<Integer> getAudioHalPids() {
+ HashSet<Integer> pids = new HashSet<>();
+ getAudioAidlHalPids(pids);
+ getAudioHalHidlPids(pids);
+ return pids;
+ }
+
private void updateAudioHalPids() {
Set<Integer> pidsSet = getAudioHalPids();
if (pidsSet.isEmpty()) {
diff --git a/services/core/java/com/android/server/audio/AudioSystemAdapter.java b/services/core/java/com/android/server/audio/AudioSystemAdapter.java
index e70b6497538e..4f46dd13f973 100644
--- a/services/core/java/com/android/server/audio/AudioSystemAdapter.java
+++ b/services/core/java/com/android/server/audio/AudioSystemAdapter.java
@@ -26,6 +26,7 @@ import android.media.IDevicesForAttributesCallback;
import android.media.ISoundDose;
import android.media.ISoundDoseCallback;
import android.media.audiopolicy.AudioMix;
+import android.media.audiopolicy.AudioMixingRule;
import android.os.IBinder;
import android.os.RemoteCallbackList;
import android.os.RemoteException;
@@ -601,6 +602,21 @@ public class AudioSystemAdapter implements AudioSystem.RoutingUpdateCallback,
}
/**
+ * Update already {@link AudioMixingRule}-s for already registered {@link AudioMix}-es.
+ *
+ * @param mixes - array of registered {@link AudioMix}-es to update.
+ * @param updatedMixingRules - array of {@link AudioMixingRule}-s corresponding to
+ * {@code mixesToUpdate} mixes. The array must be same size as
+ * {@code mixesToUpdate} and i-th {@link AudioMixingRule} must
+ * correspond to i-th {@link AudioMix} from mixesToUpdate array.
+ */
+ public int updateMixingRules(@NonNull AudioMix[] mixes,
+ @NonNull AudioMixingRule[] updatedMixingRules) {
+ invalidateRoutingCache();
+ return AudioSystem.updatePolicyMixes(mixes, updatedMixingRules);
+ }
+
+ /**
* Same as {@link AudioSystem#setUidDeviceAffinities(int, int[], String[])}
* @param uid
* @param types
diff --git a/services/core/java/com/android/server/audio/SpatializerHelper.java b/services/core/java/com/android/server/audio/SpatializerHelper.java
index 9fa569af316d..35260ed6f148 100644
--- a/services/core/java/com/android/server/audio/SpatializerHelper.java
+++ b/services/core/java/com/android/server/audio/SpatializerHelper.java
@@ -16,6 +16,8 @@
package com.android.server.audio;
+import static android.media.AudioManager.AUDIO_DEVICE_CATEGORY_HEADPHONES;
+import static android.media.AudioManager.AUDIO_DEVICE_CATEGORY_UNKNOWN;
import static android.media.AudioSystem.isBluetoothDevice;
import android.annotation.NonNull;
@@ -682,8 +684,20 @@ public class SpatializerHelper {
Log.i(TAG, "no spatialization device state found for Spatial Audio device:" + ada);
return new Pair<>(false, false);
}
+ boolean available = true;
+ if (isBluetoothDevice(deviceType)) {
+ // only checking headphones/binaural because external speakers cannot use transaural
+ // since their physical characteristics are unknown
+ if (deviceState.getAudioDeviceCategory() == AUDIO_DEVICE_CATEGORY_UNKNOWN
+ || deviceState.getAudioDeviceCategory() == AUDIO_DEVICE_CATEGORY_HEADPHONES) {
+ available = (spatMode == SpatializationMode.SPATIALIZER_BINAURAL)
+ && mBinauralSupported;
+ } else {
+ available = false;
+ }
+ }
// found the matching device state.
- return new Pair<>(deviceState.isSAEnabled(), true /* available */);
+ return new Pair<>(deviceState.isSAEnabled(), available);
}
private synchronized void addWirelessDeviceIfNew(@NonNull AudioDeviceAttributes ada) {
@@ -740,11 +754,36 @@ public class SpatializerHelper {
}
}
+ synchronized void refreshDevice(@NonNull AudioDeviceAttributes ada) {
+ final AdiDeviceState deviceState = findSACompatibleDeviceStateForAudioDeviceAttributes(ada);
+ if (isAvailableForAdiDeviceState(deviceState)) {
+ addCompatibleAudioDevice(ada, /*forceEnable=*/deviceState.isSAEnabled());
+ setHeadTrackerEnabled(deviceState.isHeadTrackerEnabled(), ada);
+ } else {
+ removeCompatibleAudioDevice(ada);
+ }
+ }
+
synchronized boolean isAvailableForDevice(@NonNull AudioDeviceAttributes ada) {
if (ada.getRole() != AudioDeviceAttributes.ROLE_OUTPUT) {
return false;
}
- return findSACompatibleDeviceStateForAudioDeviceAttributes(ada) != null;
+
+ return isAvailableForAdiDeviceState(
+ findSACompatibleDeviceStateForAudioDeviceAttributes(ada));
+ }
+
+ private boolean isAvailableForAdiDeviceState(AdiDeviceState deviceState) {
+ if (deviceState == null) {
+ return false;
+ }
+
+ if (isBluetoothDevice(deviceState.getInternalDeviceType())
+ && deviceState.getAudioDeviceCategory() != AUDIO_DEVICE_CATEGORY_UNKNOWN
+ && deviceState.getAudioDeviceCategory() != AUDIO_DEVICE_CATEGORY_HEADPHONES) {
+ return false;
+ }
+ return true;
}
private synchronized boolean canBeSpatializedOnDevice(@NonNull AudioAttributes attributes,
diff --git a/services/core/java/com/android/server/biometrics/AuthenticationStatsCollector.java b/services/core/java/com/android/server/biometrics/AuthenticationStatsCollector.java
index e8a20def02cb..fdf607d04ec7 100644
--- a/services/core/java/com/android/server/biometrics/AuthenticationStatsCollector.java
+++ b/services/core/java/com/android/server/biometrics/AuthenticationStatsCollector.java
@@ -98,6 +98,8 @@ public class AuthenticationStatsCollector {
mAuthenticationStatsPersister.getAllFrrStats(mModality)) {
mUserAuthenticationStatsMap.put(stats.getUserId(), stats);
}
+ mAuthenticationStatsPersister.persistFrrThreshold(mThreshold);
+
mPersisterInitialized = true;
} catch (IllegalStateException e) {
Slog.w(TAG, "Failed to initialize AuthenticationStatsPersister.", e);
diff --git a/services/core/java/com/android/server/biometrics/AuthenticationStatsPersister.java b/services/core/java/com/android/server/biometrics/AuthenticationStatsPersister.java
index 8122b1d131f8..5625bfd21e76 100644
--- a/services/core/java/com/android/server/biometrics/AuthenticationStatsPersister.java
+++ b/services/core/java/com/android/server/biometrics/AuthenticationStatsPersister.java
@@ -52,6 +52,7 @@ public class AuthenticationStatsPersister {
private static final String FINGERPRINT_REJECTIONS = "fingerprint_rejections";
private static final String ENROLLMENT_NOTIFICATIONS = "enrollment_notifications";
private static final String KEY = "frr_stats";
+ private static final String THRESHOLD_KEY = "frr_threshold";
@NonNull private final SharedPreferences mSharedPreferences;
@@ -157,6 +158,13 @@ public class AuthenticationStatsPersister {
}
}
+ /**
+ * Persist frr threshold.
+ */
+ public void persistFrrThreshold(float frrThreshold) {
+ mSharedPreferences.edit().putFloat(THRESHOLD_KEY, frrThreshold).apply();
+ }
+
private Set<String> readFrrStats() {
return mSharedPreferences.getStringSet(KEY, Set.of());
}
diff --git a/services/core/java/com/android/server/biometrics/sensors/BiometricNotificationUtils.java b/services/core/java/com/android/server/biometrics/sensors/BiometricNotificationUtils.java
index 0fc8ababbafb..f1c74f0b9fb2 100644
--- a/services/core/java/com/android/server/biometrics/sensors/BiometricNotificationUtils.java
+++ b/services/core/java/com/android/server/biometrics/sensors/BiometricNotificationUtils.java
@@ -78,7 +78,8 @@ public class BiometricNotificationUtils {
null /* options */, UserHandle.CURRENT);
showNotificationHelper(context, name, title, content, pendingIntent, FACE_RE_ENROLL_CHANNEL,
- FACE_RE_ENROLL_NOTIFICATION_TAG, Notification.VISIBILITY_SECRET);
+ Notification.CATEGORY_SYSTEM, FACE_RE_ENROLL_NOTIFICATION_TAG,
+ Notification.VISIBILITY_SECRET);
}
/**
@@ -101,7 +102,8 @@ public class BiometricNotificationUtils {
null /* options */, UserHandle.CURRENT);
showNotificationHelper(context, name, title, content, pendingIntent, FACE_ENROLL_CHANNEL,
- FACE_ENROLL_NOTIFICATION_TAG, Notification.VISIBILITY_PUBLIC);
+ Notification.CATEGORY_RECOMMENDATION, FACE_ENROLL_NOTIFICATION_TAG,
+ Notification.VISIBILITY_PUBLIC);
}
/**
@@ -124,8 +126,8 @@ public class BiometricNotificationUtils {
null /* options */, UserHandle.CURRENT);
showNotificationHelper(context, name, title, content, pendingIntent,
- FINGERPRINT_ENROLL_CHANNEL, FINGERPRINT_ENROLL_NOTIFICATION_TAG,
- Notification.VISIBILITY_PUBLIC);
+ Notification.CATEGORY_RECOMMENDATION, FINGERPRINT_ENROLL_CHANNEL,
+ FINGERPRINT_ENROLL_NOTIFICATION_TAG, Notification.VISIBILITY_PUBLIC);
}
/**
@@ -159,13 +161,13 @@ public class BiometricNotificationUtils {
null /* options */, UserHandle.CURRENT);
showNotificationHelper(context, name, title, content, pendingIntent,
- FINGERPRINT_BAD_CALIBRATION_CHANNEL, BAD_CALIBRATION_NOTIFICATION_TAG,
- Notification.VISIBILITY_SECRET);
+ Notification.CATEGORY_SYSTEM, FINGERPRINT_BAD_CALIBRATION_CHANNEL,
+ BAD_CALIBRATION_NOTIFICATION_TAG, Notification.VISIBILITY_SECRET);
}
private static void showNotificationHelper(Context context, String name, String title,
- String content, PendingIntent pendingIntent, String channelName,
- String notificationTag, int visibility) {
+ String content, PendingIntent pendingIntent, String category,
+ String channelName, String notificationTag, int visibility) {
final NotificationManager notificationManager =
context.getSystemService(NotificationManager.class);
final NotificationChannel channel = new NotificationChannel(channelName, name,
@@ -178,7 +180,7 @@ public class BiometricNotificationUtils {
.setOnlyAlertOnce(true)
.setLocalOnly(true)
.setAutoCancel(true)
- .setCategory(Notification.CATEGORY_SYSTEM)
+ .setCategory(category)
.setContentIntent(pendingIntent)
.setVisibility(visibility)
.build();
diff --git a/services/core/java/com/android/server/connectivity/Vpn.java b/services/core/java/com/android/server/connectivity/Vpn.java
index ff35b192cccd..bfccd58b3f5d 100644
--- a/services/core/java/com/android/server/connectivity/Vpn.java
+++ b/services/core/java/com/android/server/connectivity/Vpn.java
@@ -3066,7 +3066,8 @@ public class Vpn {
* <p>This variable controls the retry delay, and is reset when the VPN pass network
* validation.
*/
- private int mValidationFailRetryCount = 0;
+ @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
+ int mValidationFailRetryCount = 0;
/**
* The number of attempts since the last successful connection.
@@ -3897,6 +3898,18 @@ public class Vpn {
// Skip other invalid status if the scheduled recovery exists.
if (mScheduledHandleDataStallFuture != null) return;
+ // Trigger network validation on the underlying network to possibly cause system
+ // switch default network or try recover if the current default network is broken.
+ //
+ // For the same underlying network, the first validation result should clarify if
+ // it's caused by broken underlying network. So only perform underlying network
+ // re-evaluation after first validation failure to prevent extra network resource
+ // costs on sending probes.
+ if (mValidationFailRetryCount == 0) {
+ mConnectivityManager.reportNetworkConnectivity(
+ mActiveNetwork, false /* hasConnectivity */);
+ }
+
if (mValidationFailRetryCount < MAX_MOBIKE_RECOVERY_ATTEMPT) {
Log.d(TAG, "Validation failed");
diff --git a/services/core/java/com/android/server/display/BrightnessMappingStrategy.java b/services/core/java/com/android/server/display/BrightnessMappingStrategy.java
index df2a8301f543..99a5398aa7ee 100644
--- a/services/core/java/com/android/server/display/BrightnessMappingStrategy.java
+++ b/services/core/java/com/android/server/display/BrightnessMappingStrategy.java
@@ -25,6 +25,7 @@ import android.content.res.TypedArray;
import android.hardware.display.BrightnessConfiguration;
import android.hardware.display.BrightnessCorrection;
import android.os.PowerManager;
+import android.util.LongArray;
import android.util.MathUtils;
import android.util.Pair;
import android.util.Slog;
@@ -37,7 +38,11 @@ import com.android.server.display.utils.Plog;
import com.android.server.display.whitebalance.DisplayWhiteBalanceController;
import java.io.PrintWriter;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
import java.util.Arrays;
+import java.util.Date;
+import java.util.List;
import java.util.Locale;
import java.util.Objects;
@@ -840,6 +845,13 @@ public abstract class BrightnessMappingStrategy {
private final boolean mIsForIdleMode;
private final DisplayWhiteBalanceController mDisplayWhiteBalanceController;
+ // Previous short-term models and the times that they were computed stored for debugging
+ // purposes
+ private List<Spline> mPreviousBrightnessSplines = new ArrayList<>();
+ private LongArray mBrightnessSplineChangeTimes = new LongArray();
+ private static final int NO_OF_PREVIOUS_CONFIGS_TO_LOG = 5;
+ private static final SimpleDateFormat FORMAT = new SimpleDateFormat("MM-dd HH:mm:ss.SSS");
+
public PhysicalMappingStrategy(BrightnessConfiguration config, float[] nits,
float[] brightness, float maxGamma, boolean isForIdleMode,
DisplayWhiteBalanceController displayWhiteBalanceController) {
@@ -982,6 +994,13 @@ public abstract class BrightnessMappingStrategy {
mUserLux = lux;
mUserBrightness = brightness;
computeSpline();
+
+ if (mPreviousBrightnessSplines.size() == NO_OF_PREVIOUS_CONFIGS_TO_LOG) {
+ mPreviousBrightnessSplines.remove(0);
+ mBrightnessSplineChangeTimes.remove(0);
+ }
+ mPreviousBrightnessSplines.add(mBrightnessSpline);
+ mBrightnessSplineChangeTimes.add(System.currentTimeMillis());
}
@Override
@@ -1042,7 +1061,16 @@ public abstract class BrightnessMappingStrategy {
pw.println(" mDefaultConfig=" + mDefaultConfig);
pw.println(" mBrightnessRangeAdjustmentApplied=" + mBrightnessRangeAdjustmentApplied);
- dumpConfigDiff(pw, hbmTransition);
+ pw.println(" Previous short-term models (oldest to newest): ");
+ for (int i = 0; i < mPreviousBrightnessSplines.size(); i++) {
+ pw.println(" Computed at "
+ + FORMAT.format(new Date(mBrightnessSplineChangeTimes.get(i))) + ": ");
+ dumpConfigDiff(pw, hbmTransition, mPreviousBrightnessSplines.get(i),
+ /* shortTermModelOnly= */ true);
+ }
+
+ pw.println(" Difference between current config and default: ");
+ dumpConfigDiff(pw, hbmTransition, mBrightnessSpline, /* shortTermModelOnly= */ false);
}
@Override
@@ -1066,9 +1094,8 @@ public abstract class BrightnessMappingStrategy {
*
* @param pw The print-writer to write to.
*/
- private void dumpConfigDiff(PrintWriter pw, float hbmTransition) {
- pw.println(" Difference between current config and default: ");
-
+ private void dumpConfigDiff(PrintWriter pw, float hbmTransition, Spline brightnessSpline,
+ boolean shortTermModelOnly) {
Pair<float[], float[]> currentCurve = mConfig.getCurve();
Spline currSpline = Spline.createSpline(currentCurve.first, currentCurve.second);
@@ -1107,7 +1134,7 @@ public abstract class BrightnessMappingStrategy {
float defaultNits = defaultSpline.interpolate(lux);
float longTermNits = currSpline.interpolate(lux);
- float shortTermNits = mBrightnessSpline.interpolate(lux);
+ float shortTermNits = brightnessSpline.interpolate(lux);
float brightness = mAdjustedNitsToBrightnessSpline.interpolate(shortTermNits);
String luxPrefix = (lux == mUserLux ? "^" : "");
@@ -1142,8 +1169,10 @@ public abstract class BrightnessMappingStrategy {
// At 80 chars, start another row
if (sbLux.length() > 80 || (i == luxes.length - 1)) {
pw.println(sbLux);
- pw.println(sbNits);
- pw.println(sbLong);
+ if (!shortTermModelOnly) {
+ pw.println(sbNits);
+ pw.println(sbLong);
+ }
pw.println(sbShort);
pw.println(sbBrightness);
pw.println(sbPercent);
diff --git a/services/core/java/com/android/server/display/ColorFade.java b/services/core/java/com/android/server/display/ColorFade.java
index 0d6635d5b6e4..2d763bc486bb 100644
--- a/services/core/java/com/android/server/display/ColorFade.java
+++ b/services/core/java/com/android/server/display/ColorFade.java
@@ -407,6 +407,12 @@ final class ColorFade {
}
}
+ void stop() {
+ if (mEglContext != null && mEglDisplay != null) {
+ EGL14.eglDestroyContext(mEglDisplay, mEglContext);
+ }
+ }
+
/**
* Draws an animation frame showing the color fade activated at the
* specified level.
diff --git a/services/core/java/com/android/server/display/DisplayDeviceConfig.java b/services/core/java/com/android/server/display/DisplayDeviceConfig.java
index c0c60a47263a..e3dafa4a4cc0 100644
--- a/services/core/java/com/android/server/display/DisplayDeviceConfig.java
+++ b/services/core/java/com/android/server/display/DisplayDeviceConfig.java
@@ -282,6 +282,8 @@ import javax.xml.datatype.DatatypeConfigurationException;
* <screenBrightnessRampFastIncrease>0.02</screenBrightnessRampFastIncrease>
* <screenBrightnessRampSlowDecrease>0.03</screenBrightnessRampSlowDecrease>
* <screenBrightnessRampSlowIncrease>0.04</screenBrightnessRampSlowIncrease>
+ * <screenBrightnessRampSlowDecreaseIdle>0.05</screenBrightnessRampSlowDecreaseIdle>
+ * <screenBrightnessRampSlowIncreaseIdle>0.06</screenBrightnessRampSlowIncreaseIdle>
*
* <screenBrightnessRampIncreaseMaxMillis>2000</screenBrightnessRampIncreaseMaxMillis>
* <screenBrightnessRampDecreaseMaxMillis>3000</screenBrightnessRampDecreaseMaxMillis>
@@ -597,6 +599,8 @@ public class DisplayDeviceConfig {
private float mBrightnessRampFastIncrease = Float.NaN;
private float mBrightnessRampSlowDecrease = Float.NaN;
private float mBrightnessRampSlowIncrease = Float.NaN;
+ private float mBrightnessRampSlowDecreaseIdle = Float.NaN;
+ private float mBrightnessRampSlowIncreaseIdle = Float.NaN;
private long mBrightnessRampDecreaseMaxMillis = 0;
private long mBrightnessRampIncreaseMaxMillis = 0;
private int mAmbientHorizonLong = AMBIENT_LIGHT_LONG_HORIZON_MILLIS;
@@ -1039,6 +1043,14 @@ public class DisplayDeviceConfig {
return mBrightnessRampSlowIncrease;
}
+ public float getBrightnessRampSlowDecreaseIdle() {
+ return mBrightnessRampSlowDecreaseIdle;
+ }
+
+ public float getBrightnessRampSlowIncreaseIdle() {
+ return mBrightnessRampSlowIncreaseIdle;
+ }
+
public long getBrightnessRampDecreaseMaxMillis() {
return mBrightnessRampDecreaseMaxMillis;
}
@@ -1654,6 +1666,8 @@ public class DisplayDeviceConfig {
+ ", mBrightnessRampFastIncrease=" + mBrightnessRampFastIncrease
+ ", mBrightnessRampSlowDecrease=" + mBrightnessRampSlowDecrease
+ ", mBrightnessRampSlowIncrease=" + mBrightnessRampSlowIncrease
+ + ", mBrightnessRampSlowDecreaseIdle=" + mBrightnessRampSlowDecreaseIdle
+ + ", mBrightnessRampSlowIncreaseIdle=" + mBrightnessRampSlowIncreaseIdle
+ ", mBrightnessRampDecreaseMaxMillis=" + mBrightnessRampDecreaseMaxMillis
+ ", mBrightnessRampIncreaseMaxMillis=" + mBrightnessRampIncreaseMaxMillis
+ "\n"
@@ -1845,6 +1859,8 @@ public class DisplayDeviceConfig {
mBrightnessRampFastIncrease = PowerManager.BRIGHTNESS_MAX;
mBrightnessRampSlowDecrease = PowerManager.BRIGHTNESS_MAX;
mBrightnessRampSlowIncrease = PowerManager.BRIGHTNESS_MAX;
+ mBrightnessRampSlowDecreaseIdle = PowerManager.BRIGHTNESS_MAX;
+ mBrightnessRampSlowIncreaseIdle = PowerManager.BRIGHTNESS_MAX;
mBrightnessRampDecreaseMaxMillis = 0;
mBrightnessRampIncreaseMaxMillis = 0;
setSimpleMappingStrategyValues();
@@ -2665,6 +2681,12 @@ public class DisplayDeviceConfig {
}
private void loadBrightnessRamps(DisplayConfiguration config) {
+ // Interactive must come first, since idle falls back to it when values are unspecified.
+ loadBrightnessRampsInteractive(config);
+ loadBrightnessRampsIdle(config);
+ }
+
+ private void loadBrightnessRampsInteractive(DisplayConfiguration config) {
// Priority 1: Value in the display device config (float)
// Priority 2: Value in the config.xml (int)
final BigDecimal fastDownDecimal = config.getScreenBrightnessRampFastDecrease();
@@ -2697,6 +2719,27 @@ public class DisplayDeviceConfig {
}
}
+ private void loadBrightnessRampsIdle(DisplayConfiguration config) {
+ // Priority 1: Idle value in the display device config (float)
+ // Priority 2: Fallback - Interactive value from wherever.
+ final BigDecimal slowDownDecimalIdle = config.getScreenBrightnessRampSlowDecreaseIdle();
+ final BigDecimal slowUpDecimalIdle = config.getScreenBrightnessRampSlowIncreaseIdle();
+
+ if (slowDownDecimalIdle != null && slowUpDecimalIdle != null) {
+ mBrightnessRampSlowDecreaseIdle = slowDownDecimalIdle.floatValue();
+ mBrightnessRampSlowIncreaseIdle = slowUpDecimalIdle.floatValue();
+ } else {
+ if (slowDownDecimalIdle != null || slowUpDecimalIdle != null) {
+ Slog.w(TAG, "Per display idle brightness ramp values ignored because not all "
+ + "values are present in display device config");
+ }
+ // If these values don't exist, fall back to interactive mode values, since
+ // there are no idle ramp values in config.xml
+ mBrightnessRampSlowDecreaseIdle = mBrightnessRampSlowDecrease;
+ mBrightnessRampSlowIncreaseIdle = mBrightnessRampSlowIncrease;
+ }
+ }
+
private void loadBrightnessRampsFromConfigXml() {
mBrightnessRampFastIncrease = BrightnessSynchronizer.brightnessIntToFloat(
mContext.getResources().getInteger(R.integer.config_brightness_ramp_rate_fast));
diff --git a/services/core/java/com/android/server/display/DisplayManagerService.java b/services/core/java/com/android/server/display/DisplayManagerService.java
index b994105de406..90c7ce7d5bc8 100644
--- a/services/core/java/com/android/server/display/DisplayManagerService.java
+++ b/services/core/java/com/android/server/display/DisplayManagerService.java
@@ -146,6 +146,7 @@ import com.android.internal.util.ArrayUtils;
import com.android.internal.util.DumpUtils;
import com.android.internal.util.FrameworkStatsLog;
import com.android.internal.util.IndentingPrintWriter;
+import com.android.internal.util.SettingsWrapper;
import com.android.server.AnimationThread;
import com.android.server.DisplayThread;
import com.android.server.LocalServices;
@@ -159,7 +160,7 @@ import com.android.server.display.layout.Layout;
import com.android.server.display.mode.DisplayModeDirector;
import com.android.server.display.utils.SensorUtils;
import com.android.server.input.InputManagerInternal;
-import com.android.server.utils.FoldSettingWrapper;
+import com.android.server.utils.FoldSettingProvider;
import com.android.server.wm.SurfaceAnimationThread;
import com.android.server.wm.WindowManagerInternal;
@@ -472,6 +473,8 @@ public final class DisplayManagerService extends SystemService {
private SensorManager mSensorManager;
private BrightnessTracker mBrightnessTracker;
+ private SmallAreaDetectionController mSmallAreaDetectionController;
+
// Whether minimal post processing is allowed by the user.
@GuardedBy("mSyncRoot")
@@ -547,9 +550,9 @@ public final class DisplayManagerService extends SystemService {
mHandler = new DisplayManagerHandler(DisplayThread.get().getLooper());
mUiHandler = UiThread.getHandler();
mDisplayDeviceRepo = new DisplayDeviceRepository(mSyncRoot, mPersistentDataStore);
- mLogicalDisplayMapper = new LogicalDisplayMapper(mContext, mDisplayDeviceRepo,
- new LogicalDisplayListener(), mSyncRoot, mHandler,
- new FoldSettingWrapper(mContext.getContentResolver()), mFlags);
+ mLogicalDisplayMapper = new LogicalDisplayMapper(mContext,
+ new FoldSettingProvider(mContext, new SettingsWrapper()), mDisplayDeviceRepo,
+ new LogicalDisplayListener(), mSyncRoot, mHandler, mFlags);
mDisplayModeDirector = new DisplayModeDirector(context, mHandler);
mBrightnessSynchronizer = new BrightnessSynchronizer(mContext);
Resources resources = mContext.getResources();
@@ -738,6 +741,8 @@ public final class DisplayManagerService extends SystemService {
filter.addAction(Intent.ACTION_DOCK_EVENT);
mContext.registerReceiver(mIdleModeReceiver, filter);
+
+ mSmallAreaDetectionController = SmallAreaDetectionController.create(mContext);
}
@VisibleForTesting
@@ -3128,6 +3133,9 @@ public final class DisplayManagerService extends SystemService {
pw.println();
mDisplayModeDirector.dump(pw);
mBrightnessSynchronizer.dump(pw);
+ if (mSmallAreaDetectionController != null) {
+ mSmallAreaDetectionController.dump(pw);
+ }
}
private static float[] getFloatArray(TypedArray array) {
diff --git a/services/core/java/com/android/server/display/DisplayPowerController.java b/services/core/java/com/android/server/display/DisplayPowerController.java
index 79b73430b934..40dbabf29807 100644
--- a/services/core/java/com/android/server/display/DisplayPowerController.java
+++ b/services/core/java/com/android/server/display/DisplayPowerController.java
@@ -430,6 +430,8 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
private float mBrightnessRampRateFastIncrease;
private float mBrightnessRampRateSlowDecrease;
private float mBrightnessRampRateSlowIncrease;
+ private float mBrightnessRampRateSlowDecreaseIdle;
+ private float mBrightnessRampRateSlowIncreaseIdle;
// Report HBM brightness change to StatsD
private int mDisplayStatsId;
@@ -1312,6 +1314,10 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
mBrightnessRampRateFastIncrease = mDisplayDeviceConfig.getBrightnessRampFastIncrease();
mBrightnessRampRateSlowDecrease = mDisplayDeviceConfig.getBrightnessRampSlowDecrease();
mBrightnessRampRateSlowIncrease = mDisplayDeviceConfig.getBrightnessRampSlowIncrease();
+ mBrightnessRampRateSlowDecreaseIdle =
+ mDisplayDeviceConfig.getBrightnessRampSlowDecreaseIdle();
+ mBrightnessRampRateSlowIncreaseIdle =
+ mDisplayDeviceConfig.getBrightnessRampSlowIncreaseIdle();
mBrightnessRampDecreaseMaxTimeMillis =
mDisplayDeviceConfig.getBrightnessRampDecreaseMaxMillis();
mBrightnessRampIncreaseMaxTimeMillis =
@@ -1922,12 +1928,16 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
} else {
boolean isIncreasing = animateValue > currentBrightness;
final float rampSpeed;
+ final boolean idle = mAutomaticBrightnessController != null
+ && mAutomaticBrightnessController.isInIdleMode();
if (isIncreasing && slowChange) {
- rampSpeed = mBrightnessRampRateSlowIncrease;
+ rampSpeed = idle ? mBrightnessRampRateSlowIncreaseIdle
+ : mBrightnessRampRateSlowIncrease;
} else if (isIncreasing && !slowChange) {
rampSpeed = mBrightnessRampRateFastIncrease;
} else if (!isIncreasing && slowChange) {
- rampSpeed = mBrightnessRampRateSlowDecrease;
+ rampSpeed = idle ? mBrightnessRampRateSlowDecreaseIdle
+ : mBrightnessRampRateSlowDecrease;
} else {
rampSpeed = mBrightnessRampRateFastDecrease;
}
@@ -3526,7 +3536,8 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
DisplayPowerState getDisplayPowerState(DisplayBlanker blanker, ColorFade colorFade,
int displayId, int displayState) {
- return new DisplayPowerState(blanker, colorFade, displayId, displayState);
+ return new DisplayPowerState(blanker, colorFade, displayId, displayState,
+ new Handler(/*async=*/ true));
}
DualRampAnimator<DisplayPowerState> getDualRampAnimator(DisplayPowerState dps,
diff --git a/services/core/java/com/android/server/display/DisplayPowerController2.java b/services/core/java/com/android/server/display/DisplayPowerController2.java
index 6c2240becbff..051c88690713 100644
--- a/services/core/java/com/android/server/display/DisplayPowerController2.java
+++ b/services/core/java/com/android/server/display/DisplayPowerController2.java
@@ -319,8 +319,6 @@ final class DisplayPowerController2 implements AutomaticBrightnessController.Cal
// Must only be accessed on the handler thread.
private DisplayPowerState mPowerState;
-
-
// The currently active screen on unblocker. This field is non-null whenever
// we are waiting for a callback to release it and unblock the screen.
private ScreenOnUnblocker mPendingScreenOnUnblocker;
@@ -357,6 +355,8 @@ final class DisplayPowerController2 implements AutomaticBrightnessController.Cal
private float mBrightnessRampRateFastIncrease;
private float mBrightnessRampRateSlowDecrease;
private float mBrightnessRampRateSlowIncrease;
+ private float mBrightnessRampRateSlowDecreaseIdle;
+ private float mBrightnessRampRateSlowIncreaseIdle;
// Report HBM brightness change to StatsD
private int mDisplayStatsId;
@@ -1127,6 +1127,10 @@ final class DisplayPowerController2 implements AutomaticBrightnessController.Cal
mBrightnessRampRateFastIncrease = mDisplayDeviceConfig.getBrightnessRampFastIncrease();
mBrightnessRampRateSlowDecrease = mDisplayDeviceConfig.getBrightnessRampSlowDecrease();
mBrightnessRampRateSlowIncrease = mDisplayDeviceConfig.getBrightnessRampSlowIncrease();
+ mBrightnessRampRateSlowDecreaseIdle =
+ mDisplayDeviceConfig.getBrightnessRampSlowDecreaseIdle();
+ mBrightnessRampRateSlowIncreaseIdle =
+ mDisplayDeviceConfig.getBrightnessRampSlowIncreaseIdle();
mBrightnessRampDecreaseMaxTimeMillis =
mDisplayDeviceConfig.getBrightnessRampDecreaseMaxMillis();
mBrightnessRampIncreaseMaxTimeMillis =
@@ -1535,12 +1539,16 @@ final class DisplayPowerController2 implements AutomaticBrightnessController.Cal
} else {
boolean isIncreasing = animateValue > currentBrightness;
final float rampSpeed;
+ final boolean idle = mAutomaticBrightnessController != null
+ && mAutomaticBrightnessController.isInIdleMode();
if (isIncreasing && slowChange) {
- rampSpeed = mBrightnessRampRateSlowIncrease;
+ rampSpeed = idle ? mBrightnessRampRateSlowIncreaseIdle
+ : mBrightnessRampRateSlowIncrease;
} else if (isIncreasing && !slowChange) {
rampSpeed = mBrightnessRampRateFastIncrease;
} else if (!isIncreasing && slowChange) {
- rampSpeed = mBrightnessRampRateSlowDecrease;
+ rampSpeed = idle ? mBrightnessRampRateSlowDecreaseIdle
+ : mBrightnessRampRateSlowDecrease;
} else {
rampSpeed = mBrightnessRampRateFastDecrease;
}
@@ -2861,7 +2869,8 @@ final class DisplayPowerController2 implements AutomaticBrightnessController.Cal
DisplayPowerState getDisplayPowerState(DisplayBlanker blanker, ColorFade colorFade,
int displayId, int displayState) {
- return new DisplayPowerState(blanker, colorFade, displayId, displayState);
+ return new DisplayPowerState(blanker, colorFade, displayId, displayState,
+ new Handler(/*async=*/ true));
}
DualRampAnimator<DisplayPowerState> getDualRampAnimator(DisplayPowerState dps,
diff --git a/services/core/java/com/android/server/display/DisplayPowerState.java b/services/core/java/com/android/server/display/DisplayPowerState.java
index 2c257a17af91..85c6a6de860f 100644
--- a/services/core/java/com/android/server/display/DisplayPowerState.java
+++ b/services/core/java/com/android/server/display/DisplayPowerState.java
@@ -74,8 +74,9 @@ final class DisplayPowerState {
private volatile boolean mStopped;
DisplayPowerState(
- DisplayBlanker blanker, ColorFade colorFade, int displayId, int displayState) {
- mHandler = new Handler(true /*async*/);
+ DisplayBlanker blanker, ColorFade colorFade, int displayId, int displayState,
+ Handler handler) {
+ mHandler = handler;
mChoreographer = Choreographer.getInstance();
mBlanker = blanker;
mColorFade = colorFade;
@@ -317,6 +318,7 @@ final class DisplayPowerState {
mStopped = true;
mPhotonicModulator.interrupt();
dismissColorFade();
+ stopColorFade();
mCleanListener = null;
mHandler.removeCallbacksAndMessages(null);
}
@@ -376,6 +378,11 @@ final class DisplayPowerState {
}
}
+ // Clears up color fade resources.
+ private void stopColorFade() {
+ if (mColorFade != null) mColorFade.stop();
+ }
+
private final Runnable mScreenUpdateRunnable = new Runnable() {
@Override
public void run() {
diff --git a/services/core/java/com/android/server/display/LogicalDisplayMapper.java b/services/core/java/com/android/server/display/LogicalDisplayMapper.java
index cbe0fc7e713b..b3b16ade0546 100644
--- a/services/core/java/com/android/server/display/LogicalDisplayMapper.java
+++ b/services/core/java/com/android/server/display/LogicalDisplayMapper.java
@@ -43,7 +43,7 @@ import com.android.internal.annotations.VisibleForTesting;
import com.android.server.display.feature.DisplayManagerFlags;
import com.android.server.display.layout.DisplayIdProducer;
import com.android.server.display.layout.Layout;
-import com.android.server.utils.FoldSettingWrapper;
+import com.android.server.utils.FoldSettingProvider;
import java.io.PrintWriter;
import java.util.Arrays;
@@ -149,7 +149,7 @@ class LogicalDisplayMapper implements DisplayDeviceRepository.Listener {
private final Listener mListener;
private final DisplayManagerService.SyncRoot mSyncRoot;
private final LogicalDisplayMapperHandler mHandler;
- private final FoldSettingWrapper mFoldSettingWrapper;
+ private final FoldSettingProvider mFoldSettingProvider;
private final PowerManager mPowerManager;
/**
@@ -196,26 +196,27 @@ class LogicalDisplayMapper implements DisplayDeviceRepository.Listener {
private boolean mInteractive;
private final DisplayManagerFlags mFlags;
- LogicalDisplayMapper(@NonNull Context context, @NonNull DisplayDeviceRepository repo,
+ LogicalDisplayMapper(@NonNull Context context, FoldSettingProvider foldSettingProvider,
+ @NonNull DisplayDeviceRepository repo,
@NonNull Listener listener, @NonNull DisplayManagerService.SyncRoot syncRoot,
- @NonNull Handler handler, FoldSettingWrapper foldSettingWrapper,
- DisplayManagerFlags flags) {
- this(context, repo, listener, syncRoot, handler, new DeviceStateToLayoutMap(
- (isDefault) -> isDefault ? DEFAULT_DISPLAY : sNextNonDefaultDisplayId++),
- foldSettingWrapper, flags);
+ @NonNull Handler handler, DisplayManagerFlags flags) {
+ this(context, foldSettingProvider, repo, listener, syncRoot, handler,
+ new DeviceStateToLayoutMap((isDefault) -> isDefault ? DEFAULT_DISPLAY
+ : sNextNonDefaultDisplayId++), flags);
}
- LogicalDisplayMapper(@NonNull Context context, @NonNull DisplayDeviceRepository repo,
+ LogicalDisplayMapper(@NonNull Context context, FoldSettingProvider foldSettingProvider,
+ @NonNull DisplayDeviceRepository repo,
@NonNull Listener listener, @NonNull DisplayManagerService.SyncRoot syncRoot,
@NonNull Handler handler, @NonNull DeviceStateToLayoutMap deviceStateToLayoutMap,
- FoldSettingWrapper foldSettingWrapper, DisplayManagerFlags flags) {
+ DisplayManagerFlags flags) {
mSyncRoot = syncRoot;
mPowerManager = context.getSystemService(PowerManager.class);
mInteractive = mPowerManager.isInteractive();
mHandler = new LogicalDisplayMapperHandler(handler.getLooper());
mDisplayDeviceRepo = repo;
mListener = listener;
- mFoldSettingWrapper = foldSettingWrapper;
+ mFoldSettingProvider = foldSettingProvider;
mSingleDisplayDemoMode = SystemProperties.getBoolean("persist.demo.singledisplay", false);
mSupportsConcurrentInternalDisplays = context.getResources().getBoolean(
com.android.internal.R.bool.config_supportsConcurrentInternalDisplays);
@@ -488,10 +489,13 @@ class LogicalDisplayMapper implements DisplayDeviceRepository.Listener {
});
} else if (sleepDevice) {
// Send the device to sleep when required.
+ int goToSleepFlag =
+ mFoldSettingProvider.shouldSleepOnFold() ? 0
+ : PowerManager.GO_TO_SLEEP_FLAG_SOFT_SLEEP;
mHandler.post(() -> {
mPowerManager.goToSleep(SystemClock.uptimeMillis(),
PowerManager.GO_TO_SLEEP_REASON_DEVICE_FOLD,
- PowerManager.GO_TO_SLEEP_FLAG_SOFT_SLEEP);
+ goToSleepFlag);
});
}
}
@@ -565,7 +569,8 @@ class LogicalDisplayMapper implements DisplayDeviceRepository.Listener {
&& mDeviceStatesOnWhichToSleep.get(pendingState)
&& !mDeviceStatesOnWhichToSleep.get(currentState)
&& !isOverrideActive
- && isInteractive && isBootCompleted && !mFoldSettingWrapper.shouldStayAwakeOnFold();
+ && isInteractive && isBootCompleted
+ && !mFoldSettingProvider.shouldStayAwakeOnFold();
}
private boolean areAllTransitioningDisplaysOffLocked() {
diff --git a/services/core/java/com/android/server/display/SmallAreaDetectionController.java b/services/core/java/com/android/server/display/SmallAreaDetectionController.java
new file mode 100644
index 000000000000..adaa5390cb9b
--- /dev/null
+++ b/services/core/java/com/android/server/display/SmallAreaDetectionController.java
@@ -0,0 +1,177 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.display;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.content.Context;
+import android.content.pm.PackageManagerInternal;
+import android.provider.DeviceConfig;
+import android.provider.DeviceConfigInterface;
+import android.util.ArrayMap;
+import android.util.SparseArray;
+
+import com.android.internal.R;
+import com.android.internal.annotations.GuardedBy;
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.os.BackgroundThread;
+import com.android.server.LocalServices;
+import com.android.server.pm.UserManagerInternal;
+
+import java.io.PrintWriter;
+import java.util.Arrays;
+import java.util.Map;
+
+final class SmallAreaDetectionController {
+ private static native void nativeUpdateSmallAreaDetection(int[] uids, float[] thresholds);
+ private static native void nativeSetSmallAreaDetectionThreshold(int uid, float threshold);
+
+ // TODO(b/281720315): Move this to DeviceConfig once server side ready.
+ private static final String KEY_SMALL_AREA_DETECTION_ALLOWLIST =
+ "small_area_detection_allowlist";
+
+ private final Object mLock = new Object();
+ private final Context mContext;
+ private final PackageManagerInternal mPackageManager;
+ private final UserManagerInternal mUserManager;
+ @GuardedBy("mLock")
+ private final Map<String, Float> mAllowPkgMap = new ArrayMap<>();
+ // TODO(b/298722189): Update allowlist when user changes
+ @GuardedBy("mLock")
+ private int[] mUserIds;
+
+ static SmallAreaDetectionController create(@NonNull Context context) {
+ final SmallAreaDetectionController controller =
+ new SmallAreaDetectionController(context, DeviceConfigInterface.REAL);
+ final String property = DeviceConfigInterface.REAL.getProperty(
+ DeviceConfig.NAMESPACE_DISPLAY_MANAGER, KEY_SMALL_AREA_DETECTION_ALLOWLIST);
+ controller.updateAllowlist(property);
+ return controller;
+ }
+
+ @VisibleForTesting
+ SmallAreaDetectionController(Context context, DeviceConfigInterface deviceConfig) {
+ mContext = context;
+ mPackageManager = LocalServices.getService(PackageManagerInternal.class);
+ mUserManager = LocalServices.getService(UserManagerInternal.class);
+ deviceConfig.addOnPropertiesChangedListener(DeviceConfig.NAMESPACE_DISPLAY_MANAGER,
+ BackgroundThread.getExecutor(),
+ new SmallAreaDetectionController.OnPropertiesChangedListener());
+ mPackageManager.getPackageList(new PackageReceiver());
+ }
+
+ @VisibleForTesting
+ void updateAllowlist(@Nullable String property) {
+ synchronized (mLock) {
+ mAllowPkgMap.clear();
+ if (property != null) {
+ final String[] mapStrings = property.split(",");
+ for (String mapString : mapStrings) putToAllowlist(mapString);
+ } else {
+ final String[] defaultMapStrings = mContext.getResources()
+ .getStringArray(R.array.config_smallAreaDetectionAllowlist);
+ for (String defaultMapString : defaultMapStrings) putToAllowlist(defaultMapString);
+ }
+ updateSmallAreaDetection();
+ }
+ }
+
+ @GuardedBy("mLock")
+ private void putToAllowlist(String rowData) {
+ // Data format: package:threshold - e.g. "com.abc.music:0.05"
+ final String[] items = rowData.split(":");
+ if (items.length == 2) {
+ try {
+ final String pkg = items[0];
+ final float threshold = Float.valueOf(items[1]);
+ mAllowPkgMap.put(pkg, threshold);
+ } catch (Exception e) {
+ // Just skip if items[1] - the threshold is not parsable number
+ }
+ }
+ }
+
+ @GuardedBy("mLock")
+ private void updateUidListForAllUsers(SparseArray<Float> list, String pkg, float threshold) {
+ for (int i = 0; i < mUserIds.length; i++) {
+ final int userId = mUserIds[i];
+ final int uid = mPackageManager.getPackageUid(pkg, 0, userId);
+ if (uid > 0) list.put(uid, threshold);
+ }
+ }
+
+ @GuardedBy("mLock")
+ private void updateSmallAreaDetection() {
+ if (mAllowPkgMap.isEmpty()) return;
+
+ mUserIds = mUserManager.getUserIds();
+
+ final SparseArray<Float> uidThresholdList = new SparseArray<>();
+ for (String pkg : mAllowPkgMap.keySet()) {
+ final float threshold = mAllowPkgMap.get(pkg);
+ updateUidListForAllUsers(uidThresholdList, pkg, threshold);
+ }
+
+ final int[] uids = new int[uidThresholdList.size()];
+ final float[] thresholds = new float[uidThresholdList.size()];
+ for (int i = 0; i < uidThresholdList.size(); i++) {
+ uids[i] = uidThresholdList.keyAt(i);
+ thresholds[i] = uidThresholdList.valueAt(i);
+ }
+ updateSmallAreaDetection(uids, thresholds);
+ }
+
+ @VisibleForTesting
+ void updateSmallAreaDetection(int[] uids, float[] thresholds) {
+ nativeUpdateSmallAreaDetection(uids, thresholds);
+ }
+
+ void setSmallAreaDetectionThreshold(int uid, float threshold) {
+ nativeSetSmallAreaDetectionThreshold(uid, threshold);
+ }
+
+ void dump(PrintWriter pw) {
+ pw.println("Small area detection allowlist");
+ pw.println(" Packages:");
+ synchronized (mLock) {
+ for (String pkg : mAllowPkgMap.keySet()) {
+ pw.println(" " + pkg + " threshold = " + mAllowPkgMap.get(pkg));
+ }
+ pw.println(" mUserIds=" + Arrays.toString(mUserIds));
+ }
+ }
+
+ private class OnPropertiesChangedListener implements DeviceConfig.OnPropertiesChangedListener {
+ public void onPropertiesChanged(@NonNull DeviceConfig.Properties properties) {
+ if (properties.getKeyset().contains(KEY_SMALL_AREA_DETECTION_ALLOWLIST)) {
+ updateAllowlist(
+ properties.getString(KEY_SMALL_AREA_DETECTION_ALLOWLIST, null /*default*/));
+ }
+ }
+ }
+
+ private final class PackageReceiver implements PackageManagerInternal.PackageListObserver {
+ @Override
+ public void onPackageAdded(@NonNull String packageName, int uid) {
+ synchronized (mLock) {
+ if (mAllowPkgMap.containsKey(packageName)) {
+ setSmallAreaDetectionThreshold(uid, mAllowPkgMap.get(packageName));
+ }
+ }
+ }
+ }
+}
diff --git a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
index 1ec8b10813cd..131eec36f403 100644
--- a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
+++ b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
@@ -116,6 +116,7 @@ import android.util.Slog;
import android.util.SparseArray;
import android.util.SparseBooleanArray;
import android.util.proto.ProtoOutputStream;
+import android.view.IWindowManager;
import android.view.InputChannel;
import android.view.InputDevice;
import android.view.MotionEvent;
@@ -123,6 +124,7 @@ import android.view.WindowManager;
import android.view.WindowManager.DisplayImePolicy;
import android.view.WindowManager.LayoutParams;
import android.view.WindowManager.LayoutParams.SoftInputModeFlags;
+import android.view.WindowManagerGlobal;
import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.ImeTracker;
import android.view.inputmethod.InputBinding;
@@ -2988,7 +2990,8 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub
"Waiting for the lazy init of mImeDrawsImeNavBarRes");
}
final boolean canImeDrawsImeNavBar =
- mImeDrawsImeNavBarRes != null && mImeDrawsImeNavBarRes.get();
+ mImeDrawsImeNavBarRes != null && mImeDrawsImeNavBarRes.get()
+ && hasNavigationBarOnCurrentDisplay();
final boolean shouldShowImeSwitcherWhenImeIsShown = shouldShowImeSwitcherLocked(
InputMethodService.IME_ACTIVE | InputMethodService.IME_VISIBLE);
return (canImeDrawsImeNavBar ? InputMethodNavButtonFlags.IME_DRAWS_IME_NAV_BAR : 0)
@@ -2996,6 +2999,21 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub
? InputMethodNavButtonFlags.SHOW_IME_SWITCHER_WHEN_IME_IS_SHOWN : 0);
}
+ /**
+ * Whether the current display has a navigation bar. When this is {@code false} (e.g. emulator),
+ * the IME should <em>not</em> draw the IME navigation bar.
+ */
+ @GuardedBy("ImfLock.class")
+ private boolean hasNavigationBarOnCurrentDisplay() {
+ final IWindowManager wm = WindowManagerGlobal.getWindowManagerService();
+ try {
+ return wm.hasNavigationBar(mCurTokenDisplayId != INVALID_DISPLAY
+ ? mCurTokenDisplayId : DEFAULT_DISPLAY);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
@GuardedBy("ImfLock.class")
private boolean shouldShowImeSwitcherLocked(int visibility) {
if (!mShowOngoingImeSwitcherForPhones) return false;
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index 1afa3ed97463..69b9e25b411c 100755
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -2677,7 +2677,7 @@ public class NotificationManagerService extends SystemService {
mStatsManager.setPullAtomCallback(
DND_MODE_RULE,
null, // use default PullAtomMetadata values
- BackgroundThread.getExecutor(),
+ ConcurrentUtils.DIRECT_EXECUTOR,
mPullAtomCallback
);
}
diff --git a/services/core/java/com/android/server/notification/ZenModeHelper.java b/services/core/java/com/android/server/notification/ZenModeHelper.java
index e49074573ed3..a700d3235ea4 100644
--- a/services/core/java/com/android/server/notification/ZenModeHelper.java
+++ b/services/core/java/com/android/server/notification/ZenModeHelper.java
@@ -1101,8 +1101,11 @@ public class ZenModeHelper {
.allowAlarms(true)
.allowMedia(true)
.build());
- } else {
+ } else if (rule.zenPolicy != null) {
policy.apply(rule.zenPolicy);
+ } else {
+ // active rule with no specified policy inherits the default settings
+ policy.apply(mConfig.toZenPolicy());
}
}
diff --git a/services/core/java/com/android/server/notification/flags.aconfig b/services/core/java/com/android/server/notification/flags.aconfig
index 1908e4dff234..dcac8c98d19f 100644
--- a/services/core/java/com/android/server/notification/flags.aconfig
+++ b/services/core/java/com/android/server/notification/flags.aconfig
@@ -13,3 +13,10 @@ flag {
description: "This flag controls the polite notification feature"
bug: "270456865"
}
+
+flag {
+ name: "refactor_attention_helper"
+ namespace: "systemui"
+ description: "This flag controls the refactoring of NMS to NotificationAttentionHelper"
+ bug: "291907312"
+}
diff --git a/services/core/java/com/android/server/pm/ComputerEngine.java b/services/core/java/com/android/server/pm/ComputerEngine.java
index 1cfc7d76919a..69a6c1357350 100644
--- a/services/core/java/com/android/server/pm/ComputerEngine.java
+++ b/services/core/java/com/android/server/pm/ComputerEngine.java
@@ -33,6 +33,7 @@ import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_ENABLED;
import static android.content.pm.PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_NEVER;
import static android.content.pm.PackageManager.MATCH_ANY_USER;
import static android.content.pm.PackageManager.MATCH_APEX;
+import static android.content.pm.PackageManager.MATCH_ARCHIVED_PACKAGES;
import static android.content.pm.PackageManager.MATCH_DIRECT_BOOT_AWARE;
import static android.content.pm.PackageManager.MATCH_DIRECT_BOOT_UNAWARE;
import static android.content.pm.PackageManager.MATCH_DISABLED_COMPONENTS;
@@ -1507,7 +1508,7 @@ public class ComputerEngine implements Computer {
resolveExternalPackageName(p);
return packageInfo;
- } else if ((flags & MATCH_UNINSTALLED_PACKAGES) != 0
+ } else if ((flags & (MATCH_UNINSTALLED_PACKAGES | MATCH_ARCHIVED_PACKAGES)) != 0
&& PackageUserStateUtils.isAvailable(state, flags)) {
PackageInfo pi = new PackageInfo();
pi.packageName = ps.getPackageName();
@@ -1516,6 +1517,7 @@ public class ComputerEngine implements Computer {
pi.sharedUserId = (sharedUser != null) ? sharedUser.getName() : null;
pi.firstInstallTime = state.getFirstInstallTimeMillis();
pi.lastUpdateTime = ps.getLastUpdateTime();
+ pi.isArchived = isArchived(state);
ApplicationInfo ai = new ApplicationInfo();
ai.packageName = ps.getPackageName();
@@ -1614,7 +1616,7 @@ public class ComputerEngine implements Computer {
return generatePackageInfo(ps, flags, userId);
}
- if (!matchFactoryOnly && (flags & MATCH_KNOWN_PACKAGES) != 0) {
+ if (!matchFactoryOnly && (flags & (MATCH_KNOWN_PACKAGES | MATCH_ARCHIVED_PACKAGES)) != 0) {
final PackageStateInternal ps = mSettings.getPackage(packageName);
if (ps == null) return null;
if (filterSharedLibPackage(ps, filterCallingUid, userId, flags)) {
@@ -1678,9 +1680,11 @@ public class ComputerEngine implements Computer {
final boolean listUninstalled = (flags & MATCH_KNOWN_PACKAGES) != 0;
final boolean listApex = (flags & MATCH_APEX) != 0;
final boolean listFactory = (flags & MATCH_FACTORY_ONLY) != 0;
+ // Only list archived apps, not fully uninstalled ones. Other entries are unaffected.
+ final boolean listArchivedOnly = !listUninstalled && (flags & MATCH_ARCHIVED_PACKAGES) != 0;
ArrayList<PackageInfo> list;
- if (listUninstalled) {
+ if (listUninstalled || listArchivedOnly) {
list = new ArrayList<>(mSettings.getPackages().size());
for (PackageStateInternal ps : mSettings.getPackages().values()) {
if (listFactory) {
@@ -1696,6 +1700,9 @@ public class ComputerEngine implements Computer {
if (!listApex && ps.getPkg() != null && ps.getPkg().isApex()) {
continue;
}
+ if (listArchivedOnly && !isArchived(ps.getUserStateOrDefault(userId))) {
+ continue;
+ }
if (filterSharedLibPackage(ps, callingUid, userId, flags)) {
continue;
}
@@ -1739,6 +1746,13 @@ public class ComputerEngine implements Computer {
return new ParceledListSlice<>(list);
}
+ // TODO(b/288142708) Check for userState.isInstalled() here once this bug is fixed.
+ // If an app has isInstalled() == true - it should not be filtered above in any case, currently
+ // it is.
+ private static boolean isArchived(PackageUserStateInternal userState) {
+ return userState.getArchiveState() != null;
+ }
+
public final ResolveInfo createForwardingResolveInfoUnchecked(WatchedIntentFilter filter,
int sourceUserId, int targetUserId) {
ResolveInfo forwardingResolveInfo = new ResolveInfo();
@@ -2612,7 +2626,7 @@ public class ComputerEngine implements Computer {
return UserHandle.getUid(userId, p.getUid());
}
}
- if ((flags & MATCH_KNOWN_PACKAGES) != 0) {
+ if ((flags & (MATCH_KNOWN_PACKAGES | MATCH_ARCHIVED_PACKAGES)) != 0) {
final PackageStateInternal ps = mSettings.getPackage(packageName);
if (ps != null && PackageStateUtils.isMatch(ps, flags)
&& !shouldFilterApplication(ps, callingUid, userId)) {
@@ -3671,7 +3685,7 @@ public class ComputerEngine implements Computer {
ps.getAppId()));
}
}
- if ((flags & MATCH_KNOWN_PACKAGES) != 0) {
+ if ((flags & (MATCH_KNOWN_PACKAGES | MATCH_ARCHIVED_PACKAGES)) != 0) {
if (PackageStateUtils.isMatch(ps, flags)
&& !shouldFilterApplication(ps, callingUid, userId)) {
return mPermissionManager.getGidsForUid(
@@ -4525,7 +4539,8 @@ public class ComputerEngine implements Computer {
flags = updateFlagsForPackage(flags, userId);
enforceCrossUserPermission(Binder.getCallingUid(), userId, true /* requireFullPermission */,
false /* checkShell */, "get packages holding permissions");
- final boolean listUninstalled = (flags & MATCH_KNOWN_PACKAGES) != 0;
+ final boolean listUninstalled =
+ (flags & (MATCH_KNOWN_PACKAGES | MATCH_ARCHIVED_PACKAGES)) != 0;
ArrayList<PackageInfo> list = new ArrayList<>();
boolean[] tmpBools = new boolean[permissions.length];
diff --git a/services/core/java/com/android/server/pm/DeletePackageHelper.java b/services/core/java/com/android/server/pm/DeletePackageHelper.java
index a988821fe915..967998a790ac 100644
--- a/services/core/java/com/android/server/pm/DeletePackageHelper.java
+++ b/services/core/java/com/android/server/pm/DeletePackageHelper.java
@@ -20,6 +20,7 @@ import static android.Manifest.permission.CONTROL_KEYGUARD;
import static android.Manifest.permission.MANAGE_PROFILE_AND_DEVICE_OWNERS;
import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DEFAULT;
import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_ENABLED;
+import static android.content.pm.PackageManager.DELETE_KEEP_DATA;
import static android.content.pm.PackageManager.DELETE_SUCCEEDED;
import static android.content.pm.PackageManager.MATCH_KNOWN_PACKAGES;
import static android.content.pm.PackageManager.PERMISSION_GRANTED;
@@ -63,6 +64,7 @@ import com.android.internal.util.ArrayUtils;
import com.android.internal.util.Preconditions;
import com.android.server.pm.permission.PermissionManagerServiceInternal;
import com.android.server.pm.pkg.AndroidPackage;
+import com.android.server.pm.pkg.ArchiveState;
import com.android.server.pm.pkg.PackageStateInternal;
import com.android.server.pm.pkg.PackageUserState;
import com.android.server.wm.ActivityTaskManagerInternal;
@@ -433,6 +435,12 @@ final class DeletePackageHelper {
}
final int userId = user == null ? UserHandle.USER_ALL : user.getIdentifier();
+ if (outInfo != null) {
+ // Remember which users are affected, before the installed states are modified
+ outInfo.mRemovedUsers = (systemApp || userId == UserHandle.USER_ALL)
+ ? ps.queryInstalledUsers(allUserHandles, /* installed= */true)
+ : new int[]{userId};
+ }
if ((!systemApp || (flags & PackageManager.DELETE_SYSTEM_APP) != 0)
&& userId != UserHandle.USER_ALL) {
@@ -443,7 +451,7 @@ final class DeletePackageHelper {
// semantics than normal for uninstalling system apps.
final boolean clearPackageStateAndReturn;
synchronized (mPm.mLock) {
- markPackageUninstalledForUserLPw(ps, user);
+ markPackageUninstalledForUserLPw(ps, user, flags);
if (!systemApp) {
// Do not uninstall the APK if an app should be cached
boolean keepUninstalledPackage =
@@ -547,7 +555,7 @@ final class DeletePackageHelper {
}
@GuardedBy("mPm.mLock")
- private void markPackageUninstalledForUserLPw(PackageSetting ps, UserHandle user) {
+ private void markPackageUninstalledForUserLPw(PackageSetting ps, UserHandle user, int flags) {
final int[] userIds = (user == null || user.getIdentifier() == UserHandle.USER_ALL)
? mUserManagerInternal.getUserIds()
: new int[] {user.getIdentifier()};
@@ -556,6 +564,12 @@ final class DeletePackageHelper {
Slog.d(TAG, "Marking package:" + ps.getPackageName()
+ " uninstalled for user:" + nextUserId);
}
+ // Preserve ArchiveState if this is not a full uninstall
+ ArchiveState archiveState =
+ (flags & DELETE_KEEP_DATA) == 0
+ ? null
+ : ps.getUserStateOrDefault(nextUserId).getArchiveState();
+
ps.setUserState(nextUserId,
ps.getCeDataInode(nextUserId),
COMPONENT_ENABLED_STATE_DEFAULT,
@@ -576,7 +590,7 @@ final class DeletePackageHelper {
null /*splashScreenTheme*/,
0 /*firstInstallTime*/,
PackageManager.USER_MIN_ASPECT_RATIO_UNSET,
- null /*archiveState*/);
+ archiveState);
}
mPm.mSettings.writeKernelMappingLPr(ps);
}
@@ -622,7 +636,6 @@ final class DeletePackageHelper {
// Preserve data by setting flag
flags |= PackageManager.DELETE_KEEP_DATA;
}
-
synchronized (mPm.mInstallLock) {
deleteInstalledPackageLIF(deletedPs, true, flags, allUserHandles, outInfo,
writeSettings);
diff --git a/services/core/java/com/android/server/pm/InstallPackageHelper.java b/services/core/java/com/android/server/pm/InstallPackageHelper.java
index f8313e7d18ff..2712fa782c27 100644
--- a/services/core/java/com/android/server/pm/InstallPackageHelper.java
+++ b/services/core/java/com/android/server/pm/InstallPackageHelper.java
@@ -44,7 +44,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 com.android.server.pm.DexOptHelper.useArtService;
import static com.android.server.pm.InstructionSets.getAppDexInstructionSets;
import static com.android.server.pm.InstructionSets.getDexCodeInstructionSet;
@@ -1144,8 +1143,15 @@ final class InstallPackageHelper {
Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "parsePackage");
final ParsedPackage parsedPackage;
try (PackageParser2 pp = mPm.mInjector.getPreparingPackageParser()) {
- parsedPackage = pp.parsePackage(tmpPackageFile, parseFlags, false);
- AndroidPackageUtils.validatePackageDexMetadata(parsedPackage);
+ if (request.getPackageLite() == null || !request.isArchived()) {
+ // TODO: pass packageLite from install request instead of reparsing the package
+ parsedPackage = pp.parsePackage(tmpPackageFile, parseFlags, false);
+ AndroidPackageUtils.validatePackageDexMetadata(parsedPackage);
+ } else {
+ // Archived install mode, no APK.
+ parsedPackage = pp.parsePackageFromPackageLite(request.getPackageLite(),
+ parseFlags);
+ }
} catch (PackageManagerException e) {
throw new PrepareFailure("Failed parse during installPackageLI", e);
} finally {
@@ -1547,6 +1553,7 @@ final class InstallPackageHelper {
// TODO: Are these system flags actually set properly at this stage?
boolean isUpdatedSystemAppInferred =
pkgSetting != null && pkgSetting.isSystem();
+ // derivePackageAbi works OK for archived packages despite logging some errors.
final Pair<PackageAbiHelper.Abis, PackageAbiHelper.NativeLibraryPaths>
derivedAbi = mPackageAbiHelper.derivePackageAbi(parsedPackage,
systemApp, (isUpdatedSystemAppFromExistingSetting
@@ -3547,7 +3554,7 @@ final class InstallPackageHelper {
logCriticalInfo(Log.WARN, "System package " + packageName
+ " no longer exists; its data will be wiped");
mInjector.getHandler().post(
- () -> mRemovePackageHelper.removePackageData(ps, userIds, null, 0, false));
+ () -> mRemovePackageHelper.removePackageData(ps, userIds));
expectingBetter.put(ps.getPackageName(), ps.getPath());
} else {
// we still have a disabled system package, but, it still might have
@@ -3622,7 +3629,7 @@ final class InstallPackageHelper {
// partition], completely remove the package data.
final PackageSetting ps = mPm.mSettings.getPackageLPr(packageName);
if (ps != null && mPm.mPackages.get(packageName) == null) {
- mRemovePackageHelper.removePackageData(ps, userIds, null, 0, false);
+ mRemovePackageHelper.removePackageData(ps, userIds);
}
logCriticalInfo(Log.WARN, msg);
}
diff --git a/services/core/java/com/android/server/pm/InstallRequest.java b/services/core/java/com/android/server/pm/InstallRequest.java
index 6c265314c0cc..e1cfc418bfe5 100644
--- a/services/core/java/com/android/server/pm/InstallRequest.java
+++ b/services/core/java/com/android/server/pm/InstallRequest.java
@@ -21,7 +21,6 @@ import static android.content.pm.PackageManager.INSTALL_REASON_UNKNOWN;
import static android.content.pm.PackageManager.INSTALL_SCENARIO_DEFAULT;
import static android.content.pm.PackageManager.INSTALL_SUCCEEDED;
import static android.os.Process.INVALID_UID;
-
import static com.android.server.pm.PackageManagerService.SCAN_AS_INSTANT_APP;
import static com.android.server.pm.PackageManagerService.TAG;
@@ -35,6 +34,7 @@ import android.content.pm.PackageInstaller;
import android.content.pm.PackageManager;
import android.content.pm.SharedLibraryInfo;
import android.content.pm.SigningDetails;
+import android.content.pm.parsing.PackageLite;
import android.net.Uri;
import android.os.Build;
import android.os.Process;
@@ -93,6 +93,8 @@ final class InstallRequest {
private int[] mNewUsers;
@Nullable
private AndroidPackage mPkg;
+ @Nullable
+ private PackageLite mPackageLite;
private int mReturnCode;
private int mInternalErrorCode;
@Nullable
@@ -142,6 +144,7 @@ final class InstallRequest {
params.mInstallReason, params.mInstallScenario, params.mForceQueryableOverride,
params.mDataLoaderType, params.mPackageSource,
params.mApplicationEnabledSettingPersistent);
+ mPackageLite = params.mPackageLite;
mPackageMetrics = new PackageMetrics(this);
mIsInstallInherit = params.mIsInherit;
mSessionId = params.mSessionId;
@@ -306,6 +309,11 @@ final class InstallRequest {
}
@Nullable
+ public PackageLite getPackageLite() {
+ return mPackageLite;
+ }
+
+ @Nullable
public String getTraceMethod() {
return mInstallArgs == null ? null : mInstallArgs.mTraceMethod;
}
@@ -318,6 +326,10 @@ final class InstallRequest {
return mRemovedInfo != null && mRemovedInfo.mRemovedPackage != null;
}
+ public boolean isArchived() {
+ return PackageInstallerSession.isArchivedInstallation(getInstallFlags());
+ }
+
@Nullable
public String getRemovedPackage() {
return mRemovedInfo != null ? mRemovedInfo.mRemovedPackage : null;
diff --git a/services/core/java/com/android/server/pm/PackageArchiverService.java b/services/core/java/com/android/server/pm/PackageArchiverService.java
index 9c31dc9a1215..c7f067be8581 100644
--- a/services/core/java/com/android/server/pm/PackageArchiverService.java
+++ b/services/core/java/com/android/server/pm/PackageArchiverService.java
@@ -17,17 +17,26 @@
package com.android.server.pm;
import static android.content.pm.PackageManager.DELETE_KEEP_DATA;
+import static android.os.PowerExemptionManager.REASON_PACKAGE_UNARCHIVE;
+import static android.os.PowerExemptionManager.TEMPORARY_ALLOW_LIST_TYPE_FOREGROUND_SERVICE_ALLOWED;
+import android.Manifest;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.RequiresPermission;
+import android.app.AppOpsManager;
+import android.app.BroadcastOptions;
import android.content.Context;
+import android.content.Intent;
import android.content.IntentSender;
import android.content.pm.IPackageArchiverService;
import android.content.pm.LauncherActivityInfo;
import android.content.pm.LauncherApps;
+import android.content.pm.PackageArchiver;
import android.content.pm.PackageManager;
import android.content.pm.VersionedPackage;
import android.os.Binder;
+import android.os.Bundle;
import android.os.ParcelableException;
import android.os.UserHandle;
import android.text.TextUtils;
@@ -36,6 +45,7 @@ import com.android.internal.annotations.GuardedBy;
import com.android.server.pm.pkg.ArchiveState;
import com.android.server.pm.pkg.ArchiveState.ArchiveActivityInfo;
import com.android.server.pm.pkg.PackageStateInternal;
+import com.android.server.pm.pkg.PackageUserStateInternal;
import java.nio.file.Path;
import java.util.ArrayList;
@@ -51,7 +61,12 @@ import java.util.Objects;
*/
public class PackageArchiverService extends IPackageArchiverService.Stub {
- private static final String TAG = "PackageArchiver";
+ /**
+ * The maximum time granted for an app store to start a foreground service when unarchival
+ * is requested.
+ */
+ // TODO(b/297358628) Make this configurable through a flag.
+ private static final int DEFAULT_UNARCHIVE_FOREGROUND_TIMEOUT_MS = 120 * 1000;
private final Context mContext;
private final PackageManagerService mPm;
@@ -82,17 +97,14 @@ public class PackageArchiverService extends IPackageArchiverService.Stub {
snapshot.enforceCrossUserPermission(binderUid, userId, true, true,
"archiveApp");
verifyCaller(providedUid, binderUid);
- PackageStateInternal ps = getPackageState(packageName, snapshot, binderUid, userId);
- verifyInstaller(packageName, ps);
-
- // TODO(b/291569242) Verify that this list is not empty and return failure with
- // intentsender
- List<LauncherActivityInfo> mainActivities = getLauncherApps().getActivityList(
- ps.getPackageName(),
- new UserHandle(userId));
-
- // TODO(b/282952870) Bug: should happen after the uninstall completes successfully
- storeArchiveState(ps, mainActivities, userId);
+ ArchiveState archiveState;
+ try {
+ archiveState = createArchiveState(packageName, userId);
+ // TODO(b/282952870) Should be reverted if uninstall fails/cancels
+ storeArchiveState(packageName, archiveState, userId);
+ } catch (PackageManager.NameNotFoundException e) {
+ throw new ParcelableException(e);
+ }
// TODO(b/278553670) Add special strings for the delete dialog
mPm.mInstallerService.uninstall(
@@ -100,25 +112,173 @@ public class PackageArchiverService extends IPackageArchiverService.Stub {
callerPackageName, DELETE_KEEP_DATA, intentSender, userId);
}
- private static void verifyInstaller(String packageName, PackageStateInternal ps) {
- if (ps.getInstallSource().mUpdateOwnerPackageName == null
- && ps.getInstallSource().mInstallerPackageName == null) {
+ /**
+ * Creates archived state for the package and user.
+ */
+ public ArchiveState createArchiveState(String packageName, int userId)
+ throws PackageManager.NameNotFoundException {
+ PackageStateInternal ps = getPackageState(packageName, mPm.snapshotComputer(),
+ Binder.getCallingUid(), userId);
+ String responsibleInstallerPackage = getResponsibleInstallerPackage(ps);
+ verifyInstaller(responsibleInstallerPackage);
+
+ List<LauncherActivityInfo> mainActivities = getLauncherActivityInfos(ps, userId);
+ List<ArchiveActivityInfo> archiveActivityInfos = new ArrayList<>();
+ for (int i = 0; i < mainActivities.size(); i++) {
+ // TODO(b/278553670) Extract and store launcher icons
+ ArchiveActivityInfo activityInfo = new ArchiveActivityInfo(
+ mainActivities.get(i).getLabel().toString(),
+ Path.of("/TODO"), null);
+ archiveActivityInfos.add(activityInfo);
+ }
+
+ return new ArchiveState(archiveActivityInfos, responsibleInstallerPackage);
+ }
+
+ private void verifyInstaller(String installerPackage)
+ throws PackageManager.NameNotFoundException {
+ if (TextUtils.isEmpty(installerPackage)) {
+ throw new PackageManager.NameNotFoundException("No installer found");
+ }
+ if (!verifySupportsUnarchival(installerPackage)) {
+ throw new PackageManager.NameNotFoundException("Installer does not support unarchival");
+ }
+ }
+
+ /**
+ * @return true if installerPackage support unarchival:
+ * - has an action Intent.ACTION_UNARCHIVE_PACKAGE,
+ * - has permissions to install packages.
+ */
+ public boolean verifySupportsUnarchival(String installerPackage) {
+ // TODO(b/278553670) Check if installerPackage supports unarchival.
+ return true;
+ }
+
+ @Override
+ public void requestUnarchive(
+ @NonNull String packageName,
+ @NonNull String callerPackageName,
+ @NonNull UserHandle userHandle) {
+ Objects.requireNonNull(packageName);
+ Objects.requireNonNull(callerPackageName);
+ Objects.requireNonNull(userHandle);
+
+ Computer snapshot = mPm.snapshotComputer();
+ int userId = userHandle.getIdentifier();
+ int binderUid = Binder.getCallingUid();
+ int providedUid = snapshot.getPackageUid(callerPackageName, 0, userId);
+ snapshot.enforceCrossUserPermission(binderUid, userId, true, true,
+ "unarchiveApp");
+ verifyCaller(providedUid, binderUid);
+ PackageStateInternal ps;
+ try {
+ ps = getPackageState(packageName, snapshot, binderUid, userId);
+ verifyArchived(ps, userId);
+ } catch (PackageManager.NameNotFoundException e) {
+ throw new ParcelableException(e);
+ }
+ String installerPackage = getResponsibleInstallerPackage(ps);
+ if (installerPackage == null) {
throw new ParcelableException(
new PackageManager.NameNotFoundException(
- TextUtils.formatSimple("No installer found to archive app %s.",
+ TextUtils.formatSimple("No installer found to unarchive app %s.",
packageName)));
}
+
+ mPm.mHandler.post(() -> unarchiveInternal(packageName, userHandle, installerPackage));
+ }
+
+ private void verifyArchived(PackageStateInternal ps, int userId)
+ throws PackageManager.NameNotFoundException {
+ PackageUserStateInternal userState = ps.getUserStateOrDefault(userId);
+ // TODO(b/288142708) Check for isInstalled false here too.
+ if (userState.getArchiveState() == null) {
+ throw new PackageManager.NameNotFoundException(
+ TextUtils.formatSimple("Package %s is not currently archived.",
+ ps.getPackageName()));
+ }
+ }
+
+ @RequiresPermission(
+ allOf = {
+ Manifest.permission.INTERACT_ACROSS_USERS,
+ android.Manifest.permission.CHANGE_DEVICE_IDLE_TEMP_WHITELIST,
+ android.Manifest.permission.START_ACTIVITIES_FROM_BACKGROUND,
+ android.Manifest.permission.START_FOREGROUND_SERVICES_FROM_BACKGROUND},
+ conditional = true)
+ private void unarchiveInternal(String packageName, UserHandle userHandle,
+ String installerPackage) {
+ int userId = userHandle.getIdentifier();
+ Intent unarchiveIntent = new Intent(Intent.ACTION_UNARCHIVE_PACKAGE);
+ unarchiveIntent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
+ unarchiveIntent.putExtra(PackageArchiver.EXTRA_UNARCHIVE_PACKAGE_NAME, packageName);
+ unarchiveIntent.putExtra(PackageArchiver.EXTRA_UNARCHIVE_ALL_USERS,
+ userId == UserHandle.USER_ALL);
+ unarchiveIntent.setPackage(installerPackage);
+
+ // If the unarchival is requested for all users, the current user is used for unarchival.
+ UserHandle userForUnarchival = userId == UserHandle.USER_ALL
+ ? UserHandle.of(mPm.mUserManager.getCurrentUserId())
+ : userHandle;
+ mContext.sendOrderedBroadcastAsUser(
+ unarchiveIntent,
+ userForUnarchival,
+ /* receiverPermission = */ null,
+ AppOpsManager.OP_NONE,
+ createUnarchiveOptions(),
+ /* resultReceiver= */ null,
+ /* scheduler= */ null,
+ /* initialCode= */ 0,
+ /* initialData= */ null,
+ /* initialExtras= */ null);
+ }
+
+ private List<LauncherActivityInfo> getLauncherActivityInfos(PackageStateInternal ps,
+ int userId) throws PackageManager.NameNotFoundException {
+ List<LauncherActivityInfo> mainActivities =
+ Binder.withCleanCallingIdentity(() -> getLauncherApps().getActivityList(
+ ps.getPackageName(),
+ new UserHandle(userId)));
+ if (mainActivities.isEmpty()) {
+ throw new PackageManager.NameNotFoundException(
+ TextUtils.formatSimple("The app %s does not have a main activity.",
+ ps.getPackageName()));
+ }
+
+ return mainActivities;
+ }
+
+ @RequiresPermission(anyOf = {android.Manifest.permission.CHANGE_DEVICE_IDLE_TEMP_WHITELIST,
+ android.Manifest.permission.START_ACTIVITIES_FROM_BACKGROUND,
+ android.Manifest.permission.START_FOREGROUND_SERVICES_FROM_BACKGROUND})
+ private Bundle createUnarchiveOptions() {
+ BroadcastOptions options = BroadcastOptions.makeBasic();
+ options.setTemporaryAppAllowlist(getUnarchiveForegroundTimeout(),
+ TEMPORARY_ALLOW_LIST_TYPE_FOREGROUND_SERVICE_ALLOWED,
+ REASON_PACKAGE_UNARCHIVE, "");
+ return options.toBundle();
+ }
+
+ private static int getUnarchiveForegroundTimeout() {
+ return DEFAULT_UNARCHIVE_FOREGROUND_TIMEOUT_MS;
+ }
+
+ private String getResponsibleInstallerPackage(PackageStateInternal ps) {
+ return TextUtils.isEmpty(ps.getInstallSource().mUpdateOwnerPackageName)
+ ? ps.getInstallSource().mInstallerPackageName
+ : ps.getInstallSource().mUpdateOwnerPackageName;
}
@NonNull
private static PackageStateInternal getPackageState(String packageName,
- Computer snapshot, int callingUid, int userId) {
+ Computer snapshot, int callingUid, int userId)
+ throws PackageManager.NameNotFoundException {
PackageStateInternal ps = snapshot.getPackageStateFiltered(packageName, callingUid,
userId);
if (ps == null) {
- throw new ParcelableException(
- new PackageManager.NameNotFoundException(
- TextUtils.formatSimple("Package %s not found.", packageName)));
+ throw new PackageManager.NameNotFoundException(
+ TextUtils.formatSimple("Package %s not found.", packageName));
}
return ps;
}
@@ -130,38 +290,25 @@ public class PackageArchiverService extends IPackageArchiverService.Stub {
return mLauncherApps;
}
- private void storeArchiveState(PackageStateInternal ps,
- List<LauncherActivityInfo> mainActivities, int userId) {
- List<ArchiveActivityInfo> activityInfos = new ArrayList<>();
- for (int i = 0; i < mainActivities.size(); i++) {
- // TODO(b/278553670) Extract and store launcher icons
- ArchiveActivityInfo activityInfo = new ArchiveActivityInfo(
- mainActivities.get(i).getLabel().toString(),
- Path.of("/TODO"), null);
- activityInfos.add(activityInfo);
- }
-
- InstallSource installSource = ps.getInstallSource();
- String installerPackageName = installSource.mUpdateOwnerPackageName != null
- ? installSource.mUpdateOwnerPackageName : installSource.mInstallerPackageName;
-
+ private void storeArchiveState(String packageName, ArchiveState archiveState, int userId)
+ throws PackageManager.NameNotFoundException {
synchronized (mPm.mLock) {
- PackageSetting packageSetting = getPackageSettingLocked(ps.getPackageName(), userId);
+ PackageSetting packageSetting = getPackageSettingLocked(packageName, userId);
packageSetting
.modifyUserState(userId)
- .setArchiveState(new ArchiveState(activityInfos, installerPackageName));
+ .setArchiveState(archiveState);
}
}
@NonNull
@GuardedBy("mPm.mLock")
- private PackageSetting getPackageSettingLocked(String packageName, int userId) {
+ private PackageSetting getPackageSettingLocked(String packageName, int userId)
+ throws PackageManager.NameNotFoundException {
PackageSetting ps = mPm.mSettings.getPackageLPr(packageName);
// Shouldn't happen, we already verify presence of the package in getPackageState()
if (ps == null || !ps.getUserStateOrDefault(userId).isInstalled()) {
- throw new ParcelableException(
- new PackageManager.NameNotFoundException(
- TextUtils.formatSimple("Package %s not found.", packageName)));
+ throw new PackageManager.NameNotFoundException(
+ TextUtils.formatSimple("Package %s not found.", packageName));
}
return ps;
}
diff --git a/services/core/java/com/android/server/pm/PackageInstallerHistoricalSession.java b/services/core/java/com/android/server/pm/PackageInstallerHistoricalSession.java
new file mode 100644
index 000000000000..d40a7157253b
--- /dev/null
+++ b/services/core/java/com/android/server/pm/PackageInstallerHistoricalSession.java
@@ -0,0 +1,203 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.pm;
+
+import android.content.pm.PackageInstaller.PreapprovalDetails;
+import android.content.pm.PackageInstaller.SessionInfo;
+import android.content.pm.PackageInstaller.SessionParams;
+
+import com.android.internal.util.IndentingPrintWriter;
+
+import java.io.CharArrayWriter;
+import java.io.File;
+
+/**
+ * A historical session object that stores minimal session info.
+ */
+public final class PackageInstallerHistoricalSession {
+ public final int sessionId;
+ public final int userId;
+ private final String mParams;
+ private final long mCreatedMillis;
+
+ private final File mStageDir;
+ private final String mStageCid;
+
+ private final long mUpdatedMillis;
+
+ private final long mCommittedMillis;
+
+ private final int mOriginalInstallerUid;
+
+ private final String mOriginalInstallerPackageName;
+
+ private final int mInstallerUid;
+
+ private final InstallSource mInstallSource;
+
+ private final float mClientProgress;
+
+ private final float mProgress;
+ private final boolean mSealed;
+
+ private final boolean mPreapprovalRequested;
+ private final boolean mCommitted;
+
+ private final boolean mStageDirInUse;
+
+ private final boolean mPermissionsManuallyAccepted;
+
+ private final int mFinalStatus;
+ private final String mFinalMessage;
+
+ private final int mFds;
+ private final int mBridges;
+
+ private final String mPreapprovalDetails;
+ private final int mParentSessionId;
+ private final boolean mDestroyed;
+ private final int[] mChildSessionIds;
+ private final boolean mSessionApplied;
+ private final boolean mSessionReady;
+ private final boolean mSessionFailed;
+ private final int mSessionErrorCode;
+ private final String mSessionErrorMessage;
+
+ PackageInstallerHistoricalSession(int sessionId, int userId, int originalInstallerUid,
+ String originalInstallerPackageName, InstallSource installSource, int installerUid,
+ long createdMillis, long updatedMillis, long committedMillis, File stageDir,
+ String stageCid, float clientProgress, float progress, boolean committed,
+ boolean preapprovalRequested, boolean sealed, boolean permissionsManuallyAccepted,
+ boolean stageDirInUse, boolean destroyed, int fds, int bridges, int finalStatus,
+ String finalMessage, SessionParams params, int parentSessionId,
+ int[] childSessionIds, boolean sessionApplied, boolean sessionFailed,
+ boolean sessionReady, int sessionErrorCode, String sessionErrorMessage,
+ PreapprovalDetails preapprovalDetails) {
+ this.sessionId = sessionId;
+ this.userId = userId;
+ this.mOriginalInstallerUid = originalInstallerUid;
+ this.mOriginalInstallerPackageName = originalInstallerPackageName;
+ this.mInstallSource = installSource;
+ this.mInstallerUid = installerUid;
+ this.mCreatedMillis = createdMillis;
+ this.mUpdatedMillis = updatedMillis;
+ this.mCommittedMillis = committedMillis;
+ this.mStageDir = stageDir;
+ this.mStageCid = stageCid;
+ this.mClientProgress = clientProgress;
+ this.mProgress = progress;
+ this.mCommitted = committed;
+ this.mPreapprovalRequested = preapprovalRequested;
+ this.mSealed = sealed;
+ this.mPermissionsManuallyAccepted = permissionsManuallyAccepted;
+ this.mStageDirInUse = stageDirInUse;
+ this.mDestroyed = destroyed;
+ this.mFds = fds;
+ this.mBridges = bridges;
+ this.mFinalStatus = finalStatus;
+ this.mFinalMessage = finalMessage;
+
+ CharArrayWriter writer = new CharArrayWriter();
+ IndentingPrintWriter pw = new IndentingPrintWriter(writer, " ");
+ params.dump(pw);
+ this.mParams = writer.toString();
+
+ this.mParentSessionId = parentSessionId;
+ this.mChildSessionIds = childSessionIds;
+ this.mSessionApplied = sessionApplied;
+ this.mSessionFailed = sessionFailed;
+ this.mSessionReady = sessionReady;
+ this.mSessionErrorCode = sessionErrorCode;
+ this.mSessionErrorMessage = sessionErrorMessage;
+ if (preapprovalDetails != null) {
+ this.mPreapprovalDetails = preapprovalDetails.toString();
+ } else {
+ this.mPreapprovalDetails = null;
+ }
+ }
+
+ void dump(IndentingPrintWriter pw) {
+ pw.println("Session " + sessionId + ":");
+ pw.increaseIndent();
+
+ pw.printPair("userId", userId);
+ pw.printPair("mOriginalInstallerUid", mOriginalInstallerUid);
+ pw.printPair("mOriginalInstallerPackageName", mOriginalInstallerPackageName);
+ pw.printPair("installerPackageName", mInstallSource.mInstallerPackageName);
+ pw.printPair("installInitiatingPackageName", mInstallSource.mInitiatingPackageName);
+ pw.printPair("installOriginatingPackageName", mInstallSource.mOriginatingPackageName);
+ pw.printPair("mInstallerUid", mInstallerUid);
+ pw.printPair("createdMillis", mCreatedMillis);
+ pw.printPair("updatedMillis", mUpdatedMillis);
+ pw.printPair("committedMillis", mCommittedMillis);
+ pw.printPair("stageDir", mStageDir);
+ pw.printPair("stageCid", mStageCid);
+ pw.println();
+
+ pw.print(mParams);
+
+ pw.printPair("mClientProgress", mClientProgress);
+ pw.printPair("mProgress", mProgress);
+ pw.printPair("mCommitted", mCommitted);
+ pw.printPair("mPreapprovalRequested", mPreapprovalRequested);
+ pw.printPair("mSealed", mSealed);
+ pw.printPair("mPermissionsManuallyAccepted", mPermissionsManuallyAccepted);
+ pw.printPair("mStageDirInUse", mStageDirInUse);
+ pw.printPair("mDestroyed", mDestroyed);
+ pw.printPair("mFds", mFds);
+ pw.printPair("mBridges", mBridges);
+ pw.printPair("mFinalStatus", mFinalStatus);
+ pw.printPair("mFinalMessage", mFinalMessage);
+ pw.printPair("mParentSessionId", mParentSessionId);
+ pw.printPair("mChildSessionIds", mChildSessionIds);
+ pw.printPair("mSessionApplied", mSessionApplied);
+ pw.printPair("mSessionFailed", mSessionFailed);
+ pw.printPair("mSessionReady", mSessionReady);
+ pw.printPair("mSessionErrorCode", mSessionErrorCode);
+ pw.printPair("mSessionErrorMessage", mSessionErrorMessage);
+ pw.printPair("mPreapprovalDetails", mPreapprovalDetails);
+ pw.println();
+
+ pw.decreaseIndent();
+ }
+
+ /**
+ * Generates a {@link SessionInfo} object.
+ */
+ public SessionInfo generateInfo() {
+ final SessionInfo info = new SessionInfo();
+ info.sessionId = sessionId;
+ info.userId = userId;
+ info.installerPackageName = mInstallSource.mInstallerPackageName;
+ info.installerAttributionTag = mInstallSource.mInstallerAttributionTag;
+ info.progress = mProgress;
+ info.sealed = mSealed;
+ info.isCommitted = mCommitted;
+ info.isPreapprovalRequested = mPreapprovalRequested;
+
+ info.parentSessionId = mParentSessionId;
+ info.childSessionIds = mChildSessionIds;
+ info.isSessionApplied = mSessionApplied;
+ info.isSessionReady = mSessionReady;
+ info.isSessionFailed = mSessionFailed;
+ info.setSessionErrorCode(mSessionErrorCode, mSessionErrorMessage);
+ info.createdMillis = mCreatedMillis;
+ info.updatedMillis = mUpdatedMillis;
+ info.installerUid = mInstallerUid;
+ return info;
+ }
+}
diff --git a/services/core/java/com/android/server/pm/PackageInstallerService.java b/services/core/java/com/android/server/pm/PackageInstallerService.java
index 10cd51a717cb..e3602565ef5b 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerService.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerService.java
@@ -111,7 +111,6 @@ import libcore.io.IoUtils;
import org.xmlpull.v1.XmlPullParserException;
-import java.io.CharArrayWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
@@ -230,7 +229,7 @@ public class PackageInstallerService extends IPackageInstaller.Stub implements
/** Historical sessions kept around for debugging purposes */
@GuardedBy("mSessions")
- private final List<String> mHistoricalSessions = new ArrayList<>();
+ private final List<PackageInstallerHistoricalSession> mHistoricalSessions = new ArrayList<>();
@GuardedBy("mSessions")
private final SparseIntArray mHistoricalSessionsByInstaller = new SparseIntArray();
@@ -570,14 +569,11 @@ public class PackageInstallerService extends IPackageInstaller.Stub implements
@GuardedBy("mSessions")
private void addHistoricalSessionLocked(PackageInstallerSession session) {
- CharArrayWriter writer = new CharArrayWriter();
- IndentingPrintWriter pw = new IndentingPrintWriter(writer, " ");
- session.dump(pw);
if (mHistoricalSessions.size() > HISTORICAL_SESSIONS_THRESHOLD) {
Slog.d(TAG, "Historical sessions size reaches threshold, clear the oldest");
mHistoricalSessions.subList(0, HISTORICAL_CLEAR_SIZE).clear();
}
- mHistoricalSessions.add(writer.toString());
+ mHistoricalSessions.add(session.createHistoricalSession());
int installerUid = session.getInstallerUid();
// Increment the number of sessions by this installerUid.
@@ -1223,6 +1219,24 @@ public class PackageInstallerService extends IPackageInstaller.Stub implements
return new ParceledListSlice<>(result);
}
+ ParceledListSlice<SessionInfo> getHistoricalSessions(int userId) {
+ final int callingUid = Binder.getCallingUid();
+ final Computer snapshot = mPm.snapshotComputer();
+ snapshot.enforceCrossUserPermission(callingUid, userId, true, false, "getAllSessions");
+
+ final List<SessionInfo> result = new ArrayList<>();
+ synchronized (mSessions) {
+ for (int i = 0; i < mHistoricalSessions.size(); i++) {
+ final PackageInstallerHistoricalSession session = mHistoricalSessions.get(i);
+ if (userId == UserHandle.USER_ALL || session.userId == userId) {
+ result.add(session.generateInfo());
+ }
+ }
+ }
+ result.removeIf(info -> shouldFilterSession(snapshot, callingUid, info));
+ return new ParceledListSlice<>(result);
+ }
+
@Override
public void uninstall(VersionedPackage versionedPackage, String callerPackageName, int flags,
IntentSender statusReceiver, int userId) {
@@ -1837,7 +1851,7 @@ public class PackageInstallerService extends IPackageInstaller.Stub implements
pw.increaseIndent();
N = mHistoricalSessions.size();
for (int i = 0; i < N; i++) {
- pw.print(mHistoricalSessions.get(i));
+ mHistoricalSessions.get(i).dump(pw);
pw.println();
}
pw.println();
diff --git a/services/core/java/com/android/server/pm/PackageInstallerSession.java b/services/core/java/com/android/server/pm/PackageInstallerSession.java
index 923bbab42ab3..0dd4111adbfa 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerSession.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerSession.java
@@ -31,6 +31,7 @@ import static android.content.pm.PackageManager.INSTALL_FAILED_INVALID_APK;
import static android.content.pm.PackageManager.INSTALL_FAILED_MEDIA_UNAVAILABLE;
import static android.content.pm.PackageManager.INSTALL_FAILED_MISSING_SPLIT;
import static android.content.pm.PackageManager.INSTALL_FAILED_PRE_APPROVAL_NOT_AVAILABLE;
+import static android.content.pm.PackageManager.INSTALL_FAILED_VERIFICATION_FAILURE;
import static android.content.pm.PackageManager.INSTALL_PARSE_FAILED_NO_CERTIFICATES;
import static android.content.pm.PackageManager.INSTALL_STAGED;
import static android.content.pm.PackageManager.INSTALL_SUCCEEDED;
@@ -39,7 +40,6 @@ import static android.provider.DeviceConfig.NAMESPACE_PACKAGE_MANAGER_SERVICE;
import static android.system.OsConstants.O_CREAT;
import static android.system.OsConstants.O_RDONLY;
import static android.system.OsConstants.O_WRONLY;
-
import static com.android.internal.annotations.VisibleForTesting.Visibility.PACKAGE;
import static com.android.internal.util.XmlUtils.readBitmapAttribute;
import static com.android.internal.util.XmlUtils.readByteArrayAttribute;
@@ -52,6 +52,7 @@ import static com.android.internal.util.XmlUtils.writeUriAttribute;
import static com.android.server.pm.PackageInstallerService.prepareStageDir;
import static com.android.server.pm.PackageManagerService.APP_METADATA_FILE_NAME;
import static com.android.server.pm.PackageManagerServiceUtils.isInstalledByAdb;
+import static com.android.server.pm.PackageManagerShellCommandDataLoader.Metadata;
import android.Manifest;
import android.annotation.AnyThread;
@@ -838,6 +839,10 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
params.dataLoaderParams.getComponentName().getPackageName());
}
+ static boolean isArchivedInstallation(int installFlags) {
+ return (installFlags & PackageManager.INSTALL_ARCHIVED) != 0;
+ }
+
private final Handler.Callback mHandlerCallback = new Handler.Callback() {
@Override
public boolean handleMessage(Message msg) {
@@ -896,6 +901,10 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
return isSystemDataLoaderInstallation(this.params);
}
+ private boolean isArchivedInstallation() {
+ return isArchivedInstallation(this.params.installFlags);
+ }
+
/**
* @return {@code true} iff the installing is app an device owner or affiliated profile owner.
*/
@@ -1146,6 +1155,41 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
if (isIncrementalInstallation() && !IncrementalManager.isAllowed()) {
throw new IllegalArgumentException("Incremental installation not allowed.");
}
+
+ if (isArchivedInstallation()) {
+ if (params.mode != SessionParams.MODE_FULL_INSTALL) {
+ throw new IllegalArgumentException(
+ "Archived installation can only be full install.");
+ }
+ if (!isStreamingInstallation() || !isSystemDataLoaderInstallation()) {
+ throw new IllegalArgumentException(
+ "Archived installation can only use Streaming System DataLoader.");
+ }
+ if (!TextUtils.isEmpty(params.appPackageName) && !isArchivedInstallationAllowed(
+ params.appPackageName)) {
+ throw new IllegalArgumentException(
+ "Archived installation of this package is not allowed.");
+ }
+ }
+ }
+
+ PackageInstallerHistoricalSession createHistoricalSession() {
+ final float progress;
+ final float clientProgress;
+ synchronized (mProgressLock) {
+ progress = mProgress;
+ clientProgress = mClientProgress;
+ }
+ synchronized (mLock) {
+ return new PackageInstallerHistoricalSession(sessionId, userId, mOriginalInstallerUid,
+ mOriginalInstallerPackageName, mInstallSource, mInstallerUid, createdMillis,
+ updatedMillis, committedMillis, stageDir, stageCid, clientProgress, progress,
+ isCommitted(), isPreapprovalRequested(), mSealed, mPermissionsManuallyAccepted,
+ mStageDirInUse, mDestroyed, mFds.size(), mBridges.size(), mFinalStatus,
+ mFinalMessage, params, mParentSessionId, getChildSessionIdsLocked(),
+ mSessionApplied, mSessionFailed, mSessionReady, mSessionErrorCode,
+ mSessionErrorMessage, mPreapprovalDetails);
+ }
}
/**
@@ -1462,6 +1506,58 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
}
@GuardedBy("mLock")
+ private List<ApkLite> getAddedApkLitesLocked() throws PackageManagerException {
+ if (!isArchivedInstallation()) {
+ List<File> files = getAddedApksLocked();
+ final List<ApkLite> result = new ArrayList<>(files.size());
+
+ final ParseTypeImpl input = ParseTypeImpl.forDefaultParsing();
+ for (int i = 0, size = files.size(); i < size; ++i) {
+ final ParseResult<ApkLite> parseResult = ApkLiteParseUtils.parseApkLite(
+ input.reset(), files.get(i),
+ ParsingPackageUtils.PARSE_COLLECT_CERTIFICATES);
+ if (parseResult.isError()) {
+ throw new PackageManagerException(parseResult.getErrorCode(),
+ parseResult.getErrorMessage(), parseResult.getException());
+ }
+ result.add(parseResult.getResult());
+ }
+
+ return result;
+ }
+
+ InstallationFile[] files = getInstallationFilesLocked();
+ final List<ApkLite> result = new ArrayList<>(files.length);
+
+ for (int i = 0, size = files.length; i < size; ++i) {
+ File file = new File(stageDir, files[i].getName());
+ if (!sAddedApkFilter.accept(file)) {
+ continue;
+ }
+
+ final Metadata metadata;
+ try {
+ metadata = Metadata.fromByteArray(files[i].getMetadata());
+ } catch (IOException e) {
+ throw new PackageManagerException(INSTALL_FAILED_INTERNAL_ERROR,
+ "Failed to ", e);
+ }
+ if (metadata.getMode() != Metadata.ARCHIVED) {
+ throw new PackageManagerException(INSTALL_FAILED_VERIFICATION_FAILURE,
+ "File metadata is not for ARCHIVED package: " + file);
+ }
+
+ var archPkg = metadata.getArchivedPackage();
+ if (archPkg.packageName == null || archPkg.signingDetails == null) {
+ throw new PackageManagerException(INSTALL_FAILED_VERIFICATION_FAILURE,
+ "ArchivedPackage does not contain required info: " + file);
+ }
+ result.add(new ApkLite(file.getAbsolutePath(), archPkg));
+ }
+ return result;
+ }
+
+ @GuardedBy("mLock")
private List<File> getRemovedFilesLocked() {
String[] names = getNamesLocked();
return filterFiles(stageDir, names, sRemovedFilter);
@@ -2128,6 +2224,19 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
}
/**
+ * Check if this package can be installed archived.
+ */
+ private static boolean isArchivedInstallationAllowed(String packageName) {
+ final PackageManagerInternal pmi = LocalServices.getService(PackageManagerInternal.class);
+ final PackageStateInternal existingPkgSetting = pmi.getPackageStateInternal(packageName);
+ if (existingPkgSetting == null) {
+ return true;
+ }
+
+ return false;
+ }
+
+ /**
* Checks if the package can be installed on IncFs.
*/
private static boolean isIncrementalInstallationAllowed(String packageName) {
@@ -2732,9 +2841,18 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
throw new PackageManagerException(INSTALL_FAILED_INTERNAL_ERROR,
"Session not sealed");
}
- Objects.requireNonNull(mPackageName);
- Objects.requireNonNull(mSigningDetails);
- Objects.requireNonNull(mResolvedBaseFile);
+ if (mPackageName == null) {
+ throw new PackageManagerException(INSTALL_FAILED_INTERNAL_ERROR,
+ "Session no package name");
+ }
+ if (mSigningDetails == null) {
+ throw new PackageManagerException(INSTALL_FAILED_INTERNAL_ERROR,
+ "Session no signing data");
+ }
+ if (mResolvedBaseFile == null) {
+ throw new PackageManagerException(INSTALL_FAILED_INTERNAL_ERROR,
+ "Session no resolved base file");
+ }
final PackageLite result;
if (!isApexSession()) {
// For mode inherit existing, it would link/copy existing files to stage dir in
@@ -3176,7 +3294,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
}
}
- final List<File> addedFiles = getAddedApksLocked();
+ final List<ApkLite> addedFiles = getAddedApkLitesLocked();
if (addedFiles.isEmpty()
&& (removeSplitList.size() == 0 || getStagedAppMetadataFile() != null)) {
throw new PackageManagerException(INSTALL_FAILED_INVALID_APK,
@@ -3190,15 +3308,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
final ArraySet<String> requiredSplitTypes = new ArraySet<>();
final ArrayMap<String, ApkLite> splitApks = new ArrayMap<>();
final ParseTypeImpl input = ParseTypeImpl.forDefaultParsing();
- for (File addedFile : addedFiles) {
- final ParseResult<ApkLite> result = ApkLiteParseUtils.parseApkLite(input.reset(),
- addedFile, ParsingPackageUtils.PARSE_COLLECT_CERTIFICATES);
- if (result.isError()) {
- throw new PackageManagerException(result.getErrorCode(),
- result.getErrorMessage(), result.getException());
- }
-
- final ApkLite apk = result.getResult();
+ for (ApkLite apk : addedFiles) {
if (!stagedSplits.add(apk.getSplitName())) {
throw new PackageManagerException(INSTALL_FAILED_INVALID_APK,
"Split " + apk.getSplitName() + " was defined multiple times");
@@ -3214,7 +3324,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
}
mHasDeviceAdminReceiver = apk.isHasDeviceAdminReceiver();
- assertApkConsistentLocked(String.valueOf(addedFile), apk);
+ assertApkConsistentLocked(String.valueOf(apk), apk);
// Take this opportunity to enforce uniform naming
final String targetName = ApkLiteParseUtils.splitNameToFileName(apk);
@@ -3235,7 +3345,10 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
}
final File targetFile = new File(stageDir, targetName);
- resolveAndStageFileLocked(addedFile, targetFile, apk.getSplitName());
+ if (!isArchivedInstallation()) {
+ final File sourceFile = new File(apk.getPath());
+ resolveAndStageFileLocked(sourceFile, targetFile, apk.getSplitName());
+ }
// Base is coming from session
if (apk.getSplitName() == null) {
@@ -3275,6 +3388,23 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
}
}
+ if (isArchivedInstallation()) {
+ if (!isArchivedInstallationAllowed(mPackageName)) {
+ throw new PackageManagerException(
+ PackageManager.INSTALL_FAILED_SESSION_INVALID,
+ "Archived installation of this package is not allowed.");
+ }
+
+ if (!isInstalledByAdb(getInstallSource().mInitiatingPackageName)
+ && !mPm.mArchiverService.verifySupportsUnarchival(
+ getInstallSource().mInstallerPackageName)) {
+ throw new PackageManagerException(
+ PackageManager.INSTALL_FAILED_SESSION_INVALID,
+ "Installer has to support unarchival in order to install archived "
+ + "packages.");
+ }
+ }
+
if (isIncrementalInstallation()) {
if (!isIncrementalInstallationAllowed(mPackageName)) {
throw new PackageManagerException(
@@ -4005,6 +4135,11 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
NativeLibraryHelper.removeNativeBinariesFromDirLI(libDir, true);
}
+ // Skip native libraries processing for archival installation.
+ if (isArchivedInstallation()) {
+ return;
+ }
+
NativeLibraryHelper.Handle handle = null;
try {
handle = NativeLibraryHelper.Handle.create(packageLite);
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index c0c3ec421979..0c2f1ca54f73 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -36,7 +36,6 @@ 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.provider.DeviceConfig.NAMESPACE_PACKAGE_MANAGER_SERVICE;
-
import static com.android.internal.annotations.VisibleForTesting.Visibility;
import static com.android.internal.util.FrameworkStatsLog.BOOT_TIME_EVENT_DURATION__EVENT__OTA_PACKAGE_MANAGER_INIT_TIME;
import static com.android.server.pm.DexOptHelper.useArtService;
@@ -77,6 +76,7 @@ import android.content.IntentSender;
import android.content.IntentSender.SendIntentException;
import android.content.pm.ActivityInfo;
import android.content.pm.ApplicationInfo;
+import android.content.pm.ArchivedPackageParcel;
import android.content.pm.AuxiliaryResolveInfo;
import android.content.pm.ChangedPackages;
import android.content.pm.Checksum;
@@ -115,7 +115,11 @@ import android.content.pm.UserPackage;
import android.content.pm.VerifierDeviceIdentity;
import android.content.pm.VersionedPackage;
import android.content.pm.overlay.OverlayPaths;
+import android.content.pm.parsing.ApkLite;
+import android.content.pm.parsing.ApkLiteParseUtils;
import android.content.pm.parsing.PackageLite;
+import android.content.pm.parsing.result.ParseResult;
+import android.content.pm.parsing.result.ParseTypeImpl;
import android.content.res.Resources;
import android.database.ContentObserver;
import android.graphics.Bitmap;
@@ -6298,6 +6302,37 @@ public class PackageManagerService implements PackageSender, TestUtilityService
}
}
+ @Override
+ public ArchivedPackageParcel getArchivedPackage(String apkPath) {
+ ParseTypeImpl input = ParseTypeImpl.forDefaultParsing();
+ ParseResult<ApkLite> result = ApkLiteParseUtils.parseApkLite(input.reset(),
+ new File(apkPath), ParsingPackageUtils.PARSE_COLLECT_CERTIFICATES);
+ if (result.isError()) {
+ throw new IllegalArgumentException(result.getErrorMessage(), result.getException());
+ }
+ final ApkLite apk = result.getResult();
+
+ ArchivedPackageParcel archPkg = new ArchivedPackageParcel();
+ archPkg.packageName = apk.getPackageName();
+ archPkg.signingDetails = apk.getSigningDetails();
+
+ archPkg.versionCodeMajor = apk.getVersionCodeMajor();
+ archPkg.versionCode = apk.getVersionCode();
+
+ archPkg.targetSdkVersion = apk.getTargetSdkVersion();
+
+ // These get translated in flags important for user data management.
+ archPkg.backupAllowed = apk.isBackupAllowed();
+ archPkg.defaultToDeviceProtectedStorage =
+ apk.isDefaultToDeviceProtectedStorage();
+ archPkg.requestLegacyExternalStorage = apk.isRequestLegacyExternalStorage();
+ archPkg.userDataFragile = apk.isUserDataFragile();
+ archPkg.clearUserDataOnFailedRestoreAllowed =
+ apk.isClearUserDataOnFailedRestoreAllowed();
+
+ return archPkg;
+ }
+
/**
* Wait for the handler to finish handling all pending messages.
* @param timeoutMillis Maximum time in milliseconds to wait.
@@ -6939,6 +6974,11 @@ public class PackageManagerService implements PackageSender, TestUtilityService
return mDistractingPackageHelper.getDistractingPackageRestrictionsAsUser(snapshot,
packageNames, userId, callingUid);
}
+
+ @Override
+ public ParceledListSlice<PackageInstaller.SessionInfo> getHistoricalSessions(int userId) {
+ return mInstallerService.getHistoricalSessions(userId);
+ }
}
private void setEnabledOverlayPackages(@UserIdInt int userId,
@@ -7754,7 +7794,6 @@ public class PackageManagerService implements PackageSender, TestUtilityService
consumer.accept(mPackageStateMutator);
mPackageStateMutator.onFinished();
- onChanged();
}
return PackageStateMutator.Result.SUCCESS;
diff --git a/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java b/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java
index db997d8d1d79..2028231ab36b 100644
--- a/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java
+++ b/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java
@@ -919,16 +919,22 @@ public class PackageManagerServiceUtils {
final File packageFile = new File(packagePath);
final long sizeBytes;
- try {
- sizeBytes = InstallLocationUtils.calculateInstalledSize(pkg, abiOverride);
- } catch (IOException e) {
- if (!packageFile.exists()) {
- ret.recommendedInstallLocation = InstallLocationUtils.RECOMMEND_FAILED_INVALID_URI;
- } else {
- ret.recommendedInstallLocation = InstallLocationUtils.RECOMMEND_FAILED_INVALID_APK;
- }
+ if (!PackageInstallerSession.isArchivedInstallation(flags)) {
+ try {
+ sizeBytes = InstallLocationUtils.calculateInstalledSize(pkg, abiOverride);
+ } catch (IOException e) {
+ if (!packageFile.exists()) {
+ ret.recommendedInstallLocation =
+ InstallLocationUtils.RECOMMEND_FAILED_INVALID_URI;
+ } else {
+ ret.recommendedInstallLocation =
+ InstallLocationUtils.RECOMMEND_FAILED_INVALID_APK;
+ }
- return ret;
+ return ret;
+ }
+ } else {
+ sizeBytes = 0;
}
final PackageInstaller.SessionParams sessionParams = new PackageInstaller.SessionParams(
diff --git a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
index 8bdbe04ec4e6..d9f1df5e02c9 100644
--- a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
+++ b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
@@ -43,6 +43,7 @@ import android.content.IIntentSender;
import android.content.Intent;
import android.content.IntentSender;
import android.content.pm.ApplicationInfo;
+import android.content.pm.ArchivedPackageParcel;
import android.content.pm.FeatureInfo;
import android.content.pm.IPackageDataObserver;
import android.content.pm.IPackageInstaller;
@@ -82,6 +83,7 @@ import android.net.Uri;
import android.os.Binder;
import android.os.Build;
import android.os.Bundle;
+import android.os.Environment;
import android.os.IBinder;
import android.os.IUserManager;
import android.os.ParcelFileDescriptor;
@@ -105,6 +107,7 @@ import android.text.TextUtils;
import android.text.format.DateUtils;
import android.util.ArrayMap;
import android.util.IntArray;
+import android.util.Pair;
import android.util.PrintWriterPrinter;
import android.util.Slog;
import android.util.SparseArray;
@@ -246,6 +249,8 @@ class PackageManagerShellCommand extends ShellCommand {
return runStreamingInstall();
case "install-incremental":
return runIncrementalInstall();
+ case "install-archived":
+ return runArchivedInstall();
case "install-abandon":
case "install-destroy":
return runInstallAbandon();
@@ -1549,6 +1554,16 @@ class PackageManagerShellCommand extends ShellCommand {
return doRunInstall(params);
}
+ private int runArchivedInstall() throws RemoteException {
+ final InstallParams params = makeInstallParams(UNSUPPORTED_INSTALL_CMD_OPTS);
+ params.sessionParams.installFlags |= PackageManager.INSTALL_ARCHIVED;
+ if (params.sessionParams.dataLoaderParams == null) {
+ params.sessionParams.setDataLoaderParams(
+ PackageManagerShellCommandDataLoader.getStreamingDataLoaderParams(this));
+ }
+ return doRunInstall(params);
+ }
+
private int runIncrementalInstall() throws RemoteException {
final InstallParams params = makeInstallParams(UNSUPPORTED_INSTALL_CMD_OPTS);
if (params.sessionParams.dataLoaderParams == null) {
@@ -1565,9 +1580,22 @@ class PackageManagerShellCommand extends ShellCommand {
private int doRunInstall(final InstallParams params) throws RemoteException {
final PrintWriter pw = getOutPrintWriter();
+ int requestUserId = params.userId;
+ if (requestUserId != UserHandle.USER_ALL && requestUserId != UserHandle.USER_CURRENT) {
+ UserManagerInternal umi =
+ LocalServices.getService(UserManagerInternal.class);
+ UserInfo userInfo = umi.getUserInfo(requestUserId);
+ if (userInfo == null) {
+ pw.println("Failure [user " + requestUserId + " doesn't exist]");
+ return 1;
+ }
+ }
+
final boolean isStreaming = params.sessionParams.dataLoaderParams != null;
final boolean isApex =
(params.sessionParams.installFlags & PackageManager.INSTALL_APEX) != 0;
+ final boolean installArchived =
+ (params.sessionParams.installFlags & PackageManager.INSTALL_ARCHIVED) != 0;
ArrayList<String> args = getRemainingArgs();
@@ -1584,6 +1612,13 @@ class PackageManagerShellCommand extends ShellCommand {
return 1;
}
+ if (installArchived) {
+ if (hasSplits) {
+ pw.println("Error: can't have SPLIT(s) for Archival install");
+ return 1;
+ }
+ }
+
if (!isStreaming) {
if (fromStdIn && hasSplits) {
pw.println("Error: can't specify SPLIT(s) along with STDIN");
@@ -1602,8 +1637,8 @@ class PackageManagerShellCommand extends ShellCommand {
boolean abandonSession = true;
try {
if (isStreaming) {
- if (doAddFiles(sessionId, args, params.sessionParams.sizeBytes, isApex)
- != PackageInstaller.STATUS_SUCCESS) {
+ if (doAddFiles(sessionId, args, params.sessionParams.sizeBytes, isApex,
+ installArchived) != PackageInstaller.STATUS_SUCCESS) {
return 1;
}
} else {
@@ -2319,6 +2354,15 @@ class PackageManagerShellCommand extends ShellCommand {
break;
case "--user":
userId = UserHandle.parseUserArg(getNextArgRequired());
+ if (userId != UserHandle.USER_ALL && userId != UserHandle.USER_CURRENT) {
+ UserManagerInternal umi =
+ LocalServices.getService(UserManagerInternal.class);
+ UserInfo userInfo = umi.getUserInfo(userId);
+ if (userInfo == null) {
+ pw.println("Failure [user " + userId + " doesn't exist]");
+ return 1;
+ }
+ }
break;
case "--versionCode":
versionCode = Long.parseLong(getNextArgRequired());
@@ -3836,7 +3880,7 @@ class PackageManagerShellCommand extends ShellCommand {
}
private int doAddFiles(int sessionId, ArrayList<String> args, long sessionSizeBytes,
- boolean isApex) throws RemoteException {
+ boolean isApex, boolean installArchived) throws RemoteException {
PackageInstaller.Session session = null;
try {
session = new PackageInstaller.Session(
@@ -3845,9 +3889,17 @@ class PackageManagerShellCommand extends ShellCommand {
// 1. Single file from stdin.
if (args.isEmpty() || STDIN_PATH.equals(args.get(0))) {
final String name = "base" + RANDOM.nextInt() + "." + (isApex ? "apex" : "apk");
- final Metadata metadata = Metadata.forStdIn(name);
- session.addFile(LOCATION_DATA_APP, name, sessionSizeBytes,
- metadata.toByteArray(), null);
+ final long size;
+ final Metadata metadata;
+ if (!installArchived) {
+ metadata = Metadata.forStdIn(name);
+ size = sessionSizeBytes;
+ } else {
+ metadata = Metadata.forArchived(
+ getArchivedPackage(STDIN_PATH, sessionSizeBytes));
+ size = -1;
+ }
+ session.addFile(LOCATION_DATA_APP, name, size, metadata.toByteArray(), null);
return 0;
}
@@ -3856,16 +3908,21 @@ class PackageManagerShellCommand extends ShellCommand {
if (delimLocation != -1) {
// 2. File with specified size read from stdin.
+ if (installArchived) {
+ getOutPrintWriter().println(
+ "Error: can't install with size from STDIN for Archival install");
+ return 1;
+ }
if (processArgForStdin(arg, session) != 0) {
return 1;
}
} else {
// 3. Local file.
- processArgForLocalFile(arg, session);
+ processArgForLocalFile(arg, session, installArchived);
}
}
return 0;
- } catch (IllegalArgumentException e) {
+ } catch (IOException | IllegalArgumentException e) {
getErrPrintWriter().println("Failed to add file(s), reason: " + e);
getOutPrintWriter().println("Failure [failed to add file(s)]");
return 1;
@@ -3954,26 +4011,67 @@ class PackageManagerShellCommand extends ShellCommand {
}
}
- private void processArgForLocalFile(String arg, PackageInstaller.Session session) {
+ private ArchivedPackageParcel getArchivedPackage(String inPath, long sizeBytes)
+ throws RemoteException, IOException {
+ final var fdWithSize = openInFile(inPath, sizeBytes);
+ if (fdWithSize.first == null) {
+ throw new IllegalArgumentException("Error: Can't open file: " + inPath);
+ }
+
+ File tmpFile = null;
+ final ParcelFileDescriptor fd = fdWithSize.first;
+ try (InputStream inStream = new AutoCloseInputStream(fd)) {
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ File tmpStagingDir = Environment.getDataAppDirectory(null);
+ tmpFile = new File(tmpStagingDir, "tmdl" + RANDOM.nextInt() + ".tmp");
+
+ try (OutputStream outStream = new FileOutputStream(tmpFile)) {
+ Streams.copy(inStream, outStream);
+ }
+
+ return mInterface.getArchivedPackage(tmpFile.getAbsolutePath());
+ } finally {
+ if (tmpFile != null) {
+ tmpFile.delete();
+ }
+ Binder.restoreCallingIdentity(identity);
+ }
+ } catch (IOException e) {
+ throw new IllegalArgumentException("Error: Can't stage file: " + inPath, e);
+ }
+ }
+
+ private void processArgForLocalFile(String arg, PackageInstaller.Session session,
+ boolean installArchived) throws IOException, RemoteException {
final String inPath = arg;
final File file = new File(inPath);
final String name = file.getName();
- final long size = getFileStatSize(file);
- final Metadata metadata = Metadata.forLocalFile(inPath);
+ final long size;
+ final Metadata metadata;
+ if (installArchived) {
+ metadata = Metadata.forArchived(getArchivedPackage(inPath, -1));
+ size = 0;
+ } else {
+ metadata = Metadata.forLocalFile(inPath);
+ size = getFileStatSize(file);
+ }
byte[] v4signatureBytes = null;
- // Try to load the v4 signature file for the APK; it might not exist.
- final String v4SignaturePath = inPath + V4Signature.EXT;
- final ParcelFileDescriptor pfd = openFileForSystem(v4SignaturePath, "r");
- if (pfd != null) {
- try {
- final V4Signature v4signature = V4Signature.readFrom(pfd);
- v4signatureBytes = v4signature.toByteArray();
- } catch (IOException ex) {
- Slog.e(TAG, "V4 signature file exists but failed to be parsed.", ex);
- } finally {
- IoUtils.closeQuietly(pfd);
+ if (!installArchived) {
+ // Try to load the v4 signature file for the APK; it might not exist.
+ final String v4SignaturePath = inPath + V4Signature.EXT;
+ final ParcelFileDescriptor pfd = openFileForSystem(v4SignaturePath, "r");
+ if (pfd != null) {
+ try {
+ final V4Signature v4signature = V4Signature.readFrom(pfd);
+ v4signatureBytes = v4signature.toByteArray();
+ } catch (IOException ex) {
+ Slog.e(TAG, "V4 signature file exists but failed to be parsed.", ex);
+ } finally {
+ IoUtils.closeQuietly(pfd);
+ }
}
}
@@ -3995,6 +4093,32 @@ class PackageManagerShellCommand extends ShellCommand {
return 0;
}
+ private Pair<ParcelFileDescriptor, Long> openInFile(String inPath, long sizeBytes)
+ throws IOException {
+ final ParcelFileDescriptor fd;
+ if (STDIN_PATH.equals(inPath)) {
+ fd = ParcelFileDescriptor.dup(getInFileDescriptor());
+ } else if (inPath != null) {
+ fd = openFileForSystem(inPath, "r");
+ if (fd == null) {
+ return Pair.create(null, -1L);
+ }
+ sizeBytes = fd.getStatSize();
+ if (sizeBytes < 0) {
+ fd.close();
+ getErrPrintWriter().println("Unable to get size of: " + inPath);
+ return Pair.create(null, -1L);
+ }
+ } else {
+ fd = ParcelFileDescriptor.dup(getInFileDescriptor());
+ }
+ if (sizeBytes <= 0) {
+ getErrPrintWriter().println("Error: must specify an APK size");
+ return Pair.create(null, 1L);
+ }
+ return Pair.create(fd, sizeBytes);
+ }
+
private int doWriteSplit(int sessionId, String inPath, long sizeBytes, String splitName,
boolean logSuccess) throws RemoteException {
PackageInstaller.Session session = null;
@@ -4004,26 +4128,13 @@ class PackageManagerShellCommand extends ShellCommand {
final PrintWriter pw = getOutPrintWriter();
- final ParcelFileDescriptor fd;
- if (STDIN_PATH.equals(inPath)) {
- fd = ParcelFileDescriptor.dup(getInFileDescriptor());
- } else if (inPath != null) {
- fd = openFileForSystem(inPath, "r");
- if (fd == null) {
- return -1;
- }
- sizeBytes = fd.getStatSize();
- if (sizeBytes < 0) {
- getErrPrintWriter().println("Unable to get size of: " + inPath);
- return -1;
- }
- } else {
- fd = ParcelFileDescriptor.dup(getInFileDescriptor());
- }
- if (sizeBytes <= 0) {
- getErrPrintWriter().println("Error: must specify an APK size");
- return 1;
+ final var fdWithSize = openInFile(inPath, sizeBytes);
+ if (fdWithSize.first == null) {
+ long resultCode = fdWithSize.second;
+ return (int) resultCode;
}
+ final ParcelFileDescriptor fd = fdWithSize.first;
+ sizeBytes = fdWithSize.second;
session.write(splitName, 0, sizeBytes, fd);
diff --git a/services/core/java/com/android/server/pm/PackageManagerShellCommandDataLoader.java b/services/core/java/com/android/server/pm/PackageManagerShellCommandDataLoader.java
index a1e5153194c1..fbe5a51587fc 100644
--- a/services/core/java/com/android/server/pm/PackageManagerShellCommandDataLoader.java
+++ b/services/core/java/com/android/server/pm/PackageManagerShellCommandDataLoader.java
@@ -18,9 +18,11 @@ package com.android.server.pm;
import android.annotation.NonNull;
import android.content.ComponentName;
+import android.content.pm.ArchivedPackageParcel;
import android.content.pm.DataLoaderParams;
import android.content.pm.InstallationFile;
import android.content.pm.PackageInstaller;
+import android.os.Parcel;
import android.os.ParcelFileDescriptor;
import android.os.ShellCommand;
import android.service.dataloader.DataLoaderService;
@@ -37,6 +39,7 @@ import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.charset.StandardCharsets;
import java.security.SecureRandom;
+import java.util.Arrays;
import java.util.Collection;
import java.util.concurrent.atomic.AtomicLong;
@@ -136,9 +139,13 @@ public class PackageManagerShellCommandDataLoader extends DataLoaderService {
* Everything streamed.
*/
static final byte STREAMING = 3;
+ /**
+ * Archived install.
+ */
+ static final byte ARCHIVED = 4;
private final byte mMode;
- private final String mData;
+ private final byte[] mData;
private final String mSalt;
private static AtomicLong sGlobalSalt = new AtomicLong((new SecureRandom()).nextLong());
@@ -156,6 +163,21 @@ public class PackageManagerShellCommandDataLoader extends DataLoaderService {
return new Metadata(LOCAL_FILE, filePath, nextGlobalSalt().toString());
}
+ /** @hide */
+ @VisibleForTesting
+ public static Metadata forArchived(ArchivedPackageParcel archivedPackage) {
+ Parcel parcel = Parcel.obtain();
+ byte[] bytes;
+ try {
+ parcel.writeParcelable(archivedPackage, 0);
+ bytes = parcel.marshall();
+ } finally {
+ parcel.recycle();
+ }
+
+ return new Metadata(ARCHIVED, bytes, null);
+ }
+
static Metadata forDataOnlyStreaming(String fileId) {
return new Metadata(DATA_ONLY_STREAMING, fileId);
}
@@ -169,8 +191,12 @@ public class PackageManagerShellCommandDataLoader extends DataLoaderService {
}
private Metadata(byte mode, String data, String salt) {
+ this(mode, (data != null ? data : "").getBytes(StandardCharsets.UTF_8), salt);
+ }
+
+ private Metadata(byte mode, byte[] data, String salt) {
this.mMode = mode;
- this.mData = (data == null) ? "" : data;
+ this.mData = data;
this.mSalt = salt;
}
@@ -181,22 +207,21 @@ public class PackageManagerShellCommandDataLoader extends DataLoaderService {
int offset = 0;
final byte mode = bytes[offset];
offset += 1;
- final String data;
+ final byte[] data;
final String salt;
switch (mode) {
case LOCAL_FILE: {
int dataSize = ByteBuffer.wrap(bytes, offset, 4).order(
ByteOrder.LITTLE_ENDIAN).getInt();
offset += 4;
- data = new String(bytes, offset, dataSize, StandardCharsets.UTF_8);
+ data = Arrays.copyOfRange(bytes, offset, offset + dataSize);
offset += dataSize;
salt = new String(bytes, offset, bytes.length - offset,
StandardCharsets.UTF_8);
break;
}
default:
- data = new String(bytes, offset, bytes.length - offset,
- StandardCharsets.UTF_8);
+ data = Arrays.copyOfRange(bytes, offset, bytes.length);
salt = null;
break;
}
@@ -207,7 +232,7 @@ public class PackageManagerShellCommandDataLoader extends DataLoaderService {
@VisibleForTesting
public byte[] toByteArray() {
final byte[] result;
- final byte[] dataBytes = this.mData.getBytes(StandardCharsets.UTF_8);
+ final byte[] dataBytes = this.mData;
switch (this.mMode) {
case LOCAL_FILE: {
int dataSize = dataBytes.length;
@@ -237,9 +262,26 @@ public class PackageManagerShellCommandDataLoader extends DataLoaderService {
return this.mMode;
}
- String getData() {
+ byte[] getData() {
return this.mData;
}
+
+ ArchivedPackageParcel getArchivedPackage() {
+ if (getMode() != ARCHIVED) {
+ throw new IllegalStateException("Not an archived package metadata.");
+ }
+
+ Parcel parcel = Parcel.obtain();
+ ArchivedPackageParcel result;
+ try {
+ parcel.unmarshall(this.mData, 0, this.mData.length);
+ parcel.setDataPosition(0);
+ result = parcel.readParcelable(ArchivedPackageParcel.class.getClassLoader());
+ } finally {
+ parcel.recycle();
+ }
+ return result;
+ }
}
private static class DataLoader implements DataLoaderService.DataLoader {
@@ -278,7 +320,9 @@ public class PackageManagerShellCommandDataLoader extends DataLoaderService {
case Metadata.LOCAL_FILE: {
ParcelFileDescriptor incomingFd = null;
try {
- incomingFd = getLocalFilePFD(shellCommand, metadata.getData());
+ final String filePath = new String(metadata.getData(),
+ StandardCharsets.UTF_8);
+ incomingFd = getLocalFilePFD(shellCommand, filePath);
mConnector.writeData(file.getName(), 0, incomingFd.getStatSize(),
incomingFd);
} finally {
@@ -286,6 +330,10 @@ public class PackageManagerShellCommandDataLoader extends DataLoaderService {
}
break;
}
+ case Metadata.ARCHIVED: {
+ // Do nothing, metadata already contains everything needed for install.
+ break;
+ }
default:
Slog.e(TAG, "Unsupported metadata mode: " + metadata.getMode());
return false;
diff --git a/services/core/java/com/android/server/pm/PackageMetrics.java b/services/core/java/com/android/server/pm/PackageMetrics.java
index c1580c4b1cb9..7ad336c9074d 100644
--- a/services/core/java/com/android/server/pm/PackageMetrics.java
+++ b/services/core/java/com/android/server/pm/PackageMetrics.java
@@ -120,7 +120,7 @@ final class PackageMetrics {
versionCode = ps.getVersionCode();
apksSize = getApksSize(ps.getPath());
}
- } catch (IllegalStateException e) {
+ } catch (IllegalStateException | NullPointerException e) {
// no-op
}
}
diff --git a/services/core/java/com/android/server/pm/PackageRemovedInfo.java b/services/core/java/com/android/server/pm/PackageRemovedInfo.java
index c762fd3f9648..5f4452884fc9 100644
--- a/services/core/java/com/android/server/pm/PackageRemovedInfo.java
+++ b/services/core/java/com/android/server/pm/PackageRemovedInfo.java
@@ -164,8 +164,7 @@ final class PackageRemovedInfo {
}
}
- public void populateUsers(int[] userIds, PackageSetting deletedPackageSetting) {
- mRemovedUsers = userIds;
+ public void populateBroadcastUsers(PackageSetting deletedPackageSetting) {
if (mRemovedUsers == null) {
mBroadcastUsers = null;
return;
@@ -173,8 +172,8 @@ final class PackageRemovedInfo {
mBroadcastUsers = EMPTY_INT_ARRAY;
mInstantUserIds = EMPTY_INT_ARRAY;
- for (int i = userIds.length - 1; i >= 0; --i) {
- final int userId = userIds[i];
+ for (int i = mRemovedUsers.length - 1; i >= 0; --i) {
+ final int userId = mRemovedUsers[i];
if (deletedPackageSetting.getInstantApp(userId)) {
mInstantUserIds = ArrayUtils.appendInt(mInstantUserIds, userId);
} else {
diff --git a/services/core/java/com/android/server/pm/PackageSetting.java b/services/core/java/com/android/server/pm/PackageSetting.java
index 7cac3e1b9842..88184c0cb490 100644
--- a/services/core/java/com/android/server/pm/PackageSetting.java
+++ b/services/core/java/com/android/server/pm/PackageSetting.java
@@ -818,7 +818,7 @@ public class PackageSetting extends SettingBase implements PackageStateInternal
if (userState.isInstalled()) {
return true;
}
- if (userState.getCeDataInode() > 0) {
+ if (userState.dataExists()) {
return true;
}
}
diff --git a/services/core/java/com/android/server/pm/PrepareFailure.java b/services/core/java/com/android/server/pm/PrepareFailure.java
index 3180bac2e7b3..09cb6b907e23 100644
--- a/services/core/java/com/android/server/pm/PrepareFailure.java
+++ b/services/core/java/com/android/server/pm/PrepareFailure.java
@@ -42,7 +42,8 @@ final class PrepareFailure extends PackageManagerException {
}
PrepareFailure(String message, Exception e) {
- super(((PackageManagerException) e).error,
+ super(e instanceof PackageManagerException ? ((PackageManagerException) e).error
+ : PackageManager.INSTALL_FAILED_INTERNAL_ERROR,
ExceptionUtils.getCompleteMessage(message, e));
}
diff --git a/services/core/java/com/android/server/pm/RemovePackageHelper.java b/services/core/java/com/android/server/pm/RemovePackageHelper.java
index d4f30fed6967..2aedf0d8960c 100644
--- a/services/core/java/com/android/server/pm/RemovePackageHelper.java
+++ b/services/core/java/com/android/server/pm/RemovePackageHelper.java
@@ -295,25 +295,24 @@ final class RemovePackageHelper {
outInfo.mInstallerPackageName = ps.getInstallSource().mInstallerPackageName;
outInfo.mIsStaticSharedLib = pkg != null && pkg.getStaticSharedLibraryName() != null;
outInfo.mRemovedAppId = ps.getAppId();
- outInfo.mRemovedUsers = userIds;
- outInfo.mBroadcastUsers = userIds;
+ outInfo.mBroadcastUsers = outInfo.mRemovedUsers;
outInfo.mIsExternal = ps.isExternalStorage();
outInfo.mRemovedPackageVersionCode = ps.getVersionCode();
}
}
// Called to clean up disabled system packages
- public void removePackageData(final PackageSetting deletedPs, @NonNull int[] allUserHandles,
- PackageRemovedInfo outInfo, int flags, boolean writeSettings) {
+ public void removePackageData(final PackageSetting deletedPs, @NonNull int[] allUserHandles) {
synchronized (mPm.mInstallLock) {
- removePackageDataLIF(deletedPs, allUserHandles, outInfo, flags, writeSettings);
+ removePackageDataLIF(deletedPs, allUserHandles, /* outInfo= */ null,
+ /* flags= */ 0, /* writeSettings= */ false);
}
}
/*
* This method deletes the package from internal data structures. If the DELETE_KEEP_DATA
* flag is not set, the data directory is removed as well.
- * make sure this flag is set for partially installed apps. If not its meaningless to
+ * make sure this flag is set for partially installed apps. If not it's meaningless to
* delete a partially installed application.
*/
@GuardedBy("mPm.mInstallLock")
@@ -328,8 +327,7 @@ final class RemovePackageHelper {
outInfo.mInstallerPackageName = deletedPs.getInstallSource().mInstallerPackageName;
outInfo.mIsStaticSharedLib = deletedPkg != null
&& deletedPkg.getStaticSharedLibraryName() != null;
- outInfo.populateUsers(deletedPs.queryInstalledUsers(
- mUserManagerInternal.getUserIds(), true), deletedPs);
+ outInfo.populateBroadcastUsers(deletedPs);
outInfo.mIsExternal = deletedPs.isExternalStorage();
outInfo.mRemovedPackageVersionCode = deletedPs.getVersionCode();
}
diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java
index d2adfddb4be3..1137681de5cf 100644
--- a/services/core/java/com/android/server/pm/Settings.java
+++ b/services/core/java/com/android/server/pm/Settings.java
@@ -27,7 +27,6 @@ import static android.content.pm.PackageManager.UNINSTALL_REASON_USER_TYPE;
import static android.os.Process.INVALID_UID;
import static android.os.Process.PACKAGE_INFO_GID;
import static android.os.Process.SYSTEM_UID;
-
import static com.android.server.pm.PackageManagerService.PLATFORM_PACKAGE_NAME;
import static com.android.server.pm.PackageManagerService.WRITE_USER_PACKAGE_RESTRICTIONS;
import static com.android.server.pm.SharedUidMigration.BEST_EFFORT;
@@ -2065,8 +2064,10 @@ public final class Settings implements Watchable, Snappable, ResilientAtomicFile
ATTR_ARCHIVE_ACTIVITY_TITLE);
Path iconPath = Path.of(parser.getAttributeValue(null,
ATTR_ARCHIVE_ICON_PATH));
- Path monochromeIconPath = Path.of(parser.getAttributeValue(null,
- ATTR_ARCHIVE_MONOCHROME_ICON_PATH));
+ String monochromeAttribute = parser.getAttributeValue(null,
+ ATTR_ARCHIVE_MONOCHROME_ICON_PATH);
+ Path monochromeIconPath = monochromeAttribute == null ? null : Path.of(
+ monochromeAttribute);
if (title == null || iconPath == null) {
Slog.wtf(TAG,
@@ -2916,11 +2917,7 @@ public final class Settings implements Watchable, Snappable, ResilientAtomicFile
StringBuilder sb = new StringBuilder();
for (final PackageSetting ps : mPackages.values()) {
- // TODO(b/135203078): This doesn't handle multiple users
- final String dataPath = PackageInfoUtils.getDataDir(ps, UserHandle.USER_SYSTEM)
- .getAbsolutePath();
-
- if (ps.getPkg() == null || dataPath == null) {
+ if (ps.getPkg() == null) {
if (!"android".equals(ps.getPackageName())) {
Slog.w(TAG, "Skipping " + ps + " due to missing metadata");
}
@@ -2932,6 +2929,10 @@ public final class Settings implements Watchable, Snappable, ResilientAtomicFile
continue;
}
+ // TODO(b/135203078): This doesn't handle multiple users
+ final File dataDir = PackageInfoUtils.getDataDir(ps, UserHandle.USER_SYSTEM);
+ final String dataPath = dataDir == null ? "null" : dataDir.getAbsolutePath();
+
final boolean isDebug = ps.getPkg().isDebuggable();
final IntArray gids = new IntArray();
for (final int userId : userIds) {
@@ -2973,7 +2974,7 @@ public final class Settings implements Watchable, Snappable, ResilientAtomicFile
sb.append(ps.getSeInfo());
sb.append(" ");
final int gidsSize = gids.size();
- if (gids != null && gids.size() > 0) {
+ if (gids.size() > 0) {
sb.append(gids.get(0));
for (int i = 1; i < gidsSize; i++) {
sb.append(",");
@@ -4746,6 +4747,7 @@ public final class Settings implements Watchable, Snappable, ResilientAtomicFile
ApplicationInfo.PRIVATE_FLAG_VIRTUAL_PRELOAD, "VIRTUAL_PRELOAD",
ApplicationInfo.PRIVATE_FLAG_ODM, "ODM",
ApplicationInfo.PRIVATE_FLAG_ALLOW_NATIVE_HEAP_POINTER_TAGGING, "PRIVATE_FLAG_ALLOW_NATIVE_HEAP_POINTER_TAGGING",
+ ApplicationInfo.PRIVATE_FLAG_HAS_FRAGILE_USER_DATA, "PRIVATE_FLAG_HAS_FRAGILE_USER_DATA",
};
void dumpVersionLPr(IndentingPrintWriter pw) {
@@ -5193,9 +5195,9 @@ public final class Settings implements Watchable, Snappable, ResilientAtomicFile
pw.print(" installReason=");
pw.println(userState.getInstallReason());
- final File dataDir = PackageInfoUtils.getDataDir(ps, user.id);
+ File dataDir = PackageInfoUtils.getDataDir(ps, user.id);
pw.print(" dataDir=");
- pw.println(dataDir == null ? "null" : dataDir.getAbsolutePath());
+ pw.println(dataDir.getAbsolutePath());
final PackageUserStateInternal pus = ps.readUserState(user.id);
pw.print(" firstInstallTime=");
diff --git a/services/core/java/com/android/server/pm/ShortcutService.java b/services/core/java/com/android/server/pm/ShortcutService.java
index 3e4dd1637387..c6aba2ab9cbe 100644
--- a/services/core/java/com/android/server/pm/ShortcutService.java
+++ b/services/core/java/com/android/server/pm/ShortcutService.java
@@ -1743,6 +1743,10 @@ public class ShortcutService extends IShortcutService.Stub {
android.util.EventLog.writeEvent(0x534e4554, "109824443", -1, "");
throw new SecurityException("Shortcut package name mismatch");
}
+ final int callingUid = injectBinderCallingUid();
+ if (UserHandle.getUserId(callingUid) != si.getUserId()) {
+ throw new SecurityException("User-ID in shortcut doesn't match the caller");
+ }
}
private void verifyShortcutInfoPackages(
diff --git a/services/core/java/com/android/server/pm/ShortcutUser.java b/services/core/java/com/android/server/pm/ShortcutUser.java
index d32eb22afb61..e9c6aabccbf2 100644
--- a/services/core/java/com/android/server/pm/ShortcutUser.java
+++ b/services/core/java/com/android/server/pm/ShortcutUser.java
@@ -363,14 +363,14 @@ class ShortcutUser {
private void saveShortcutPackageItem(TypedXmlSerializer out, ShortcutPackageItem spi,
boolean forBackup) throws IOException, XmlPullParserException {
- spi.waitForBitmapSaves();
if (forBackup) {
if (spi.getPackageUserId() != spi.getOwnerUserId()) {
return; // Don't save cross-user information.
}
+ spi.waitForBitmapSaves();
spi.saveToXml(out, forBackup);
} else {
- spi.saveShortcutPackageItem();
+ spi.scheduleSave();
}
}
diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java
index f2797eb48305..803b94be3c7a 100644
--- a/services/core/java/com/android/server/pm/UserManagerService.java
+++ b/services/core/java/com/android/server/pm/UserManagerService.java
@@ -23,6 +23,7 @@ import static android.os.UserManager.DISALLOW_USER_SWITCH;
import static android.os.UserManager.SYSTEM_USER_MODE_EMULATION_PROPERTY;
import static android.os.UserManager.USER_OPERATION_ERROR_UNKNOWN;
+import static com.android.internal.util.ConcurrentUtils.DIRECT_EXECUTOR;
import static com.android.server.pm.UserJourneyLogger.ERROR_CODE_ABORTED;
import static com.android.server.pm.UserJourneyLogger.ERROR_CODE_UNSPECIFIED;
import static com.android.server.pm.UserJourneyLogger.ERROR_CODE_USER_ALREADY_AN_ADMIN;
@@ -2938,8 +2939,10 @@ public class UserManagerService extends IUserManager.Stub {
UserHandle.USER_NULL, UserManager.RESTRICTION_SOURCE_SYSTEM));
}
- result.addAll(getDevicePolicyManagerInternal()
- .getUserRestrictionSources(restrictionKey, userId));
+ final DevicePolicyManagerInternal dpmi = getDevicePolicyManagerInternal();
+ if (dpmi != null) {
+ result.addAll(dpmi.getUserRestrictionSources(restrictionKey, userId));
+ }
return result;
}
@@ -4787,11 +4790,14 @@ public class UserManagerService extends IUserManager.Stub {
// default check is for DISALLOW_ADD_USER
// If new user is of type CLONE, check if creation of clone profile is allowed
// If new user is of type MANAGED, check if creation of managed profile is allowed
+ // If new user is of type PRIVATE, check if creation of private profile is allowed
String restriction = UserManager.DISALLOW_ADD_USER;
if (UserManager.isUserTypeCloneProfile(userType)) {
restriction = UserManager.DISALLOW_ADD_CLONE_PROFILE;
} else if (UserManager.isUserTypeManagedProfile(userType)) {
restriction = UserManager.DISALLOW_ADD_MANAGED_PROFILE;
+ } else if (UserManager.isUserTypePrivateProfile(userType)) {
+ restriction = UserManager.DISALLOW_ADD_PRIVATE_PROFILE;
}
enforceUserRestriction(restriction, UserHandle.getCallingUserId(),
@@ -5329,12 +5335,12 @@ public class UserManagerService extends IUserManager.Stub {
statsManager.setPullAtomCallback(
FrameworkStatsLog.USER_INFO,
null, // use default PullAtomMetadata values
- BackgroundThread.getExecutor(),
+ DIRECT_EXECUTOR,
this::onPullAtom);
statsManager.setPullAtomCallback(
FrameworkStatsLog.MULTI_USER_INFO,
null, // use default PullAtomMetadata values
- BackgroundThread.getExecutor(),
+ DIRECT_EXECUTOR,
this::onPullAtom);
}
diff --git a/services/core/java/com/android/server/pm/UserRestrictionsUtils.java b/services/core/java/com/android/server/pm/UserRestrictionsUtils.java
index 4e2ceab290d4..35861d79875d 100644
--- a/services/core/java/com/android/server/pm/UserRestrictionsUtils.java
+++ b/services/core/java/com/android/server/pm/UserRestrictionsUtils.java
@@ -103,6 +103,7 @@ public class UserRestrictionsUtils {
UserManager.DISALLOW_ADD_USER,
UserManager.DISALLOW_ADD_MANAGED_PROFILE,
UserManager.DISALLOW_ADD_CLONE_PROFILE,
+ UserManager.DISALLOW_ADD_PRIVATE_PROFILE,
UserManager.ENSURE_VERIFY_APPS,
UserManager.DISALLOW_CONFIG_CELL_BROADCASTS,
UserManager.DISALLOW_CONFIG_MOBILE_NETWORKS,
@@ -212,7 +213,8 @@ public class UserRestrictionsUtils {
private static final Set<String> IMMUTABLE_BY_OWNERS = Sets.newArraySet(
UserManager.DISALLOW_RECORD_AUDIO,
UserManager.DISALLOW_WALLPAPER,
- UserManager.DISALLOW_OEM_UNLOCK
+ UserManager.DISALLOW_OEM_UNLOCK,
+ UserManager.DISALLOW_ADD_PRIVATE_PROFILE
);
/**
diff --git a/services/core/java/com/android/server/pm/UserTypeFactory.java b/services/core/java/com/android/server/pm/UserTypeFactory.java
index b7f9aafc53f8..85b60a07b003 100644
--- a/services/core/java/com/android/server/pm/UserTypeFactory.java
+++ b/services/core/java/com/android/server/pm/UserTypeFactory.java
@@ -51,6 +51,7 @@ import android.os.UserManager;
import android.util.ArrayMap;
import android.util.Slog;
+import com.android.internal.R;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.XmlUtils;
@@ -284,9 +285,9 @@ public final class UserTypeFactory {
.setBadgeLabels(
com.android.internal.R.string.private_profile_label_badge)
.setBadgeColors(
- com.android.internal.R.color.system_accent1_900)
+ R.color.black)
.setDarkThemeBadgeColors(
- com.android.internal.R.color.system_accent1_900)
+ R.color.white)
.setDefaultRestrictions(getDefaultProfileRestrictions())
.setDefaultSecureSettings(getDefaultNonManagedProfileSecureSettings())
.setDefaultUserProperties(new UserProperties.Builder()
diff --git a/services/core/java/com/android/server/pm/VerifyingSession.java b/services/core/java/com/android/server/pm/VerifyingSession.java
index 3a1fd7cfb451..8c73ce8b6b95 100644
--- a/services/core/java/com/android/server/pm/VerifyingSession.java
+++ b/services/core/java/com/android/server/pm/VerifyingSession.java
@@ -191,7 +191,7 @@ final class VerifyingSession {
// Perform package verification and enable rollback (unless we are simply moving the
// package).
if (!mOriginInfo.mExisting) {
- if (!isApex()) {
+ if (!isApex() && !isArchivedInstallation()) {
// TODO(b/182426975): treat APEX as APK when APK verification is concerned
sendApkVerificationRequest(pkgLite);
}
@@ -896,6 +896,9 @@ final class VerifyingSession {
public boolean isApex() {
return (mInstallFlags & PackageManager.INSTALL_APEX) != 0;
}
+ public boolean isArchivedInstallation() {
+ return (mInstallFlags & PackageManager.INSTALL_ARCHIVED) != 0;
+ }
public boolean isStaged() {
return mIsStaged;
}
diff --git a/services/core/java/com/android/server/pm/dex/ArtManagerService.java b/services/core/java/com/android/server/pm/dex/ArtManagerService.java
index f4f03f4c9c4e..31856f1630bb 100644
--- a/services/core/java/com/android/server/pm/dex/ArtManagerService.java
+++ b/services/core/java/com/android/server/pm/dex/ArtManagerService.java
@@ -544,6 +544,11 @@ public class ArtManagerService extends android.content.pm.dex.IArtManager.Stub {
*/
public boolean compileLayouts(@NonNull PackageStateInternal ps, @NonNull AndroidPackage pkg) {
try {
+ final String packageName = pkg.getPackageName();
+ final String apkPath = pkg.getSplits().get(0).getPath();
+ // TODO(b/143971007): Use a cross-user directory
+ File dataDir = PackageInfoUtils.getDataDir(ps, UserHandle.myUserId());
+ final String outDexFile = dataDir.getAbsolutePath() + "/code_cache/compiled_view.dex";
if (ps.isPrivileged() || pkg.isUseEmbeddedDex()
|| pkg.isDefaultToDeviceProtectedStorage()) {
// Privileged apps prefer to load trusted code so they don't use compiled views.
@@ -553,14 +558,6 @@ public class ArtManagerService extends android.content.pm.dex.IArtManager.Stub {
// selinux permissions required for writing to user_de.
return false;
}
- final String packageName = pkg.getPackageName();
- final String apkPath = pkg.getSplits().get(0).getPath();
- final File dataDir = PackageInfoUtils.getDataDir(ps, UserHandle.myUserId());
- if (dataDir == null) {
- // The app is not installed on the target user and doesn't have a data dir
- return false;
- }
- final String outDexFile = dataDir.getAbsolutePath() + "/code_cache/compiled_view.dex";
Log.i("PackageManager", "Compiling layouts in " + packageName + " (" + apkPath +
") to " + outDexFile);
final long callingId = Binder.clearCallingIdentity();
diff --git a/services/core/java/com/android/server/pm/dex/ViewCompiler.java b/services/core/java/com/android/server/pm/dex/ViewCompiler.java
index c5b65a3641c1..6405ea5667d3 100644
--- a/services/core/java/com/android/server/pm/dex/ViewCompiler.java
+++ b/services/core/java/com/android/server/pm/dex/ViewCompiler.java
@@ -40,11 +40,8 @@ public class ViewCompiler {
public boolean compileLayouts(PackageStateInternal ps, String apkPath) {
try {
final String packageName = ps.getPackageName();
- final File dataDir = PackageInfoUtils.getDataDir(ps, UserHandle.myUserId());
- if (dataDir == null) {
- // The app is not installed on the target user and doesn't have a data dir
- return false;
- }
+ // TODO(b/143971007): Use a cross-user directory
+ File dataDir = PackageInfoUtils.getDataDir(ps, UserHandle.myUserId());
final String outDexFile = dataDir.getAbsolutePath() + "/code_cache/compiled_view.dex";
Log.i("PackageManager", "Compiling layouts in " + packageName + " (" + apkPath +
") to " + outDexFile);
diff --git a/services/core/java/com/android/server/pm/flags.aconfig b/services/core/java/com/android/server/pm/flags.aconfig
index 368a8432c805..7779c08e8d5a 100644
--- a/services/core/java/com/android/server/pm/flags.aconfig
+++ b/services/core/java/com/android/server/pm/flags.aconfig
@@ -6,3 +6,11 @@ flag {
description: "Feature flag for Quarantined state"
bug: "269127435"
}
+
+flag {
+ name: "new_match_uninstalled_enabled"
+ namespace: "package_manager_service"
+ description: "Feature flag for new MATCH_UNINSTALLED_PACKAGES behavior"
+ bug: "298681254"
+ is_fixed_read_only: true
+}
diff --git a/services/core/java/com/android/server/pm/parsing/PackageInfoUtils.java b/services/core/java/com/android/server/pm/parsing/PackageInfoUtils.java
index fc079093c9e3..4eceb7738836 100644
--- a/services/core/java/com/android/server/pm/parsing/PackageInfoUtils.java
+++ b/services/core/java/com/android/server/pm/parsing/PackageInfoUtils.java
@@ -443,7 +443,7 @@ public class PackageInfoUtils {
updateApplicationInfo(info, flags, state);
- initForUser(info, pkg, userId, state);
+ initForUser(info, pkg, userId);
// TODO(b/135203078): Remove PackageParser1/toAppInfoWithoutState and clean all this up
PackageStateUnserialized pkgState = pkgSetting.getTransientState();
@@ -689,7 +689,7 @@ public class PackageInfoUtils {
info.splitDependencies = pkg.getSplitDependencies().size() == 0
? null : pkg.getSplitDependencies();
- initForUser(info, pkg, userId, state);
+ initForUser(info, pkg, userId);
info.primaryCpuAbi = pkgSetting.getPrimaryCpuAbi();
info.secondaryCpuAbi = pkgSetting.getSecondaryCpuAbi();
@@ -802,9 +802,7 @@ public class PackageInfoUtils {
// If available for the target user, or trying to match uninstalled packages and it's
// a system app.
return PackageUserStateUtils.isAvailable(state, flags)
- || (pkgSetting.isSystem()
- && ((flags & PackageManager.MATCH_KNOWN_PACKAGES) != 0
- || (flags & PackageManager.MATCH_HIDDEN_UNTIL_INSTALLED_COMPONENTS) != 0));
+ || (pkgSetting.isSystem() && matchUninstalledOrHidden(flags));
}
private static boolean checkUseInstalledOrHidden(long flags,
@@ -819,9 +817,15 @@ public class PackageInfoUtils {
// If available for the target user, or trying to match uninstalled packages and it's
// a system app.
return PackageUserStateUtils.isAvailable(state, flags)
- || (appInfo != null && appInfo.isSystemApp()
- && ((flags & PackageManager.MATCH_KNOWN_PACKAGES) != 0
- || (flags & PackageManager.MATCH_HIDDEN_UNTIL_INSTALLED_COMPONENTS) != 0));
+ || (appInfo != null && appInfo.isSystemApp() && matchUninstalledOrHidden(flags));
+ }
+
+ private static boolean matchUninstalledOrHidden(long flags) {
+ return (flags
+ & (PackageManager.MATCH_KNOWN_PACKAGES
+ | PackageManager.MATCH_ARCHIVED_PACKAGES
+ | PackageManager.MATCH_HIDDEN_UNTIL_INSTALLED_COMPONENTS))
+ != 0;
}
private static void assignFieldsComponentInfoParsedMainComponent(
@@ -1001,7 +1005,7 @@ public class PackageInfoUtils {
}
private static void initForUser(ApplicationInfo output, AndroidPackage input,
- @UserIdInt int userId, PackageUserStateInternal state) {
+ @UserIdInt int userId) {
PackageImpl pkg = ((PackageImpl) input);
String packageName = input.getPackageName();
output.uid = UserHandle.getUid(userId, UserHandle.getAppId(input.getUid()));
@@ -1011,12 +1015,6 @@ public class PackageInfoUtils {
return;
}
- if (!pkg.isSystem() && state.getCeDataInode() <= 0) {
- // The data dir has been deleted
- output.dataDir = null;
- return;
- }
-
// For performance reasons, all these paths are built as strings
if (userId == UserHandle.USER_SYSTEM) {
output.credentialProtectedDataDir =
@@ -1051,7 +1049,7 @@ public class PackageInfoUtils {
// This duplicates the ApplicationInfo variant because it uses field assignment and the classes
// don't inherit from each other, unfortunately. Consolidating logic would introduce overhead.
private static void initForUser(InstrumentationInfo output, AndroidPackage input,
- @UserIdInt int userId, PackageUserStateInternal state) {
+ @UserIdInt int userId) {
PackageImpl pkg = ((PackageImpl) input);
String packageName = input.getPackageName();
if ("android".equals(packageName)) {
@@ -1059,12 +1057,6 @@ public class PackageInfoUtils {
return;
}
- if (!pkg.isSystem() && state.getCeDataInode() <= 0) {
- // The data dir has been deleted
- output.dataDir = null;
- return;
- }
-
// For performance reasons, all these paths are built as strings
if (userId == UserHandle.USER_SYSTEM) {
output.credentialProtectedDataDir =
@@ -1096,21 +1088,12 @@ public class PackageInfoUtils {
}
}
- /**
- * Returns the data dir of the app for the target user. Return null if the app isn't installed
- * on the target user and doesn't have a data dir on the target user.
- */
- @Nullable
+ @NonNull
public static File getDataDir(PackageStateInternal ps, int userId) {
if ("android".equals(ps.getPackageName())) {
return Environment.getDataSystemDirectory();
}
- if (!ps.isSystem() && ps.getUserStateOrDefault(userId).getCeDataInode() <= 0) {
- // The data dir has been deleted
- return null;
- }
-
if (ps.isDefaultToDeviceProtectedStorage()
&& PackageManager.APPLY_DEFAULT_TO_DEVICE_PROTECTED_STORAGE) {
return Environment.getDataUserDePackageDirectory(ps.getVolumeUuid(), userId,
diff --git a/services/core/java/com/android/server/pm/parsing/PackageParser2.java b/services/core/java/com/android/server/pm/parsing/PackageParser2.java
index f5ba3f61a00c..d82a5000844f 100644
--- a/services/core/java/com/android/server/pm/parsing/PackageParser2.java
+++ b/services/core/java/com/android/server/pm/parsing/PackageParser2.java
@@ -22,6 +22,7 @@ import android.annotation.Nullable;
import android.app.ActivityThread;
import android.content.Context;
import android.content.pm.ApplicationInfo;
+import android.content.pm.parsing.PackageLite;
import android.content.pm.parsing.result.ParseInput;
import android.content.pm.parsing.result.ParseResult;
import android.content.pm.parsing.result.ParseTypeImpl;
@@ -183,6 +184,23 @@ public class PackageParser2 implements AutoCloseable {
}
/**
+ * Creates a ParsedPackage from PackageLite without any additional parsing or processing.
+ * Most fields will get reasonable default values, corresponding to "deleted-keep-data".
+ */
+ @AnyThread
+ public ParsedPackage parsePackageFromPackageLite(PackageLite packageLite, int flags)
+ throws PackageManagerException {
+ ParseInput input = mSharedResult.get().reset();
+ ParseResult<ParsingPackage> result = parsingUtils.parsePackageFromPackageLite(input,
+ packageLite, flags);
+ if (result.isError()) {
+ throw new PackageManagerException(result.getErrorCode(), result.getErrorMessage(),
+ result.getException());
+ }
+ return result.getResult().hideAsParsed();
+ }
+
+ /**
* Removes the cached value for the thread the parser was created on. It is assumed that
* any threads created for parallel parsing will be created and released, so they don't
* need an explicit close call.
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 b01a89e672be..fc6b12c78208 100644
--- a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
+++ b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
@@ -1024,7 +1024,9 @@ public class PermissionManagerService extends IPermissionManager.Stub {
}
synchronized (mLock) {
- mAttributions.put(source.getToken(), source);
+ // Change the token for the AttributionSource we're storing, so that we don't store
+ // a strong reference to the original token inside the map itself.
+ mAttributions.put(source.getToken(), source.withDefaultToken());
}
}
@@ -1032,7 +1034,7 @@ public class PermissionManagerService extends IPermissionManager.Stub {
synchronized (mLock) {
final AttributionSource cachedSource = mAttributions.get(source.getToken());
if (cachedSource != null) {
- return cachedSource.equals(source);
+ return cachedSource.equalsExceptToken(source);
}
return false;
}
diff --git a/services/core/java/com/android/server/pm/pkg/PackageUserState.java b/services/core/java/com/android/server/pm/pkg/PackageUserState.java
index 7bc518c5516e..c05b3c2be622 100644
--- a/services/core/java/com/android/server/pm/pkg/PackageUserState.java
+++ b/services/core/java/com/android/server/pm/pkg/PackageUserState.java
@@ -242,4 +242,11 @@ public interface PackageUserState {
@Nullable
ArchiveState getArchiveState();
+ /**
+ * @return whether the data dir exists. True when the app is installed for the user, or when the
+ * app is uninstalled for the user with {@link PackageManager#DELETE_KEEP_DATA}.
+ *
+ * @hide
+ */
+ boolean dataExists();
}
diff --git a/services/core/java/com/android/server/pm/pkg/PackageUserStateDefault.java b/services/core/java/com/android/server/pm/pkg/PackageUserStateDefault.java
index 3534d7564c50..fc4b6863b9b8 100644
--- a/services/core/java/com/android/server/pm/pkg/PackageUserStateDefault.java
+++ b/services/core/java/com/android/server/pm/pkg/PackageUserStateDefault.java
@@ -196,4 +196,9 @@ class PackageUserStateDefault implements PackageUserStateInternal {
public ArchiveState getArchiveState() {
return null;
}
+
+ @Override
+ public boolean dataExists() {
+ return true;
+ }
}
diff --git a/services/core/java/com/android/server/pm/pkg/PackageUserStateImpl.java b/services/core/java/com/android/server/pm/pkg/PackageUserStateImpl.java
index 2349fbff11a7..0b35d8ae16ea 100644
--- a/services/core/java/com/android/server/pm/pkg/PackageUserStateImpl.java
+++ b/services/core/java/com/android/server/pm/pkg/PackageUserStateImpl.java
@@ -685,6 +685,10 @@ public class PackageUserStateImpl extends WatchableImpl implements PackageUserSt
return false;
}
+ @Override
+ public boolean dataExists() {
+ return getCeDataInode() > 0;
+ }
diff --git a/services/core/java/com/android/server/pm/pkg/PackageUserStateUtils.java b/services/core/java/com/android/server/pm/pkg/PackageUserStateUtils.java
index e3424534c275..9ab3060ce325 100644
--- a/services/core/java/com/android/server/pm/pkg/PackageUserStateUtils.java
+++ b/services/core/java/com/android/server/pm/pkg/PackageUserStateUtils.java
@@ -27,6 +27,7 @@ import android.os.Debug;
import android.util.DebugUtils;
import android.util.Slog;
+import com.android.server.pm.Flags;
import com.android.server.pm.pkg.component.ParsedMainComponent;
/** @hide */
@@ -82,14 +83,38 @@ public class PackageUserStateUtils {
return reportIfDebug(matchesUnaware || matchesAware, flags);
}
+ /**
+ * @return true if any of the following conditions is met:
+ * <p><ul>
+ * <li> If it is installed and not hidden for this user;
+ * <li> If it is installed but hidden for this user, still return true if
+ * {@link PackageManager#MATCH_UNINSTALLED_PACKAGES} or
+ * {@link PackageManager#MATCH_ARCHIVED_PACKAGES} is requested;
+ * <li> If MATCH_ANY_USER is requested, always return true, because the fact that
+ * this object exists means that the package must be installed or has data on at least one user;
+ * <li> (When feature enabled) If it is not installed but still has data (i.e., it was
+ * previously uninstalled with {@link PackageManager#DELETE_KEEP_DATA}), return true if the
+ * caller requested {@link PackageManager#MATCH_UNINSTALLED_PACKAGES} or
+ * {@link PackageManager#MATCH_ARCHIVED_PACKAGES};
+ * </ul><p>
+ */
public static boolean isAvailable(@NonNull PackageUserState state, long flags) {
- // True if it is installed for this user and it is not hidden. If it is hidden,
- // still return true if the caller requested MATCH_UNINSTALLED_PACKAGES
final boolean matchAnyUser = (flags & PackageManager.MATCH_ANY_USER) != 0;
final boolean matchUninstalled = (flags & PackageManager.MATCH_UNINSTALLED_PACKAGES) != 0;
- return matchAnyUser
- || (state.isInstalled()
- && (!state.isHidden() || matchUninstalled));
+ final boolean matchArchived = (flags & PackageManager.MATCH_ARCHIVED_PACKAGES) != 0;
+ final boolean matchDataExists = matchUninstalled || matchArchived;
+
+ if (matchAnyUser) {
+ return true;
+ }
+ if (state.isInstalled()) {
+ if (!state.isHidden()) {
+ return true;
+ } else return matchDataExists;
+ } else {
+ // not installed
+ return matchDataExists && Flags.newMatchUninstalledEnabled() && state.dataExists();
+ }
}
public static boolean reportIfDebug(boolean result, long flags) {
diff --git a/services/core/java/com/android/server/pm/pkg/parsing/ParsingPackage.java b/services/core/java/com/android/server/pm/pkg/parsing/ParsingPackage.java
index f1f0fa35578d..699ccbdc5a83 100644
--- a/services/core/java/com/android/server/pm/pkg/parsing/ParsingPackage.java
+++ b/services/core/java/com/android/server/pm/pkg/parsing/ParsingPackage.java
@@ -375,6 +375,10 @@ public interface ParsingPackage {
ParsingPackage setBaseRevisionCode(int baseRevisionCode);
+ ParsingPackage setVersionCode(int vesionCode);
+
+ ParsingPackage setVersionCodeMajor(int vesionCodeMajor);
+
ParsingPackage setVersionName(String versionName);
ParsingPackage setCompileSdkVersion(int compileSdkVersion);
diff --git a/services/core/java/com/android/server/pm/pkg/parsing/ParsingPackageUtils.java b/services/core/java/com/android/server/pm/pkg/parsing/ParsingPackageUtils.java
index dc022f70e47c..81c2f0760705 100644
--- a/services/core/java/com/android/server/pm/pkg/parsing/ParsingPackageUtils.java
+++ b/services/core/java/com/android/server/pm/pkg/parsing/ParsingPackageUtils.java
@@ -28,7 +28,6 @@ import static android.content.pm.PackageManager.INSTALL_PARSE_FAILED_UNEXPECTED_
import static android.os.Build.VERSION_CODES.DONUT;
import static android.os.Build.VERSION_CODES.O;
import static android.os.Trace.TRACE_TAG_PACKAGE_MANAGER;
-
import static com.android.server.pm.pkg.parsing.ParsingUtils.parseKnownActivityEmbeddingCerts;
import android.annotation.AnyRes;
@@ -474,15 +473,121 @@ public class ParsingPackageUtils {
}
}
- private ParseResult<ParsingPackage> parseBaseApk(ParseInput input, File apkFile,
- String codePath, SplitAssetLoader assetLoader, int flags) {
- final String apkPath = apkFile.getAbsolutePath();
+ /**
+ * Creates ParsingPackage using only PackageLite.
+ * Missing fields will contain reasonable defaults.
+ * Used for packageless (aka archived) package installation.
+ */
+ public ParseResult<ParsingPackage> parsePackageFromPackageLite(ParseInput input,
+ PackageLite lite, int flags) {
+ final String volumeUuid = getVolumeUuid(lite.getPath());
+ final String pkgName = lite.getPackageName();
+
+ final TypedArray manifestArray = null;
+ final ParsingPackage pkg = mCallback.startParsingPackage(pkgName,
+ lite.getBaseApkPath(), lite.getPath(), manifestArray, lite.isCoreApp());
+
+ final int targetSdk = lite.getTargetSdk();
+ final String versionName = null;
+ final int compileSdkVersion = 0;
+ final String compileSdkVersionCodeName = null;
+ final boolean isolatedSplitLoading = false;
+
+ // Normally set from manifestArray.
+ pkg.setVersionCode(lite.getVersionCode());
+ pkg.setVersionCodeMajor(lite.getVersionCodeMajor());
+ pkg.setBaseRevisionCode(lite.getBaseRevisionCode());
+ pkg.setVersionName(versionName);
+ pkg.setCompileSdkVersion(compileSdkVersion);
+ pkg.setCompileSdkVersionCodeName(compileSdkVersionCodeName);
+ pkg.setIsolatedSplitLoading(isolatedSplitLoading);
+ pkg.setTargetSdkVersion(targetSdk);
+
+ // parseBaseApkTags
+ pkg.setInstallLocation(lite.getInstallLocation())
+ .setTargetSandboxVersion(PARSE_DEFAULT_TARGET_SANDBOX)
+ /* Set the global "on SD card" flag */
+ .setExternalStorage((flags & PARSE_EXTERNAL_STORAGE) != 0);
+
+ // parseBaseAppBasicFlags
+ pkg
+ // Default true
+ .setBackupAllowed(lite.isBackupAllowed())
+ .setClearUserDataAllowed(true)
+ .setClearUserDataOnFailedRestoreAllowed(
+ lite.isClearUserDataOnFailedRestoreAllowed())
+ .setAllowNativeHeapPointerTagging(true)
+ .setEnabled(true)
+ .setExtractNativeLibrariesRequested(true)
+ // targetSdkVersion gated
+ .setAllowAudioPlaybackCapture(targetSdk >= Build.VERSION_CODES.Q)
+ .setHardwareAccelerated(targetSdk >= Build.VERSION_CODES.ICE_CREAM_SANDWICH)
+ .setRequestLegacyExternalStorage(lite.isRequestLegacyExternalStorage())
+ .setCleartextTrafficAllowed(targetSdk < Build.VERSION_CODES.P)
+ // Default false
+ .setDefaultToDeviceProtectedStorage(lite.isDefaultToDeviceProtectedStorage())
+ .setUserDataFragile(lite.isUserDataFragile())
+ // Ints
+ .setCategory(ApplicationInfo.CATEGORY_UNDEFINED)
+ // Floats Default 0f
+ .setMaxAspectRatio(0f)
+ .setMinAspectRatio(0f);
+
+ // No APK - no code.
+ pkg.setDeclaredHavingCode(false);
+
+ final String taskAffinity = null;
+ ParseResult<String> taskAffinityResult = ComponentParseUtils.buildTaskAffinityName(
+ pkgName, pkgName, taskAffinity, input);
+ if (taskAffinityResult.isError()) {
+ return input.error(taskAffinityResult);
+ }
+ pkg.setTaskAffinity(taskAffinityResult.getResult());
+ final CharSequence pname = null;
+ ParseResult<String> processNameResult = ComponentParseUtils.buildProcessName(
+ pkgName, null /*defProc*/, pname, flags, mSeparateProcesses, input);
+ if (processNameResult.isError()) {
+ return input.error(processNameResult);
+ }
+ pkg.setProcessName(processNameResult.getResult());
+
+ pkg.setGwpAsanMode(-1);
+ pkg.setMemtagMode(-1);
+
+ afterParseBaseApplication(pkg);
+
+ final ParseResult<ParsingPackage> result = validateBaseApkTags(input, pkg);
+ if (result.isError()) {
+ return result;
+ }
+
+ pkg.setVolumeUuid(volumeUuid);
+
+ if ((flags & PARSE_COLLECT_CERTIFICATES) != 0) {
+ pkg.setSigningDetails(lite.getSigningDetails());
+ } else {
+ pkg.setSigningDetails(SigningDetails.UNKNOWN);
+ }
+
+ return input.success(pkg
+ .set32BitAbiPreferred(lite.isUse32bitAbi()));
+ }
+
+ private static String getVolumeUuid(final String apkPath) {
String volumeUuid = null;
if (apkPath.startsWith(MNT_EXPAND)) {
final int end = apkPath.indexOf('/', MNT_EXPAND.length());
volumeUuid = apkPath.substring(MNT_EXPAND.length(), end);
}
+ return volumeUuid;
+ }
+
+ private ParseResult<ParsingPackage> parseBaseApk(ParseInput input, File apkFile,
+ String codePath, SplitAssetLoader assetLoader, int flags) {
+ final String apkPath = apkFile.getAbsolutePath();
+
+ final String volumeUuid = getVolumeUuid(apkPath);
if (DEBUG_JAR) Slog.d(TAG, "Scanning base APK: " + apkPath);
@@ -882,7 +987,7 @@ public class ParsingPackageUtils {
}
pkg.setInstallLocation(anInteger(PARSE_DEFAULT_INSTALL_LOCATION,
- R.styleable.AndroidManifest_installLocation, sa))
+ R.styleable.AndroidManifest_installLocation, sa))
.setTargetSandboxVersion(anInteger(PARSE_DEFAULT_TARGET_SANDBOX,
R.styleable.AndroidManifest_targetSandboxVersion, sa))
/* Set the global "on SD card" flag */
@@ -932,6 +1037,10 @@ public class ParsingPackageUtils {
}
}
+ return validateBaseApkTags(input, pkg);
+ }
+
+ private ParseResult<ParsingPackage> validateBaseApkTags(ParseInput input, ParsingPackage pkg) {
if (!ParsedAttributionUtils.isCombinationValid(pkg.getAttributions())) {
return input.error(
INSTALL_PARSE_FAILED_BAD_MANIFEST,
@@ -2199,15 +2308,19 @@ public class ParsingPackageUtils {
pkg.sortServices();
}
- // Must be run after the entire {@link ApplicationInfo} has been fully processed and after
- // every activity info has had a chance to set it from its attributes.
+ afterParseBaseApplication(pkg);
+
+ return input.success(pkg);
+ }
+
+ // Must be run after the entire {@link ApplicationInfo} has been fully processed and after
+ // every activity info has had a chance to set it from its attributes.
+ private void afterParseBaseApplication(ParsingPackage pkg) {
setMaxAspectRatio(pkg);
setMinAspectRatio(pkg);
setSupportsSizeChanges(pkg);
pkg.setHasDomainUrls(hasDomainURLs(pkg));
-
- return input.success(pkg);
}
/**
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index b3aa09b8f17b..9dcc2ab082c0 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -559,6 +559,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
boolean mWakeOnDpadKeyPress;
boolean mWakeOnAssistKeyPress;
boolean mWakeOnBackKeyPress;
+ boolean mSilenceRingerOnSleepKey;
long mWakeUpToLastStateTimeout;
int mSearchKeyBehavior;
ComponentName mSearchKeyTargetActivity;
@@ -1423,6 +1424,15 @@ public class PhoneWindowManager implements WindowManagerPolicy {
}
private void sleepRelease(long eventTime) {
+ if (mSilenceRingerOnSleepKey) {
+ TelecomManager telecomManager = getTelecommService();
+ if (telecomManager != null && telecomManager.isRinging()) {
+ telecomManager.silenceRinger();
+ Slog.i(TAG, "sleepRelease() silence ringer");
+ return;
+ }
+ }
+
switch (mShortPressOnSleepBehavior) {
case SHORT_PRESS_SLEEP_GO_TO_SLEEP:
case SHORT_PRESS_SLEEP_GO_TO_SLEEP_AND_GO_HOME:
@@ -2347,6 +2357,8 @@ public class PhoneWindowManager implements WindowManagerPolicy {
com.android.internal.R.string.config_primaryShortPressTargetActivity));
mShortPressOnSleepBehavior = mContext.getResources().getInteger(
com.android.internal.R.integer.config_shortPressOnSleepBehavior);
+ mSilenceRingerOnSleepKey = mContext.getResources().getBoolean(
+ com.android.internal.R.bool.config_silenceRingerOnSleepKey);
mAllowStartActivityForLongPressOnPowerDuringSetup = mContext.getResources().getBoolean(
com.android.internal.R.bool.config_allowStartActivityForLongPressOnPowerInSetup);
@@ -3342,6 +3354,13 @@ public class PhoneWindowManager implements WindowManagerPolicy {
return true;
}
break;
+ case KeyEvent.KEYCODE_DEL:
+ case KeyEvent.KEYCODE_GRAVE:
+ if (firstDown && event.isMetaPressed()) {
+ logKeyboardSystemsEvent(event, KeyboardLogEvent.BACK);
+ injectBackGesture(event.getDownTime());
+ return true;
+ }
case KeyEvent.KEYCODE_DPAD_UP:
if (firstDown && event.isMetaPressed() && event.isCtrlPressed()) {
StatusBarManagerInternal statusbar = getStatusBarManagerInternal();
@@ -3353,9 +3372,14 @@ public class PhoneWindowManager implements WindowManagerPolicy {
}
break;
case KeyEvent.KEYCODE_DPAD_LEFT:
- if (firstDown && event.isMetaPressed() && event.isCtrlPressed()) {
- enterStageSplitFromRunningApp(true /* leftOrTop */);
- logKeyboardSystemsEvent(event, KeyboardLogEvent.SPLIT_SCREEN_NAVIGATION);
+ if (firstDown && event.isMetaPressed()) {
+ if (event.isCtrlPressed()) {
+ enterStageSplitFromRunningApp(true /* leftOrTop */);
+ logKeyboardSystemsEvent(event, KeyboardLogEvent.SPLIT_SCREEN_NAVIGATION);
+ } else {
+ logKeyboardSystemsEvent(event, KeyboardLogEvent.BACK);
+ injectBackGesture(event.getDownTime());
+ }
return true;
}
break;
@@ -3618,6 +3642,25 @@ public class PhoneWindowManager implements WindowManagerPolicy {
return (metaState & KeyEvent.META_META_ON) != 0;
}
+ @SuppressLint("MissingPermission")
+ private void injectBackGesture(long downtime) {
+ // Create and inject down event
+ KeyEvent downEvent = new KeyEvent(downtime, downtime, KeyEvent.ACTION_DOWN,
+ KeyEvent.KEYCODE_BACK, 0 /* repeat */, 0 /* metaState */,
+ KeyCharacterMap.VIRTUAL_KEYBOARD, 0 /* scancode */,
+ KeyEvent.FLAG_FROM_SYSTEM | KeyEvent.FLAG_VIRTUAL_HARD_KEY,
+ InputDevice.SOURCE_KEYBOARD);
+ mInputManager.injectInputEvent(downEvent, InputManager.INJECT_INPUT_EVENT_MODE_ASYNC);
+
+
+ // Create and inject up event
+ KeyEvent upEvent = KeyEvent.changeAction(downEvent, KeyEvent.ACTION_UP);
+ mInputManager.injectInputEvent(upEvent, InputManager.INJECT_INPUT_EVENT_MODE_ASYNC);
+
+ downEvent.recycle();
+ upEvent.recycle();
+ }
+
private boolean handleHomeShortcuts(int displayId, IBinder focusedToken, KeyEvent event) {
// First we always handle the home key here, so applications
// can never break it, although if keyguard is on, we do let
@@ -5290,11 +5333,6 @@ public class PhoneWindowManager implements WindowManagerPolicy {
return false;
}
- if (theaterModeEnabled) {
- Settings.Global.putInt(mContext.getContentResolver(),
- Settings.Global.THEATER_MODE_ON, 0);
- }
-
mPowerManager.wakeUp(wakeTime, reason, details);
return true;
}
diff --git a/services/core/java/com/android/server/power/hint/HintManagerService.java b/services/core/java/com/android/server/power/hint/HintManagerService.java
index 33bed3d42e50..88c2e095453d 100644
--- a/services/core/java/com/android/server/power/hint/HintManagerService.java
+++ b/services/core/java/com/android/server/power/hint/HintManagerService.java
@@ -16,6 +16,8 @@
package com.android.server.power.hint;
+import static com.android.internal.util.ConcurrentUtils.DIRECT_EXECUTOR;
+
import android.annotation.NonNull;
import android.app.ActivityManager;
import android.app.ActivityManagerInternal;
@@ -37,7 +39,6 @@ import android.util.StatsEvent;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.os.BackgroundThread;
import com.android.internal.util.DumpUtils;
import com.android.internal.util.FrameworkStatsLog;
import com.android.internal.util.Preconditions;
@@ -142,7 +143,7 @@ public final class HintManagerService extends SystemService {
statsManager.setPullAtomCallback(
FrameworkStatsLog.ADPF_SYSTEM_COMPONENT_INFO,
null, // use default PullAtomMetadata values
- BackgroundThread.getExecutor(),
+ DIRECT_EXECUTOR,
this::onPullAtom);
}
diff --git a/services/core/java/com/android/server/power/stats/BatteryUsageStatsProvider.java b/services/core/java/com/android/server/power/stats/BatteryUsageStatsProvider.java
index 3a3273328a7a..f6fa9f244252 100644
--- a/services/core/java/com/android/server/power/stats/BatteryUsageStatsProvider.java
+++ b/services/core/java/com/android/server/power/stats/BatteryUsageStatsProvider.java
@@ -170,10 +170,11 @@ public class BatteryUsageStatsProvider {
&& mStats.isProcessStateDataAvailable();
final boolean includeVirtualUids = ((query.getFlags()
& BatteryUsageStatsQuery.FLAG_BATTERY_USAGE_STATS_INCLUDE_VIRTUAL_UIDS) != 0);
+ final double minConsumedPowerThreshold = query.getMinConsumedPowerThreshold();
final BatteryUsageStats.Builder batteryUsageStatsBuilder = new BatteryUsageStats.Builder(
mStats.getCustomEnergyConsumerNames(), includePowerModels,
- includeProcessStateData);
+ includeProcessStateData, minConsumedPowerThreshold);
// TODO(b/188068523): use a monotonic clock to ensure resilience of order and duration
// of stats sessions to wall-clock adjustments
batteryUsageStatsBuilder.setStatsStartTimestamp(mStats.getStartClockTime());
@@ -307,10 +308,12 @@ public class BatteryUsageStatsProvider {
final boolean includeProcessStateData = ((query.getFlags()
& BatteryUsageStatsQuery.FLAG_BATTERY_USAGE_STATS_INCLUDE_PROCESS_STATE_DATA) != 0)
&& mStats.isProcessStateDataAvailable();
+ final double minConsumedPowerThreshold = query.getMinConsumedPowerThreshold();
final String[] customEnergyConsumerNames = mStats.getCustomEnergyConsumerNames();
final BatteryUsageStats.Builder builder = new BatteryUsageStats.Builder(
- customEnergyConsumerNames, includePowerModels, includeProcessStateData);
+ customEnergyConsumerNames, includePowerModels, includeProcessStateData,
+ minConsumedPowerThreshold);
if (mBatteryUsageStatsStore == null) {
Log.e(TAG, "BatteryUsageStatsStore is unavailable");
return builder.build();
diff --git a/services/core/java/com/android/server/security/Android.bp b/services/core/java/com/android/server/security/Android.bp
new file mode 100644
index 000000000000..3f644c44111a
--- /dev/null
+++ b/services/core/java/com/android/server/security/Android.bp
@@ -0,0 +1,17 @@
+aconfig_declarations {
+ name: "com.android.server.security.flags-aconfig",
+ package: "com.android.server.security",
+ srcs: ["*.aconfig"],
+}
+
+java_aconfig_library {
+ name: "com.android.server.security.flags-aconfig-java",
+ aconfig_declarations: "com.android.server.security.flags-aconfig",
+}
+
+java_aconfig_library {
+ name: "com.android.server.security.flags-aconfig-java-host",
+ aconfig_declarations: "com.android.server.security.flags-aconfig",
+ host_supported: true,
+ test: true,
+}
diff --git a/services/core/java/com/android/server/security/OWNERS b/services/core/java/com/android/server/security/OWNERS
index 5bcc98b600fc..f408d7c2efac 100644
--- a/services/core/java/com/android/server/security/OWNERS
+++ b/services/core/java/com/android/server/security/OWNERS
@@ -1,4 +1,6 @@
# Bug component: 36824
+include /core/java/android/security/OWNERS
+
per-file *AttestationVerification* = file:/core/java/android/security/attestationverification/OWNERS
per-file FileIntegrity*.java = victorhsieh@google.com
diff --git a/services/core/java/com/android/server/security/flags.aconfig b/services/core/java/com/android/server/security/flags.aconfig
new file mode 100644
index 000000000000..0440989f3981
--- /dev/null
+++ b/services/core/java/com/android/server/security/flags.aconfig
@@ -0,0 +1,8 @@
+package: "com.android.server.security"
+
+flag {
+ name: "deprecate_fsv_sig"
+ namespace: "hardware_backed_security"
+ description: "Feature flag for deprecating .fsv_sig"
+ bug: "277916185"
+}
diff --git a/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java b/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java
index 5d04e5df6a04..97420d055bd2 100644
--- a/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java
+++ b/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java
@@ -1599,7 +1599,7 @@ public class StatsPullAtomService extends SystemService {
mStatsManager.setPullAtomCallback(
tagId,
metadata,
- BackgroundThread.getExecutor(),
+ DIRECT_EXECUTOR,
mStatsCallbackImpl
);
}
@@ -1612,7 +1612,7 @@ public class StatsPullAtomService extends SystemService {
mStatsManager.setPullAtomCallback(
tagId,
metadata,
- BackgroundThread.getExecutor(),
+ DIRECT_EXECUTOR,
mStatsCallbackImpl
);
}
@@ -1625,7 +1625,7 @@ public class StatsPullAtomService extends SystemService {
mStatsManager.setPullAtomCallback(
tagId,
metadata,
- BackgroundThread.getExecutor(),
+ DIRECT_EXECUTOR,
mStatsCallbackImpl
);
}
diff --git a/services/core/java/com/android/server/trust/TrustManagerService.java b/services/core/java/com/android/server/trust/TrustManagerService.java
index cc95da57647f..9905ddfbdaa9 100644
--- a/services/core/java/com/android/server/trust/TrustManagerService.java
+++ b/services/core/java/com/android/server/trust/TrustManagerService.java
@@ -31,7 +31,6 @@ import android.app.trust.ITrustListener;
import android.app.trust.ITrustManager;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
-import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
@@ -42,11 +41,9 @@ import android.content.pm.UserInfo;
import android.content.res.Resources;
import android.content.res.TypedArray;
import android.content.res.XmlResourceParser;
-import android.database.ContentObserver;
import android.graphics.drawable.Drawable;
import android.hardware.biometrics.BiometricManager;
import android.hardware.biometrics.BiometricSourceType;
-import android.net.Uri;
import android.os.Binder;
import android.os.Build;
import android.os.Bundle;
@@ -161,9 +158,6 @@ public class TrustManagerService extends SystemService {
private final ActivityManager mActivityManager;
private VirtualDeviceManagerInternal mVirtualDeviceManager;
- @GuardedBy("mUserIsTrusted")
- private final SparseBooleanArray mUserIsTrusted = new SparseBooleanArray();
-
private enum TrustState {
UNTRUSTED, // the phone is not unlocked by any trustagents
TRUSTABLE, // the phone is in a semi-locked state that can be unlocked if
@@ -224,7 +218,6 @@ public class TrustManagerService extends SystemService {
mIdleTrustableTimeoutAlarmListenerForUser = new SparseArray<>();
private AlarmManager mAlarmManager;
private final Object mAlarmLock = new Object();
- private final SettingsObserver mSettingsObserver;
private final StrongAuthTracker mStrongAuthTracker;
@@ -266,7 +259,6 @@ public class TrustManagerService extends SystemService {
mLockPatternUtils = injector.getLockPatternUtils();
mStrongAuthTracker = new StrongAuthTracker(context, injector.getLooper());
mAlarmManager = (AlarmManager) mContext.getSystemService(Context.ALARM_SERVICE);
- mSettingsObserver = new SettingsObserver(mHandler);
}
@Override
@@ -294,103 +286,10 @@ public class TrustManagerService extends SystemService {
}
}
- // Extend unlock config and logic
- private final class SettingsObserver extends ContentObserver {
- private final Uri TRUST_AGENTS_EXTEND_UNLOCK =
- Settings.Secure.getUriFor(Settings.Secure.TRUST_AGENTS_EXTEND_UNLOCK);
-
- private final Uri LOCK_SCREEN_WHEN_TRUST_LOST =
- Settings.Secure.getUriFor(Settings.Secure.LOCK_SCREEN_WHEN_TRUST_LOST);
-
- private final boolean mIsAutomotive;
- private final ContentResolver mContentResolver;
- private boolean mTrustAgentsNonrenewableTrust;
- private boolean mLockWhenTrustLost;
-
- /**
- * Creates a settings observer
- *
- * @param handler The handler to run {@link #onChange} on, or null if none.
- */
- SettingsObserver(Handler handler) {
- super(handler);
-
- PackageManager packageManager = getContext().getPackageManager();
- mIsAutomotive = packageManager.hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE);
-
- mContentResolver = getContext().getContentResolver();
- updateContentObserver();
- }
-
- void updateContentObserver() {
- mContentResolver.unregisterContentObserver(this);
- mContentResolver.registerContentObserver(TRUST_AGENTS_EXTEND_UNLOCK,
- false /* notifyForDescendents */,
- this /* observer */,
- mCurrentUser);
- mContentResolver.registerContentObserver(LOCK_SCREEN_WHEN_TRUST_LOST,
- false /* notifyForDescendents */,
- this /* observer */,
- mCurrentUser);
-
- // Update the value immediately
- onChange(true /* selfChange */, TRUST_AGENTS_EXTEND_UNLOCK);
- onChange(true /* selfChange */, LOCK_SCREEN_WHEN_TRUST_LOST);
- }
-
- @Override
- public void onChange(boolean selfChange, Uri uri) {
- if (TRUST_AGENTS_EXTEND_UNLOCK.equals(uri)) {
- // Smart lock should only grant non-renewable trust. The only exception is for
- // automotive, where it can actively unlock the head unit.
- int defaultValue = mIsAutomotive ? 0 : 1;
-
- mTrustAgentsNonrenewableTrust =
- Settings.Secure.getIntForUser(
- mContentResolver,
- Settings.Secure.TRUST_AGENTS_EXTEND_UNLOCK,
- defaultValue,
- mCurrentUser) != 0;
- } else if (LOCK_SCREEN_WHEN_TRUST_LOST.equals(uri)) {
- mLockWhenTrustLost =
- Settings.Secure.getIntForUser(
- mContentResolver,
- Settings.Secure.LOCK_SCREEN_WHEN_TRUST_LOST,
- 0 /* default */,
- mCurrentUser) != 0;
- }
- }
-
- boolean getTrustAgentsNonrenewableTrust() {
- return mTrustAgentsNonrenewableTrust;
- }
-
- boolean getLockWhenTrustLost() {
- return mLockWhenTrustLost;
- }
- }
-
- private void maybeLockScreen(int userId) {
- if (userId != mCurrentUser) {
- return;
- }
-
- if (mSettingsObserver.getLockWhenTrustLost()) {
- if (DEBUG) Slog.d(TAG, "Locking device because trust was lost");
- try {
- WindowManagerGlobal.getWindowManagerService().lockNow(null);
- } catch (RemoteException e) {
- Slog.e(TAG, "Error locking screen when trust was lost");
- }
-
- // If active unlocking is not allowed, cancel any pending trust timeouts because the
- // screen is already locked.
- TrustedTimeoutAlarmListener alarm = mTrustTimeoutAlarmListenerForUser.get(userId);
- if (alarm != null && mSettingsObserver.getTrustAgentsNonrenewableTrust()) {
- mAlarmManager.cancel(alarm);
- alarm.setQueued(false /* isQueued */);
- }
- }
+ // Automotive head units can be unlocked by a trust agent, even when the agent doesn't use
+ // FLAG_GRANT_TRUST_TEMPORARY_AND_RENEWABLE.
+ private boolean isAutomotive() {
+ return getContext().getPackageManager().hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE);
}
private void scheduleTrustTimeout(boolean override, boolean isTrustableTimeout) {
@@ -587,12 +486,10 @@ public class TrustManagerService extends SystemService {
synchronized (mUserTrustState) {
wasTrusted = (mUserTrustState.get(userId) == TrustState.TRUSTED);
wasTrustable = (mUserTrustState.get(userId) == TrustState.TRUSTABLE);
- boolean isAutomotive = getContext().getPackageManager().hasSystemFeature(
- PackageManager.FEATURE_AUTOMOTIVE);
boolean renewingTrust = wasTrustable && (
(flags & TrustAgentService.FLAG_GRANT_TRUST_TEMPORARY_AND_RENEWABLE) != 0);
boolean canMoveToTrusted =
- alreadyUnlocked || isFromUnlock || renewingTrust || isAutomotive;
+ alreadyUnlocked || isFromUnlock || renewingTrust || isAutomotive();
boolean upgradingTrustForCurrentUser = (userId == mCurrentUser);
if (trustedByAtLeastOneAgent && wasTrusted) {
@@ -619,9 +516,7 @@ public class TrustManagerService extends SystemService {
isNowTrusted, newlyUnlocked, userId, flags, getTrustGrantedMessages(userId));
if (isNowTrusted != wasTrusted) {
refreshDeviceLockedForUser(userId);
- if (!isNowTrusted) {
- maybeLockScreen(userId);
- } else {
+ if (isNowTrusted) {
boolean isTrustableTimeout =
(flags & FLAG_GRANT_TRUST_TEMPORARY_AND_RENEWABLE) != 0;
// Every time we grant renewable trust we should override the idle trustable
@@ -1831,9 +1726,7 @@ public class TrustManagerService extends SystemService {
synchronized(mUsersUnlockedByBiometric) {
mUsersUnlockedByBiometric.put(userId, true);
}
- // In non-renewable trust mode we need to refresh trust state here, which will call
- // refreshDeviceLockedForUser()
- int updateTrustOnUnlock = mSettingsObserver.getTrustAgentsNonrenewableTrust() ? 1 : 0;
+ int updateTrustOnUnlock = isAutomotive() ? 0 : 1;
mHandler.obtainMessage(MSG_REFRESH_DEVICE_LOCKED_FOR_USER, userId,
updateTrustOnUnlock).sendToTarget();
mHandler.obtainMessage(MSG_REFRESH_TRUSTABLE_TIMERS_AFTER_AUTH, userId).sendToTarget();
@@ -1942,7 +1835,6 @@ public class TrustManagerService extends SystemService {
break;
case MSG_SWITCH_USER:
mCurrentUser = msg.arg1;
- mSettingsObserver.updateContentObserver();
refreshDeviceLockedForUser(UserHandle.USER_ALL);
break;
case MSG_STOP_USER:
@@ -2041,9 +1933,6 @@ public class TrustManagerService extends SystemService {
} else if (Intent.ACTION_USER_REMOVED.equals(action)) {
int userId = getUserId(intent);
if (userId > 0) {
- synchronized (mUserIsTrusted) {
- mUserIsTrusted.delete(userId);
- }
synchronized (mDeviceLockedForUser) {
mDeviceLockedForUser.delete(userId);
}
@@ -2175,7 +2064,6 @@ public class TrustManagerService extends SystemService {
mLockPatternUtils.requireStrongAuth(
mStrongAuthTracker.SOME_AUTH_REQUIRED_AFTER_TRUSTAGENT_EXPIRED, mUserId);
}
- maybeLockScreen(mUserId);
}
protected abstract void handleAlarm();
diff --git a/services/core/java/com/android/server/tv/TvInputHardwareManager.java b/services/core/java/com/android/server/tv/TvInputHardwareManager.java
index 0ab6d5769b5e..06a851637b82 100755
--- a/services/core/java/com/android/server/tv/TvInputHardwareManager.java
+++ b/services/core/java/com/android/server/tv/TvInputHardwareManager.java
@@ -96,6 +96,8 @@ class TvInputHardwareManager implements TvInputHal.Callback {
/* A map from a HDMI logical address to the matching TV input ID. */
private final SparseArray<String> mHdmiInputIdMap = new SparseArray<>();
private final Map<String, TvInputInfo> mInputMap = new ArrayMap<>();
+ /* A map from a HDMI input parent ID to the related input IDs. */
+ private final Map<String, List<String>> mHdmiParentInputMap = new ArrayMap<>();
private final AudioManager mAudioManager;
private final IHdmiHotplugEventListener mHdmiHotplugEventListener =
@@ -293,6 +295,12 @@ class TvInputHardwareManager implements TvInputHal.Callback {
}
}
+ public Map<String, List<String>> getHdmiParentInputMap() {
+ synchronized (mLock) {
+ return Collections.unmodifiableMap(mHdmiParentInputMap);
+ }
+ }
+
private boolean checkUidChangedLocked(
Connection connection, int callingUid, int resolvedUserId) {
Integer connectionCallingUid = connection.getCallingUidLocked();
@@ -379,12 +387,15 @@ class TvInputHardwareManager implements TvInputHal.Callback {
}
mHdmiInputIdMap.put(id, info.getId());
mInputMap.put(info.getId(), info);
+ if (!mHdmiParentInputMap.containsKey(parentId)) {
+ mHdmiParentInputMap.put(parentId, new ArrayList<String>());
+ }
+ mHdmiParentInputMap.get(parentId).add(info.getId());
}
}
public void removeHardwareInput(String inputId) {
synchronized (mLock) {
- mInputMap.remove(inputId);
int hardwareIndex = indexOfEqualValue(mHardwareInputIdMap, inputId);
if (hardwareIndex >= 0) {
mHardwareInputIdMap.removeAt(hardwareIndex);
@@ -393,6 +404,17 @@ class TvInputHardwareManager implements TvInputHal.Callback {
if (deviceIndex >= 0) {
mHdmiInputIdMap.removeAt(deviceIndex);
}
+ if (mInputMap.containsKey(inputId)) {
+ String parentId = mInputMap.get(inputId).getParentId();
+ if (parentId != null && mHdmiParentInputMap.containsKey(parentId)) {
+ List<String> parentInputList = mHdmiParentInputMap.get(parentId);
+ parentInputList.remove(inputId);
+ if (parentInputList.isEmpty()) {
+ mHdmiParentInputMap.remove(parentId);
+ }
+ }
+ mInputMap.remove(inputId);
+ }
}
}
diff --git a/services/core/java/com/android/server/tv/TvInputManagerService.java b/services/core/java/com/android/server/tv/TvInputManagerService.java
index 234e3f4c4b54..b12ecc333d1f 100644
--- a/services/core/java/com/android/server/tv/TvInputManagerService.java
+++ b/services/core/java/com/android/server/tv/TvInputManagerService.java
@@ -1839,22 +1839,22 @@ public final class TvInputManagerService extends SystemService {
getSessionLocked(sessionToken, callingUid, resolvedUserId).tune(
channelUri, params);
UserState userState = getOrCreateUserStateLocked(resolvedUserId);
- SessionState sessionState = getSessionStateLocked(sessionToken, callingUid,
- userState);
+ SessionState sessionState =
+ getSessionStateLocked(sessionToken, callingUid, userState);
if (!sessionState.isCurrent
|| !Objects.equals(sessionState.currentChannel, channelUri)) {
sessionState.isCurrent = true;
sessionState.currentChannel = channelUri;
notifyCurrentChannelInfosUpdatedLocked(userState);
if (!sessionState.isRecordingSession) {
- if (mOnScreenInputId == null
- || !TextUtils.equals(mOnScreenInputId, sessionState.inputId)) {
+ String actualInputId = getActualInputId(sessionState);
+ if (!TextUtils.equals(mOnScreenInputId, actualInputId)) {
logExternalInputEvent(
- FrameworkStatsLog
- .EXTERNAL_TV_INPUT_EVENT__EVENT_TYPE__TUNED,
- sessionState.inputId, sessionState);
+ FrameworkStatsLog
+ .EXTERNAL_TV_INPUT_EVENT__EVENT_TYPE__TUNED,
+ actualInputId, sessionState);
}
- mOnScreenInputId = sessionState.inputId;
+ mOnScreenInputId = actualInputId;
mOnScreenSessionState = sessionState;
}
}
@@ -2977,6 +2977,31 @@ public final class TvInputManagerService extends SystemService {
}
}
+ // get the actual input id of the specific sessionState.
+ // e.g. if an HDMI port has a CEC device plugged in, the actual input id of the HDMI
+ // session should be the input id of CEC device instead of the default HDMI input id.
+ @GuardedBy("mLock")
+ private String getActualInputId(SessionState sessionState) {
+ UserState userState = getOrCreateUserStateLocked(sessionState.userId);
+ TvInputState tvInputState = userState.inputMap.get(sessionState.inputId);
+ TvInputInfo tvInputInfo = tvInputState.info;
+ String actualInputId = sessionState.inputId;
+ switch (tvInputInfo.getType()) {
+ case TvInputInfo.TYPE_HDMI:
+ // TODO: find a better approach towards active CEC device in future
+ Map<String, List<String>> hdmiParentInputMap =
+ mTvInputHardwareManager.getHdmiParentInputMap();
+ if (hdmiParentInputMap.containsKey(sessionState.inputId)) {
+ List<String> parentInputList = hdmiParentInputMap.get(sessionState.inputId);
+ actualInputId = parentInputList.get(0);
+ }
+ break;
+ default:
+ break;
+ }
+ return actualInputId;
+ }
+
@Nullable
private static TvInputState getTvInputState(
SessionState sessionState,
@@ -3078,6 +3103,7 @@ public final class TvInputManagerService extends SystemService {
hdmiPort);
}
+ @GuardedBy("mLock")
private void logExternalInputEvent(int eventType, String inputId, SessionState sessionState) {
UserState userState = getOrCreateUserStateLocked(sessionState.userId);
TvInputState tvInputState = userState.inputMap.get(inputId);
@@ -3472,6 +3498,10 @@ public final class TvInputManagerService extends SystemService {
final long identity = Binder.clearCallingIdentity();
try {
synchronized (mLock) {
+ ServiceState serviceState = getServiceStateLocked(mComponent, mUserId);
+ if (serviceState.hardwareInputMap.containsKey(inputInfo.getId())) {
+ return;
+ }
mTvInputHardwareManager.addHardwareInput(deviceId, inputInfo);
addHardwareInputLocked(inputInfo);
}
@@ -3486,6 +3516,10 @@ public final class TvInputManagerService extends SystemService {
final long identity = Binder.clearCallingIdentity();
try {
synchronized (mLock) {
+ ServiceState serviceState = getServiceStateLocked(mComponent, mUserId);
+ if (serviceState.hardwareInputMap.containsKey(inputInfo.getId())) {
+ return;
+ }
mTvInputHardwareManager.addHdmiInput(id, inputInfo);
addHardwareInputLocked(inputInfo);
if (mOnScreenInputId != null && mOnScreenSessionState != null) {
@@ -3609,13 +3643,14 @@ public final class TvInputManagerService extends SystemService {
mSessionState.currentChannel = channelUri;
notifyCurrentChannelInfosUpdatedLocked(userState);
if (!mSessionState.isRecordingSession) {
- if (mOnScreenInputId == null
- || !TextUtils.equals(mOnScreenInputId, mSessionState.inputId)) {
+ String actualInputId = getActualInputId(mSessionState);
+ if (!TextUtils.equals(mOnScreenInputId, actualInputId)) {
logExternalInputEvent(
- FrameworkStatsLog.EXTERNAL_TV_INPUT_EVENT__EVENT_TYPE__TUNED,
- mSessionState.inputId, mSessionState);
+ FrameworkStatsLog
+ .EXTERNAL_TV_INPUT_EVENT__EVENT_TYPE__TUNED,
+ actualInputId, mSessionState);
}
- mOnScreenInputId = mSessionState.inputId;
+ mOnScreenInputId = actualInputId;
mOnScreenSessionState = mSessionState;
}
}
diff --git a/services/core/java/com/android/server/uri/UriGrantsManagerService.java b/services/core/java/com/android/server/uri/UriGrantsManagerService.java
index 01fdc8800c0e..7862f58374a3 100644
--- a/services/core/java/com/android/server/uri/UriGrantsManagerService.java
+++ b/services/core/java/com/android/server/uri/UriGrantsManagerService.java
@@ -41,6 +41,7 @@ import static org.xmlpull.v1.XmlPullParser.START_TAG;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.RequiresPermission;
import android.app.ActivityManager;
import android.app.ActivityManagerInternal;
import android.app.AppGlobals;
@@ -62,6 +63,7 @@ import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
import android.os.Message;
+import android.os.Process;
import android.os.RemoteException;
import android.os.SystemClock;
import android.os.UserHandle;
@@ -1304,6 +1306,46 @@ public class UriGrantsManagerService extends IUriGrantsManager.Stub implements
return false;
}
+ /**
+ * Check if the targetPkg can be granted permission to access uri by
+ * the callingUid using the given modeFlags. See {@link #checkGrantUriPermissionUnlocked}.
+ *
+ * @param callingUid The uid of the grantor app that has permissions to the uri.
+ * @param targetPkg The package name of the granted app that needs permissions to the uri.
+ * @param uri The uri for which permissions should be granted.
+ * @param modeFlags The modes to grant. See {@link Intent#FLAG_GRANT_READ_URI_PERMISSION}, etc.
+ * @param userId The userId in which the uri is to be resolved.
+ * @return uid of the target or -1 if permission grant not required. Returns -1 if the caller
+ * does not hold INTERACT_ACROSS_USERS_FULL
+ * @throws SecurityException if the grant is not allowed.
+ */
+ @Override
+ @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS_FULL)
+ public int checkGrantUriPermission_ignoreNonSystem(int callingUid, String targetPkg, Uri uri,
+ int modeFlags, int userId) {
+ if (!isCallerIsSystemOrPrivileged()) {
+ return Process.INVALID_UID;
+ }
+ final long origId = Binder.clearCallingIdentity();
+ try {
+ return checkGrantUriPermissionUnlocked(callingUid, targetPkg, uri, modeFlags,
+ userId);
+ } finally {
+ Binder.restoreCallingIdentity(origId);
+ }
+ }
+
+ private boolean isCallerIsSystemOrPrivileged() {
+ final int uid = Binder.getCallingUid();
+ if (uid == Process.SYSTEM_UID || uid == Process.ROOT_UID) {
+ return true;
+ }
+ return ActivityManager.checkComponentPermission(
+ android.Manifest.permission.INTERACT_ACROSS_USERS_FULL,
+ uid, /* owningUid = */-1, /* exported = */ true)
+ == PackageManager.PERMISSION_GRANTED;
+ }
+
@Override
public ArrayList<UriPermission> providePersistentUriGrants() {
final ArrayList<UriPermission> result = new ArrayList<>();
diff --git a/services/core/java/com/android/server/utils/FoldSettingProvider.java b/services/core/java/com/android/server/utils/FoldSettingProvider.java
new file mode 100644
index 000000000000..d62628b73019
--- /dev/null
+++ b/services/core/java/com/android/server/utils/FoldSettingProvider.java
@@ -0,0 +1,102 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.utils;
+
+import android.content.ContentResolver;
+import android.content.Context;
+import android.os.UserHandle;
+import android.provider.Settings;
+import android.util.Log;
+
+import com.android.internal.R;
+import com.android.internal.util.SettingsWrapper;
+
+import java.util.Set;
+
+/**
+ * This class provides a convenient way to access the {@link Settings.System#FOLD_LOCK_BEHAVIOR}.
+ * The {@link Settings.System#FOLD_LOCK_BEHAVIOR} setting controls the behavior of the device when
+ * it is folded, and provides the user with three different options to choose from. Those are:
+ * 1. Stay awake on fold: The device will remain unlocked when it is folded.
+ * 2. Selective stay awake: The device will remain unlocked when it is folded only if there are
+ * apps with wakelocks running. This is also the set default behavior.
+ * 3. Sleep on fold: The device will lock when it is folded, regardless of which apps are running
+ * or whether any wakelocks are held.
+ *
+ * Keep the setting values in this class in sync with the values in
+ * {@link com.android.settings.display.FoldLockBehaviorSettings}
+ */
+public class FoldSettingProvider {
+
+ public static final String SETTING_VALUE_STAY_AWAKE_ON_FOLD = "stay_awake_on_fold_key";
+ public static final String SETTING_VALUE_SELECTIVE_STAY_AWAKE = "selective_stay_awake_key";
+ public static final String SETTING_VALUE_SLEEP_ON_FOLD = "sleep_on_fold_key";
+ private static final String SETTING_VALUE_DEFAULT = SETTING_VALUE_SELECTIVE_STAY_AWAKE;
+ private static final Set<String> SETTING_VALUES = Set.of(SETTING_VALUE_STAY_AWAKE_ON_FOLD,
+ SETTING_VALUE_SELECTIVE_STAY_AWAKE, SETTING_VALUE_SLEEP_ON_FOLD);
+ private static final String TAG = "FoldSettingProvider";
+
+ private final ContentResolver mContentResolver;
+ private final boolean mIsFoldLockBehaviorAvailable;
+ private final SettingsWrapper mSettingsWrapper;
+
+ public FoldSettingProvider(Context context, SettingsWrapper settingsWrapper) {
+ mContentResolver = context.getContentResolver();
+ mSettingsWrapper = settingsWrapper;
+ mIsFoldLockBehaviorAvailable = context.getResources().getBoolean(
+ R.bool.config_fold_lock_behavior);
+ }
+
+ /**
+ * Returns whether the device should remain awake after folding.
+ */
+ public boolean shouldStayAwakeOnFold() {
+ return getFoldSettingValue().equals(SETTING_VALUE_STAY_AWAKE_ON_FOLD);
+ }
+
+ /**
+ * Returns whether the device should selective remain awake after folding.
+ */
+ public boolean shouldSelectiveStayAwakeOnFold() {
+ return getFoldSettingValue().equals(SETTING_VALUE_SELECTIVE_STAY_AWAKE);
+ }
+
+ /**
+ * Returns whether the device should strictly sleep after folding.
+ */
+ public boolean shouldSleepOnFold() {
+ return getFoldSettingValue().equals(SETTING_VALUE_SLEEP_ON_FOLD);
+ }
+
+ private String getFoldSettingValue() {
+ if (!mIsFoldLockBehaviorAvailable) {
+ return SETTING_VALUE_DEFAULT;
+ }
+ String foldSettingValue = mSettingsWrapper.getStringForUser(
+ mContentResolver,
+ Settings.System.FOLD_LOCK_BEHAVIOR,
+ UserHandle.USER_CURRENT);
+ foldSettingValue = (foldSettingValue != null) ? foldSettingValue : SETTING_VALUE_DEFAULT;
+ if (!SETTING_VALUES.contains(foldSettingValue)) {
+ Log.e(TAG,
+ "getFoldSettingValue: Invalid setting value, returning default setting value");
+ foldSettingValue = SETTING_VALUE_DEFAULT;
+ }
+
+ return foldSettingValue;
+ }
+}
diff --git a/services/core/java/com/android/server/utils/FoldSettingWrapper.java b/services/core/java/com/android/server/utils/FoldSettingWrapper.java
deleted file mode 100644
index 97a1ac06e24c..000000000000
--- a/services/core/java/com/android/server/utils/FoldSettingWrapper.java
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Copyright (C) 2023 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server.utils;
-
-import android.content.ContentResolver;
-import android.provider.Settings;
-
-/**
- * A wrapper class for the {@link Settings.System#STAY_AWAKE_ON_FOLD} setting.
- *
- * This class provides a convenient way to access the {@link Settings.System#STAY_AWAKE_ON_FOLD}
- * setting for testing.
- */
-public class FoldSettingWrapper {
- private final ContentResolver mContentResolver;
-
- public FoldSettingWrapper(ContentResolver contentResolver) {
- mContentResolver = contentResolver;
- }
-
- /**
- * Returns whether the device should remain awake after folding.
- */
- public boolean shouldStayAwakeOnFold() {
- try {
- return (Settings.System.getIntForUser(
- mContentResolver,
- Settings.System.STAY_AWAKE_ON_FOLD,
- 0) == 1);
- } catch (Settings.SettingNotFoundException e) {
- return false;
- }
- }
-}
diff --git a/services/core/java/com/android/server/vibrator/HapticFeedbackCustomization.java b/services/core/java/com/android/server/vibrator/HapticFeedbackCustomization.java
index 3fb845f064e3..e4f960763d54 100644
--- a/services/core/java/com/android/server/vibrator/HapticFeedbackCustomization.java
+++ b/services/core/java/com/android/server/vibrator/HapticFeedbackCustomization.java
@@ -19,7 +19,7 @@ package com.android.server.vibrator;
import android.annotation.Nullable;
import android.content.res.Resources;
import android.os.VibrationEffect;
-import android.os.Vibrator;
+import android.os.VibratorInfo;
import android.os.vibrator.persistence.ParsedVibration;
import android.os.vibrator.persistence.VibrationXmlParser;
import android.text.TextUtils;
@@ -107,10 +107,10 @@ final class HapticFeedbackCustomization {
* @hide
*/
@Nullable
- static SparseArray<VibrationEffect> loadVibrations(Resources res, Vibrator vibrator)
+ static SparseArray<VibrationEffect> loadVibrations(Resources res, VibratorInfo vibratorInfo)
throws CustomizationParserException, IOException {
try {
- return loadVibrationsInternal(res, vibrator);
+ return loadVibrationsInternal(res, vibratorInfo);
} catch (VibrationXmlParser.VibrationXmlParserException
| XmlParserException
| XmlPullParserException e) {
@@ -121,7 +121,7 @@ final class HapticFeedbackCustomization {
@Nullable
private static SparseArray<VibrationEffect> loadVibrationsInternal(
- Resources res, Vibrator vibrator) throws
+ Resources res, VibratorInfo vibratorInfo) throws
CustomizationParserException,
IOException,
VibrationXmlParser.VibrationXmlParserException,
@@ -175,7 +175,7 @@ final class HapticFeedbackCustomization {
throw new CustomizationParserException(
"Unable to parse vibration element for effect " + effectId);
}
- VibrationEffect effect = parsedVibration.resolve(vibrator);
+ VibrationEffect effect = parsedVibration.resolve(vibratorInfo);
if (effect != null) {
if (effect.getDuration() == Long.MAX_VALUE) {
throw new CustomizationParserException(String.format(
diff --git a/services/core/java/com/android/server/vibrator/HapticFeedbackVibrationProvider.java b/services/core/java/com/android/server/vibrator/HapticFeedbackVibrationProvider.java
index 7c9954391d8c..3d89afaae88f 100644
--- a/services/core/java/com/android/server/vibrator/HapticFeedbackVibrationProvider.java
+++ b/services/core/java/com/android/server/vibrator/HapticFeedbackVibrationProvider.java
@@ -21,6 +21,7 @@ import android.content.res.Resources;
import android.os.VibrationAttributes;
import android.os.VibrationEffect;
import android.os.Vibrator;
+import android.os.VibratorInfo;
import android.util.Slog;
import android.util.SparseArray;
import android.view.HapticFeedbackConstants;
@@ -29,8 +30,6 @@ import com.android.internal.annotations.VisibleForTesting;
import java.io.IOException;
import java.io.PrintWriter;
-import java.util.HashSet;
-import java.util.Set;
/**
* Provides the {@link VibrationEffect} and {@link VibrationAttributes} for haptic feedback.
@@ -47,7 +46,7 @@ public final class HapticFeedbackVibrationProvider {
private static final VibrationAttributes HARDWARE_FEEDBACK_VIBRATION_ATTRIBUTES =
VibrationAttributes.createForUsage(VibrationAttributes.USAGE_HARDWARE_FEEDBACK);
- private final Vibrator mVibrator;
+ private final VibratorInfo mVibratorInfo;
private final boolean mHapticTextHandleEnabled;
// Vibrator effect for haptic feedback during boot when safe mode is enabled.
private final VibrationEffect mSafeModeEnabledVibrationEffect;
@@ -58,25 +57,25 @@ public final class HapticFeedbackVibrationProvider {
/** @hide */
public HapticFeedbackVibrationProvider(Resources res, Vibrator vibrator) {
- this(res, vibrator, loadHapticCustomizations(res, vibrator));
+ this(res, vibrator.getInfo());
+ }
+
+ /** @hide */
+ public HapticFeedbackVibrationProvider(Resources res, VibratorInfo vibratorInfo) {
+ this(res, vibratorInfo, loadHapticCustomizations(res, vibratorInfo));
}
/** @hide */
@VisibleForTesting HapticFeedbackVibrationProvider(
Resources res,
- Vibrator vibrator,
+ VibratorInfo vibratorInfo,
@Nullable SparseArray<VibrationEffect> hapticCustomizations) {
- mVibrator = vibrator;
+ mVibratorInfo = vibratorInfo;
mHapticTextHandleEnabled = res.getBoolean(
com.android.internal.R.bool.config_enableHapticTextHandle);
- if (hapticCustomizations != null) {
- // Clean up the customizations to remove vibrations which may not ever be used due to
- // Vibrator properties or other device configurations.
- removeUnsupportedVibrations(hapticCustomizations, vibrator);
- if (hapticCustomizations.size() == 0) {
- hapticCustomizations = null;
- }
+ if (hapticCustomizations != null && hapticCustomizations.size() == 0) {
+ hapticCustomizations = null;
}
mHapticCustomizations = hapticCustomizations;
@@ -257,7 +256,7 @@ public final class HapticFeedbackVibrationProvider {
if (effectHasCustomization(hapticFeedbackId)) {
return mHapticCustomizations.get(hapticFeedbackId);
}
- if (mVibrator.areAllPrimitivesSupported(primitiveId)) {
+ if (mVibratorInfo.isPrimitiveSupported(primitiveId)) {
return VibrationEffect.startComposition()
.addPrimitive(primitiveId, primitiveScale)
.compose();
@@ -270,9 +269,8 @@ public final class HapticFeedbackVibrationProvider {
if (effectHasCustomization(HapticFeedbackConstants.ASSISTANT_BUTTON)) {
return mHapticCustomizations.get(HapticFeedbackConstants.ASSISTANT_BUTTON);
}
- if (mVibrator.areAllPrimitivesSupported(
- VibrationEffect.Composition.PRIMITIVE_QUICK_RISE,
- VibrationEffect.Composition.PRIMITIVE_TICK)) {
+ if (mVibratorInfo.isPrimitiveSupported(VibrationEffect.Composition.PRIMITIVE_QUICK_RISE)
+ && mVibratorInfo.isPrimitiveSupported(VibrationEffect.Composition.PRIMITIVE_TICK)) {
// quiet ramp, short pause, then sharp tick
return VibrationEffect.startComposition()
.addPrimitive(VibrationEffect.Composition.PRIMITIVE_QUICK_RISE, 0.25f)
@@ -289,27 +287,12 @@ public final class HapticFeedbackVibrationProvider {
@Nullable
private static SparseArray<VibrationEffect> loadHapticCustomizations(
- Resources res, Vibrator vibrator) {
+ Resources res, VibratorInfo vibratorInfo) {
try {
- return HapticFeedbackCustomization.loadVibrations(res, vibrator);
+ return HapticFeedbackCustomization.loadVibrations(res, vibratorInfo);
} catch (IOException | HapticFeedbackCustomization.CustomizationParserException e) {
Slog.e(TAG, "Unable to load haptic customizations.", e);
return null;
}
}
-
- private static void removeUnsupportedVibrations(
- SparseArray<VibrationEffect> customizations, Vibrator vibrator) {
- Set<Integer> keysToRemove = new HashSet<>();
- for (int i = 0; i < customizations.size(); i++) {
- int key = customizations.keyAt(i);
- if (!vibrator.areVibrationFeaturesSupported(customizations.get(key))) {
- keysToRemove.add(key);
- }
- }
-
- for (int key : keysToRemove) {
- customizations.remove(key);
- }
- }
}
diff --git a/services/core/java/com/android/server/vibrator/VibratorManagerService.java b/services/core/java/com/android/server/vibrator/VibratorManagerService.java
index e296c7b764e5..ee3d697cddb8 100644
--- a/services/core/java/com/android/server/vibrator/VibratorManagerService.java
+++ b/services/core/java/com/android/server/vibrator/VibratorManagerService.java
@@ -28,6 +28,7 @@ import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageManager;
+import android.content.res.Resources;
import android.hardware.vibrator.IVibrator;
import android.os.BatteryStats;
import android.os.Binder;
@@ -131,6 +132,7 @@ public class VibratorManagerService extends IVibratorManagerService.Stub {
private final Object mLock = new Object();
private final Context mContext;
+ private final Injector mInjector;
private final PowerManager.WakeLock mWakeLock;
private final IBatteryStats mBatteryStatsService;
private final VibratorFrameworkStatsLogger mFrameworkStatsLogger;
@@ -162,6 +164,8 @@ public class VibratorManagerService extends IVibratorManagerService.Stub {
@GuardedBy("mLock")
@Nullable private VibratorInfo mCombinedVibratorInfo;
+ @GuardedBy("mLock")
+ @Nullable private HapticFeedbackVibrationProvider mHapticFeedbackVibrationProvider;
private BroadcastReceiver mIntentReceiver = new BroadcastReceiver() {
@Override
@@ -201,6 +205,7 @@ public class VibratorManagerService extends IVibratorManagerService.Stub {
@VisibleForTesting
VibratorManagerService(Context context, Injector injector) {
mContext = context;
+ mInjector = injector;
mHandler = injector.createHandler(Looper.myLooper());
mVibrationSettings = new VibrationSettings(mContext, mHandler);
@@ -393,7 +398,42 @@ public class VibratorManagerService extends IVibratorManagerService.Stub {
@Override // Binder call
public void vibrate(int uid, int displayId, String opPkg, @NonNull CombinedVibration effect,
@Nullable VibrationAttributes attrs, String reason, IBinder token) {
- vibrateInternal(uid, displayId, opPkg, effect, attrs, reason, token);
+ vibrateWithPermissionCheck(uid, displayId, opPkg, effect, attrs, reason, token);
+ }
+
+ @Override // Binder call
+ public void performHapticFeedback(
+ int uid, int displayId, String opPkg, int constant, boolean always, String reason,
+ IBinder token) {
+ performHapticFeedbackInternal(uid, displayId, opPkg, constant, always, reason, token);
+ }
+
+ /**
+ * An internal-only version of performHapticFeedback that allows the caller access to the
+ * {@link HalVibration}.
+ * The Vibration is only returned if it is ongoing after this method returns.
+ */
+ @VisibleForTesting
+ @Nullable
+ HalVibration performHapticFeedbackInternal(
+ int uid, int displayId, String opPkg, int constant, boolean always, String reason,
+ IBinder token) {
+ HapticFeedbackVibrationProvider hapticVibrationProvider = getHapticVibrationProvider();
+ if (hapticVibrationProvider == null) {
+ Slog.w(TAG, "performHapticFeedback; haptic vibration provider not ready.");
+ return null;
+ }
+ VibrationEffect effect = hapticVibrationProvider.getVibrationForHapticFeedback(constant);
+ if (effect == null) {
+ Slog.w(TAG, "performHapticFeedback; vibration absent for effect " + constant);
+ return null;
+ }
+ CombinedVibration combinedVibration = CombinedVibration.createParallel(effect);
+ VibrationAttributes attrs =
+ hapticVibrationProvider.getVibrationAttributesForHapticFeedback(
+ constant, /* bypassVibrationIntensitySetting= */ always);
+ return vibrateWithoutPermissionCheck(uid, displayId, opPkg, combinedVibration, attrs,
+ "performHapticFeedback: " + reason, token);
}
/**
@@ -403,90 +443,107 @@ public class VibratorManagerService extends IVibratorManagerService.Stub {
*/
@VisibleForTesting
@Nullable
- HalVibration vibrateInternal(int uid, int displayId, String opPkg,
+ HalVibration vibrateWithPermissionCheck(int uid, int displayId, String opPkg,
@NonNull CombinedVibration effect, @Nullable VibrationAttributes attrs,
String reason, IBinder token) {
Trace.traceBegin(Trace.TRACE_TAG_VIBRATOR, "vibrate, reason = " + reason);
try {
- mContext.enforceCallingOrSelfPermission(android.Manifest.permission.VIBRATE, "vibrate");
+ mContext.enforceCallingOrSelfPermission(
+ android.Manifest.permission.VIBRATE, "vibrate");
+ return vibrateInternal(uid, displayId, opPkg, effect, attrs, reason, token);
+ } finally {
+ Trace.traceEnd(Trace.TRACE_TAG_VIBRATOR);
+ }
+ }
- if (token == null) {
- Slog.e(TAG, "token must not be null");
- return null;
- }
- enforceUpdateAppOpsStatsPermission(uid);
- if (!isEffectValid(effect)) {
- return null;
- }
- attrs = fixupVibrationAttributes(attrs, effect);
- // Create Vibration.Stats as close to the received request as possible, for tracking.
- HalVibration vib = new HalVibration(token, effect,
- new Vibration.CallerInfo(attrs, uid, displayId, opPkg, reason));
- fillVibrationFallbacks(vib, effect);
+ HalVibration vibrateWithoutPermissionCheck(int uid, int displayId, String opPkg,
+ @NonNull CombinedVibration effect, @Nullable VibrationAttributes attrs,
+ String reason, IBinder token) {
+ Trace.traceBegin(Trace.TRACE_TAG_VIBRATOR, "vibrate no perm check, reason = " + reason);
+ try {
+ return vibrateInternal(uid, displayId, opPkg, effect, attrs, reason, token);
+ } finally {
+ Trace.traceEnd(Trace.TRACE_TAG_VIBRATOR);
+ }
+ }
- if (attrs.isFlagSet(VibrationAttributes.FLAG_INVALIDATE_SETTINGS_CACHE)) {
- // Force update of user settings before checking if this vibration effect should
- // be ignored or scaled.
- mVibrationSettings.update();
- }
+ private HalVibration vibrateInternal(int uid, int displayId, String opPkg,
+ @NonNull CombinedVibration effect, @Nullable VibrationAttributes attrs,
+ String reason, IBinder token) {
+ if (token == null) {
+ Slog.e(TAG, "token must not be null");
+ return null;
+ }
+ enforceUpdateAppOpsStatsPermission(uid);
+ if (!isEffectValid(effect)) {
+ return null;
+ }
+ attrs = fixupVibrationAttributes(attrs, effect);
+ // Create Vibration.Stats as close to the received request as possible, for tracking.
+ HalVibration vib = new HalVibration(token, effect,
+ new Vibration.CallerInfo(attrs, uid, displayId, opPkg, reason));
+ fillVibrationFallbacks(vib, effect);
- synchronized (mLock) {
- if (DEBUG) {
- Slog.d(TAG, "Starting vibrate for vibration " + vib.id);
- }
+ if (attrs.isFlagSet(VibrationAttributes.FLAG_INVALIDATE_SETTINGS_CACHE)) {
+ // Force update of user settings before checking if this vibration effect should
+ // be ignored or scaled.
+ mVibrationSettings.update();
+ }
- // Check if user settings or DnD is set to ignore this vibration.
- Vibration.EndInfo vibrationEndInfo = shouldIgnoreVibrationLocked(vib.callerInfo);
+ synchronized (mLock) {
+ if (DEBUG) {
+ Slog.d(TAG, "Starting vibrate for vibration " + vib.id);
+ }
- // Check if ongoing vibration is more important than this vibration.
- if (vibrationEndInfo == null) {
- vibrationEndInfo = shouldIgnoreVibrationForOngoingLocked(vib);
- }
+ // Check if user settings or DnD is set to ignore this vibration.
+ Vibration.EndInfo vibrationEndInfo = shouldIgnoreVibrationLocked(vib.callerInfo);
- // If not ignored so far then try to start this vibration.
- if (vibrationEndInfo == null) {
- final long ident = Binder.clearCallingIdentity();
- try {
- if (mCurrentExternalVibration != null) {
- mCurrentExternalVibration.mute();
+ // Check if ongoing vibration is more important than this vibration.
+ if (vibrationEndInfo == null) {
+ vibrationEndInfo = shouldIgnoreVibrationForOngoingLocked(vib);
+ }
+
+ // If not ignored so far then try to start this vibration.
+ if (vibrationEndInfo == null) {
+ final long ident = Binder.clearCallingIdentity();
+ try {
+ if (mCurrentExternalVibration != null) {
+ mCurrentExternalVibration.mute();
+ vib.stats.reportInterruptedAnotherVibration(
+ mCurrentExternalVibration.callerInfo);
+ endExternalVibrateLocked(
+ new Vibration.EndInfo(Vibration.Status.CANCELLED_SUPERSEDED,
+ vib.callerInfo),
+ /* continueExternalControl= */ false);
+ } else if (mCurrentVibration != null) {
+ if (mCurrentVibration.getVibration().canPipelineWith(vib)) {
+ // Don't cancel the current vibration if it's pipeline-able.
+ // Note that if there is a pending next vibration that can't be
+ // pipelined, it will have already cancelled the current one, so we
+ // don't need to consider it here as well.
+ if (DEBUG) {
+ Slog.d(TAG, "Pipelining vibration " + vib.id);
+ }
+ } else {
vib.stats.reportInterruptedAnotherVibration(
- mCurrentExternalVibration.callerInfo);
- endExternalVibrateLocked(
+ mCurrentVibration.getVibration().callerInfo);
+ mCurrentVibration.notifyCancelled(
new Vibration.EndInfo(Vibration.Status.CANCELLED_SUPERSEDED,
vib.callerInfo),
- /* continueExternalControl= */ false);
- } else if (mCurrentVibration != null) {
- if (mCurrentVibration.getVibration().canPipelineWith(vib)) {
- // Don't cancel the current vibration if it's pipeline-able.
- // Note that if there is a pending next vibration that can't be
- // pipelined, it will have already cancelled the current one, so we
- // don't need to consider it here as well.
- if (DEBUG) {
- Slog.d(TAG, "Pipelining vibration " + vib.id);
- }
- } else {
- vib.stats.reportInterruptedAnotherVibration(
- mCurrentVibration.getVibration().callerInfo);
- mCurrentVibration.notifyCancelled(
- new Vibration.EndInfo(Vibration.Status.CANCELLED_SUPERSEDED,
- vib.callerInfo),
- /* immediate= */ false);
- }
+ /* immediate= */ false);
}
- vibrationEndInfo = startVibrationLocked(vib);
- } finally {
- Binder.restoreCallingIdentity(ident);
}
+ vibrationEndInfo = startVibrationLocked(vib);
+ } finally {
+ Binder.restoreCallingIdentity(ident);
}
+ }
- // Ignored or failed to start the vibration, end it and report metrics right away.
- if (vibrationEndInfo != null) {
- endVibrationLocked(vib, vibrationEndInfo, /* shouldWriteStats= */ true);
- }
- return vib;
+ // Ignored or failed to start the vibration, end it and report metrics right away.
+ if (vibrationEndInfo != null) {
+ endVibrationLocked(vib, vibrationEndInfo, /* shouldWriteStats= */ true);
}
- } finally {
- Trace.traceEnd(Trace.TRACE_TAG_VIBRATOR);
+ return vib;
}
}
@@ -1315,6 +1372,11 @@ public class VibratorManagerService extends IVibratorManagerService.Stub {
return new VibratorController(vibratorId, listener);
}
+ HapticFeedbackVibrationProvider createHapticFeedbackVibrationProvider(
+ Resources resources, VibratorInfo vibratorInfo) {
+ return new HapticFeedbackVibrationProvider(resources, vibratorInfo);
+ }
+
void addService(String name, IBinder service) {
ServiceManager.addService(name, service);
}
@@ -1831,6 +1893,22 @@ public class VibratorManagerService extends IVibratorManagerService.Stub {
}
}
+ private HapticFeedbackVibrationProvider getHapticVibrationProvider() {
+ synchronized (mLock) {
+ // Used a cached haptic vibration provider if one exists.
+ if (mHapticFeedbackVibrationProvider != null) {
+ return mHapticFeedbackVibrationProvider;
+ }
+ VibratorInfo combinedVibratorInfo = getCombinedVibratorInfo();
+ if (combinedVibratorInfo == null) {
+ return null;
+ }
+ return mHapticFeedbackVibrationProvider =
+ mInjector.createHapticFeedbackVibrationProvider(
+ mContext.getResources(), combinedVibratorInfo);
+ }
+ }
+
private VibratorInfo getCombinedVibratorInfo() {
synchronized (mLock) {
// Used a cached resolving vibrator if one exists.
@@ -2068,6 +2146,9 @@ public class VibratorManagerService extends IVibratorManagerService.Stub {
if ("cancel".equals(cmd)) {
return runCancel();
}
+ if ("feedback".equals(cmd)) {
+ return runHapticFeedback();
+ }
return handleDefaultCommands(cmd);
} finally {
Trace.traceEnd(Trace.TRACE_TAG_VIBRATOR);
@@ -2098,16 +2179,10 @@ public class VibratorManagerService extends IVibratorManagerService.Stub {
// only cancel background vibrations.
IBinder deathBinder = commonOptions.background ? VibratorManagerService.this
: mShellCallbacksToken;
- HalVibration vib = vibrateInternal(Binder.getCallingUid(), Display.DEFAULT_DISPLAY,
- SHELL_PACKAGE_NAME, combined, attrs, commonOptions.description, deathBinder);
- if (vib != null && !commonOptions.background) {
- try {
- // Waits for the client vibration to finish, but the VibrationThread may still
- // do cleanup after this.
- vib.waitForEnd();
- } catch (InterruptedException e) {
- }
- }
+ HalVibration vib = vibrateWithPermissionCheck(Binder.getCallingUid(),
+ Display.DEFAULT_DISPLAY, SHELL_PACKAGE_NAME, combined, attrs,
+ commonOptions.description, deathBinder);
+ maybeWaitOnVibration(vib, commonOptions);
}
private int runMono() {
@@ -2155,6 +2230,21 @@ public class VibratorManagerService extends IVibratorManagerService.Stub {
return 0;
}
+ private int runHapticFeedback() {
+ CommonOptions commonOptions = new CommonOptions();
+ int constant = Integer.parseInt(getNextArgRequired());
+
+ IBinder deathBinder = commonOptions.background ? VibratorManagerService.this
+ : mShellCallbacksToken;
+ HalVibration vib = performHapticFeedbackInternal(Binder.getCallingUid(),
+ Display.DEFAULT_DISPLAY, SHELL_PACKAGE_NAME, constant,
+ /* always= */ commonOptions.force, /* reason= */ commonOptions.description,
+ deathBinder);
+ maybeWaitOnVibration(vib, commonOptions);
+
+ return 0;
+ }
+
private VibrationEffect nextEffect() {
VibrationEffect.Composition composition = VibrationEffect.startComposition();
String nextArg;
@@ -2364,6 +2454,17 @@ public class VibratorManagerService extends IVibratorManagerService.Stub {
}
}
+ private void maybeWaitOnVibration(HalVibration vib, CommonOptions commonOptions) {
+ if (vib != null && !commonOptions.background) {
+ try {
+ // Waits for the client vibration to finish, but the VibrationThread may still
+ // do cleanup after this.
+ vib.waitForEnd();
+ } catch (InterruptedException e) {
+ }
+ }
+ }
+
@Override
public void onHelp() {
try (PrintWriter pw = getOutPrintWriter();) {
@@ -2389,6 +2490,10 @@ public class VibratorManagerService extends IVibratorManagerService.Stub {
pw.println(" XML containing a single effect it runs on all vibrators in sync.");
pw.println(" cancel");
pw.println(" Cancels any active vibration");
+ pw.println(" feedback [-f] [-d <description>] <constant>");
+ pw.println(" Performs a haptic feedback with the given constant.");
+ pw.println(" The force (-f) option enables the `always` configuration, which");
+ pw.println(" plays the haptic irrespective of the vibration intensity settings");
pw.println("");
pw.println("Effect commands:");
pw.println(" oneshot [-w delay] [-a] <duration> [<amplitude>]");
diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java
index 60854885d5bb..582536b662ce 100644
--- a/services/core/java/com/android/server/wm/ActivityRecord.java
+++ b/services/core/java/com/android/server/wm/ActivityRecord.java
@@ -2929,7 +2929,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
reparent(newTaskFrag, position);
}
- private boolean isHomeIntent(Intent intent) {
+ static boolean isHomeIntent(Intent intent) {
return ACTION_MAIN.equals(intent.getAction())
&& (intent.hasCategory(CATEGORY_HOME)
|| intent.hasCategory(CATEGORY_SECONDARY_HOME))
@@ -3363,7 +3363,11 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
// current focused activity could be another activity in the same Task if activities are
// displayed on adjacent TaskFragments.
final ActivityRecord currentFocusedApp = mDisplayContent.mFocusedApp;
- if (currentFocusedApp != null && currentFocusedApp.task == task) {
+ final int topFocusedDisplayId = mRootWindowContainer.getTopFocusedDisplayContent() != null
+ ? mRootWindowContainer.getTopFocusedDisplayContent().getDisplayId()
+ : INVALID_DISPLAY;
+ if (currentFocusedApp != null && currentFocusedApp.task == task
+ && topFocusedDisplayId == mDisplayContent.getDisplayId()) {
final Task topFocusableTask = mDisplayContent.getTask(
(t) -> t.isLeafTask() && t.isFocusable(), true /* traverseTopToBottom */);
if (task == topFocusableTask) {
diff --git a/services/core/java/com/android/server/wm/ActivityStartInterceptor.java b/services/core/java/com/android/server/wm/ActivityStartInterceptor.java
index 1eb56f1b7d1c..a5b1132fe499 100644
--- a/services/core/java/com/android/server/wm/ActivityStartInterceptor.java
+++ b/services/core/java/com/android/server/wm/ActivityStartInterceptor.java
@@ -55,6 +55,7 @@ import android.os.IBinder;
import android.os.RemoteException;
import android.os.UserHandle;
import android.os.UserManager;
+import android.util.Pair;
import android.util.SparseArray;
import com.android.internal.annotations.VisibleForTesting;
@@ -77,7 +78,6 @@ class ActivityStartInterceptor {
private final ActivityTaskManagerService mService;
private final ActivityTaskSupervisor mSupervisor;
- private final RootWindowContainer mRootWindowContainer;
private final Context mServiceContext;
// UserManager cannot be final as it's not ready when this class is instantiated during boot
@@ -110,17 +110,23 @@ class ActivityStartInterceptor {
TaskFragment mInTaskFragment;
ActivityOptions mActivityOptions;
+ /*
+ * Note that this is just a hint of what the launch display area will be as it is
+ * based only on the information at the early pre-interception stage of starting the
+ * intent. The real launch display area calculated later may be different from this one.
+ */
+ TaskDisplayArea mPresumableLaunchDisplayArea;
+
ActivityStartInterceptor(
ActivityTaskManagerService service, ActivityTaskSupervisor supervisor) {
- this(service, supervisor, service.mRootWindowContainer, service.mContext);
+ this(service, supervisor, service.mContext);
}
@VisibleForTesting
ActivityStartInterceptor(ActivityTaskManagerService service, ActivityTaskSupervisor supervisor,
- RootWindowContainer root, Context context) {
+ Context context) {
mService = service;
mSupervisor = supervisor;
- mRootWindowContainer = root;
mServiceContext = context;
}
@@ -162,7 +168,7 @@ class ActivityStartInterceptor {
/**
* A helper function to obtain the targeted {@link TaskFragment} during
* {@link #intercept(Intent, ResolveInfo, ActivityInfo, String, Task, TaskFragment, int, int,
- * ActivityOptions)} if any.
+ * ActivityOptions, TaskDisplayArea)} if any.
*/
@Nullable
private TaskFragment getLaunchTaskFragment() {
@@ -187,7 +193,7 @@ class ActivityStartInterceptor {
*/
boolean intercept(Intent intent, ResolveInfo rInfo, ActivityInfo aInfo, String resolvedType,
Task inTask, TaskFragment inTaskFragment, int callingPid, int callingUid,
- ActivityOptions activityOptions) {
+ ActivityOptions activityOptions, TaskDisplayArea presumableLaunchDisplayArea) {
mUserManager = UserManager.get(mServiceContext);
mIntent = intent;
@@ -199,6 +205,7 @@ class ActivityStartInterceptor {
mInTask = inTask;
mInTaskFragment = inTaskFragment;
mActivityOptions = activityOptions;
+ mPresumableLaunchDisplayArea = presumableLaunchDisplayArea;
if (interceptQuietProfileIfNeeded()) {
// If work profile is turned off, skip the work challenge since the profile can only
@@ -221,6 +228,11 @@ class ActivityStartInterceptor {
if (interceptLockedManagedProfileIfNeeded()) {
return true;
}
+ if (interceptHomeIfNeeded()) {
+ // Replace primary home intents directed at displays that do not support primary home
+ // but support secondary home with the relevant secondary home activity.
+ return true;
+ }
final SparseArray<ActivityInterceptorCallback> callbacks =
mService.getActivityInterceptorCallbacks();
@@ -470,6 +482,47 @@ class ActivityStartInterceptor {
return true;
}
+ private boolean interceptHomeIfNeeded() {
+ if (mPresumableLaunchDisplayArea == null || mService.mRootWindowContainer == null) {
+ return false;
+ }
+ if (!ActivityRecord.isHomeIntent(mIntent)) {
+ return false;
+ }
+ if (!mIntent.hasCategory(Intent.CATEGORY_HOME)) {
+ // Already a secondary home intent, leave it alone.
+ return false;
+ }
+ if (mService.mRootWindowContainer.shouldPlacePrimaryHomeOnDisplay(
+ mPresumableLaunchDisplayArea.getDisplayId())) {
+ // Primary home can be launched to the display area.
+ return false;
+ }
+ if (!mService.mRootWindowContainer.shouldPlaceSecondaryHomeOnDisplayArea(
+ mPresumableLaunchDisplayArea)) {
+ // Secondary home cannot be launched on the display area.
+ return false;
+ }
+
+ // At this point we have a primary home intent for a display that does not support primary
+ // home activity but it supports secondary home one. So replace it with secondary home.
+ Pair<ActivityInfo, Intent> info = mService.mRootWindowContainer
+ .resolveSecondaryHomeActivity(mUserId, mPresumableLaunchDisplayArea);
+ mIntent = info.second;
+ // The new task flag is needed because the home activity should already be in the root task
+ // and should not be moved to the caller's task. Also, activities cannot change their type,
+ // e.g. a standard activity cannot become a home activity.
+ mIntent.addFlags(FLAG_ACTIVITY_NEW_TASK);
+ mCallingPid = mRealCallingPid;
+ mCallingUid = mRealCallingUid;
+ mResolvedType = null;
+
+ mRInfo = mSupervisor.resolveIntent(mIntent, mResolvedType, mUserId, /* flags= */ 0,
+ mRealCallingUid, mRealCallingPid);
+ mAInfo = mSupervisor.resolveActivity(mIntent, mRInfo, mStartFlags, /*profilerInfo=*/ null);
+ return true;
+ }
+
private boolean isPackageSuspended() {
return mAInfo != null && mAInfo.applicationInfo != null
&& (mAInfo.applicationInfo.flags & FLAG_SUSPENDED) != 0;
diff --git a/services/core/java/com/android/server/wm/ActivityStarter.java b/services/core/java/com/android/server/wm/ActivityStarter.java
index 1bc78d6e0820..458d1e8fa04b 100644
--- a/services/core/java/com/android/server/wm/ActivityStarter.java
+++ b/services/core/java/com/android/server/wm/ActivityStarter.java
@@ -1154,10 +1154,12 @@ class ActivityStarter {
}
}
+ final TaskDisplayArea suggestedLaunchDisplayArea =
+ computeSuggestedLaunchDisplayArea(inTask, sourceRecord, checkedOptions);
mInterceptor.setStates(userId, realCallingPid, realCallingUid, startFlags, callingPackage,
callingFeatureId);
if (mInterceptor.intercept(intent, rInfo, aInfo, resolvedType, inTask, inTaskFragment,
- callingPid, callingUid, checkedOptions)) {
+ callingPid, callingUid, checkedOptions, suggestedLaunchDisplayArea)) {
// activity start was intercepted, e.g. because the target user is currently in quiet
// mode (turn off work) or the target application is suspended
intent = mInterceptor.mIntent;
@@ -1890,6 +1892,15 @@ class ActivityStarter {
mPreferredWindowingMode = mLaunchParams.mWindowingMode;
}
+ private TaskDisplayArea computeSuggestedLaunchDisplayArea(
+ Task task, ActivityRecord source, ActivityOptions options) {
+ mSupervisor.getLaunchParamsController().calculate(task, /*layout=*/null,
+ /*activity=*/ null, source, options, mRequest, PHASE_DISPLAY, mLaunchParams);
+ return mLaunchParams.hasPreferredTaskDisplayArea()
+ ? mLaunchParams.mPreferredTaskDisplayArea
+ : mRootWindowContainer.getDefaultTaskDisplayArea();
+ }
+
@VisibleForTesting
int isAllowedToStart(ActivityRecord r, boolean newTask, Task targetTask) {
if (r.packageName == null) {
diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
index 42c363085017..fd42077bed7d 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
@@ -2648,9 +2648,15 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
mAmInternal.enforceCallingPermission(Manifest.permission.UPDATE_LOCK_TASK_PACKAGES,
"updateLockTaskPackages()");
}
- synchronized (mGlobalLock) {
- ProtoLog.w(WM_DEBUG_LOCKTASK, "Allowlisting %d:%s", userId, Arrays.toString(packages));
- getLockTaskController().updateLockTaskPackages(userId, packages);
+ final long origId = Binder.clearCallingIdentity();
+ try {
+ synchronized (mGlobalLock) {
+ ProtoLog.w(WM_DEBUG_LOCKTASK, "Allowlisting %d:%s", userId,
+ Arrays.toString(packages));
+ getLockTaskController().updateLockTaskPackages(userId, packages);
+ }
+ } finally {
+ Binder.restoreCallingIdentity(origId);
}
}
@@ -6177,6 +6183,8 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
@Override
public void onPackageReplaced(ApplicationInfo aInfo) {
synchronized (mGlobalLock) {
+ // In case if setWindowManager hasn't been called yet when booting.
+ if (mRootWindowContainer == null) return;
mRootWindowContainer.updateActivityApplicationInfo(aInfo);
}
}
diff --git a/services/core/java/com/android/server/wm/DesktopModeLaunchParamsModifier.java b/services/core/java/com/android/server/wm/DesktopModeLaunchParamsModifier.java
index 4180cd2298ea..15a0445b8ad4 100644
--- a/services/core/java/com/android/server/wm/DesktopModeLaunchParamsModifier.java
+++ b/services/core/java/com/android/server/wm/DesktopModeLaunchParamsModifier.java
@@ -40,8 +40,6 @@ public class DesktopModeLaunchParamsModifier implements LaunchParamsModifier {
private static final boolean DEBUG = false;
// Desktop mode feature flags.
- private static final boolean DESKTOP_MODE_PROTO1_SUPPORTED =
- SystemProperties.getBoolean("persist.wm.debug.desktop_mode", false);
private static final boolean DESKTOP_MODE_PROTO2_SUPPORTED =
SystemProperties.getBoolean("persist.wm.debug.desktop_mode_2", false);
// Override default freeform task width when desktop mode is enabled. In dips.
@@ -142,6 +140,6 @@ public class DesktopModeLaunchParamsModifier implements LaunchParamsModifier {
/** Whether desktop mode is supported. */
static boolean isDesktopModeSupported() {
- return DESKTOP_MODE_PROTO1_SUPPORTED || DESKTOP_MODE_PROTO2_SUPPORTED;
+ return DESKTOP_MODE_PROTO2_SUPPORTED;
}
}
diff --git a/services/core/java/com/android/server/wm/Dimmer.java b/services/core/java/com/android/server/wm/Dimmer.java
index 4f3ab8bbbe0a..ae29afa9fc49 100644
--- a/services/core/java/com/android/server/wm/Dimmer.java
+++ b/services/core/java/com/android/server/wm/Dimmer.java
@@ -22,6 +22,7 @@ import static com.android.server.wm.AlphaAnimationSpecProto.TO;
import static com.android.server.wm.AnimationSpecProto.ALPHA;
import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_DIMMER;
+import android.annotation.NonNull;
import android.graphics.Rect;
import android.util.Log;
import android.util.proto.ProtoOutputStream;
@@ -178,6 +179,7 @@ class Dimmer {
mSurfaceAnimatorStarter = surfaceAnimatorStarter;
}
+ @NonNull
WindowContainer<?> getHost() {
return mHost;
}
@@ -199,13 +201,6 @@ class Dimmer {
try {
final SurfaceControl ctl = makeDimLayer();
mDimState = new DimState(ctl);
- /**
- * See documentation on {@link #dimAbove} to understand lifecycle management of
- * Dim's via state resetting for Dim's with containers.
- */
- if (container == null) {
- mDimState.mDontReset = true;
- }
} catch (Surface.OutOfResourcesException e) {
Log.w(TAG, "OutOfResourcesException creating dim surface");
}
@@ -241,7 +236,7 @@ class Dimmer {
* @param container The container which to dim above. Should be a child of our host.
* @param alpha The alpha at which to Dim.
*/
- void dimAbove(WindowContainer container, float alpha) {
+ void dimAbove(@NonNull WindowContainer container, float alpha) {
dim(container, 1, alpha, 0);
}
@@ -253,7 +248,7 @@ class Dimmer {
* @param blurRadius The amount of blur added to the Dim.
*/
- void dimBelow(WindowContainer container, float alpha, int blurRadius) {
+ void dimBelow(@NonNull WindowContainer container, float alpha, int blurRadius) {
dim(container, -1, alpha, blurRadius);
}
@@ -316,7 +311,12 @@ class Dimmer {
if (!mDimState.isVisible) {
mDimState.isVisible = true;
t.show(mDimState.mDimLayer);
- startDimEnter(mLastRequestedDimContainer, mDimState.mSurfaceAnimator, t);
+ // Skip enter animation while starting window is on top of its activity
+ final WindowState ws = mLastRequestedDimContainer.asWindowState();
+ if (ws == null || ws.mActivityRecord == null
+ || ws.mActivityRecord.mStartingData == null) {
+ startDimEnter(mLastRequestedDimContainer, mDimState.mSurfaceAnimator, t);
+ }
}
return true;
}
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index 2e51fe410f46..daa73db4684d 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -743,9 +743,6 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
/** Set of activities in foreground size compat mode. */
private Set<ActivityRecord> mActiveSizeCompatActivities = new ArraySet<>();
- // Used in updating the display size
- private Point mTmpDisplaySize = new Point();
-
// Used in updating override configurations
private final Configuration mTempConfig = new Configuration();
@@ -4797,25 +4794,6 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
}, false /* traverseTopToBottom */);
}
- /**
- * Starts the Keyguard exit animation on all windows that don't belong to an app token.
- */
- void startKeyguardExitOnNonAppWindows(boolean onWallpaper, boolean goingToShade,
- boolean subtle) {
- final WindowManagerPolicy policy = mWmService.mPolicy;
- forAllWindows(w -> {
- if (w.mActivityRecord == null && w.canBeHiddenByKeyguard()
- && w.wouldBeVisibleIfPolicyIgnored() && !w.isVisible()) {
- w.startAnimation(policy.createHiddenByKeyguardExit(
- onWallpaper, goingToShade, subtle));
- }
- }, true /* traverseTopToBottom */);
- for (int i = mShellRoots.size() - 1; i >= 0; --i) {
- mShellRoots.valueAt(i).startAnimation(policy.createHiddenByKeyguardExit(
- onWallpaper, goingToShade, subtle));
- }
- }
-
/** @return {@code true} if there is window to wait before enabling the screen. */
boolean shouldWaitForSystemDecorWindowsOnBoot() {
if (!isDefaultDisplay && !supportsSystemDecorations()) {
@@ -6519,10 +6497,11 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
}
/**
- * @return whether the physical display has a fixed orientation and cannot be rotated.
+ * @return whether the physical display orientation should change when its content rotates to
+ * match the orientation of the content.
*/
- boolean isDisplayOrientationFixed() {
- return (mDisplayInfo.flags & Display.FLAG_ROTATES_WITH_CONTENT) == 0;
+ boolean shouldRotateWithContent() {
+ return (mDisplayInfo.flags & Display.FLAG_ROTATES_WITH_CONTENT) != 0;
}
/**
diff --git a/services/core/java/com/android/server/wm/DisplayPolicy.java b/services/core/java/com/android/server/wm/DisplayPolicy.java
index 1871cf6175c5..707b7799460e 100644
--- a/services/core/java/com/android/server/wm/DisplayPolicy.java
+++ b/services/core/java/com/android/server/wm/DisplayPolicy.java
@@ -17,6 +17,7 @@
package com.android.server.wm;
import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
+import static android.inputmethodservice.InputMethodService.ENABLE_HIDE_IME_CAPTION_BAR;
import static android.view.Display.TYPE_INTERNAL;
import static android.view.InsetsFrameProvider.SOURCE_ARBITRARY_RECTANGLE;
import static android.view.InsetsFrameProvider.SOURCE_CONTAINER_BOUNDS;
@@ -1201,8 +1202,8 @@ public class DisplayPolicy {
throw new IllegalArgumentException("IME insets must be provided by a window.");
}
- if (mNavigationBar != null && navigationBarPosition(displayFrames.mRotation)
- == NAV_BAR_BOTTOM) {
+ if (!ENABLE_HIDE_IME_CAPTION_BAR && mNavigationBar != null
+ && navigationBarPosition(displayFrames.mRotation) == NAV_BAR_BOTTOM) {
// In gesture navigation, nav bar frame is larger than frame to calculate insets.
// IME should not provide frame which is smaller than the nav bar frame. Otherwise,
// nav bar might be overlapped with the content of the client when IME is shown.
diff --git a/services/core/java/com/android/server/wm/DisplayRotation.java b/services/core/java/com/android/server/wm/DisplayRotation.java
index 9ef25b6e71b1..d461d1ec02f0 100644
--- a/services/core/java/com/android/server/wm/DisplayRotation.java
+++ b/services/core/java/com/android/server/wm/DisplayRotation.java
@@ -435,7 +435,7 @@ public class DisplayRotation {
PackageManager.FEATURE_LEANBACK);
mDefaultFixedToUserRotation =
(isCar || isTv || mService.mIsPc || mDisplayContent.forceDesktopMode()
- || mDisplayContent.isDisplayOrientationFixed())
+ || !mDisplayContent.shouldRotateWithContent())
// For debug purposes the next line turns this feature off with:
// $ adb shell setprop config.override_forced_orient true
// $ adb shell wm size reset
@@ -948,7 +948,7 @@ public class DisplayRotation {
mDisplayWindowSettings.setUserRotation(mDisplayContent, userRotationMode,
userRotation);
if (changed) {
- mService.updateRotation(true /* alwaysSendConfiguration */,
+ mService.updateRotation(false /* alwaysSendConfiguration */,
false /* forceRelayout */);
}
}
@@ -2127,7 +2127,7 @@ public class DisplayRotation {
@Override
public void onChange(boolean selfChange) {
if (updateSettings()) {
- mService.updateRotation(true /* alwaysSendConfiguration */,
+ mService.updateRotation(false /* alwaysSendConfiguration */,
false /* forceRelayout */);
}
}
diff --git a/services/core/java/com/android/server/wm/DisplayWindowPolicyControllerHelper.java b/services/core/java/com/android/server/wm/DisplayWindowPolicyControllerHelper.java
index 2fb98690f661..6b33746ad3c4 100644
--- a/services/core/java/com/android/server/wm/DisplayWindowPolicyControllerHelper.java
+++ b/services/core/java/com/android/server/wm/DisplayWindowPolicyControllerHelper.java
@@ -68,19 +68,15 @@ class DisplayWindowPolicyControllerHelper {
}
/**
- * @see DisplayWindowPolicyController#canContainActivities(List, int)
+ * @see DisplayWindowPolicyController#canContainActivities
*/
public boolean canContainActivities(@NonNull List<ActivityInfo> activities,
@WindowConfiguration.WindowingMode int windowingMode) {
if (mDisplayWindowPolicyController == null) {
- for (int i = activities.size() - 1; i >= 0; i--) {
- final ActivityInfo aInfo = activities.get(i);
- if (aInfo.requiredDisplayCategory != null) {
- Slog.e(TAG,
- String.format("Activity with requiredDisplayCategory='%s' cannot be"
- + " displayed on display %d because that display does"
- + " not have a matching category",
- aInfo.requiredDisplayCategory, mDisplayContent.mDisplayId));
+ for (int i = 0; i < activities.size(); ++i) {
+ // Missing controller means that this display has no categories for activity launch
+ // restriction.
+ if (hasDisplayCategory(activities.get(i))) {
return false;
}
}
@@ -90,26 +86,31 @@ class DisplayWindowPolicyControllerHelper {
}
/**
- * @see DisplayWindowPolicyController#canActivityBeLaunched(ActivityInfo, int, int, boolean)
+ * @see DisplayWindowPolicyController#canActivityBeLaunched
*/
public boolean canActivityBeLaunched(ActivityInfo activityInfo,
Intent intent, @WindowConfiguration.WindowingMode int windowingMode,
int launchingFromDisplayId, boolean isNewTask) {
if (mDisplayWindowPolicyController == null) {
- if (activityInfo.requiredDisplayCategory != null) {
- Slog.e(TAG,
- String.format("Activity with requiredDisplayCategory='%s' cannot be"
- + " launched on display %d because that display does"
- + " not have a matching category",
- activityInfo.requiredDisplayCategory, mDisplayContent.mDisplayId));
- return false;
- }
- return true;
+ // Missing controller means that this display has no categories for activity launch
+ // restriction.
+ return !hasDisplayCategory(activityInfo);
}
return mDisplayWindowPolicyController.canActivityBeLaunched(activityInfo, intent,
windowingMode, launchingFromDisplayId, isNewTask);
}
+ private boolean hasDisplayCategory(ActivityInfo aInfo) {
+ if (aInfo.requiredDisplayCategory != null) {
+ Slog.d(TAG,
+ String.format("Checking activity launch with requiredDisplayCategory='%s' on"
+ + " display %d, which doesn't have a matching category.",
+ aInfo.requiredDisplayCategory, mDisplayContent.mDisplayId));
+ return true;
+ }
+ return false;
+ }
+
/**
* @see DisplayWindowPolicyController#keepActivityOnWindowFlagsChanged(ActivityInfo, int, int)
*/
@@ -199,7 +200,6 @@ class DisplayWindowPolicyControllerHelper {
return mDisplayWindowPolicyController.isEnteringPipAllowed(uid);
}
-
void dump(String prefix, PrintWriter pw) {
if (mDisplayWindowPolicyController != null) {
pw.println();
diff --git a/services/core/java/com/android/server/wm/LetterboxConfiguration.java b/services/core/java/com/android/server/wm/LetterboxConfiguration.java
index 9e3a611c0e70..45cf10bd3f5e 100644
--- a/services/core/java/com/android/server/wm/LetterboxConfiguration.java
+++ b/services/core/java/com/android/server/wm/LetterboxConfiguration.java
@@ -80,10 +80,10 @@ final class LetterboxConfiguration {
// Whether per-app user aspect ratio override settings is enabled
private static final String KEY_ENABLE_USER_ASPECT_RATIO_SETTINGS =
- "enable_app_compat_user_aspect_ratio_settings";
+ "enable_app_compat_aspect_ratio_user_settings";
// TODO(b/288142656): Enable user aspect ratio settings by default.
- private static final boolean DEFAULT_VALUE_ENABLE_USER_ASPECT_RATIO_SETTINGS = false;
+ private static final boolean DEFAULT_VALUE_ENABLE_USER_ASPECT_RATIO_SETTINGS = true;
// Whether per-app fullscreen user aspect ratio override option is enabled
private static final String KEY_ENABLE_USER_ASPECT_RATIO_FULLSCREEN =
@@ -880,6 +880,58 @@ final class LetterboxConfiguration {
false /* forTabletopMode */);
}
+ /**
+ * Overrides persistent horizontal position of the letterboxed app window when horizontal
+ * reachability is enabled.
+ */
+ void setPersistentLetterboxPositionForHorizontalReachability(boolean forBookMode,
+ @LetterboxHorizontalReachabilityPosition int position) {
+ mLetterboxConfigurationPersister.setLetterboxPositionForHorizontalReachability(
+ forBookMode, position);
+ }
+
+ /**
+ * Overrides persistent vertical position of the letterboxed app window when vertical
+ * reachability is enabled.
+ */
+ void setPersistentLetterboxPositionForVerticalReachability(boolean forTabletopMode,
+ @LetterboxVerticalReachabilityPosition int position) {
+ mLetterboxConfigurationPersister.setLetterboxPositionForVerticalReachability(
+ forTabletopMode, position);
+ }
+
+ /**
+ * Resets persistent horizontal position of the letterboxed app window when horizontal
+ * reachability
+ * is enabled to default position.
+ */
+ void resetPersistentLetterboxPositionForHorizontalReachability() {
+ mLetterboxConfigurationPersister.setLetterboxPositionForHorizontalReachability(
+ false /* forBookMode */,
+ readLetterboxHorizontalReachabilityPositionFromConfig(mContext,
+ false /* forBookMode */));
+ mLetterboxConfigurationPersister.setLetterboxPositionForHorizontalReachability(
+ true /* forBookMode */,
+ readLetterboxHorizontalReachabilityPositionFromConfig(mContext,
+ true /* forBookMode */));
+ }
+
+ /**
+ * Resets persistent vertical position of the letterboxed app window when vertical reachability
+ * is
+ * enabled to default position.
+ */
+ void resetPersistentLetterboxPositionForVerticalReachability() {
+ mLetterboxConfigurationPersister.setLetterboxPositionForVerticalReachability(
+ false /* forTabletopMode */,
+ readLetterboxVerticalReachabilityPositionFromConfig(mContext,
+ false /* forTabletopMode */));
+ mLetterboxConfigurationPersister.setLetterboxPositionForVerticalReachability(
+ true /* forTabletopMode */,
+ readLetterboxVerticalReachabilityPositionFromConfig(mContext,
+ true /* forTabletopMode */));
+ }
+
@LetterboxHorizontalReachabilityPosition
private static int readLetterboxHorizontalReachabilityPositionFromConfig(Context context,
boolean forBookMode) {
diff --git a/services/core/java/com/android/server/wm/RemoteDisplayChangeController.java b/services/core/java/com/android/server/wm/RemoteDisplayChangeController.java
index e646f14a3e13..106e142cc342 100644
--- a/services/core/java/com/android/server/wm/RemoteDisplayChangeController.java
+++ b/services/core/java/com/android/server/wm/RemoteDisplayChangeController.java
@@ -21,6 +21,7 @@ import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_CONFIGURATION
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.os.RemoteException;
+import android.os.Trace;
import android.util.Slog;
import android.view.IDisplayChangeWindowCallback;
import android.window.DisplayAreaInfo;
@@ -40,6 +41,7 @@ import java.util.List;
public class RemoteDisplayChangeController {
private static final String TAG = "RemoteDisplayChangeController";
+ private static final String REMOTE_DISPLAY_CHANGE_TRACE_TAG = "RemoteDisplayChange";
private static final int REMOTE_DISPLAY_CHANGE_TIMEOUT_MS = 800;
@@ -82,6 +84,10 @@ public class RemoteDisplayChangeController {
}
mCallbacks.add(callback);
+ if (Trace.isTagEnabled(Trace.TRACE_TAG_WINDOW_MANAGER)) {
+ Trace.beginAsyncSection(REMOTE_DISPLAY_CHANGE_TRACE_TAG, callback.hashCode());
+ }
+
if (newDisplayAreaInfo != null) {
ProtoLog.v(WM_DEBUG_CONFIGURATION,
"Starting remote display change: "
@@ -122,6 +128,10 @@ public class RemoteDisplayChangeController {
mCallbacks.clear();
}
callback.onContinueRemoteDisplayChange(null /* transaction */);
+
+ if (Trace.isTagEnabled(Trace.TRACE_TAG_WINDOW_MANAGER)) {
+ Trace.endAsyncSection(REMOTE_DISPLAY_CHANGE_TRACE_TAG, callback.hashCode());
+ }
}
}
}
@@ -137,13 +147,23 @@ public class RemoteDisplayChangeController {
for (int i = 0; i < idx; ++i) {
// Expect remote callbacks in order. If they don't come in order, then force
// ordering by continuing everything up until this one with empty transactions.
- mCallbacks.get(i).onContinueRemoteDisplayChange(null /* transaction */);
+ ContinueRemoteDisplayChangeCallback currentCallback = mCallbacks.get(i);
+ currentCallback.onContinueRemoteDisplayChange(null /* transaction */);
+
+ if (Trace.isTagEnabled(Trace.TRACE_TAG_WINDOW_MANAGER)) {
+ Trace.endAsyncSection(REMOTE_DISPLAY_CHANGE_TRACE_TAG,
+ currentCallback.hashCode());
+ }
}
mCallbacks.subList(0, idx + 1).clear();
if (mCallbacks.isEmpty()) {
mService.mH.removeCallbacks(mTimeoutRunnable);
}
callback.onContinueRemoteDisplayChange(transaction);
+
+ if (Trace.isTagEnabled(Trace.TRACE_TAG_WINDOW_MANAGER)) {
+ Trace.endAsyncSection(REMOTE_DISPLAY_CHANGE_TRACE_TAG, callback.hashCode());
+ }
}
}
diff --git a/services/core/java/com/android/server/wm/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java
index 57f8268b2fdc..2fdfec04b895 100644
--- a/services/core/java/com/android/server/wm/RootWindowContainer.java
+++ b/services/core/java/com/android/server/wm/RootWindowContainer.java
@@ -258,10 +258,6 @@ class RootWindowContainer extends WindowContainer<DisplayContent>
*/
final SparseArray<SleepToken> mSleepTokens = new SparseArray<>();
- // The default minimal size that will be used if the activity doesn't specify its minimal size.
- // It will be calculated when the default display gets added.
- int mDefaultMinSizeOfResizeableTaskDp = -1;
-
// Whether tasks have moved and we need to rank the tasks before next OOM scoring
private boolean mTaskLayersChanged = true;
private int mTmpTaskLayerRank;
@@ -1608,6 +1604,19 @@ class RootWindowContainer extends WindowContainer<DisplayContent>
}
/**
+ * Check if the display is valid for primary home activity.
+ *
+ * @param displayId The target display ID
+ * @return {@code true} if allowed to launch, {@code false} otherwise.
+ */
+ boolean shouldPlacePrimaryHomeOnDisplay(int displayId) {
+ // No restrictions to default display, vr 2d display or main display for visible users.
+ return displayId == DEFAULT_DISPLAY || (displayId != INVALID_DISPLAY
+ && (displayId == mService.mVr2dDisplayId
+ || mWmService.shouldPlacePrimaryHomeOnDisplay(displayId)));
+ }
+
+ /**
* Check if the display area is valid for secondary home activity.
*
* @param taskDisplayArea The target display area.
@@ -1680,10 +1689,7 @@ class RootWindowContainer extends WindowContainer<DisplayContent>
final int displayId = taskDisplayArea != null ? taskDisplayArea.getDisplayId()
: INVALID_DISPLAY;
- if (displayId == DEFAULT_DISPLAY || (displayId != INVALID_DISPLAY
- && (displayId == mService.mVr2dDisplayId
- || mWmService.shouldPlacePrimaryHomeOnDisplay(displayId)))) {
- // No restrictions to default display, vr 2d display or main display for visible users.
+ if (shouldPlacePrimaryHomeOnDisplay(displayId)) {
return true;
}
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index 387a8767ced3..21526e789c04 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -2815,7 +2815,7 @@ class Task extends TaskFragment {
final WindowManager.LayoutParams attrs = win.mAttrs;
visibleFrame.set(win.getFrame());
visibleFrame.inset(win.getInsetsStateWithVisibilityOverride().calculateVisibleInsets(
- visibleFrame, attrs.type, win.getWindowingMode(), attrs.softInputMode,
+ visibleFrame, attrs.type, win.getActivityType(), attrs.softInputMode,
attrs.flags));
out.union(visibleFrame);
}
@@ -3543,11 +3543,6 @@ class Task extends TaskFragment {
? null : new PictureInPictureParams(top.pictureInPictureArgs);
}
- private boolean shouldDockBigOverlays() {
- final ActivityRecord topMostActivity = getTopMostActivity();
- return topMostActivity != null && topMostActivity.shouldDockBigOverlays;
- }
-
Rect getDisplayCutoutInsets() {
if (mDisplayContent == null || getDisplayInfo().displayCutout == null) return null;
final WindowState w = getTopVisibleAppMainWindow();
diff --git a/services/core/java/com/android/server/wm/TaskLaunchParamsModifier.java b/services/core/java/com/android/server/wm/TaskLaunchParamsModifier.java
index ad46770432a1..4e7a9bd2881a 100644
--- a/services/core/java/com/android/server/wm/TaskLaunchParamsModifier.java
+++ b/services/core/java/com/android/server/wm/TaskLaunchParamsModifier.java
@@ -118,12 +118,14 @@ class TaskLaunchParamsModifier implements LaunchParamsModifier {
root = activity;
}
- if (root == null) {
+ if (root == null && phase != PHASE_DISPLAY) {
// There is a case that can lead us here. The caller is moving the top activity that is
// in a task that has multiple activities to PIP mode. For that the caller is creating a
// new task to host the activity so that we only move the top activity to PIP mode and
// keep other activities in the previous task. There is no point to apply the launch
// logic in this case.
+ // However, for PHASE_DISPLAY the root may be null, but we still want to get a hint of
+ // what the suggested launch display area would be.
return RESULT_SKIP;
}
@@ -395,8 +397,9 @@ class TaskLaunchParamsModifier implements LaunchParamsModifier {
}
private TaskDisplayArea getPreferredLaunchTaskDisplayArea(@Nullable Task task,
- @Nullable ActivityOptions options, ActivityRecord source, LaunchParams currentParams,
- @NonNull ActivityRecord activityRecord, @Nullable Request request) {
+ @Nullable ActivityOptions options, @Nullable ActivityRecord source,
+ @Nullable LaunchParams currentParams, @Nullable ActivityRecord activityRecord,
+ @Nullable Request request) {
TaskDisplayArea taskDisplayArea = null;
final WindowContainerToken optionLaunchTaskDisplayAreaToken = options != null
@@ -438,8 +441,7 @@ class TaskLaunchParamsModifier implements LaunchParamsModifier {
// If the source activity is a no-display activity, pass on the launch display area token
// from source activity as currently preferred.
- if (taskDisplayArea == null && source != null
- && source.noDisplay) {
+ if (taskDisplayArea == null && source != null && source.noDisplay) {
taskDisplayArea = source.mHandoverTaskDisplayArea;
if (taskDisplayArea != null) {
if (DEBUG) appendLog("display-area-from-no-display-source=" + taskDisplayArea);
@@ -478,21 +480,24 @@ class TaskLaunchParamsModifier implements LaunchParamsModifier {
}
}
- if (taskDisplayArea == null) {
+ if (taskDisplayArea == null && currentParams != null) {
taskDisplayArea = currentParams.mPreferredTaskDisplayArea;
+ if (DEBUG) appendLog("display-area-from-current-params=" + taskDisplayArea);
}
// Re-route to default display if the device didn't declare support for multi-display
if (taskDisplayArea != null && !mSupervisor.mService.mSupportsMultiDisplay
&& taskDisplayArea.getDisplayId() != DEFAULT_DISPLAY) {
taskDisplayArea = mSupervisor.mRootWindowContainer.getDefaultTaskDisplayArea();
+ if (DEBUG) appendLog("display-area-from-no-multidisplay=" + taskDisplayArea);
}
// Re-route to default display if the home activity doesn't support multi-display
- if (taskDisplayArea != null && activityRecord.isActivityTypeHome()
+ if (taskDisplayArea != null && activityRecord != null && activityRecord.isActivityTypeHome()
&& !mSupervisor.mRootWindowContainer.canStartHomeOnDisplayArea(activityRecord.info,
taskDisplayArea, false /* allowInstrumenting */)) {
taskDisplayArea = mSupervisor.mRootWindowContainer.getDefaultTaskDisplayArea();
+ if (DEBUG) appendLog("display-area-from-home=" + taskDisplayArea);
}
return (taskDisplayArea != null)
@@ -516,34 +521,56 @@ class TaskLaunchParamsModifier implements LaunchParamsModifier {
* @return {@link TaskDisplayArea} to house the task
*/
private TaskDisplayArea getFallbackDisplayAreaForActivity(
- @NonNull ActivityRecord activityRecord, @Nullable Request request) {
-
- WindowProcessController controllerFromLaunchingRecord = mSupervisor.mService
- .getProcessController(activityRecord.launchedFromPid,
- activityRecord.launchedFromUid);
- final TaskDisplayArea displayAreaForLaunchingRecord = controllerFromLaunchingRecord == null
- ? null : controllerFromLaunchingRecord.getTopActivityDisplayArea();
- if (displayAreaForLaunchingRecord != null) {
- return displayAreaForLaunchingRecord;
- }
+ @Nullable ActivityRecord activityRecord, @Nullable Request request) {
+ if (activityRecord != null) {
+ WindowProcessController controllerFromLaunchingRecord =
+ mSupervisor.mService.getProcessController(
+ activityRecord.launchedFromPid, activityRecord.launchedFromUid);
+ if (controllerFromLaunchingRecord != null) {
+ final TaskDisplayArea taskDisplayAreaForLaunchingRecord =
+ controllerFromLaunchingRecord.getTopActivityDisplayArea();
+ if (taskDisplayAreaForLaunchingRecord != null) {
+ if (DEBUG) {
+ appendLog("display-area-for-launching-record="
+ + taskDisplayAreaForLaunchingRecord);
+ }
+ return taskDisplayAreaForLaunchingRecord;
+ }
+ }
- WindowProcessController controllerFromProcess = mSupervisor.mService.getProcessController(
- activityRecord.getProcessName(), activityRecord.getUid());
- final TaskDisplayArea displayAreaForRecord = controllerFromProcess == null ? null
- : controllerFromProcess.getTopActivityDisplayArea();
- if (displayAreaForRecord != null) {
- return displayAreaForRecord;
+ WindowProcessController controllerFromProcess =
+ mSupervisor.mService.getProcessController(
+ activityRecord.getProcessName(), activityRecord.getUid());
+ if (controllerFromProcess != null) {
+ final TaskDisplayArea displayAreaForRecord =
+ controllerFromProcess.getTopActivityDisplayArea();
+ if (displayAreaForRecord != null) {
+ if (DEBUG) appendLog("display-area-for-record=" + displayAreaForRecord);
+ return displayAreaForRecord;
+ }
+ }
}
- WindowProcessController controllerFromRequest = request == null ? null : mSupervisor
- .mService.getProcessController(request.realCallingPid, request.realCallingUid);
- final TaskDisplayArea displayAreaFromSourceProcess = controllerFromRequest == null ? null
- : controllerFromRequest.getTopActivityDisplayArea();
- if (displayAreaFromSourceProcess != null) {
- return displayAreaFromSourceProcess;
+ if (request != null) {
+ WindowProcessController controllerFromRequest =
+ mSupervisor.mService.getProcessController(
+ request.realCallingPid, request.realCallingUid);
+ if (controllerFromRequest != null) {
+ final TaskDisplayArea displayAreaFromSourceProcess =
+ controllerFromRequest.getTopActivityDisplayArea();
+ if (displayAreaFromSourceProcess != null) {
+ if (DEBUG) {
+ appendLog("display-area-source-process=" + displayAreaFromSourceProcess);
+ }
+ return displayAreaFromSourceProcess;
+ }
+ }
}
- return mSupervisor.mRootWindowContainer.getDefaultTaskDisplayArea();
+ final TaskDisplayArea defaultTaskDisplayArea =
+ mSupervisor.mRootWindowContainer.getDefaultTaskDisplayArea();
+ if (DEBUG) appendLog("display-area-from-default-fallback=" + defaultTaskDisplayArea);
+ return defaultTaskDisplayArea;
}
private boolean canInheritWindowingModeFromSource(@NonNull DisplayContent display,
@@ -559,7 +586,7 @@ class TaskLaunchParamsModifier implements LaunchParamsModifier {
return false;
}
- final int sourceWindowingMode = source.getWindowingMode();
+ final int sourceWindowingMode = source.getTask().getWindowingMode();
if (sourceWindowingMode != WINDOWING_MODE_FULLSCREEN
&& sourceWindowingMode != WINDOWING_MODE_FREEFORM) {
return false;
diff --git a/services/core/java/com/android/server/wm/Transition.java b/services/core/java/com/android/server/wm/Transition.java
index 81f91c739bc3..a6c64912edd3 100644
--- a/services/core/java/com/android/server/wm/Transition.java
+++ b/services/core/java/com/android/server/wm/Transition.java
@@ -440,10 +440,11 @@ class Transition implements BLASTSyncEngine.TransactionReadyListener {
boolean canApplyDim(@NonNull Task task) {
if (mTransientLaunches == null) return true;
final Dimmer dimmer = task.getDimmer();
- final WindowContainer<?> dimmerHost = dimmer != null ? dimmer.getHost() : null;
- if (dimmerHost == null) return false;
- if (isInTransientHide(dimmerHost)) {
- // The layer of dimmer is inside transient-hide task, then allow to dim.
+ if (dimmer == null) {
+ return false;
+ }
+ if (dimmer.getHost().asTask() != null) {
+ // Always allow to dim if the host only affects its task.
return true;
}
// The dimmer host of a translucent task can be a display, then it is not in transient-hide.
diff --git a/services/core/java/com/android/server/wm/WindowContainer.java b/services/core/java/com/android/server/wm/WindowContainer.java
index dae61da26b68..4a0f44b58ecf 100644
--- a/services/core/java/com/android/server/wm/WindowContainer.java
+++ b/services/core/java/com/android/server/wm/WindowContainer.java
@@ -1135,13 +1135,6 @@ class WindowContainer<E extends WindowContainer> extends ConfigurationContainer<
return parent != null && parent.isAttached();
}
- void setWaitingForDrawnIfResizingChanged() {
- for (int i = mChildren.size() - 1; i >= 0; --i) {
- final WindowContainer wc = mChildren.get(i);
- wc.setWaitingForDrawnIfResizingChanged();
- }
- }
-
void onResize() {
if (mControllableInsetProvider != null) {
mControllableInsetProvider.onWindowContainerBoundsChanged();
diff --git a/services/core/java/com/android/server/wm/WindowManagerShellCommand.java b/services/core/java/com/android/server/wm/WindowManagerShellCommand.java
index ceebb27642ce..bfe055354b9c 100644
--- a/services/core/java/com/android/server/wm/WindowManagerShellCommand.java
+++ b/services/core/java/com/android/server/wm/WindowManagerShellCommand.java
@@ -911,6 +911,70 @@ public class WindowManagerShellCommand extends ShellCommand {
return 0;
}
+ private int runSetPersistentLetterboxPositionForHorizontalReachability(PrintWriter pw)
+ throws RemoteException {
+ @LetterboxHorizontalReachabilityPosition final int position;
+ try {
+ String arg = getNextArgRequired();
+ switch (arg) {
+ case "left":
+ position = LETTERBOX_HORIZONTAL_REACHABILITY_POSITION_LEFT;
+ break;
+ case "center":
+ position = LETTERBOX_HORIZONTAL_REACHABILITY_POSITION_CENTER;
+ break;
+ case "right":
+ position = LETTERBOX_HORIZONTAL_REACHABILITY_POSITION_RIGHT;
+ break;
+ default:
+ getErrPrintWriter().println(
+ "Error: 'left', 'center' or 'right' are expected as an argument");
+ return -1;
+ }
+ } catch (IllegalArgumentException e) {
+ getErrPrintWriter().println(
+ "Error: 'left', 'center' or 'right' are expected as an argument" + e);
+ return -1;
+ }
+ synchronized (mInternal.mGlobalLock) {
+ mLetterboxConfiguration.setPersistentLetterboxPositionForHorizontalReachability(
+ false /* IsInBookMode */, position);
+ }
+ return 0;
+ }
+
+ private int runSetPersistentLetterboxPositionForVerticalReachability(PrintWriter pw)
+ throws RemoteException {
+ @LetterboxVerticalReachabilityPosition final int position;
+ try {
+ String arg = getNextArgRequired();
+ switch (arg) {
+ case "top":
+ position = LETTERBOX_VERTICAL_REACHABILITY_POSITION_TOP;
+ break;
+ case "center":
+ position = LETTERBOX_VERTICAL_REACHABILITY_POSITION_CENTER;
+ break;
+ case "bottom":
+ position = LETTERBOX_VERTICAL_REACHABILITY_POSITION_BOTTOM;
+ break;
+ default:
+ getErrPrintWriter().println(
+ "Error: 'top', 'center' or 'bottom' are expected as an argument");
+ return -1;
+ }
+ } catch (IllegalArgumentException e) {
+ getErrPrintWriter().println(
+ "Error: 'top', 'center' or 'bottom' are expected as an argument" + e);
+ return -1;
+ }
+ synchronized (mInternal.mGlobalLock) {
+ mLetterboxConfiguration.setPersistentLetterboxPositionForVerticalReachability(
+ false /* forTabletopMode */, position);
+ }
+ return 0;
+ }
+
private int runSetBooleanFlag(PrintWriter pw, Consumer<Boolean> setter)
throws RemoteException {
String arg = getNextArg();
@@ -994,6 +1058,12 @@ public class WindowManagerShellCommand extends ShellCommand {
case "--defaultPositionForVerticalReachability":
runSetLetterboxDefaultPositionForVerticalReachability(pw);
break;
+ case "--persistentPositionForHorizontalReachability":
+ runSetPersistentLetterboxPositionForHorizontalReachability(pw);
+ break;
+ case "--persistentPositionForVerticalReachability":
+ runSetPersistentLetterboxPositionForVerticalReachability(pw);
+ break;
case "--isEducationEnabled":
runSetBooleanFlag(pw, mLetterboxConfiguration::setIsEducationEnabled);
break;
@@ -1080,6 +1150,14 @@ public class WindowManagerShellCommand extends ShellCommand {
case "defaultPositionForVerticalReachability":
mLetterboxConfiguration.resetDefaultPositionForVerticalReachability();
break;
+ case "persistentPositionForHorizontalReachability":
+ mLetterboxConfiguration
+ .resetPersistentLetterboxPositionForHorizontalReachability();
+ break;
+ case "persistentPositionForVerticalReachability":
+ mLetterboxConfiguration
+ .resetPersistentLetterboxPositionForVerticalReachability();
+ break;
case "isEducationEnabled":
mLetterboxConfiguration.resetIsEducationEnabled();
break;
@@ -1206,6 +1284,8 @@ public class WindowManagerShellCommand extends ShellCommand {
mLetterboxConfiguration.resetEnabledAutomaticReachabilityInBookMode();
mLetterboxConfiguration.resetDefaultPositionForHorizontalReachability();
mLetterboxConfiguration.resetDefaultPositionForVerticalReachability();
+ mLetterboxConfiguration.resetPersistentLetterboxPositionForHorizontalReachability();
+ mLetterboxConfiguration.resetPersistentLetterboxPositionForVerticalReachability();
mLetterboxConfiguration.resetIsEducationEnabled();
mLetterboxConfiguration.resetIsSplitScreenAspectRatioForUnresizableAppsEnabled();
mLetterboxConfiguration.resetIsDisplayAspectRatioEnabledForFixedOrientationLetterbox();
@@ -1233,6 +1313,12 @@ public class WindowManagerShellCommand extends ShellCommand {
pw.println("Vertical position multiplier (tabletop mode): "
+ mLetterboxConfiguration.getLetterboxVerticalPositionMultiplier(
true /* isInTabletopMode */));
+ pw.println("Horizontal position multiplier for reachability: "
+ + mLetterboxConfiguration.getHorizontalMultiplierForReachability(
+ false /* isInBookMode */));
+ pw.println("Vertical position multiplier for reachability: "
+ + mLetterboxConfiguration.getVerticalMultiplierForReachability(
+ false /* isInTabletopMode */));
pw.println("Aspect ratio: "
+ mLetterboxConfiguration.getFixedOrientationLetterboxAspectRatio());
pw.println("Default min aspect ratio for unresizable apps: "
@@ -1472,6 +1558,12 @@ public class WindowManagerShellCommand extends ShellCommand {
pw.println(" --defaultPositionForVerticalReachability [top|center|bottom]");
pw.println(" Default position of app window when vertical reachability is.");
pw.println(" enabled.");
+ pw.println(" --persistentPositionForHorizontalReachability [left|center|right]");
+ pw.println(" Persistent position of app window when horizontal reachability is.");
+ pw.println(" enabled.");
+ pw.println(" --persistentPositionForVerticalReachability [top|center|bottom]");
+ pw.println(" Persistent position of app window when vertical reachability is.");
+ pw.println(" enabled.");
pw.println(" --isEducationEnabled [true|1|false|0]");
pw.println(" Whether education is allowed for letterboxed fullscreen apps.");
pw.println(" --isSplitScreenAspectRatioForUnresizableAppsEnabled [true|1|false|0]");
@@ -1493,8 +1585,10 @@ public class WindowManagerShellCommand extends ShellCommand {
pw.println(" |backgroundColor|wallpaperBlurRadius|wallpaperDarkScrimAlpha");
pw.println(" |horizontalPositionMultiplier|verticalPositionMultiplier");
pw.println(" |isHorizontalReachabilityEnabled|isVerticalReachabilityEnabled");
- pw.println(" |isEducationEnabled||defaultPositionMultiplierForHorizontalReachability");
+ pw.println(" |isEducationEnabled|defaultPositionMultiplierForHorizontalReachability");
pw.println(" |isTranslucentLetterboxingEnabled|isUserAppAspectRatioSettingsEnabled");
+ pw.println(" |persistentPositionMultiplierForHorizontalReachability");
+ pw.println(" |persistentPositionMultiplierForVerticalReachability");
pw.println(" |defaultPositionMultiplierForVerticalReachability]");
pw.println(" Resets overrides to default values for specified properties separated");
pw.println(" by space, e.g. 'reset-letterbox-style aspectRatio cornerRadius'.");
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index a172d9912cbd..b12cc0b30f53 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -1717,29 +1717,6 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
}
/**
- * This is a form of rectangle "difference". It cut off each dimension of rect by the amount
- * that toRemove is "pushing into" it from the outside. Any dimension that fully contains
- * toRemove won't change.
- */
- private void cutRect(Rect rect, Rect toRemove) {
- if (toRemove.isEmpty()) return;
- if (toRemove.top < rect.bottom && toRemove.bottom > rect.top) {
- if (toRemove.right >= rect.right && toRemove.left >= rect.left) {
- rect.right = toRemove.left;
- } else if (toRemove.left <= rect.left && toRemove.right <= rect.right) {
- rect.left = toRemove.right;
- }
- }
- if (toRemove.left < rect.right && toRemove.right > rect.left) {
- if (toRemove.bottom >= rect.bottom && toRemove.top >= rect.top) {
- rect.bottom = toRemove.top;
- } else if (toRemove.top <= rect.top && toRemove.bottom <= rect.bottom) {
- rect.top = toRemove.bottom;
- }
- }
- }
-
- /**
* Retrieves the visible bounds of the window.
* @param bounds The rect which gets the bounds.
*/
@@ -1759,7 +1736,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
bounds.set(mWindowFrames.mFrame);
bounds.inset(getInsetsStateWithVisibilityOverride().calculateVisibleInsets(
- bounds, mAttrs.type, getWindowingMode(), mAttrs.softInputMode, mAttrs.flags));
+ bounds, mAttrs.type, getActivityType(), mAttrs.softInputMode, mAttrs.flags));
if (intersectWithRootTaskBounds) {
bounds.intersect(mTmpRect);
}
@@ -3965,14 +3942,6 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
return mDragResizing != computeDragResizing();
}
- @Override
- void setWaitingForDrawnIfResizingChanged() {
- if (isDragResizeChanged()) {
- mWmService.mRoot.mWaitingForDrawn.add(this);
- }
- super.setWaitingForDrawnIfResizingChanged();
- }
-
/**
* Resets the state whether we reported a drag resize change to the app.
*/
@@ -5524,10 +5493,6 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
outRegion.translate(mWindowFrames.mFrame.left, mWindowFrames.mFrame.top);
}
- boolean hasTapExcludeRegion() {
- return !mTapExcludeRegion.isEmpty();
- }
-
boolean isImeLayeringTarget() {
return getDisplayContent().getImeTarget(IME_TARGET_LAYERING) == this;
}
diff --git a/services/core/java/com/android/server/wm/WindowToken.java b/services/core/java/com/android/server/wm/WindowToken.java
index 4d7335873074..e434f296bbb5 100644
--- a/services/core/java/com/android/server/wm/WindowToken.java
+++ b/services/core/java/com/android/server/wm/WindowToken.java
@@ -17,7 +17,6 @@
package com.android.server.wm;
import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
-import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR;
import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_ADD_REMOVE;
import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_APP_TRANSITIONS;
@@ -746,17 +745,6 @@ class WindowToken extends WindowContainer<WindowState> {
return this;
}
- /**
- * Return whether windows from this token can layer above the
- * system bars, or in other words extend outside of the "Decor Frame"
- */
- boolean canLayerAboveSystemBars() {
- int layer = getWindowLayerFromType();
- int navLayer = mWmService.mPolicy.getWindowLayerFromTypeLw(TYPE_NAVIGATION_BAR,
- mOwnerCanManageAppTokens);
- return mOwnerCanManageAppTokens && (layer > navLayer);
- }
-
int getWindowLayerFromType() {
return mWmService.mPolicy.getWindowLayerFromTypeLw(windowType, mOwnerCanManageAppTokens,
mRoundedCornerOverlay);
diff --git a/services/core/jni/Android.bp b/services/core/jni/Android.bp
index 2a995b24ef4f..ec5378f01ce3 100644
--- a/services/core/jni/Android.bp
+++ b/services/core/jni/Android.bp
@@ -41,6 +41,7 @@ cc_library_static {
"com_android_server_companion_virtual_InputController.cpp",
"com_android_server_devicepolicy_CryptoTestHelper.cpp",
"com_android_server_display_DisplayControl.cpp",
+ "com_android_server_display_SmallAreaDetectionController.cpp",
"com_android_server_connectivity_Vpn.cpp",
"com_android_server_gpu_GpuService.cpp",
"com_android_server_HardwarePropertiesManagerService.cpp",
diff --git a/services/core/jni/com_android_server_display_SmallAreaDetectionController.cpp b/services/core/jni/com_android_server_display_SmallAreaDetectionController.cpp
new file mode 100644
index 000000000000..b256f168f2af
--- /dev/null
+++ b/services/core/jni/com_android_server_display_SmallAreaDetectionController.cpp
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "SmallAreaDetectionController"
+
+#include <gui/SurfaceComposerClient.h>
+#include <nativehelper/JNIHelp.h>
+#include <nativehelper/ScopedPrimitiveArray.h>
+
+#include "jni.h"
+#include "utils/Log.h"
+
+namespace android {
+static void nativeUpdateSmallAreaDetection(JNIEnv* env, jclass clazz, jintArray juids,
+ jfloatArray jthresholds) {
+ if (juids == nullptr || jthresholds == nullptr) return;
+
+ ScopedIntArrayRO uids(env, juids);
+ ScopedFloatArrayRO thresholds(env, jthresholds);
+
+ if (uids.size() != thresholds.size()) {
+ ALOGE("uids size exceeds thresholds size!");
+ return;
+ }
+
+ std::vector<int32_t> uidVector;
+ std::vector<float> thresholdVector;
+ size_t size = uids.size();
+ uidVector.reserve(size);
+ thresholdVector.reserve(size);
+ for (int i = 0; i < size; i++) {
+ uidVector.push_back(static_cast<int32_t>(uids[i]));
+ thresholdVector.push_back(static_cast<float>(thresholds[i]));
+ }
+ SurfaceComposerClient::updateSmallAreaDetection(uidVector, thresholdVector);
+}
+
+static void nativeSetSmallAreaDetectionThreshold(JNIEnv* env, jclass clazz, jint uid,
+ jfloat threshold) {
+ SurfaceComposerClient::setSmallAreaDetectionThreshold(uid, threshold);
+}
+
+static const JNINativeMethod gMethods[] = {
+ {"nativeUpdateSmallAreaDetection", "([I[F)V", (void*)nativeUpdateSmallAreaDetection},
+ {"nativeSetSmallAreaDetectionThreshold", "(IF)V",
+ (void*)nativeSetSmallAreaDetectionThreshold},
+};
+
+int register_android_server_display_smallAreaDetectionController(JNIEnv* env) {
+ return jniRegisterNativeMethods(env, "com/android/server/display/SmallAreaDetectionController",
+ gMethods, NELEM(gMethods));
+}
+
+}; // namespace android
diff --git a/services/core/jni/onload.cpp b/services/core/jni/onload.cpp
index 97d7be6a718e..f6f673746609 100644
--- a/services/core/jni/onload.cpp
+++ b/services/core/jni/onload.cpp
@@ -67,6 +67,7 @@ int register_android_server_app_GameManagerService(JNIEnv* env);
int register_com_android_server_wm_TaskFpsCallbackController(JNIEnv* env);
int register_com_android_server_display_DisplayControl(JNIEnv* env);
int register_com_android_server_SystemClockTime(JNIEnv* env);
+int register_android_server_display_smallAreaDetectionController(JNIEnv* env);
};
using namespace android;
@@ -126,5 +127,6 @@ extern "C" jint JNI_OnLoad(JavaVM* vm, void* /* reserved */)
register_com_android_server_wm_TaskFpsCallbackController(env);
register_com_android_server_display_DisplayControl(env);
register_com_android_server_SystemClockTime(env);
+ register_android_server_display_smallAreaDetectionController(env);
return JNI_VERSION_1_4;
}
diff --git a/services/core/xsd/display-device-config/display-device-config.xsd b/services/core/xsd/display-device-config/display-device-config.xsd
index d833fbd6ffd2..d22e02e9dae6 100644
--- a/services/core/xsd/display-device-config/display-device-config.xsd
+++ b/services/core/xsd/display-device-config/display-device-config.xsd
@@ -67,6 +67,18 @@
<xs:element type="nonNegativeDecimal" name="screenBrightnessRampSlowIncrease">
<xs:annotation name="final"/>
</xs:element>
+ <!-- Ramp speed used to decrease the screen brightness when in idle mode.
+ In framework brightness units per second. Must exist with
+ screenBrightnessRampSlowIncreaseIdle-->
+ <xs:element type="nonNegativeDecimal" name="screenBrightnessRampSlowDecreaseIdle">
+ <xs:annotation name="final"/>
+ </xs:element>
+ <!-- Ramp speed used to decrease the screen brightness when in idle mode.
+ In framework brightness units per second. Must exist with
+ screenBrightnessRampSlowDecreaseIdle-->
+ <xs:element type="nonNegativeDecimal" name="screenBrightnessRampSlowIncreaseIdle">
+ <xs:annotation name="final"/>
+ </xs:element>
<!-- Maximum time in milliseconds that a brightness increase animation
can take. -->
<xs:element type="xs:nonNegativeInteger" name="screenBrightnessRampIncreaseMaxMillis">
diff --git a/services/core/xsd/display-device-config/schema/current.txt b/services/core/xsd/display-device-config/schema/current.txt
index d2ac1aae1500..6364c1feb659 100644
--- a/services/core/xsd/display-device-config/schema/current.txt
+++ b/services/core/xsd/display-device-config/schema/current.txt
@@ -115,7 +115,9 @@ package com.android.server.display.config {
method public final java.math.BigDecimal getScreenBrightnessRampFastIncrease();
method public final java.math.BigInteger getScreenBrightnessRampIncreaseMaxMillis();
method public final java.math.BigDecimal getScreenBrightnessRampSlowDecrease();
+ method public final java.math.BigDecimal getScreenBrightnessRampSlowDecreaseIdle();
method public final java.math.BigDecimal getScreenBrightnessRampSlowIncrease();
+ method public final java.math.BigDecimal getScreenBrightnessRampSlowIncreaseIdle();
method public final com.android.server.display.config.SensorDetails getScreenOffBrightnessSensor();
method public final com.android.server.display.config.IntegerArray getScreenOffBrightnessSensorValueToLux();
method @NonNull public final com.android.server.display.config.ThermalThrottling getThermalThrottling();
@@ -142,7 +144,9 @@ package com.android.server.display.config {
method public final void setScreenBrightnessRampFastIncrease(java.math.BigDecimal);
method public final void setScreenBrightnessRampIncreaseMaxMillis(java.math.BigInteger);
method public final void setScreenBrightnessRampSlowDecrease(java.math.BigDecimal);
+ method public final void setScreenBrightnessRampSlowDecreaseIdle(java.math.BigDecimal);
method public final void setScreenBrightnessRampSlowIncrease(java.math.BigDecimal);
+ method public final void setScreenBrightnessRampSlowIncreaseIdle(java.math.BigDecimal);
method public final void setScreenOffBrightnessSensor(com.android.server.display.config.SensorDetails);
method public final void setScreenOffBrightnessSensorValueToLux(com.android.server.display.config.IntegerArray);
method public final void setThermalThrottling(@NonNull com.android.server.display.config.ThermalThrottling);
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index af1bac890ff1..438a9d6753b6 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -680,7 +680,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
// to decide whether an existing policy in the {@link #DEVICE_POLICIES_XML} needs to
// be upgraded. See {@link PolicyVersionUpgrader} on instructions how to add an upgrade
// step.
- static final int DPMS_VERSION = 5;
+ static final int DPMS_VERSION = 6;
static {
SECURE_SETTINGS_ALLOWLIST = new ArraySet<>();
@@ -876,8 +876,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
private static final boolean DEFAULT_ENABLE_DEVICE_POLICY_ENGINE_FOR_FINANCE_FLAG = true;
// TODO(b/265683382) remove the flag after rollout.
- private static final String KEEP_PROFILES_RUNNING_FLAG = "enable_keep_profiles_running";
- public static final boolean DEFAULT_KEEP_PROFILES_RUNNING_FLAG = true;
+ public static final boolean DEFAULT_KEEP_PROFILES_RUNNING_FLAG = false;
// TODO(b/261999445) remove the flag after rollout.
private static final String HEADLESS_FLAG = "headless";
@@ -2594,6 +2593,12 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
mUserManager.setUserRestriction(UserManager.DISALLOW_ADD_CLONE_PROFILE, true,
userHandle);
}
+ // Enforcing the restriction of private profile creation in case device owner is set.
+ if (!mUserManager.hasUserRestriction(
+ UserManager.DISALLOW_ADD_PRIVATE_PROFILE, userHandle)) {
+ mUserManager.setUserRestriction(UserManager.DISALLOW_ADD_PRIVATE_PROFILE, true,
+ userHandle);
+ }
// Creation of managed profile is restricted in case device owner is set, enforcing this
// restriction by setting user level restriction at time of device owner setup.
if (!mUserManager.hasUserRestriction(
@@ -4036,6 +4041,15 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
mUserManager.setUserRestriction(UserManager.DISALLOW_ADD_CLONE_PROFILE,
false, user);
}
+
+ // When a device owner is set, the system automatically restricts adding a
+ // private profile.
+ // Remove this restriction when the device owner is cleared.
+ if (mUserManager.hasUserRestriction(UserManager.DISALLOW_ADD_PRIVATE_PROFILE,
+ user)) {
+ mUserManager.setUserRestriction(UserManager.DISALLOW_ADD_PRIVATE_PROFILE,
+ false, user);
+ }
}
} else {
// ManagedProvisioning/DPC sets DISALLOW_ADD_USER. Clear to recover to the original state
@@ -4061,6 +4075,15 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
false,
userHandle);
}
+
+ // When a device owner is set, the system automatically restricts adding a
+ // private profile.
+ // Remove this restriction when the device owner is cleared.
+ if (mUserManager.hasUserRestriction(UserManager.DISALLOW_ADD_PRIVATE_PROFILE,
+ userHandle)) {
+ mUserManager.setUserRestriction(UserManager.DISALLOW_ADD_PRIVATE_PROFILE,
+ false, userHandle);
+ }
}
}
@@ -9423,6 +9446,11 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
mUserManager.setUserRestriction(UserManager.DISALLOW_ADD_CLONE_PROFILE,
true,
UserHandle.of(u));
+
+ // Restrict adding a private profile when a device owner is set.
+ mUserManager.setUserRestriction(UserManager.DISALLOW_ADD_PRIVATE_PROFILE,
+ true,
+ UserHandle.of(u));
}
} else {
mUserManager.setUserRestriction(UserManager.DISALLOW_ADD_MANAGED_PROFILE,
@@ -9435,6 +9463,9 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
mUserManager.setUserRestriction(UserManager.DISALLOW_ADD_CLONE_PROFILE,
true,
UserHandle.of(userId));
+ mUserManager.setUserRestriction(UserManager.DISALLOW_ADD_PRIVATE_PROFILE,
+ true,
+ UserHandle.of(userId));
}
// TODO Send to system too?
sendOwnerChangedBroadcast(DevicePolicyManager.ACTION_DEVICE_OWNER_CHANGED, userId);
@@ -13200,6 +13231,8 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
USER_RESTRICTION_PERMISSIONS.put(
UserManager.DISALLOW_ADD_CLONE_PROFILE, new String[]{MANAGE_DEVICE_POLICY_PROFILES});
USER_RESTRICTION_PERMISSIONS.put(
+ UserManager.DISALLOW_ADD_PRIVATE_PROFILE, new String[]{MANAGE_DEVICE_POLICY_PROFILES});
+ USER_RESTRICTION_PERMISSIONS.put(
UserManager.DISALLOW_ADD_USER, new String[]{MANAGE_DEVICE_POLICY_MODIFY_USERS});
USER_RESTRICTION_PERMISSIONS.put(
UserManager.DISALLOW_ADD_WIFI_CONFIG, new String[]{MANAGE_DEVICE_POLICY_WIFI});
@@ -22977,10 +23010,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
}
private static boolean isKeepProfilesRunningFlagEnabled() {
- return DeviceConfig.getBoolean(
- NAMESPACE_DEVICE_POLICY_MANAGER,
- KEEP_PROFILES_RUNNING_FLAG,
- DEFAULT_KEEP_PROFILES_RUNNING_FLAG);
+ return DEFAULT_KEEP_PROFILES_RUNNING_FLAG;
}
private boolean isUnicornFlagEnabled() {
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/PolicyDefinition.java b/services/devicepolicy/java/com/android/server/devicepolicy/PolicyDefinition.java
index 7a877b9afdad..0fc8c5e7a46a 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/PolicyDefinition.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/PolicyDefinition.java
@@ -426,6 +426,7 @@ final class PolicyDefinition<V> {
USER_RESTRICTION_FLAGS.put(UserManager.DISALLOW_ADD_USER, /* flags= */ 0);
USER_RESTRICTION_FLAGS.put(UserManager.DISALLOW_ADD_MANAGED_PROFILE, /* flags= */ 0);
USER_RESTRICTION_FLAGS.put(UserManager.DISALLOW_ADD_CLONE_PROFILE, /* flags= */ 0);
+ USER_RESTRICTION_FLAGS.put(UserManager.DISALLOW_ADD_PRIVATE_PROFILE, /* flags= */ 0);
USER_RESTRICTION_FLAGS.put(UserManager.ENSURE_VERIFY_APPS, POLICY_FLAG_GLOBAL_ONLY_POLICY);
USER_RESTRICTION_FLAGS.put(UserManager.DISALLOW_CONFIG_CELL_BROADCASTS, /* flags= */ 0);
USER_RESTRICTION_FLAGS.put(UserManager.DISALLOW_CONFIG_MOBILE_NETWORKS, /* flags= */ 0);
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/PolicyVersionUpgrader.java b/services/devicepolicy/java/com/android/server/devicepolicy/PolicyVersionUpgrader.java
index 733b1d98f3e2..f060426ec827 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/PolicyVersionUpgrader.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/PolicyVersionUpgrader.java
@@ -117,6 +117,19 @@ public class PolicyVersionUpgrader {
currentVersion = 5;
}
+ if (currentVersion == 5) {
+ Slog.i(LOG_TAG, String.format("Upgrading from version %d", currentVersion));
+ // No-op upgrade here:
+ // DevicePolicyData.mEffectiveKeepProfilesRunning is only stored in XML file when it is
+ // different from its default value, otherwise the tag is not written. When loading, if
+ // the tag is missing, the field retains the value previously assigned in the
+ // constructor, which is the default value.
+ // In version 5 the default value was 'true', in version 6 it is 'false', so when
+ // loading XML version 5 we need to initialize the field to 'true' for it to be restored
+ // correctly in case the tag is missing. This is done in loadDataForUser().
+ currentVersion = 6;
+ }
+
writePoliciesAndVersion(allUsers, allUsersData, ownersData, currentVersion);
}
@@ -282,6 +295,10 @@ public class PolicyVersionUpgrader {
private DevicePolicyData loadDataForUser(
int userId, int loadVersion, ComponentName ownerComponent) {
DevicePolicyData policy = new DevicePolicyData(userId);
+ // See version 5 -> 6 step in upgradePolicy()
+ if (loadVersion == 5 && userId == UserHandle.USER_SYSTEM) {
+ policy.mEffectiveKeepProfilesRunning = true;
+ }
DevicePolicyData.load(policy,
mProvider.makeDevicePoliciesJournaledFile(userId),
mProvider.getAdminInfoSupplier(userId),
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/RemoteBugreportManager.java b/services/devicepolicy/java/com/android/server/devicepolicy/RemoteBugreportManager.java
index 9a8e421d5d12..8684dbe73947 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/RemoteBugreportManager.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/RemoteBugreportManager.java
@@ -111,7 +111,7 @@ public class RemoteBugreportManager {
@Override
public void onReceive(Context context, Intent intent) {
final String action = intent.getAction();
- mInjector.getNotificationManager().cancel(LOG_TAG, NOTIFICATION_ID);
+ cancelNotification();
if (ACTION_BUGREPORT_SHARING_ACCEPTED.equals(action)) {
onBugreportSharingAccepted();
} else if (ACTION_BUGREPORT_SHARING_DECLINED.equals(action)) {
@@ -213,8 +213,7 @@ public class RemoteBugreportManager {
mRemoteBugreportServiceIsActive.set(true);
mRemoteBugreportSharingAccepted.set(false);
registerRemoteBugreportReceivers();
- mInjector.getNotificationManager().notifyAsUser(LOG_TAG, NOTIFICATION_ID,
- buildNotification(NOTIFICATION_BUGREPORT_STARTED), UserHandle.ALL);
+ notify(NOTIFICATION_BUGREPORT_STARTED);
mHandler.postDelayed(mRemoteBugreportTimeoutRunnable, REMOTE_BUGREPORT_TIMEOUT_MILLIS);
return true;
} catch (RemoteException re) {
@@ -258,13 +257,10 @@ public class RemoteBugreportManager {
final String bugreportHash = intent.getStringExtra(EXTRA_REMOTE_BUGREPORT_HASH);
if (mRemoteBugreportSharingAccepted.get()) {
shareBugreportWithDeviceOwnerIfExists(bugreportUriString, bugreportHash);
- mInjector.getNotificationManager().cancel(LOG_TAG,
- NOTIFICATION_ID);
+ cancelNotification();
} else {
mService.setDeviceOwnerRemoteBugreportUriAndHash(bugreportUriString, bugreportHash);
- mInjector.getNotificationManager().notifyAsUser(LOG_TAG, NOTIFICATION_ID,
- buildNotification(NOTIFICATION_BUGREPORT_FINISHED_NOT_ACCEPTED),
- UserHandle.ALL);
+ notify(NOTIFICATION_BUGREPORT_FINISHED_NOT_ACCEPTED);
}
mContext.unregisterReceiver(mRemoteBugreportFinishedReceiver);
}
@@ -274,7 +270,7 @@ public class RemoteBugreportManager {
mInjector.systemPropertiesSet(CTL_STOP, REMOTE_BUGREPORT_SERVICE);
mRemoteBugreportSharingAccepted.set(false);
mService.setDeviceOwnerRemoteBugreportUriAndHash(null, null);
- mInjector.getNotificationManager().cancel(LOG_TAG, NOTIFICATION_ID);
+ cancelNotification();
final Bundle extras = new Bundle();
extras.putInt(DeviceAdminReceiver.EXTRA_BUGREPORT_FAILURE_REASON,
DeviceAdminReceiver.BUGREPORT_FAILURE_FAILED_COMPLETING);
@@ -289,9 +285,7 @@ public class RemoteBugreportManager {
if (uriAndHash != null) {
shareBugreportWithDeviceOwnerIfExists(uriAndHash.first, uriAndHash.second);
} else if (mRemoteBugreportServiceIsActive.get()) {
- mInjector.getNotificationManager().notifyAsUser(LOG_TAG, NOTIFICATION_ID,
- buildNotification(NOTIFICATION_BUGREPORT_ACCEPTED_NOT_FINISHED),
- UserHandle.ALL);
+ notify(NOTIFICATION_BUGREPORT_ACCEPTED_NOT_FINISHED);
}
}
@@ -340,7 +334,16 @@ public class RemoteBugreportManager {
filterConsent.addAction(ACTION_BUGREPORT_SHARING_DECLINED);
filterConsent.addAction(ACTION_BUGREPORT_SHARING_ACCEPTED);
mContext.registerReceiver(mRemoteBugreportConsentReceiver, filterConsent);
- mInjector.getNotificationManager().notifyAsUser(LOG_TAG, NOTIFICATION_ID,
- buildNotification(NOTIFICATION_BUGREPORT_FINISHED_NOT_ACCEPTED), UserHandle.ALL);
+ notify(NOTIFICATION_BUGREPORT_FINISHED_NOT_ACCEPTED);
+ }
+
+ private void notify(@RemoteBugreportNotificationType int type) {
+ mInjector.getNotificationManager()
+ .notifyAsUser(LOG_TAG, NOTIFICATION_ID, buildNotification(type), UserHandle.ALL);
+ }
+
+ private void cancelNotification() {
+ mInjector.getNotificationManager()
+ .cancelAsUser(LOG_TAG, NOTIFICATION_ID, UserHandle.ALL);
}
}
diff --git a/services/tests/InputMethodSystemServerTests/src/com/android/inputmethodservice/InputMethodServiceTest.java b/services/tests/InputMethodSystemServerTests/src/com/android/inputmethodservice/InputMethodServiceTest.java
index e8acb067f625..6ff7b2601b79 100644
--- a/services/tests/InputMethodSystemServerTests/src/com/android/inputmethodservice/InputMethodServiceTest.java
+++ b/services/tests/InputMethodSystemServerTests/src/com/android/inputmethodservice/InputMethodServiceTest.java
@@ -16,15 +16,20 @@
package com.android.inputmethodservice;
+import static android.view.WindowInsets.Type.captionBar;
+
import static com.android.compatibility.common.util.SystemUtil.eventually;
import static com.google.common.truth.Truth.assertThat;
+import static org.junit.Assert.assertEquals;
import static org.junit.Assert.fail;
+import static org.junit.Assume.assumeFalse;
import android.app.Instrumentation;
import android.content.Context;
import android.content.res.Configuration;
+import android.graphics.Insets;
import android.os.RemoteException;
import android.provider.Settings;
import android.support.test.uiautomator.By;
@@ -32,6 +37,7 @@ import android.support.test.uiautomator.UiDevice;
import android.support.test.uiautomator.UiObject2;
import android.support.test.uiautomator.Until;
import android.util.Log;
+import android.view.WindowManagerGlobal;
import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputMethodManager;
@@ -592,6 +598,20 @@ public class InputMethodServiceTest {
false /* orientationPortrait */);
}
+ /**
+ * This checks that when the system navigation bar is not created (e.g. emulator),
+ * then the IME caption bar is also not created.
+ */
+ @Test
+ public void testNoNavigationBar_thenImeNoCaptionBar() throws Exception {
+ boolean hasNavigationBar = WindowManagerGlobal.getWindowManagerService()
+ .hasNavigationBar(mInputMethodService.getDisplayId());
+ assumeFalse("Must not have a navigation bar", hasNavigationBar);
+
+ assertEquals(Insets.NONE, mInputMethodService.getWindow().getWindow().getDecorView()
+ .getRootWindowInsets().getInsetsIgnoringVisibility(captionBar()));
+ }
+
private void verifyInputViewStatus(
Runnable runnable, boolean expected, boolean inputViewStarted)
throws InterruptedException {
diff --git a/services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/PackageManagerServiceTest.java b/services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/PackageManagerServiceTest.java
index a805e5c9f87e..bea654305a9f 100644
--- a/services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/PackageManagerServiceTest.java
+++ b/services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/PackageManagerServiceTest.java
@@ -125,7 +125,7 @@ public class PackageManagerServiceTest {
Assert.assertNull(pri.mBroadcastUsers);
// populateUsers with nothing leaves nothing
- pri.populateUsers(null, setting);
+ pri.populateBroadcastUsers(setting);
Assert.assertNull(pri.mBroadcastUsers);
// Create a real (non-null) PackageSetting and confirm that the removed
@@ -139,9 +139,10 @@ public class PackageManagerServiceTest {
.setSecondaryCpuAbiString("secondaryCpuAbiString")
.setCpuAbiOverrideString("cpuAbiOverrideString")
.build();
- pri.populateUsers(new int[]{
+ pri.mRemovedUsers = new int[]{
1, 2, 3, 4, 5
- }, setting);
+ };
+ pri.populateBroadcastUsers(setting);
Assert.assertNotNull(pri.mBroadcastUsers);
Assert.assertEquals(5, pri.mBroadcastUsers.length);
Assert.assertNotNull(pri.mInstantUserIds);
@@ -151,9 +152,10 @@ public class PackageManagerServiceTest {
pri.mBroadcastUsers = null;
final int EXCLUDED_USER_ID = 4;
setting.setInstantApp(true, EXCLUDED_USER_ID);
- pri.populateUsers(new int[]{
+ pri.mRemovedUsers = new int[]{
1, 2, 3, EXCLUDED_USER_ID, 5
- }, setting);
+ };
+ pri.populateBroadcastUsers(setting);
Assert.assertNotNull(pri.mBroadcastUsers);
Assert.assertEquals(4, pri.mBroadcastUsers.length);
Assert.assertNotNull(pri.mInstantUserIds);
diff --git a/services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/ScanTests.java b/services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/ScanTests.java
index 98c6c424e223..e2939c1aff3b 100644
--- a/services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/ScanTests.java
+++ b/services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/ScanTests.java
@@ -612,9 +612,6 @@ public class ScanTests {
final PackageSetting pkgSetting = scanResult.mPkgSetting;
assertBasicPackageSetting(scanResult, packageName, isInstant, pkgSetting);
- // pretend that the data dir has been set up already, so that the generated applicationInfo
- // includes the expected data dir string
- pkgSetting.setCeDataInode(/* ceDataInode= */100, /* userId= */0);
final ApplicationInfo applicationInfo = PackageInfoUtils.generateApplicationInfo(
pkgSetting.getPkg(), 0, pkgSetting.getUserStateOrDefault(0), 0, pkgSetting);
diff --git a/services/tests/displayservicetests/Android.bp b/services/tests/displayservicetests/Android.bp
index fb14419a13c0..e28028f9fc2b 100644
--- a/services/tests/displayservicetests/Android.bp
+++ b/services/tests/displayservicetests/Android.bp
@@ -35,6 +35,7 @@ android_test {
"mockingservicestests-utils-mockito",
"platform-compat-test-rules",
"platform-test-annotations",
+ "service-permission.stubs.system_server",
"services.core",
"servicestests-utils",
"testables",
diff --git a/services/tests/displayservicetests/src/com/android/server/display/AutomaticBrightnessControllerTest.java b/services/tests/displayservicetests/src/com/android/server/display/AutomaticBrightnessControllerTest.java
index d16c37a4c07a..2bdebe26e551 100644
--- a/services/tests/displayservicetests/src/com/android/server/display/AutomaticBrightnessControllerTest.java
+++ b/services/tests/displayservicetests/src/com/android/server/display/AutomaticBrightnessControllerTest.java
@@ -267,7 +267,8 @@ public class AutomaticBrightnessControllerTest {
/* shouldResetShortTermModel= */ true);
// There should be a user data point added to the mapper.
- verify(mBrightnessMappingStrategy).addUserDataPoint(1000f, 0.5f);
+ verify(mBrightnessMappingStrategy).addUserDataPoint(/* lux= */ 1000f,
+ /* brightness= */ 0.5f);
}
@Test
@@ -295,7 +296,8 @@ public class AutomaticBrightnessControllerTest {
mController.recalculateSplines(true, adjustments);
verify(mBrightnessMappingStrategy).clearUserDataPoints();
verify(mBrightnessMappingStrategy).recalculateSplines(true, adjustments);
- verify(mBrightnessMappingStrategy, times(2)).addUserDataPoint(currentLux, 0.5f);
+ verify(mBrightnessMappingStrategy, times(2)).addUserDataPoint(currentLux,
+ /* brightness= */ 0.5f);
clearInvocations(mBrightnessMappingStrategy);
@@ -342,7 +344,7 @@ public class AutomaticBrightnessControllerTest {
// Verify only happens on the first configure. (i.e. not again when switching back)
// Intentionally using any() to ensure it's not called whatsoever.
verify(mBrightnessMappingStrategy, times(1))
- .addUserDataPoint(123.0f, 0.5f);
+ .addUserDataPoint(/* lux= */ 123.0f, /* brightness= */ 0.5f);
verify(mBrightnessMappingStrategy, times(1))
.addUserDataPoint(anyFloat(), anyFloat());
}
@@ -385,7 +387,7 @@ public class AutomaticBrightnessControllerTest {
// Verify that we add the data point once when the user sets it, and again when we return
// interactive mode.
verify(mBrightnessMappingStrategy, times(2))
- .addUserDataPoint(123.0f, 0.51f);
+ .addUserDataPoint(/* lux= */ 123.0f, /* brightness= */ 0.51f);
}
@Test
@@ -428,7 +430,7 @@ public class AutomaticBrightnessControllerTest {
// Verify only happens on the first configure. (i.e. not again when switching back)
// Intentionally using any() to ensure it's not called whatsoever.
verify(mBrightnessMappingStrategy, times(1))
- .addUserDataPoint(123.0f, 0.5f);
+ .addUserDataPoint(/* lux= */ 123.0f, /* brightness= */ 0.5f);
verify(mBrightnessMappingStrategy, times(1))
.addUserDataPoint(anyFloat(), anyFloat());
}
@@ -474,7 +476,7 @@ public class AutomaticBrightnessControllerTest {
// Verify this happens on the first configure and again when switching back
// Intentionally using any() to ensure it's not called any other times whatsoever.
verify(mBrightnessMappingStrategy, times(2))
- .addUserDataPoint(123.0f, 0.5f);
+ .addUserDataPoint(/* lux= */ 123.0f, /* brightness= */ 0.5f);
verify(mBrightnessMappingStrategy, times(2))
.addUserDataPoint(anyFloat(), anyFloat());
}
@@ -533,7 +535,8 @@ public class AutomaticBrightnessControllerTest {
/* shouldResetShortTermModel= */ true);
// There should be a user data point added to the mapper.
- verify(mBrightnessMappingStrategy, times(1)).addUserDataPoint(1000f, 0.5f);
+ verify(mBrightnessMappingStrategy, times(1)).addUserDataPoint(/* lux= */ 1000f,
+ /* brightness= */ 0.5f);
verify(mBrightnessMappingStrategy, times(2)).setBrightnessConfiguration(any());
verify(mBrightnessMappingStrategy, times(3)).getBrightness(anyFloat(), any(), anyInt());
@@ -559,7 +562,8 @@ public class AutomaticBrightnessControllerTest {
/* shouldResetShortTermModel= */ true);
// Ensure we use the correct mapping strategy
- verify(mIdleBrightnessMappingStrategy, times(1)).addUserDataPoint(1000f, 0.5f);
+ verify(mIdleBrightnessMappingStrategy, times(1)).addUserDataPoint(/* lux= */ 1000f,
+ /* brightness= */ 0.5f);
}
@Test
diff --git a/services/tests/displayservicetests/src/com/android/server/display/BrightnessMappingStrategyTest.java b/services/tests/displayservicetests/src/com/android/server/display/BrightnessMappingStrategyTest.java
index ee7826f13578..97e582607133 100644
--- a/services/tests/displayservicetests/src/com/android/server/display/BrightnessMappingStrategyTest.java
+++ b/services/tests/displayservicetests/src/com/android/server/display/BrightnessMappingStrategyTest.java
@@ -445,7 +445,7 @@ public class BrightnessMappingStrategyTest {
// Add a data point in the middle of the curve where the user has set the brightness max
final int idx = LUX_LEVELS.length / 2;
- strategy.addUserDataPoint(LUX_LEVELS[idx], 1.0f);
+ strategy.addUserDataPoint(LUX_LEVELS[idx], /* brightness= */ 1.0f);
// Then make sure that all control points after the middle lux level are also set to max...
for (int i = idx; i < LUX_LEVELS.length; i++) {
@@ -662,11 +662,11 @@ public class BrightnessMappingStrategyTest {
GAMMA_CORRECTION_NITS);
BrightnessMappingStrategy strategy = BrightnessMappingStrategy.create(resources, ddc,
mMockDwbc);
- assertEquals(0.0f, strategy.getAutoBrightnessAdjustment(), 0.0001f /* tolerance */);
- strategy.addUserDataPoint(2500, 1.0f);
- assertEquals(+1.0f, strategy.getAutoBrightnessAdjustment(), 0.0001f /* tolerance */);
- strategy.addUserDataPoint(2500, 0.0f);
- assertEquals(-1.0f, strategy.getAutoBrightnessAdjustment(), 0.0001f /* tolerance */);
+ assertEquals(0.0f, strategy.getAutoBrightnessAdjustment(), /* delta= */ 0.0001f);
+ strategy.addUserDataPoint(/* lux= */ 2500, /* brightness= */ 1.0f);
+ assertEquals(+1.0f, strategy.getAutoBrightnessAdjustment(), /* delta= */ 0.0001f);
+ strategy.addUserDataPoint(/* lux= */ 2500, /* brightness= */ 0.0f);
+ assertEquals(-1.0f, strategy.getAutoBrightnessAdjustment(), /* delta= */ 0.0001f);
}
@Test
@@ -701,7 +701,7 @@ public class BrightnessMappingStrategyTest {
// Similarly, if we set a user data point at (x4, 1.0), the adjustment should be 1 - y4.
adjustment = 1.0f - y4;
gamma = (float) MathUtils.pow(MAXIMUM_GAMMA, -adjustment);
- strategy.addUserDataPoint(x4, 1.0f);
+ strategy.addUserDataPoint(x4, /* brightness= */ 1.0f);
assertEquals(MathUtils.pow(y0, gamma), strategy.getBrightness(x0), 0.0001f /* tolerance */);
assertEquals(MathUtils.pow(y2, gamma), strategy.getBrightness(x2), 0.0001f /* tolerance */);
assertEquals(1.0f, strategy.getBrightness(x4), 0.0001f /* tolerance */);
diff --git a/services/tests/displayservicetests/src/com/android/server/display/DisplayManagerServiceTest.java b/services/tests/displayservicetests/src/com/android/server/display/DisplayManagerServiceTest.java
index d099693ffc82..a23539e37409 100644
--- a/services/tests/displayservicetests/src/com/android/server/display/DisplayManagerServiceTest.java
+++ b/services/tests/displayservicetests/src/com/android/server/display/DisplayManagerServiceTest.java
@@ -28,6 +28,7 @@ import static android.view.ContentRecordingSession.RECORD_CONTENT_TASK;
import static com.android.server.display.VirtualDisplayAdapter.UNIQUE_ID_PREFIX;
import static com.google.common.truth.Truth.assertThat;
+import static com.google.common.truth.Truth.assertWithMessage;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
@@ -53,6 +54,8 @@ import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.app.PropertyInvalidatedCache;
import android.companion.virtual.IVirtualDevice;
import android.companion.virtual.IVirtualDeviceManager;
@@ -61,6 +64,7 @@ import android.compat.testing.PlatformCompatChangeRule;
import android.content.Context;
import android.content.ContextWrapper;
import android.content.pm.PackageManager;
+import android.content.pm.PackageManagerInternal;
import android.content.res.Resources;
import android.graphics.Insets;
import android.graphics.Rect;
@@ -110,6 +114,7 @@ import com.android.server.display.DisplayManagerService.SyncRoot;
import com.android.server.display.feature.DisplayManagerFlags;
import com.android.server.input.InputManagerInternal;
import com.android.server.lights.LightsManager;
+import com.android.server.pm.UserManagerInternal;
import com.android.server.sensors.SensorManagerInternal;
import com.android.server.wm.WindowManagerInternal;
@@ -288,10 +293,11 @@ public class DisplayManagerServiceTest {
@Mock LocalDisplayAdapter.SurfaceControlProxy mSurfaceControlProxy;
@Mock IBinder mMockDisplayToken;
@Mock SensorManagerInternal mMockSensorManagerInternal;
-
@Mock SensorManager mSensorManager;
-
@Mock DisplayDeviceConfig mMockDisplayDeviceConfig;
+ @Mock PackageManagerInternal mMockPackageManagerInternal;
+ @Mock UserManagerInternal mMockUserManagerInternal;
+
@Captor ArgumentCaptor<ContentRecordingSession> mContentRecordingSessionCaptor;
@Mock DisplayManagerFlags mMockFlags;
@@ -312,6 +318,10 @@ public class DisplayManagerServiceTest {
LocalServices.removeServiceForTest(VirtualDeviceManagerInternal.class);
LocalServices.addService(
VirtualDeviceManagerInternal.class, mMockVirtualDeviceManagerInternal);
+ LocalServices.removeServiceForTest(PackageManagerInternal.class);
+ LocalServices.addService(PackageManagerInternal.class, mMockPackageManagerInternal);
+ LocalServices.removeServiceForTest(UserManagerInternal.class);
+ LocalServices.addService(UserManagerInternal.class, mMockUserManagerInternal);
// TODO: b/287945043
mContext = spy(new ContextWrapper(ApplicationProvider.getApplicationContext()));
mResources = Mockito.spy(mContext.getResources());
@@ -627,7 +637,7 @@ public class DisplayManagerServiceTest {
* Tests that the virtual display is created along-side the default display.
*/
@Test
- public void testStartVirtualDisplayWithDefaultDisplay_Succeeds() throws Exception {
+ public void testStartVirtualDisplayWithDefaultDisplay_Succeeds() {
DisplayManagerService displayManager =
new DisplayManagerService(mContext, mShortMockedInjector);
registerDefaultDisplays(displayManager);
@@ -663,7 +673,7 @@ public class DisplayManagerServiceTest {
* internal state for things like display cutout when nonOverrideDisplayInfo is changed.
*/
@Test
- public void testShouldNotifyChangeWhenNonOverrideDisplayInfoChanged() throws Exception {
+ public void testShouldNotifyChangeWhenNonOverrideDisplayInfoChanged() {
DisplayManagerService displayManager =
new DisplayManagerService(mContext, mShortMockedInjector);
registerDefaultDisplays(displayManager);
@@ -1486,7 +1496,7 @@ public class DisplayManagerServiceTest {
* a virtual device, even if ADD_TRUSTED_DISPLAY is not granted.
*/
@Test
- public void testOwnDisplayGroup_allowCreationWithVirtualDevice() throws Exception {
+ public void testOwnDisplayGroup_allowCreationWithVirtualDevice() throws Exception {
DisplayManagerService displayManager =
new DisplayManagerService(mContext, mBasicInjector);
DisplayManagerInternal localService = displayManager.new LocalService();
@@ -1650,7 +1660,7 @@ public class DisplayManagerServiceTest {
*/
@Test
@DisableCompatChanges({DisplayManagerService.DISPLAY_MODE_RETURNS_PHYSICAL_REFRESH_RATE})
- public void testDisplayInfoFrameRateOverrideModeCompat() throws Exception {
+ public void testDisplayInfoFrameRateOverrideModeCompat() {
testDisplayInfoFrameRateOverrideModeCompat(/*compatChangeEnabled*/ false);
}
@@ -1659,7 +1669,7 @@ public class DisplayManagerServiceTest {
*/
@Test
@EnableCompatChanges({DisplayManagerService.DISPLAY_MODE_RETURNS_PHYSICAL_REFRESH_RATE})
- public void testDisplayInfoFrameRateOverrideMode() throws Exception {
+ public void testDisplayInfoFrameRateOverrideMode() {
testDisplayInfoFrameRateOverrideModeCompat(/*compatChangeEnabled*/ true);
}
@@ -1742,7 +1752,7 @@ public class DisplayManagerServiceTest {
*/
@Test
@DisableCompatChanges({DisplayManagerService.DISPLAY_MODE_RETURNS_PHYSICAL_REFRESH_RATE})
- public void testDisplayInfoRenderFrameRateModeCompat() throws Exception {
+ public void testDisplayInfoRenderFrameRateModeCompat() {
testDisplayInfoRenderFrameRateModeCompat(/*compatChangeEnabled*/ false);
}
@@ -1751,7 +1761,7 @@ public class DisplayManagerServiceTest {
*/
@Test
@EnableCompatChanges({DisplayManagerService.DISPLAY_MODE_RETURNS_PHYSICAL_REFRESH_RATE})
- public void testDisplayInfoRenderFrameRateMode() throws Exception {
+ public void testDisplayInfoRenderFrameRateMode() {
testDisplayInfoRenderFrameRateModeCompat(/*compatChangeEnabled*/ true);
}
@@ -2104,10 +2114,11 @@ public class DisplayManagerServiceTest {
LogicalDisplayMapper logicalDisplayMapper = displayManager.getLogicalDisplayMapper();
FakeDisplayManagerCallback callback = new FakeDisplayManagerCallback();
bs.registerCallbackWithEventMask(callback, STANDARD_AND_CONNECTION_DISPLAY_EVENTS);
+ callback.expectsEvent(EVENT_DISPLAY_ADDED);
FakeDisplayDevice displayDevice =
createFakeDisplayDevice(displayManager, new float[]{60f}, Display.TYPE_EXTERNAL);
- waitForIdleHandler(displayManager.getDisplayHandler());
+ callback.waitForExpectedEvent();
LogicalDisplay display =
logicalDisplayMapper.getDisplayLocked(displayDevice, /* includeDisabled= */ true);
@@ -2124,16 +2135,19 @@ public class DisplayManagerServiceTest {
DisplayManagerInternal localService = displayManager.new LocalService();
DisplayManagerService.BinderService bs = displayManager.new BinderService();
LogicalDisplayMapper logicalDisplayMapper = displayManager.getLogicalDisplayMapper();
- // Create default display device
- createFakeDisplayDevice(displayManager, new float[]{60f}, Display.TYPE_INTERNAL);
FakeDisplayManagerCallback callback = new FakeDisplayManagerCallback();
-
bs.registerCallbackWithEventMask(callback, STANDARD_AND_CONNECTION_DISPLAY_EVENTS);
localService.registerDisplayGroupListener(callback);
+ callback.expectsEvent(EVENT_DISPLAY_ADDED);
+ // Create default display device
+ createFakeDisplayDevice(displayManager, new float[]{60f}, Display.TYPE_INTERNAL);
+ callback.waitForExpectedEvent();
+ callback.clear();
+ callback.expectsEvent(EVENT_DISPLAY_CONNECTED);
FakeDisplayDevice displayDevice =
createFakeDisplayDevice(displayManager, new float[]{60f}, Display.TYPE_EXTERNAL);
- waitForIdleHandler(displayManager.getDisplayHandler());
+ callback.waitForExpectedEvent();
LogicalDisplay display =
logicalDisplayMapper.getDisplayLocked(displayDevice, /* includeDisabled= */ true);
@@ -2151,8 +2165,9 @@ public class DisplayManagerServiceTest {
FakeDisplayManagerCallback callback = new FakeDisplayManagerCallback();
bs.registerCallbackWithEventMask(callback, STANDARD_AND_CONNECTION_DISPLAY_EVENTS);
+ callback.expectsEvent(EVENT_DISPLAY_ADDED);
createFakeDisplayDevice(displayManager, new float[]{60f}, Display.TYPE_INTERNAL);
- waitForIdleHandler(displayManager.getDisplayHandler());
+ callback.waitForExpectedEvent();
assertThat(callback.receivedEvents()).containsExactly(EVENT_DISPLAY_CONNECTED,
EVENT_DISPLAY_ADDED).inOrder();
@@ -2166,18 +2181,22 @@ public class DisplayManagerServiceTest {
DisplayManagerService.BinderService bs = displayManager.new BinderService();
LogicalDisplayMapper logicalDisplayMapper = displayManager.getLogicalDisplayMapper();
FakeDisplayManagerCallback callback = new FakeDisplayManagerCallback();
+ bs.registerCallbackWithEventMask(callback, STANDARD_AND_CONNECTION_DISPLAY_EVENTS);
+ callback.expectsEvent(EVENT_DISPLAY_ADDED);
// Create default display device
createFakeDisplayDevice(displayManager, new float[]{60f}, Display.TYPE_INTERNAL);
- bs.registerCallbackWithEventMask(callback, STANDARD_DISPLAY_EVENTS);
+ callback.waitForExpectedEvent();
+ callback.expectsEvent(EVENT_DISPLAY_CONNECTED);
FakeDisplayDevice displayDevice =
createFakeDisplayDevice(displayManager, new float[]{60f}, Display.TYPE_EXTERNAL);
- waitForIdleHandler(displayManager.getDisplayHandler());
+ callback.waitForExpectedEvent();
callback.clear();
+ callback.expectsEvent(EVENT_DISPLAY_ADDED);
LogicalDisplay display =
logicalDisplayMapper.getDisplayLocked(displayDevice, /* includeDisabled= */ true);
displayManager.enableConnectedDisplay(display.getDisplayIdLocked(), /* enabled= */ true);
- waitForIdleHandler(displayManager.getDisplayHandler());
+ callback.waitForExpectedEvent();
assertThat(display.isEnabledLocked()).isTrue();
assertThat(callback.receivedEvents()).containsExactly(EVENT_DISPLAY_ADDED).inOrder();
@@ -2190,11 +2209,15 @@ public class DisplayManagerServiceTest {
DisplayManagerService.BinderService bs = displayManager.new BinderService();
LogicalDisplayMapper logicalDisplayMapper = displayManager.getLogicalDisplayMapper();
FakeDisplayManagerCallback callback = new FakeDisplayManagerCallback();
+ bs.registerCallbackWithEventMask(callback, STANDARD_DISPLAY_EVENTS);
+ callback.expectsEvent(EVENT_DISPLAY_ADDED);
// Create default display device
createFakeDisplayDevice(displayManager, new float[]{60f}, Display.TYPE_INTERNAL);
+ callback.waitForExpectedEvent();
bs.registerCallbackWithEventMask(callback, STANDARD_DISPLAY_EVENTS);
FakeDisplayDevice displayDevice =
createFakeDisplayDevice(displayManager, new float[]{60f}, Display.TYPE_EXTERNAL);
+ // Withouts permission, we cannot get the CONNECTED event.
waitForIdleHandler(displayManager.getDisplayHandler());
callback.clear();
LogicalDisplay display =
@@ -2212,19 +2235,22 @@ public class DisplayManagerServiceTest {
LogicalDisplayMapper logicalDisplayMapper = displayManager.getLogicalDisplayMapper();
FakeDisplayManagerCallback callback = new FakeDisplayManagerCallback();
bs.registerCallbackWithEventMask(callback, STANDARD_DISPLAY_EVENTS);
+ callback.expectsEvent(EVENT_DISPLAY_ADDED);
FakeDisplayDevice displayDevice =
createFakeDisplayDevice(displayManager, new float[]{60f}, Display.TYPE_INTERNAL);
- waitForIdleHandler(displayManager.getDisplayHandler());
+ callback.waitForExpectedEvent();
LogicalDisplay display =
logicalDisplayMapper.getDisplayLocked(displayDevice, /* includeDisabled= */ true);
+ callback.expectsEvent(EVENT_DISPLAY_REMOVED);
logicalDisplayMapper.setEnabledLocked(display, /* isEnabled= */ false);
logicalDisplayMapper.updateLogicalDisplays();
- waitForIdleHandler(displayManager.getDisplayHandler());
+ callback.waitForExpectedEvent();
callback.clear();
+ callback.expectsEvent(EVENT_DISPLAY_ADDED);
logicalDisplayMapper.setEnabledLocked(display, /* isEnabled= */ true);
logicalDisplayMapper.updateLogicalDisplays();
- waitForIdleHandler(displayManager.getDisplayHandler());
+ callback.waitForExpectedEvent();
assertThat(callback.receivedEvents()).containsExactly(EVENT_DISPLAY_ADDED);
}
@@ -2237,16 +2263,18 @@ public class DisplayManagerServiceTest {
LogicalDisplayMapper logicalDisplayMapper = displayManager.getLogicalDisplayMapper();
FakeDisplayManagerCallback callback = new FakeDisplayManagerCallback();
bs.registerCallbackWithEventMask(callback, STANDARD_DISPLAY_EVENTS);
+ callback.expectsEvent(EVENT_DISPLAY_ADDED);
FakeDisplayDevice displayDevice =
createFakeDisplayDevice(displayManager, new float[]{60f}, Display.TYPE_INTERNAL);
- waitForIdleHandler(displayManager.getDisplayHandler());
+ callback.waitForExpectedEvent();
callback.clear();
LogicalDisplay display =
logicalDisplayMapper.getDisplayLocked(displayDevice, /* includeDisabled= */ true);
+ callback.expectsEvent(EVENT_DISPLAY_REMOVED);
logicalDisplayMapper.setEnabledLocked(display, /* isEnabled= */ false);
logicalDisplayMapper.updateLogicalDisplays();
- waitForIdleHandler(displayManager.getDisplayHandler());
+ callback.waitForExpectedEvent();
assertThat(callback.receivedEvents()).containsExactly(EVENT_DISPLAY_REMOVED);
}
@@ -2259,23 +2287,26 @@ public class DisplayManagerServiceTest {
LogicalDisplayMapper logicalDisplayMapper = displayManager.getLogicalDisplayMapper();
DisplayManagerInternal localService = displayManager.new LocalService();
FakeDisplayManagerCallback callback = new FakeDisplayManagerCallback();
- // Create default display device
- createFakeDisplayDevice(displayManager, new float[]{60f}, Display.TYPE_INTERNAL);
bs.registerCallbackWithEventMask(callback, STANDARD_DISPLAY_EVENTS);
localService.registerDisplayGroupListener(callback);
+ callback.expectsEvent(EVENT_DISPLAY_ADDED);
+ // Create default display device
+ createFakeDisplayDevice(displayManager, new float[]{60f}, Display.TYPE_INTERNAL);
+ callback.waitForExpectedEvent();
FakeDisplayDevice displayDevice =
createFakeDisplayDevice(displayManager, new float[]{60f}, Display.TYPE_EXTERNAL);
- waitForIdleHandler(displayManager.getDisplayHandler());
LogicalDisplay display =
logicalDisplayMapper.getDisplayLocked(displayDevice, /* includeDisabled= */ true);
+ callback.expectsEvent(EVENT_DISPLAY_ADDED);
logicalDisplayMapper.setEnabledLocked(display, /* isEnabled= */ true);
logicalDisplayMapper.updateLogicalDisplays();
- waitForIdleHandler(displayManager.getDisplayHandler());
+ callback.waitForExpectedEvent();
callback.clear();
+ callback.expectsEvent(EVENT_DISPLAY_REMOVED);
logicalDisplayMapper.setEnabledLocked(display, /* isEnabled= */ false);
logicalDisplayMapper.updateLogicalDisplays();
- waitForIdleHandler(displayManager.getDisplayHandler());
+ callback.waitForExpectedEvent();
assertThat(display.isEnabledLocked()).isFalse();
assertThat(callback.receivedEvents()).containsExactly(EVENT_DISPLAY_REMOVED);
@@ -2288,18 +2319,20 @@ public class DisplayManagerServiceTest {
DisplayManagerService.BinderService bs = displayManager.new BinderService();
LogicalDisplayMapper logicalDisplayMapper = displayManager.getLogicalDisplayMapper();
FakeDisplayManagerCallback callback = new FakeDisplayManagerCallback();
+ bs.registerCallbackWithEventMask(callback, STANDARD_DISPLAY_EVENTS);
+ callback.expectsEvent(EVENT_DISPLAY_ADDED);
// Create default display device
createFakeDisplayDevice(displayManager, new float[]{60f}, Display.TYPE_INTERNAL);
- bs.registerCallbackWithEventMask(callback, STANDARD_DISPLAY_EVENTS);
+ callback.waitForExpectedEvent();
FakeDisplayDevice displayDevice =
createFakeDisplayDevice(displayManager, new float[]{60f}, Display.TYPE_EXTERNAL);
- waitForIdleHandler(displayManager.getDisplayHandler());
+ callback.expectsEvent(EVENT_DISPLAY_ADDED);
LogicalDisplay display =
logicalDisplayMapper.getDisplayLocked(displayDevice, /* includeDisabled= */ true);
int displayId = display.getDisplayIdLocked();
logicalDisplayMapper.setEnabledLocked(display, /* isEnabled= */ true);
logicalDisplayMapper.updateLogicalDisplays();
- waitForIdleHandler(displayManager.getDisplayHandler());
+ callback.waitForExpectedEvent();
callback.clear();
assertThrows(SecurityException.class, () -> bs.disableConnectedDisplay(displayId));
@@ -2314,23 +2347,27 @@ public class DisplayManagerServiceTest {
DisplayManagerInternal localService = displayManager.new LocalService();
LogicalDisplayMapper logicalDisplayMapper = displayManager.getLogicalDisplayMapper();
FakeDisplayManagerCallback callback = new FakeDisplayManagerCallback();
- // Create default display device
- createFakeDisplayDevice(displayManager, new float[]{60f}, Display.TYPE_INTERNAL);
bs.registerCallbackWithEventMask(callback, STANDARD_AND_CONNECTION_DISPLAY_EVENTS);
localService.registerDisplayGroupListener(callback);
+ callback.expectsEvent(EVENT_DISPLAY_ADDED);
+ // Create default display device'
+ createFakeDisplayDevice(displayManager, new float[]{60f}, Display.TYPE_INTERNAL);
+ callback.waitForExpectedEvent();
+ callback.expectsEvent(EVENT_DISPLAY_CONNECTED);
FakeDisplayDevice displayDevice =
createFakeDisplayDevice(displayManager, new float[]{60f}, Display.TYPE_EXTERNAL);
- waitForIdleHandler(displayManager.getDisplayHandler());
+ callback.waitForExpectedEvent();
callback.clear();
LogicalDisplay display = logicalDisplayMapper.getDisplayLocked(displayDevice);
int groupId = display.getDisplayInfoLocked().displayGroupId;
DisplayGroup group = logicalDisplayMapper.getDisplayGroupLocked(groupId);
assertThat(group.getSizeLocked()).isEqualTo(1);
+ callback.expectsEvent(DISPLAY_GROUP_EVENT_REMOVED);
display.setPrimaryDisplayDeviceLocked(null);
displayManager.getDisplayDeviceRepository()
.onDisplayDeviceEvent(displayDevice, DisplayAdapter.DISPLAY_DEVICE_EVENT_REMOVED);
- waitForIdleHandler(displayManager.getDisplayHandler());
+ callback.waitForExpectedEvent();
assertThat(group.getSizeLocked()).isEqualTo(0);
assertThat(callback.receivedEvents()).containsExactly(EVENT_DISPLAY_DISCONNECTED,
@@ -2357,20 +2394,23 @@ public class DisplayManagerServiceTest {
LogicalDisplayMapper logicalDisplayMapper = displayManager.getLogicalDisplayMapper();
FakeDisplayManagerCallback callback = new FakeDisplayManagerCallback();
bs.registerCallbackWithEventMask(callback, STANDARD_AND_CONNECTION_DISPLAY_EVENTS);
+ callback.expectsEvent(EVENT_DISPLAY_CONNECTED);
FakeDisplayDevice displayDevice =
createFakeDisplayDevice(displayManager, new float[]{60f}, Display.TYPE_EXTERNAL);
- waitForIdleHandler(displayManager.getDisplayHandler());
+ callback.waitForExpectedEvent();
+ callback.expectsEvent(EVENT_DISPLAY_ADDED);
LogicalDisplay display =
logicalDisplayMapper.getDisplayLocked(displayDevice, /* includeDisabled= */ true);
int displayId = display.getDisplayIdLocked();
displayManager.enableConnectedDisplay(displayId, /* enabled= */ true);
- waitForIdleHandler(displayManager.getDisplayHandler());
+ callback.waitForExpectedEvent();
callback.clear();
+ callback.expectsEvent(EVENT_DISPLAY_DISCONNECTED);
display.setPrimaryDisplayDeviceLocked(null);
displayManager.getDisplayDeviceRepository()
.onDisplayDeviceEvent(displayDevice, DisplayAdapter.DISPLAY_DEVICE_EVENT_REMOVED);
- waitForIdleHandler(displayManager.getDisplayHandler());
+ callback.waitForExpectedEvent();
assertThat(logicalDisplayMapper.getDisplayLocked(displayId, true)).isNull();
assertThat(callback.receivedEvents()).containsExactly(EVENT_DISPLAY_REMOVED,
@@ -2386,17 +2426,19 @@ public class DisplayManagerServiceTest {
LogicalDisplayMapper logicalDisplayMapper = displayManager.getLogicalDisplayMapper();
FakeDisplayManagerCallback callback = new FakeDisplayManagerCallback();
bs.registerCallbackWithEventMask(callback, STANDARD_AND_CONNECTION_DISPLAY_EVENTS);
+ callback.expectsEvent(EVENT_DISPLAY_ADDED);
FakeDisplayDevice displayDevice =
createFakeDisplayDevice(displayManager, new float[]{60f}, Display.TYPE_INTERNAL);
LogicalDisplay display =
logicalDisplayMapper.getDisplayLocked(displayDevice, /* includeDisabled= */ true);
- waitForIdleHandler(displayManager.getDisplayHandler());
+ callback.waitForExpectedEvent();
callback.clear();
+ callback.expectsEvent(EVENT_DISPLAY_DISCONNECTED);
display.setPrimaryDisplayDeviceLocked(null);
displayManager.getDisplayDeviceRepository()
.onDisplayDeviceEvent(displayDevice, DisplayAdapter.DISPLAY_DEVICE_EVENT_REMOVED);
- waitForIdleHandler(displayManager.getDisplayHandler());
+ callback.waitForExpectedEvent();
assertThat(logicalDisplayMapper.getDisplayLocked(displayDevice,
/* includeDisabled= */ true)).isNull();
@@ -2675,6 +2717,12 @@ public class DisplayManagerServiceTest {
int mDisplayId;
List<String> mReceivedEvents = new ArrayList<>();
+ @Nullable
+ private String mExpectedEvent;
+
+ @NonNull
+ private volatile CountDownLatch mLatch = new CountDownLatch(0);
+
FakeDisplayManagerCallback(int displayId) {
mDisplayId = displayId;
}
@@ -2683,6 +2731,30 @@ public class DisplayManagerServiceTest {
mDisplayId = -1;
}
+ void expectsEvent(@NonNull String event) {
+ mExpectedEvent = event;
+ mLatch = new CountDownLatch(1);
+ }
+
+ void waitForExpectedEvent() {
+ waitForExpectedEvent(Duration.ofSeconds(1));
+ }
+
+ void waitForExpectedEvent(Duration timeout) {
+ try {
+ assertWithMessage("Event '" + mExpectedEvent + "' is received.")
+ .that(mLatch.await(timeout.toMillis(), TimeUnit.MILLISECONDS)).isTrue();
+ } catch (InterruptedException ex) {
+ throw new AssertionError("Waiting for expected event interrupted", ex);
+ }
+ }
+
+ private void eventSeen(String event) {
+ if (event.equals(mExpectedEvent)) {
+ mLatch.countDown();
+ }
+ }
+
@Override
public void onDisplayEvent(int displayId, int event) {
if (mDisplayId != -1 && displayId != mDisplayId) {
@@ -2693,22 +2765,27 @@ public class DisplayManagerServiceTest {
// 1 - The error produced is a lot easier to read
// 2 - The values used for display and group events are the same, strings are used to
// differentiate them easily.
- mReceivedEvents.add(eventTypeToString(event));
+ String eventName = eventTypeToString(event);
+ mReceivedEvents.add(eventName);
+ eventSeen(eventName);
}
@Override
public void onDisplayGroupAdded(int groupId) {
mReceivedEvents.add(DISPLAY_GROUP_EVENT_ADDED);
+ eventSeen(DISPLAY_GROUP_EVENT_ADDED);
}
@Override
public void onDisplayGroupRemoved(int groupId) {
mReceivedEvents.add(DISPLAY_GROUP_EVENT_REMOVED);
+ eventSeen(DISPLAY_GROUP_EVENT_REMOVED);
}
@Override
public void onDisplayGroupChanged(int groupId) {
mReceivedEvents.add(DISPLAY_GROUP_EVENT_CHANGED);
+ eventSeen(DISPLAY_GROUP_EVENT_CHANGED);
}
public void clear() {
diff --git a/services/tests/displayservicetests/src/com/android/server/display/DisplayPowerController2Test.java b/services/tests/displayservicetests/src/com/android/server/display/DisplayPowerController2Test.java
index 4cbdd09319cc..e7dc48e529eb 100644
--- a/services/tests/displayservicetests/src/com/android/server/display/DisplayPowerController2Test.java
+++ b/services/tests/displayservicetests/src/com/android/server/display/DisplayPowerController2Test.java
@@ -101,6 +101,8 @@ public final class DisplayPowerController2Test {
private static final float BRIGHTNESS_RAMP_RATE_FAST_INCREASE = 0.4f;
private static final float BRIGHTNESS_RAMP_RATE_SLOW_DECREASE = 0.1f;
private static final float BRIGHTNESS_RAMP_RATE_SLOW_INCREASE = 0.2f;
+ private static final float BRIGHTNESS_RAMP_RATE_SLOW_INCREASE_IDLE = 0.5f;
+ private static final float BRIGHTNESS_RAMP_RATE_SLOW_DECREASE_IDLE = 0.6f;
private OffsettableClock mClock;
private TestLooper mTestLooper;
@@ -1116,6 +1118,63 @@ public final class DisplayPowerController2Test {
verify(mDisplayWhiteBalanceControllerMock, times(1)).setStrongModeEnabled(true);
}
+ @Test
+ public void testRampRatesIdle() {
+ Settings.System.putInt(mContext.getContentResolver(),
+ Settings.System.SCREEN_BRIGHTNESS_MODE,
+ Settings.System.SCREEN_BRIGHTNESS_MODE_AUTOMATIC);
+ float brightness = 0.6f;
+ when(mHolder.displayPowerState.getScreenState()).thenReturn(Display.STATE_ON);
+ when(mHolder.displayPowerState.getColorFadeLevel()).thenReturn(1.0f);
+ when(mHolder.automaticBrightnessController.isInIdleMode()).thenReturn(true);
+ when(mHolder.automaticBrightnessController.getAutomaticScreenBrightness(
+ any(BrightnessEvent.class))).thenReturn(brightness);
+
+ DisplayPowerRequest dpr = new DisplayPowerRequest();
+ mHolder.dpc.requestPowerState(dpr, /* waitForNegativeProximity= */ false);
+ advanceTime(1); // Run updatePowerState
+
+ verify(mHolder.animator).animateTo(eq(brightness), anyFloat(),
+ eq(BRIGHTNESS_RAMP_RATE_FAST_INCREASE));
+
+ when(mHolder.displayPowerState.getScreenBrightness()).thenReturn(brightness);
+ brightness = 0.05f;
+ when(mHolder.automaticBrightnessController.getAutomaticScreenBrightness(
+ any(BrightnessEvent.class))).thenReturn(brightness);
+
+ mHolder.dpc.updateBrightness();
+ advanceTime(1); // Run updatePowerState
+
+ // The second time, the animation rate should be slow
+ verify(mHolder.animator).animateTo(eq(brightness), anyFloat(),
+ eq(BRIGHTNESS_RAMP_RATE_SLOW_DECREASE_IDLE));
+
+ brightness = 0.9f;
+ when(mHolder.automaticBrightnessController.getAutomaticScreenBrightness(
+ any(BrightnessEvent.class))).thenReturn(brightness);
+
+ mHolder.dpc.updateBrightness();
+ advanceTime(1); // Run updatePowerState
+ // The third time, the animation rate should be slow
+ verify(mHolder.animator).animateTo(eq(brightness), anyFloat(),
+ eq(BRIGHTNESS_RAMP_RATE_SLOW_INCREASE_IDLE));
+ }
+
+ @Test
+ public void testPowerStateStopsOnDpcStop() {
+ // Set up
+ DisplayPowerRequest dpr = new DisplayPowerRequest();
+ mHolder.dpc.requestPowerState(dpr, /* waitForNegativeProximity= */ false);
+ advanceTime(1);
+
+ // Stop dpc
+ mHolder.dpc.stop();
+ advanceTime(1);
+
+ // Ensure dps has stopped
+ verify(mHolder.displayPowerState, times(1)).stop();
+ }
+
/**
* Creates a mock and registers it to {@link LocalServices}.
*/
@@ -1187,6 +1246,10 @@ public final class DisplayPowerController2Test {
.thenReturn(BRIGHTNESS_RAMP_RATE_SLOW_DECREASE);
when(displayDeviceConfigMock.getBrightnessRampSlowIncrease())
.thenReturn(BRIGHTNESS_RAMP_RATE_SLOW_INCREASE);
+ when(displayDeviceConfigMock.getBrightnessRampSlowIncreaseIdle())
+ .thenReturn(BRIGHTNESS_RAMP_RATE_SLOW_INCREASE_IDLE);
+ when(displayDeviceConfigMock.getBrightnessRampSlowDecreaseIdle())
+ .thenReturn(BRIGHTNESS_RAMP_RATE_SLOW_DECREASE_IDLE);
}
private DisplayPowerControllerHolder createDisplayPowerController(int displayId,
diff --git a/services/tests/displayservicetests/src/com/android/server/display/DisplayPowerControllerTest.java b/services/tests/displayservicetests/src/com/android/server/display/DisplayPowerControllerTest.java
index 68bbcbc1df51..2640390ceecf 100644
--- a/services/tests/displayservicetests/src/com/android/server/display/DisplayPowerControllerTest.java
+++ b/services/tests/displayservicetests/src/com/android/server/display/DisplayPowerControllerTest.java
@@ -101,6 +101,8 @@ public final class DisplayPowerControllerTest {
private static final float BRIGHTNESS_RAMP_RATE_FAST_INCREASE = 0.4f;
private static final float BRIGHTNESS_RAMP_RATE_SLOW_DECREASE = 0.1f;
private static final float BRIGHTNESS_RAMP_RATE_SLOW_INCREASE = 0.2f;
+ private static final float BRIGHTNESS_RAMP_RATE_SLOW_INCREASE_IDLE = 0.5f;
+ private static final float BRIGHTNESS_RAMP_RATE_SLOW_DECREASE_IDLE = 0.6f;
private OffsettableClock mClock;
private TestLooper mTestLooper;
@@ -1123,6 +1125,63 @@ public final class DisplayPowerControllerTest {
verify(mDisplayWhiteBalanceControllerMock, times(1)).setStrongModeEnabled(true);
}
+ @Test
+ public void testRampRatesIdle() {
+ Settings.System.putInt(mContext.getContentResolver(),
+ Settings.System.SCREEN_BRIGHTNESS_MODE,
+ Settings.System.SCREEN_BRIGHTNESS_MODE_AUTOMATIC);
+ float brightness = 0.6f;
+ when(mHolder.displayPowerState.getScreenState()).thenReturn(Display.STATE_ON);
+ when(mHolder.displayPowerState.getColorFadeLevel()).thenReturn(1.0f);
+ when(mHolder.automaticBrightnessController.isInIdleMode()).thenReturn(true);
+ when(mHolder.automaticBrightnessController.getAutomaticScreenBrightness(
+ any(BrightnessEvent.class))).thenReturn(brightness);
+
+ DisplayPowerRequest dpr = new DisplayPowerRequest();
+ mHolder.dpc.requestPowerState(dpr, /* waitForNegativeProximity= */ false);
+ advanceTime(1); // Run updatePowerState
+
+ verify(mHolder.animator).animateTo(eq(brightness), anyFloat(),
+ eq(BRIGHTNESS_RAMP_RATE_FAST_INCREASE));
+
+ when(mHolder.displayPowerState.getScreenBrightness()).thenReturn(brightness);
+ brightness = 0.05f;
+ when(mHolder.automaticBrightnessController.getAutomaticScreenBrightness(
+ any(BrightnessEvent.class))).thenReturn(brightness);
+
+ mHolder.dpc.updateBrightness();
+ advanceTime(1); // Run updatePowerState
+
+ // The second time, the animation rate should be slow
+ verify(mHolder.animator).animateTo(eq(brightness), anyFloat(),
+ eq(BRIGHTNESS_RAMP_RATE_SLOW_DECREASE_IDLE));
+
+ brightness = 0.9f;
+ when(mHolder.automaticBrightnessController.getAutomaticScreenBrightness(
+ any(BrightnessEvent.class))).thenReturn(brightness);
+
+ mHolder.dpc.updateBrightness();
+ advanceTime(1); // Run updatePowerState
+ // The third time, the animation rate should be slow
+ verify(mHolder.animator).animateTo(eq(brightness), anyFloat(),
+ eq(BRIGHTNESS_RAMP_RATE_SLOW_INCREASE_IDLE));
+ }
+
+ @Test
+ public void testPowerStateStopsOnDpcStop() {
+ // Set up
+ DisplayPowerRequest dpr = new DisplayPowerRequest();
+ mHolder.dpc.requestPowerState(dpr, /* waitForNegativeProximity= */ false);
+ advanceTime(1);
+
+ // Stop dpc
+ mHolder.dpc.stop();
+ advanceTime(1);
+
+ // Ensure dps has stopped
+ verify(mHolder.displayPowerState, times(1)).stop();
+ }
+
private void advanceTime(long timeMs) {
mClock.fastForward(timeMs);
mTestLooper.dispatchAll();
@@ -1186,6 +1245,10 @@ public final class DisplayPowerControllerTest {
.thenReturn(BRIGHTNESS_RAMP_RATE_SLOW_DECREASE);
when(displayDeviceConfigMock.getBrightnessRampSlowIncrease())
.thenReturn(BRIGHTNESS_RAMP_RATE_SLOW_INCREASE);
+ when(displayDeviceConfigMock.getBrightnessRampSlowDecreaseIdle())
+ .thenReturn(BRIGHTNESS_RAMP_RATE_SLOW_DECREASE_IDLE);
+ when(displayDeviceConfigMock.getBrightnessRampSlowIncreaseIdle())
+ .thenReturn(BRIGHTNESS_RAMP_RATE_SLOW_INCREASE_IDLE);
}
private DisplayPowerControllerHolder createDisplayPowerController(int displayId,
diff --git a/services/tests/displayservicetests/src/com/android/server/display/DisplayPowerStateTest.java b/services/tests/displayservicetests/src/com/android/server/display/DisplayPowerStateTest.java
new file mode 100644
index 000000000000..167a412d3860
--- /dev/null
+++ b/services/tests/displayservicetests/src/com/android/server/display/DisplayPowerStateTest.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.display;
+
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
+
+import static org.mockito.Mockito.times;
+
+import android.os.Handler;
+import android.os.test.TestLooper;
+import android.view.Display;
+
+import androidx.test.filters.SmallTest;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoRule;
+
+
+@SmallTest
+public class DisplayPowerStateTest {
+ private static final int DISPLAY_ID = 123;
+
+ private DisplayPowerState mDisplayPowerState;
+ private TestLooper mTestLooper;
+ @Mock
+ private DisplayBlanker mDisplayBlankerMock;
+ @Mock
+ private ColorFade mColorFadeMock;
+
+ @Rule
+ public final MockitoRule mMockitoRule = MockitoJUnit.rule();
+
+ @Before
+ public void setUp() {
+ mTestLooper = new TestLooper();
+ mDisplayPowerState = new DisplayPowerState(
+ mDisplayBlankerMock, mColorFadeMock, DISPLAY_ID, Display.STATE_ON,
+ new Handler(mTestLooper.getLooper()));
+ }
+
+ @Test
+ public void testColorFadeStopsOnDpsStop() {
+ mDisplayPowerState.stop();
+ verify(mColorFadeMock, times(1)).stop();
+ }
+}
diff --git a/services/tests/displayservicetests/src/com/android/server/display/LogicalDisplayMapperTest.java b/services/tests/displayservicetests/src/com/android/server/display/LogicalDisplayMapperTest.java
index 69544356ab5b..065dd1f1f743 100644
--- a/services/tests/displayservicetests/src/com/android/server/display/LogicalDisplayMapperTest.java
+++ b/services/tests/displayservicetests/src/com/android/server/display/LogicalDisplayMapperTest.java
@@ -44,9 +44,13 @@ import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.clearInvocations;
import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@@ -58,6 +62,7 @@ import android.os.IPowerManager;
import android.os.IThermalService;
import android.os.PowerManager;
import android.os.Process;
+import android.os.RemoteException;
import android.os.test.TestLooper;
import android.view.Display;
import android.view.DisplayAddress;
@@ -69,7 +74,7 @@ import androidx.test.filters.SmallTest;
import com.android.server.display.feature.DisplayManagerFlags;
import com.android.server.display.layout.DisplayIdProducer;
import com.android.server.display.layout.Layout;
-import com.android.server.utils.FoldSettingWrapper;
+import com.android.server.utils.FoldSettingProvider;
import org.junit.Before;
import org.junit.Test;
@@ -93,6 +98,7 @@ public class LogicalDisplayMapperTest {
private static int sUniqueTestDisplayId = 0;
private static final int DEVICE_STATE_CLOSED = 0;
private static final int DEVICE_STATE_OPEN = 2;
+ private static final int FLAG_GO_TO_SLEEP_ON_FOLD = 0;
private static int sNextNonDefaultDisplayId = DEFAULT_DISPLAY + 1;
private static final File NON_EXISTING_FILE = new File("/non_existing_folder/should_not_exist");
@@ -107,7 +113,7 @@ public class LogicalDisplayMapperTest {
@Mock LogicalDisplayMapper.Listener mListenerMock;
@Mock Context mContextMock;
- @Mock FoldSettingWrapper mFoldSettingWrapperMock;
+ @Mock FoldSettingProvider mFoldSettingProviderMock;
@Mock Resources mResourcesMock;
@Mock IPowerManager mIPowerManagerMock;
@Mock IThermalService mIThermalServiceMock;
@@ -120,7 +126,7 @@ public class LogicalDisplayMapperTest {
@Captor ArgumentCaptor<Integer> mDisplayEventCaptor;
@Before
- public void setUp() {
+ public void setUp() throws RemoteException {
// Share classloader to allow package private access.
System.setProperty("dexmaker.share_classloader", "true");
MockitoAnnotations.initMocks(this);
@@ -150,7 +156,9 @@ public class LogicalDisplayMapperTest {
when(mContextMock.getSystemServiceName(PowerManager.class))
.thenReturn(Context.POWER_SERVICE);
- when(mFoldSettingWrapperMock.shouldStayAwakeOnFold()).thenReturn(false);
+ when(mFoldSettingProviderMock.shouldStayAwakeOnFold()).thenReturn(false);
+ when(mFoldSettingProviderMock.shouldSleepOnFold()).thenReturn(false);
+ when(mIPowerManagerMock.isInteractive()).thenReturn(true);
when(mContextMock.getSystemService(PowerManager.class)).thenReturn(mPowerManager);
when(mContextMock.getResources()).thenReturn(mResourcesMock);
when(mResourcesMock.getBoolean(
@@ -166,9 +174,10 @@ public class LogicalDisplayMapperTest {
when(mFlagsMock.isConnectedDisplayManagementEnabled()).thenReturn(false);
mLooper = new TestLooper();
mHandler = new Handler(mLooper.getLooper());
- mLogicalDisplayMapper = new LogicalDisplayMapper(mContextMock, mDisplayDeviceRepo,
+ mLogicalDisplayMapper = new LogicalDisplayMapper(mContextMock, mFoldSettingProviderMock,
+ mDisplayDeviceRepo,
mListenerMock, new DisplayManagerService.SyncRoot(), mHandler,
- mDeviceStateToLayoutMapSpy, mFoldSettingWrapperMock, mFlagsMock);
+ mDeviceStateToLayoutMapSpy, mFlagsMock);
}
@@ -645,8 +654,8 @@ public class LogicalDisplayMapperTest {
}
@Test
- public void testDeviceShouldNotSleepWhenFoldSettingTrue() {
- when(mFoldSettingWrapperMock.shouldStayAwakeOnFold()).thenReturn(true);
+ public void testDeviceShouldNotSleepWhenStayAwakeSettingTrue() {
+ when(mFoldSettingProviderMock.shouldStayAwakeOnFold()).thenReturn(true);
assertFalse(mLogicalDisplayMapper.shouldDeviceBePutToSleep(DEVICE_STATE_CLOSED,
DEVICE_STATE_OPEN,
@@ -679,6 +688,26 @@ public class LogicalDisplayMapperTest {
}
@Test
+ public void testDeviceShouldPutToSleepWhenSleepSettingTrue() throws RemoteException {
+ when(mFoldSettingProviderMock.shouldSleepOnFold()).thenReturn(true);
+
+ finishBootAndFoldDevice();
+
+ verify(mIPowerManagerMock, atLeastOnce()).goToSleep(anyLong(), anyInt(),
+ eq(FLAG_GO_TO_SLEEP_ON_FOLD));
+ }
+
+ @Test
+ public void testDeviceShouldNotBePutToSleepWhenSleepSettingFalse() throws RemoteException {
+ when(mFoldSettingProviderMock.shouldSleepOnFold()).thenReturn(false);
+
+ finishBootAndFoldDevice();
+
+ verify(mIPowerManagerMock, never()).goToSleep(anyLong(), anyInt(),
+ eq(FLAG_GO_TO_SLEEP_ON_FOLD));
+ }
+
+ @Test
public void testDeviceStateLocked() {
DisplayDevice device1 = createDisplayDevice(TYPE_INTERNAL, 600, 800,
FLAG_ALLOWED_TO_BE_DEFAULT_DISPLAY);
@@ -930,6 +959,15 @@ public class LogicalDisplayMapperTest {
// Helper Methods
/////////////////
+ private void finishBootAndFoldDevice() {
+ mLogicalDisplayMapper.setDeviceStateLocked(DEVICE_STATE_OPEN, false);
+ advanceTime(1000);
+ mLogicalDisplayMapper.onBootCompleted();
+ advanceTime(1000);
+ mLogicalDisplayMapper.setDeviceStateLocked(DEVICE_STATE_CLOSED, false);
+ advanceTime(1000);
+ }
+
private void createDefaultDisplay(Layout layout, DisplayDevice device) {
createDefaultDisplay(layout, info(device).address);
}
diff --git a/services/tests/mockingservicestests/src/com/android/server/display/SmallAreaDetectionControllerTest.java b/services/tests/mockingservicestests/src/com/android/server/display/SmallAreaDetectionControllerTest.java
new file mode 100644
index 000000000000..1ce79a5b596b
--- /dev/null
+++ b/services/tests/mockingservicestests/src/com/android/server/display/SmallAreaDetectionControllerTest.java
@@ -0,0 +1,138 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.display;
+
+import static android.os.Process.INVALID_UID;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.content.ContextWrapper;
+import android.content.pm.PackageManagerInternal;
+import android.provider.DeviceConfigInterface;
+
+import androidx.test.core.app.ApplicationProvider;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import com.android.server.LocalServices;
+import com.android.server.pm.UserManagerInternal;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoRule;
+
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class SmallAreaDetectionControllerTest {
+
+ @Rule
+ public MockitoRule mRule = MockitoJUnit.rule();
+
+ @Mock
+ private PackageManagerInternal mMockPackageManagerInternal;
+ @Mock
+ private UserManagerInternal mMockUserManagerInternal;
+
+ private SmallAreaDetectionController mSmallAreaDetectionController;
+
+ private static final String PKG_A = "com.a.b.c";
+ private static final String PKG_B = "com.d.e.f";
+ private static final String PKG_NOT_INSTALLED = "com.not.installed";
+ private static final float THRESHOLD_A = 0.05f;
+ private static final float THRESHOLD_B = 0.07f;
+ private static final int USER_1 = 110;
+ private static final int USER_2 = 111;
+ private static final int UID_A_1 = 11011111;
+ private static final int UID_A_2 = 11111111;
+ private static final int UID_B_1 = 11022222;
+ private static final int UID_B_2 = 11122222;
+
+ @Before
+ public void setup() {
+ LocalServices.removeServiceForTest(PackageManagerInternal.class);
+ LocalServices.addService(PackageManagerInternal.class, mMockPackageManagerInternal);
+ LocalServices.removeServiceForTest(UserManagerInternal.class);
+ LocalServices.addService(UserManagerInternal.class, mMockUserManagerInternal);
+
+ when(mMockUserManagerInternal.getUserIds()).thenReturn(new int[]{USER_1, USER_2});
+ when(mMockPackageManagerInternal.getPackageUid(PKG_A, 0, USER_1)).thenReturn(UID_A_1);
+ when(mMockPackageManagerInternal.getPackageUid(PKG_A, 0, USER_2)).thenReturn(UID_A_2);
+ when(mMockPackageManagerInternal.getPackageUid(PKG_B, 0, USER_1)).thenReturn(UID_B_1);
+ when(mMockPackageManagerInternal.getPackageUid(PKG_B, 0, USER_2)).thenReturn(UID_B_2);
+ when(mMockPackageManagerInternal.getPackageUid(PKG_NOT_INSTALLED, 0, USER_1)).thenReturn(
+ INVALID_UID);
+ when(mMockPackageManagerInternal.getPackageUid(PKG_NOT_INSTALLED, 0, USER_2)).thenReturn(
+ INVALID_UID);
+
+ mSmallAreaDetectionController = spy(new SmallAreaDetectionController(
+ new ContextWrapper(ApplicationProvider.getApplicationContext()),
+ DeviceConfigInterface.REAL));
+ doNothing().when(mSmallAreaDetectionController).updateSmallAreaDetection(any(), any());
+ }
+
+ @Test
+ public void testUpdateAllowlist_validProperty() {
+ final String property = PKG_A + ":" + THRESHOLD_A + "," + PKG_B + ":" + THRESHOLD_B;
+ mSmallAreaDetectionController.updateAllowlist(property);
+
+ final int[] resultUidArray = {UID_A_1, UID_B_1, UID_A_2, UID_B_2};
+ final float[] resultThresholdArray = {THRESHOLD_A, THRESHOLD_B, THRESHOLD_A, THRESHOLD_B};
+ verify(mSmallAreaDetectionController).updateSmallAreaDetection(eq(resultUidArray),
+ eq(resultThresholdArray));
+ }
+
+ @Test
+ public void testUpdateAllowlist_includeInvalidRow() {
+ final String property = PKG_A + "," + PKG_B + ":" + THRESHOLD_B;
+ mSmallAreaDetectionController.updateAllowlist(property);
+
+ final int[] resultUidArray = {UID_B_1, UID_B_2};
+ final float[] resultThresholdArray = {THRESHOLD_B, THRESHOLD_B};
+ verify(mSmallAreaDetectionController).updateSmallAreaDetection(eq(resultUidArray),
+ eq(resultThresholdArray));
+ }
+
+ @Test
+ public void testUpdateAllowlist_includeNotInstalledPkg() {
+ final String property =
+ PKG_A + ":" + THRESHOLD_A + "," + PKG_NOT_INSTALLED + ":" + THRESHOLD_B;
+ mSmallAreaDetectionController.updateAllowlist(property);
+
+ final int[] resultUidArray = {UID_A_1, UID_A_2};
+ final float[] resultThresholdArray = {THRESHOLD_A, THRESHOLD_A};
+ verify(mSmallAreaDetectionController).updateSmallAreaDetection(eq(resultUidArray),
+ eq(resultThresholdArray));
+ }
+
+ @Test
+ public void testUpdateAllowlist_invalidProperty() {
+ final String property = PKG_A;
+ mSmallAreaDetectionController.updateAllowlist(property);
+
+ verify(mSmallAreaDetectionController, never()).updateSmallAreaDetection(any(), any());
+ }
+}
diff --git a/services/tests/mockingservicestests/src/com/android/server/pm/PackageArchiverServiceTest.java b/services/tests/mockingservicestests/src/com/android/server/pm/PackageArchiverServiceTest.java
index c7e1bda2e1b8..80576a688fdd 100644
--- a/services/tests/mockingservicestests/src/com/android/server/pm/PackageArchiverServiceTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/pm/PackageArchiverServiceTest.java
@@ -16,41 +16,49 @@
package com.android.server.pm;
+import static android.content.Intent.FLAG_RECEIVER_FOREGROUND;
import static android.content.pm.PackageManager.DELETE_KEEP_DATA;
-
import static com.google.common.truth.Truth.assertThat;
-
import static org.junit.Assert.assertThrows;
+import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.ArgumentMatchers.isNull;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
+import android.app.AppOpsManager;
import android.content.Context;
+import android.content.Intent;
import android.content.IntentSender;
import android.content.pm.LauncherActivityInfo;
import android.content.pm.LauncherApps;
+import android.content.pm.PackageArchiver;
import android.content.pm.PackageManager;
import android.content.pm.VersionedPackage;
import android.os.Binder;
import android.os.Build;
+import android.os.Bundle;
import android.os.ParcelableException;
import android.os.UserHandle;
import android.platform.test.annotations.Presubmit;
+import android.text.TextUtils;
import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;
import com.android.server.pm.pkg.ArchiveState;
import com.android.server.pm.pkg.PackageStateInternal;
+import com.android.server.pm.pkg.PackageUserStateImpl;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
@@ -64,7 +72,8 @@ import java.util.List;
public class PackageArchiverServiceTest {
private static final String PACKAGE = "com.example";
- private static final String CALLER_PACKAGE = "com.vending";
+ private static final String CALLER_PACKAGE = "com.caller";
+ private static final String INSTALLER_PACKAGE = "com.installer";
@Rule
public final MockSystemRule mMockSystem = new MockSystemRule();
@@ -84,11 +93,11 @@ public class PackageArchiverServiceTest {
private final InstallSource mInstallSource =
InstallSource.create(
- CALLER_PACKAGE,
- CALLER_PACKAGE,
- CALLER_PACKAGE,
+ INSTALLER_PACKAGE,
+ INSTALLER_PACKAGE,
+ INSTALLER_PACKAGE,
Binder.getCallingUid(),
- CALLER_PACKAGE,
+ INSTALLER_PACKAGE,
/* installerAttributionTag= */ null,
/* packageSource= */ 0);
@@ -96,6 +105,8 @@ public class PackageArchiverServiceTest {
private final int mUserId = UserHandle.CURRENT.getIdentifier();
+ private PackageUserStateImpl mUserState;
+
private PackageSetting mPackageSetting;
private PackageArchiverService mArchiveService;
@@ -116,11 +127,16 @@ public class PackageArchiverServiceTest {
when(mComputer.getPackageStateFiltered(eq(PACKAGE), anyInt(), anyInt())).thenReturn(
mPackageState);
+ when(mComputer.getPackageStateFiltered(eq(INSTALLER_PACKAGE), anyInt(),
+ anyInt())).thenReturn(mock(PackageStateInternal.class));
when(mPackageState.getPackageName()).thenReturn(PACKAGE);
when(mPackageState.getInstallSource()).thenReturn(mInstallSource);
mPackageSetting = createBasicPackageSetting();
when(mMockSystem.mocks().getSettings().getPackageLPr(eq(PACKAGE))).thenReturn(
mPackageSetting);
+ mUserState = new PackageUserStateImpl().setInstalled(true);
+ mPackageSetting.setUserState(mUserId, mUserState);
+ when(mPackageState.getUserStateOrDefault(eq(mUserId))).thenReturn(mUserState);
when(mContext.getSystemService(LauncherApps.class)).thenReturn(mLauncherApps);
when(mLauncherApps.getActivityList(eq(PACKAGE), eq(UserHandle.CURRENT))).thenReturn(
mLauncherActivityInfos);
@@ -135,9 +151,7 @@ public class PackageArchiverServiceTest {
Exception e = assertThrows(
SecurityException.class,
() -> mArchiveService.requestArchive(PACKAGE, "different", mIntentSender,
- UserHandle.CURRENT
- )
- );
+ UserHandle.CURRENT));
assertThat(e).hasMessageThat().isEqualTo(
String.format(
"The UID %s of callerPackageName set by the caller doesn't match the "
@@ -154,9 +168,7 @@ public class PackageArchiverServiceTest {
Exception e = assertThrows(
ParcelableException.class,
() -> mArchiveService.requestArchive(PACKAGE, CALLER_PACKAGE, mIntentSender,
- UserHandle.CURRENT
- )
- );
+ UserHandle.CURRENT));
assertThat(e.getCause()).isInstanceOf(PackageManager.NameNotFoundException.class);
assertThat(e.getCause()).hasMessageThat().isEqualTo(
String.format("Package %s not found.", PACKAGE));
@@ -169,9 +181,7 @@ public class PackageArchiverServiceTest {
Exception e = assertThrows(
ParcelableException.class,
() -> mArchiveService.requestArchive(PACKAGE, CALLER_PACKAGE, mIntentSender,
- UserHandle.CURRENT
- )
- );
+ UserHandle.CURRENT));
assertThat(e.getCause()).isInstanceOf(PackageManager.NameNotFoundException.class);
assertThat(e.getCause()).hasMessageThat().isEqualTo(
String.format("Package %s not found.", PACKAGE));
@@ -193,25 +203,27 @@ public class PackageArchiverServiceTest {
Exception e = assertThrows(
ParcelableException.class,
() -> mArchiveService.requestArchive(PACKAGE, CALLER_PACKAGE, mIntentSender,
- UserHandle.CURRENT
- )
- );
+ UserHandle.CURRENT));
+ assertThat(e.getCause()).isInstanceOf(PackageManager.NameNotFoundException.class);
+ assertThat(e.getCause()).hasMessageThat().isEqualTo("No installer found");
+ }
+
+ @Test
+ public void archiveApp_noMainActivities() {
+ when(mLauncherApps.getActivityList(eq(PACKAGE), eq(UserHandle.CURRENT))).thenReturn(
+ List.of());
+
+ Exception e = assertThrows(
+ ParcelableException.class,
+ () -> mArchiveService.requestArchive(PACKAGE, CALLER_PACKAGE, mIntentSender,
+ UserHandle.CURRENT));
assertThat(e.getCause()).isInstanceOf(PackageManager.NameNotFoundException.class);
assertThat(e.getCause()).hasMessageThat().isEqualTo(
- String.format("No installer found to archive app %s.", PACKAGE));
+ TextUtils.formatSimple("The app %s does not have a main activity.", PACKAGE));
}
@Test
public void archiveApp_success() {
- List<ArchiveState.ArchiveActivityInfo> activityInfos = new ArrayList<>();
- for (LauncherActivityInfo mainActivity : createLauncherActivities()) {
- // TODO(b/278553670) Extract and store launcher icons
- ArchiveState.ArchiveActivityInfo activityInfo = new ArchiveState.ArchiveActivityInfo(
- mainActivity.getLabel().toString(),
- Path.of("/TODO"), null);
- activityInfos.add(activityInfo);
- }
-
mArchiveService.requestArchive(PACKAGE, CALLER_PACKAGE, mIntentSender, UserHandle.CURRENT);
verify(mInstallerService).uninstall(
@@ -220,7 +232,112 @@ public class PackageArchiverServiceTest {
eq(UserHandle.CURRENT.getIdentifier()));
assertThat(mPackageSetting.readUserState(
UserHandle.CURRENT.getIdentifier()).getArchiveState()).isEqualTo(
- new ArchiveState(activityInfos, CALLER_PACKAGE));
+ createArchiveState());
+ }
+
+ @Test
+ public void unarchiveApp_callerPackageNameIncorrect() {
+ mUserState.setArchiveState(createArchiveState()).setInstalled(false);
+
+ Exception e = assertThrows(
+ SecurityException.class,
+ () -> mArchiveService.requestUnarchive(PACKAGE, "different",
+ UserHandle.CURRENT));
+ assertThat(e).hasMessageThat().isEqualTo(
+ String.format(
+ "The UID %s of callerPackageName set by the caller doesn't match the "
+ + "caller's actual UID %s.",
+ 0,
+ Binder.getCallingUid()));
+ }
+
+ @Test
+ public void unarchiveApp_packageNotInstalled() {
+ mUserState.setArchiveState(createArchiveState()).setInstalled(false);
+ when(mComputer.getPackageStateFiltered(eq(PACKAGE), anyInt(), anyInt())).thenReturn(
+ null);
+
+ Exception e = assertThrows(
+ ParcelableException.class,
+ () -> mArchiveService.requestUnarchive(PACKAGE, CALLER_PACKAGE,
+ UserHandle.CURRENT));
+ assertThat(e.getCause()).isInstanceOf(PackageManager.NameNotFoundException.class);
+ assertThat(e.getCause()).hasMessageThat().isEqualTo(
+ String.format("Package %s not found.", PACKAGE));
+ }
+
+ @Test
+ public void unarchiveApp_notArchived() {
+ Exception e = assertThrows(
+ ParcelableException.class,
+ () -> mArchiveService.requestUnarchive(PACKAGE, CALLER_PACKAGE,
+ UserHandle.CURRENT));
+ assertThat(e.getCause()).isInstanceOf(PackageManager.NameNotFoundException.class);
+ assertThat(e.getCause()).hasMessageThat().isEqualTo(
+ String.format("Package %s is not currently archived.", PACKAGE));
+ }
+
+ @Test
+ public void unarchiveApp_noInstallerFound() {
+ mUserState.setArchiveState(createArchiveState());
+ InstallSource otherInstallSource =
+ InstallSource.create(
+ CALLER_PACKAGE,
+ CALLER_PACKAGE,
+ /* installerPackageName= */ null,
+ Binder.getCallingUid(),
+ /* updateOwnerPackageName= */ null,
+ /* installerAttributionTag= */ null,
+ /* packageSource= */ 0);
+ when(mPackageState.getInstallSource()).thenReturn(otherInstallSource);
+
+ Exception e = assertThrows(
+ ParcelableException.class,
+ () -> mArchiveService.requestUnarchive(PACKAGE, CALLER_PACKAGE,
+ UserHandle.CURRENT));
+ assertThat(e.getCause()).isInstanceOf(PackageManager.NameNotFoundException.class);
+ assertThat(e.getCause()).hasMessageThat().isEqualTo(
+ String.format("No installer found to unarchive app %s.", PACKAGE));
+ }
+
+ @Test
+ public void unarchiveApp_success() {
+ mUserState.setArchiveState(createArchiveState()).setInstalled(false);
+
+ mArchiveService.requestUnarchive(PACKAGE, CALLER_PACKAGE, UserHandle.CURRENT);
+ mMockSystem.mocks().getHandler().flush();
+
+ ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class);
+ verify(mContext).sendOrderedBroadcastAsUser(
+ intentCaptor.capture(),
+ eq(UserHandle.CURRENT),
+ /* receiverPermission = */ isNull(),
+ eq(AppOpsManager.OP_NONE),
+ any(Bundle.class),
+ /* resultReceiver= */ isNull(),
+ /* scheduler= */ isNull(),
+ /* initialCode= */ eq(0),
+ /* initialData= */ isNull(),
+ /* initialExtras= */ isNull());
+ Intent intent = intentCaptor.getValue();
+ assertThat(intent.getFlags() & FLAG_RECEIVER_FOREGROUND).isNotEqualTo(0);
+ assertThat(intent.getStringExtra(PackageArchiver.EXTRA_UNARCHIVE_PACKAGE_NAME)).isEqualTo(
+ PACKAGE);
+ assertThat(
+ intent.getBooleanExtra(PackageArchiver.EXTRA_UNARCHIVE_ALL_USERS, true)).isFalse();
+ assertThat(intent.getPackage()).isEqualTo(INSTALLER_PACKAGE);
+ }
+
+ private static ArchiveState createArchiveState() {
+ List<ArchiveState.ArchiveActivityInfo> activityInfos = new ArrayList<>();
+ for (LauncherActivityInfo mainActivity : createLauncherActivities()) {
+ // TODO(b/278553670) Extract and store launcher icons
+ ArchiveState.ArchiveActivityInfo activityInfo = new ArchiveState.ArchiveActivityInfo(
+ mainActivity.getLabel().toString(),
+ Path.of("/TODO"), null);
+ activityInfos.add(activityInfo);
+ }
+ return new ArchiveState(activityInfos, INSTALLER_PACKAGE);
}
private static List<LauncherActivityInfo> createLauncherActivities() {
diff --git a/services/tests/mockingservicestests/src/com/android/server/utils/FoldSettingProviderTest.java b/services/tests/mockingservicestests/src/com/android/server/utils/FoldSettingProviderTest.java
new file mode 100644
index 000000000000..3514276ccb5b
--- /dev/null
+++ b/services/tests/mockingservicestests/src/com/android/server/utils/FoldSettingProviderTest.java
@@ -0,0 +1,143 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.utils;
+
+import static com.android.server.utils.FoldSettingProvider.SETTING_VALUE_SLEEP_ON_FOLD;
+import static com.android.server.utils.FoldSettingProvider.SETTING_VALUE_STAY_AWAKE_ON_FOLD;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.when;
+
+import android.content.ContentResolver;
+import android.content.Context;
+import android.content.res.Resources;
+import android.os.UserHandle;
+import android.provider.Settings;
+
+import androidx.test.platform.app.InstrumentationRegistry;
+
+import com.android.internal.R;
+import com.android.internal.util.SettingsWrapper;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+public class FoldSettingProviderTest {
+
+ private static final String SETTING_VALUE_INVALID = "invalid_fold_lock_behavior";
+
+ @Mock
+ private Context mContext;
+ @Mock
+ private Resources mResources;
+ @Mock
+ private SettingsWrapper mSettingsWrapper;
+ private ContentResolver mContentResolver;
+ private FoldSettingProvider mFoldSettingProvider;
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+
+ mContentResolver =
+ InstrumentationRegistry.getInstrumentation().getContext().getContentResolver();
+ when(mContext.getContentResolver()).thenReturn(mContentResolver);
+ when(mContext.getResources()).thenReturn(mResources);
+ setFoldLockBehaviorAvailability(true);
+
+ mFoldSettingProvider = new FoldSettingProvider(mContext, mSettingsWrapper);
+ }
+
+ @Test
+ public void foldSettingNotAvailable_returnDefaultSetting() {
+ setFoldLockBehaviorAvailability(false);
+ setFoldLockBehaviorSettingValue(SETTING_VALUE_STAY_AWAKE_ON_FOLD);
+ mFoldSettingProvider = new FoldSettingProvider(mContext, mSettingsWrapper);
+
+ boolean shouldSelectiveStayAwakeOnFold =
+ mFoldSettingProvider.shouldSelectiveStayAwakeOnFold();
+
+ assertThat(shouldSelectiveStayAwakeOnFold).isTrue();
+ }
+
+ @Test
+ public void foldSettingNotAvailable_notReturnStayAwakeOnFoldTrue() {
+ setFoldLockBehaviorAvailability(false);
+ setFoldLockBehaviorSettingValue(SETTING_VALUE_STAY_AWAKE_ON_FOLD);
+ mFoldSettingProvider = new FoldSettingProvider(mContext, mSettingsWrapper);
+
+ boolean shouldStayAwakeOnFold = mFoldSettingProvider.shouldStayAwakeOnFold();
+
+ assertThat(shouldStayAwakeOnFold).isFalse();
+ }
+
+ @Test
+ public void foldSettingNotAvailable_notReturnSleepOnFoldTrue() {
+ setFoldLockBehaviorAvailability(false);
+ setFoldLockBehaviorSettingValue(SETTING_VALUE_SLEEP_ON_FOLD);
+ mFoldSettingProvider = new FoldSettingProvider(mContext, mSettingsWrapper);
+
+ boolean shouldSleepOnFold = mFoldSettingProvider.shouldSleepOnFold();
+
+ assertThat(shouldSleepOnFold).isFalse();
+ }
+
+ @Test
+ public void foldSettingAvailable_returnCorrectFoldSetting() {
+ setFoldLockBehaviorSettingValue(SETTING_VALUE_STAY_AWAKE_ON_FOLD);
+
+ boolean shouldStayAwakeOnFold = mFoldSettingProvider.shouldStayAwakeOnFold();
+
+ assertThat(shouldStayAwakeOnFold).isTrue();
+ }
+
+ @Test
+ public void foldSettingInvalid_returnDefaultSetting() {
+ setFoldLockBehaviorSettingValue(SETTING_VALUE_INVALID);
+
+ boolean shouldSelectiveStayAwakeOnFold =
+ mFoldSettingProvider.shouldSelectiveStayAwakeOnFold();
+
+ assertThat(shouldSelectiveStayAwakeOnFold).isTrue();
+ }
+
+ @Test
+ public void foldSettingNotDefined_returnDefaultSetting() {
+ setFoldLockBehaviorSettingValue(null);
+
+ boolean shouldSelectiveStayAwakeOnFold =
+ mFoldSettingProvider.shouldSelectiveStayAwakeOnFold();
+
+ assertThat(shouldSelectiveStayAwakeOnFold).isTrue();
+ }
+
+ private void setFoldLockBehaviorAvailability(boolean isFoldLockBehaviorEnabled) {
+ when(mResources.getBoolean(R.bool.config_fold_lock_behavior)).thenReturn(
+ isFoldLockBehaviorEnabled);
+ }
+
+ private void setFoldLockBehaviorSettingValue(String foldLockBehaviorSettingValue) {
+ when(mSettingsWrapper.getStringForUser(any(),
+ eq(Settings.System.FOLD_LOCK_BEHAVIOR),
+ eq(UserHandle.USER_CURRENT))).thenReturn(foldLockBehaviorSettingValue);
+ }
+}
diff --git a/services/tests/powerstatstests/src/com/android/server/power/stats/BatteryUsageStatsRule.java b/services/tests/powerstatstests/src/com/android/server/power/stats/BatteryUsageStatsRule.java
index 534aa89e1699..93cbea6125fa 100644
--- a/services/tests/powerstatstests/src/com/android/server/power/stats/BatteryUsageStatsRule.java
+++ b/services/tests/powerstatstests/src/com/android/server/power/stats/BatteryUsageStatsRule.java
@@ -243,8 +243,10 @@ public class BatteryUsageStatsRule implements TestRule {
& BatteryUsageStatsQuery.FLAG_BATTERY_USAGE_STATS_INCLUDE_POWER_MODELS) != 0;
final boolean includeProcessStateData = (query.getFlags()
& BatteryUsageStatsQuery.FLAG_BATTERY_USAGE_STATS_INCLUDE_PROCESS_STATE_DATA) != 0;
+ final double minConsumedPowerThreshold = query.getMinConsumedPowerThreshold();
BatteryUsageStats.Builder builder = new BatteryUsageStats.Builder(
- customPowerComponentNames, includePowerModels, includeProcessStateData);
+ customPowerComponentNames, includePowerModels, includeProcessStateData,
+ minConsumedPowerThreshold);
SparseArray<? extends BatteryStats.Uid> uidStats = mBatteryStats.getUidStats();
for (int i = 0; i < uidStats.size(); i++) {
builder.getOrCreateUidBatteryConsumerBuilder(uidStats.valueAt(i));
diff --git a/services/tests/powerstatstests/src/com/android/server/power/stats/BatteryUsageStatsTest.java b/services/tests/powerstatstests/src/com/android/server/power/stats/BatteryUsageStatsTest.java
index 266a22632a6d..07c486c6ce58 100644
--- a/services/tests/powerstatstests/src/com/android/server/power/stats/BatteryUsageStatsTest.java
+++ b/services/tests/powerstatstests/src/com/android/server/power/stats/BatteryUsageStatsTest.java
@@ -181,7 +181,7 @@ public class BatteryUsageStatsTest {
final BatteryUsageStats stats2 = buildBatteryUsageStats2(new String[]{"FOO"}, true).build();
final BatteryUsageStats sum =
- new BatteryUsageStats.Builder(new String[]{"FOO"}, true, true)
+ new BatteryUsageStats.Builder(new String[]{"FOO"}, true, true, 0)
.add(stats1)
.add(stats2)
.build();
@@ -222,7 +222,7 @@ public class BatteryUsageStatsTest {
@Test
public void testAdd_customComponentMismatch() {
final BatteryUsageStats.Builder builder =
- new BatteryUsageStats.Builder(new String[]{"FOO"}, true, true);
+ new BatteryUsageStats.Builder(new String[]{"FOO"}, true, true, 0);
final BatteryUsageStats stats = buildBatteryUsageStats2(new String[]{"BAR"}, false).build();
assertThrows(IllegalArgumentException.class, () -> builder.add(stats));
@@ -231,7 +231,7 @@ public class BatteryUsageStatsTest {
@Test
public void testAdd_processStateDataMismatch() {
final BatteryUsageStats.Builder builder =
- new BatteryUsageStats.Builder(new String[]{"FOO"}, true, true);
+ new BatteryUsageStats.Builder(new String[]{"FOO"}, true, true, 0);
final BatteryUsageStats stats = buildBatteryUsageStats2(new String[]{"FOO"}, false).build();
assertThrows(IllegalArgumentException.class, () -> builder.add(stats));
@@ -260,7 +260,7 @@ public class BatteryUsageStatsTest {
final MockBatteryStatsImpl batteryStats = new MockBatteryStatsImpl(clocks);
final BatteryUsageStats.Builder builder =
- new BatteryUsageStats.Builder(new String[]{"FOO"}, true, true)
+ new BatteryUsageStats.Builder(new String[]{"FOO"}, true, true, 0)
.setBatteryCapacity(4000)
.setDischargePercentage(20)
.setDischargedPowerRange(1000, 2000)
@@ -305,7 +305,7 @@ public class BatteryUsageStatsTest {
final BatteryUsageStats.Builder builder =
new BatteryUsageStats.Builder(customPowerComponentNames, true,
- includeProcessStateData);
+ includeProcessStateData, 0);
builder.setDischargePercentage(30)
.setDischargedPowerRange(1234, 2345)
.setStatsStartTimestamp(2000)
diff --git a/services/tests/servicestests/assets/PolicyVersionUpgraderTest/device_policies_keep_profiles_running_false.xml b/services/tests/servicestests/assets/PolicyVersionUpgraderTest/device_policies_keep_profiles_running_false.xml
new file mode 100644
index 000000000000..4785a881638f
--- /dev/null
+++ b/services/tests/servicestests/assets/PolicyVersionUpgraderTest/device_policies_keep_profiles_running_false.xml
@@ -0,0 +1,10 @@
+<?xml version='1.0' encoding='utf-8' standalone='yes' ?>
+<policies setup-complete="true" provisioning-state="3">
+ <keep-profiles-running value="false" />
+ <admin name="com.android.frameworks.servicestests/com.android.server.devicepolicy.DummyDeviceAdmins$Admin1">
+ <policies flags="991" />
+ <strong-auth-unlock-timeout value="0" />
+ <organization-color value="-16738680" />
+ <active-password value="0" />
+ </admin>
+</policies>
diff --git a/services/tests/servicestests/assets/PolicyVersionUpgraderTest/device_policies_keep_profiles_running_true.xml b/services/tests/servicestests/assets/PolicyVersionUpgraderTest/device_policies_keep_profiles_running_true.xml
new file mode 100644
index 000000000000..07ec229fa267
--- /dev/null
+++ b/services/tests/servicestests/assets/PolicyVersionUpgraderTest/device_policies_keep_profiles_running_true.xml
@@ -0,0 +1,10 @@
+<?xml version='1.0' encoding='utf-8' standalone='yes' ?>
+<policies setup-complete="true" provisioning-state="3">
+ <keep-profiles-running value="true" />
+ <admin name="com.android.frameworks.servicestests/com.android.server.devicepolicy.DummyDeviceAdmins$Admin1">
+ <policies flags="991" />
+ <strong-auth-unlock-timeout value="0" />
+ <organization-color value="-16738680" />
+ <active-password value="0" />
+ </admin>
+</policies>
diff --git a/services/tests/servicestests/src/com/android/server/biometrics/AuthenticationStatsCollectorTest.java b/services/tests/servicestests/src/com/android/server/biometrics/AuthenticationStatsCollectorTest.java
index a621c0c01067..0b730f139f3e 100644
--- a/services/tests/servicestests/src/com/android/server/biometrics/AuthenticationStatsCollectorTest.java
+++ b/services/tests/servicestests/src/com/android/server/biometrics/AuthenticationStatsCollectorTest.java
@@ -21,6 +21,7 @@ import static com.android.server.biometrics.AuthenticationStatsCollector.MAXIMUM
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyFloat;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anySet;
import static org.mockito.ArgumentMatchers.anyString;
@@ -78,6 +79,8 @@ public class AuthenticationStatsCollectorTest {
@Mock
private SharedPreferences mSharedPreferences;
@Mock
+ private SharedPreferences.Editor mEditor;
+ @Mock
private BiometricNotification mBiometricNotification;
@Before
@@ -99,6 +102,8 @@ public class AuthenticationStatsCollectorTest {
when(mContext.getSharedPreferences(any(File.class), anyInt()))
.thenReturn(mSharedPreferences);
when(mSharedPreferences.getStringSet(anyString(), anySet())).thenReturn(emptySet());
+ when(mSharedPreferences.edit()).thenReturn(mEditor);
+ when(mEditor.putFloat(anyString(), anyFloat())).thenReturn(mEditor);
mAuthenticationStatsCollector = new AuthenticationStatsCollector(mContext,
0 /* modality */, mBiometricNotification);
diff --git a/services/tests/servicestests/src/com/android/server/biometrics/AuthenticationStatsPersisterTest.java b/services/tests/servicestests/src/com/android/server/biometrics/AuthenticationStatsPersisterTest.java
index 0c0d47a6b165..32c55ebcb674 100644
--- a/services/tests/servicestests/src/com/android/server/biometrics/AuthenticationStatsPersisterTest.java
+++ b/services/tests/servicestests/src/com/android/server/biometrics/AuthenticationStatsPersisterTest.java
@@ -19,6 +19,7 @@ package com.android.server.biometrics;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyFloat;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anySet;
import static org.mockito.ArgumentMatchers.anyString;
@@ -63,6 +64,8 @@ public class AuthenticationStatsPersisterTest {
private static final String FINGERPRINT_REJECTIONS = "fingerprint_rejections";
private static final String ENROLLMENT_NOTIFICATIONS = "enrollment_notifications";
private static final String KEY = "frr_stats";
+ private static final String THRESHOLD_KEY = "frr_threshold";
+ private static final float FRR_THRESHOLD = 0.25f;
@Mock
private Context mContext;
@@ -74,6 +77,8 @@ public class AuthenticationStatsPersisterTest {
@Captor
private ArgumentCaptor<Set<String>> mStringSetArgumentCaptor;
+ @Captor
+ private ArgumentCaptor<Float> mFrrThresholdArgumentCaptor;
@Before
public void setUp() {
@@ -81,6 +86,7 @@ public class AuthenticationStatsPersisterTest {
.thenReturn(mSharedPreferences);
when(mSharedPreferences.edit()).thenReturn(mEditor);
when(mEditor.putStringSet(anyString(), anySet())).thenReturn(mEditor);
+ when(mEditor.putFloat(anyString(), anyFloat())).thenReturn(mEditor);
mAuthenticationStatsPersister = new AuthenticationStatsPersister(mContext);
}
@@ -255,6 +261,14 @@ public class AuthenticationStatsPersisterTest {
assertThat(mStringSetArgumentCaptor.getValue()).doesNotContain(authenticationStats);
}
+ @Test
+ public void persistFrrThreshold_shouldUpdateRecord() {
+ mAuthenticationStatsPersister.persistFrrThreshold(FRR_THRESHOLD);
+
+ verify(mEditor).putFloat(eq(THRESHOLD_KEY), mFrrThresholdArgumentCaptor.capture());
+ assertThat(mFrrThresholdArgumentCaptor.getValue()).isWithin(0f).of(FRR_THRESHOLD);
+ }
+
private String buildFrrStats(AuthenticationStats authenticationStats)
throws JSONException {
if (authenticationStats.getModality() == BiometricsProtoEnums.MODALITY_FACE) {
diff --git a/services/tests/servicestests/src/com/android/server/companion/virtual/VirtualDeviceManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/companion/virtual/VirtualDeviceManagerServiceTest.java
index 00e35ecece8b..41af9e31dbdd 100644
--- a/services/tests/servicestests/src/com/android/server/companion/virtual/VirtualDeviceManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/companion/virtual/VirtualDeviceManagerServiceTest.java
@@ -129,7 +129,6 @@ import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
-import java.util.ArrayList;
import java.util.Arrays;
import java.util.Set;
import java.util.function.Consumer;
@@ -296,19 +295,20 @@ public class VirtualDeviceManagerServiceTest {
DISPLAY_ID_1);
doNothing().when(mContext).startActivityAsUser(any(), any(), any());
- ArrayList<ActivityInfo> activityInfos = getActivityInfoList(
+ ActivityInfo activityInfo = getActivityInfo(
NONBLOCKED_APP_PACKAGE_NAME,
NONBLOCKED_APP_PACKAGE_NAME,
/* displayOnRemoveDevices= */ true,
targetDisplayCategory);
Intent blockedAppIntent = BlockedAppStreamingActivity.createIntent(
- activityInfos.get(0), mAssociationInfo.getDisplayName());
- gwpc.canContainActivities(activityInfos, WindowConfiguration.WINDOWING_MODE_FULLSCREEN);
+ activityInfo, mAssociationInfo.getDisplayName());
+ gwpc.canActivityBeLaunched(activityInfo, blockedAppIntent,
+ WindowConfiguration.WINDOWING_MODE_FULLSCREEN, DISPLAY_ID_1, /*isNewTask=*/false);
return blockedAppIntent;
}
- private ArrayList<ActivityInfo> getActivityInfoList(
+ private ActivityInfo getActivityInfo(
String packageName, String name, boolean displayOnRemoveDevices,
String requiredDisplayCategory) {
ActivityInfo activityInfo = new ActivityInfo();
@@ -318,7 +318,7 @@ public class VirtualDeviceManagerServiceTest {
? FLAG_CAN_DISPLAY_ON_REMOTE_DEVICES : FLAG_CANNOT_DISPLAY_ON_REMOTE_DEVICES;
activityInfo.applicationInfo = mApplicationInfoMock;
activityInfo.requiredDisplayCategory = requiredDisplayCategory;
- return new ArrayList<>(Arrays.asList(activityInfo));
+ return activityInfo;
}
@Before
@@ -1414,14 +1414,15 @@ public class VirtualDeviceManagerServiceTest {
DISPLAY_ID_1);
doNothing().when(mContext).startActivityAsUser(any(), any(), any());
- ArrayList<ActivityInfo> activityInfos = getActivityInfoList(
+ ActivityInfo activityInfo = getActivityInfo(
NONBLOCKED_APP_PACKAGE_NAME,
NONBLOCKED_APP_PACKAGE_NAME,
/* displayOnRemoveDevices */ true,
/* targetDisplayCategory */ null);
Intent blockedAppIntent = BlockedAppStreamingActivity.createIntent(
- activityInfos.get(0), mAssociationInfo.getDisplayName());
- gwpc.canContainActivities(activityInfos, WindowConfiguration.WINDOWING_MODE_FULLSCREEN);
+ activityInfo, mAssociationInfo.getDisplayName());
+ gwpc.canActivityBeLaunched(activityInfo, blockedAppIntent,
+ WindowConfiguration.WINDOWING_MODE_FULLSCREEN, DISPLAY_ID_1, /*isNewTask=*/false);
verify(mContext, never()).startActivityAsUser(argThat(intent ->
intent.filterEquals(blockedAppIntent)), any(), any());
@@ -1434,14 +1435,15 @@ public class VirtualDeviceManagerServiceTest {
DISPLAY_ID_1);
doNothing().when(mContext).startActivityAsUser(any(), any(), any());
- ArrayList<ActivityInfo> activityInfos = getActivityInfoList(
+ ActivityInfo activityInfo = getActivityInfo(
PERMISSION_CONTROLLER_PACKAGE_NAME,
PERMISSION_CONTROLLER_PACKAGE_NAME,
/* displayOnRemoveDevices */ false,
/* targetDisplayCategory */ null);
Intent blockedAppIntent = BlockedAppStreamingActivity.createIntent(
- activityInfos.get(0), mAssociationInfo.getDisplayName());
- gwpc.canContainActivities(activityInfos, WindowConfiguration.WINDOWING_MODE_FULLSCREEN);
+ activityInfo, mAssociationInfo.getDisplayName());
+ gwpc.canActivityBeLaunched(activityInfo, blockedAppIntent,
+ WindowConfiguration.WINDOWING_MODE_FULLSCREEN, DISPLAY_ID_1, /*isNewTask=*/false);
verify(mContext).startActivityAsUser(argThat(intent ->
intent.filterEquals(blockedAppIntent)), any(), any());
@@ -1454,14 +1456,15 @@ public class VirtualDeviceManagerServiceTest {
DISPLAY_ID_1);
doNothing().when(mContext).startActivityAsUser(any(), any(), any());
- ArrayList<ActivityInfo> activityInfos = getActivityInfoList(
+ ActivityInfo activityInfo = getActivityInfo(
SETTINGS_PACKAGE_NAME,
SETTINGS_PACKAGE_NAME,
/* displayOnRemoveDevices */ true,
/* targetDisplayCategory */ null);
Intent blockedAppIntent = BlockedAppStreamingActivity.createIntent(
- activityInfos.get(0), mAssociationInfo.getDisplayName());
- gwpc.canContainActivities(activityInfos, WindowConfiguration.WINDOWING_MODE_FULLSCREEN);
+ activityInfo, mAssociationInfo.getDisplayName());
+ gwpc.canActivityBeLaunched(activityInfo, blockedAppIntent,
+ WindowConfiguration.WINDOWING_MODE_FULLSCREEN, DISPLAY_ID_1, /*isNewTask=*/false);
verify(mContext).startActivityAsUser(argThat(intent ->
intent.filterEquals(blockedAppIntent)), any(), any());
@@ -1474,14 +1477,15 @@ public class VirtualDeviceManagerServiceTest {
DISPLAY_ID_1);
doNothing().when(mContext).startActivityAsUser(any(), any(), any());
- ArrayList<ActivityInfo> activityInfos = getActivityInfoList(
+ ActivityInfo activityInfo = getActivityInfo(
VENDING_PACKAGE_NAME,
VENDING_PACKAGE_NAME,
/* displayOnRemoveDevices */ true,
/* targetDisplayCategory */ null);
Intent blockedAppIntent = BlockedAppStreamingActivity.createIntent(
- activityInfos.get(0), mAssociationInfo.getDisplayName());
- gwpc.canContainActivities(activityInfos, WindowConfiguration.WINDOWING_MODE_FULLSCREEN);
+ activityInfo, mAssociationInfo.getDisplayName());
+ gwpc.canActivityBeLaunched(activityInfo, blockedAppIntent,
+ WindowConfiguration.WINDOWING_MODE_FULLSCREEN, DISPLAY_ID_1, /*isNewTask=*/false);
verify(mContext).startActivityAsUser(argThat(intent ->
intent.filterEquals(blockedAppIntent)), any(), any());
@@ -1494,14 +1498,15 @@ public class VirtualDeviceManagerServiceTest {
DISPLAY_ID_1);
doNothing().when(mContext).startActivityAsUser(any(), any(), any());
- ArrayList<ActivityInfo> activityInfos = getActivityInfoList(
+ ActivityInfo activityInfo = getActivityInfo(
GOOGLE_DIALER_PACKAGE_NAME,
GOOGLE_DIALER_PACKAGE_NAME,
/* displayOnRemoveDevices */ true,
/* targetDisplayCategory */ null);
Intent blockedAppIntent = BlockedAppStreamingActivity.createIntent(
- activityInfos.get(0), mAssociationInfo.getDisplayName());
- gwpc.canContainActivities(activityInfos, WindowConfiguration.WINDOWING_MODE_FULLSCREEN);
+ activityInfo, mAssociationInfo.getDisplayName());
+ gwpc.canActivityBeLaunched(activityInfo, blockedAppIntent,
+ WindowConfiguration.WINDOWING_MODE_FULLSCREEN, DISPLAY_ID_1, /*isNewTask=*/false);
verify(mContext).startActivityAsUser(argThat(intent ->
intent.filterEquals(blockedAppIntent)), any(), any());
@@ -1514,14 +1519,15 @@ public class VirtualDeviceManagerServiceTest {
DISPLAY_ID_1);
doNothing().when(mContext).startActivityAsUser(any(), any(), any());
- ArrayList<ActivityInfo> activityInfos = getActivityInfoList(
+ ActivityInfo activityInfo = getActivityInfo(
GOOGLE_MAPS_PACKAGE_NAME,
GOOGLE_MAPS_PACKAGE_NAME,
/* displayOnRemoveDevices */ true,
/* targetDisplayCategory */ null);
Intent blockedAppIntent = BlockedAppStreamingActivity.createIntent(
- activityInfos.get(0), mAssociationInfo.getDisplayName());
- gwpc.canContainActivities(activityInfos, WindowConfiguration.WINDOWING_MODE_FULLSCREEN);
+ activityInfo, mAssociationInfo.getDisplayName());
+ gwpc.canActivityBeLaunched(activityInfo, blockedAppIntent,
+ WindowConfiguration.WINDOWING_MODE_FULLSCREEN, DISPLAY_ID_1, /*isNewTask=*/false);
verify(mContext).startActivityAsUser(argThat(intent ->
intent.filterEquals(blockedAppIntent)), any(), any());
@@ -1561,12 +1567,12 @@ public class VirtualDeviceManagerServiceTest {
addVirtualDisplay(mDeviceImpl, DISPLAY_ID_1);
GenericWindowPolicyController gwpc = mDeviceImpl.getDisplayWindowPolicyControllerForTest(
DISPLAY_ID_1);
- ArrayList<ActivityInfo> activityInfos = getActivityInfoList(
+ ActivityInfo activityInfo = getActivityInfo(
NONBLOCKED_APP_PACKAGE_NAME,
NONBLOCKED_APP_PACKAGE_NAME,
/* displayOnRemoveDevices */ true,
/* targetDisplayCategory */ null);
- assertThat(gwpc.canActivityBeLaunched(activityInfos.get(0), intent,
+ assertThat(gwpc.canActivityBeLaunched(activityInfo, intent,
WindowConfiguration.WINDOWING_MODE_FULLSCREEN, DISPLAY_ID_1, /*isNewTask=*/false))
.isTrue();
}
@@ -1585,7 +1591,7 @@ public class VirtualDeviceManagerServiceTest {
addVirtualDisplay(mDeviceImpl, DISPLAY_ID_1);
GenericWindowPolicyController gwpc = mDeviceImpl.getDisplayWindowPolicyControllerForTest(
DISPLAY_ID_1);
- ArrayList<ActivityInfo> activityInfos = getActivityInfoList(
+ ActivityInfo activityInfo = getActivityInfo(
NONBLOCKED_APP_PACKAGE_NAME,
NONBLOCKED_APP_PACKAGE_NAME,
/* displayOnRemoveDevices */ true,
@@ -1597,7 +1603,7 @@ public class VirtualDeviceManagerServiceTest {
// register interceptor and intercept intent
mDeviceImpl.registerIntentInterceptor(interceptor, intentFilter);
- assertThat(gwpc.canActivityBeLaunched(activityInfos.get(0), intent,
+ assertThat(gwpc.canActivityBeLaunched(activityInfo, intent,
WindowConfiguration.WINDOWING_MODE_FULLSCREEN, DISPLAY_ID_1, /*isNewTask=*/false))
.isFalse();
ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class);
@@ -1609,7 +1615,7 @@ public class VirtualDeviceManagerServiceTest {
// unregister interceptor and launch activity
mDeviceImpl.unregisterIntentInterceptor(interceptor);
- assertThat(gwpc.canActivityBeLaunched(activityInfos.get(0), intent,
+ assertThat(gwpc.canActivityBeLaunched(activityInfo, intent,
WindowConfiguration.WINDOWING_MODE_FULLSCREEN, DISPLAY_ID_1, /*isNewTask=*/false))
.isTrue();
}
@@ -1628,7 +1634,7 @@ public class VirtualDeviceManagerServiceTest {
addVirtualDisplay(mDeviceImpl, DISPLAY_ID_1);
GenericWindowPolicyController gwpc = mDeviceImpl.getDisplayWindowPolicyControllerForTest(
DISPLAY_ID_1);
- ArrayList<ActivityInfo> activityInfos = getActivityInfoList(
+ ActivityInfo activityInfo = getActivityInfo(
NONBLOCKED_APP_PACKAGE_NAME,
NONBLOCKED_APP_PACKAGE_NAME,
/* displayOnRemoveDevices */ true,
@@ -1640,7 +1646,7 @@ public class VirtualDeviceManagerServiceTest {
// register interceptor with different filter
mDeviceImpl.registerIntentInterceptor(interceptor, intentFilter);
- assertThat(gwpc.canActivityBeLaunched(activityInfos.get(0), intent,
+ assertThat(gwpc.canActivityBeLaunched(activityInfo, intent,
WindowConfiguration.WINDOWING_MODE_FULLSCREEN, DISPLAY_ID_1, /*isNewTask=*/false))
.isTrue();
}
diff --git a/services/tests/servicestests/src/com/android/server/companion/virtual/VirtualDeviceTest.java b/services/tests/servicestests/src/com/android/server/companion/virtual/VirtualDeviceTest.java
index 28df24c3866a..c65452aa2fa1 100644
--- a/services/tests/servicestests/src/com/android/server/companion/virtual/VirtualDeviceTest.java
+++ b/services/tests/servicestests/src/com/android/server/companion/virtual/VirtualDeviceTest.java
@@ -16,21 +16,31 @@
package com.android.server.companion.virtual;
+import static android.companion.virtual.VirtualDeviceParams.DEVICE_POLICY_CUSTOM;
+import static android.companion.virtual.VirtualDeviceParams.DEVICE_POLICY_DEFAULT;
+import static android.companion.virtual.VirtualDeviceParams.POLICY_TYPE_SENSORS;
import static android.content.Context.DEVICE_ID_DEFAULT;
import static android.content.Context.DEVICE_ID_INVALID;
import static com.google.common.truth.Truth.assertThat;
import static org.junit.Assert.assertThrows;
+import static org.mockito.Mockito.when;
+import android.companion.virtual.IVirtualDevice;
import android.companion.virtual.VirtualDevice;
+import android.companion.virtual.flags.Flags;
import android.os.Parcel;
import android.platform.test.annotations.Presubmit;
+import android.platform.test.annotations.RequiresFlagsEnabled;
import androidx.test.ext.junit.runners.AndroidJUnit4;
+import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
@Presubmit
@RunWith(AndroidJUnit4.class)
@@ -40,24 +50,35 @@ public class VirtualDeviceTest {
private static final String PERSISTENT_ID = "persistentId";
private static final String DEVICE_NAME = "VirtualDeviceName";
+ @Mock
+ private IVirtualDevice mVirtualDevice;
+
+ @Before
+ public void setUp() throws Exception {
+ MockitoAnnotations.initMocks(this);
+ }
+
@Test
public void build_invalidId_shouldThrowIllegalArgumentException() {
assertThrows(
IllegalArgumentException.class,
- () -> new VirtualDevice(DEVICE_ID_INVALID, PERSISTENT_ID, DEVICE_NAME));
+ () -> new VirtualDevice(
+ mVirtualDevice, DEVICE_ID_INVALID, PERSISTENT_ID, DEVICE_NAME));
}
@Test
public void build_defaultId_shouldThrowIllegalArgumentException() {
assertThrows(
IllegalArgumentException.class,
- () -> new VirtualDevice(DEVICE_ID_DEFAULT, PERSISTENT_ID, DEVICE_NAME));
+ () -> new VirtualDevice(
+ mVirtualDevice, DEVICE_ID_DEFAULT, PERSISTENT_ID, DEVICE_NAME));
}
@Test
public void build_onlyRequiredFields() {
VirtualDevice virtualDevice =
- new VirtualDevice(VIRTUAL_DEVICE_ID, /*persistentId=*/null, /*name=*/null);
+ new VirtualDevice(
+ mVirtualDevice, VIRTUAL_DEVICE_ID, /*persistentId=*/null, /*name=*/null);
assertThat(virtualDevice.getDeviceId()).isEqualTo(VIRTUAL_DEVICE_ID);
assertThat(virtualDevice.getPersistentDeviceId()).isNull();
assertThat(virtualDevice.getName()).isNull();
@@ -66,15 +87,43 @@ public class VirtualDeviceTest {
@Test
public void parcelable_shouldRecreateSuccessfully() {
VirtualDevice originalDevice =
- new VirtualDevice(VIRTUAL_DEVICE_ID, PERSISTENT_ID, DEVICE_NAME);
+ new VirtualDevice(mVirtualDevice, VIRTUAL_DEVICE_ID, PERSISTENT_ID, DEVICE_NAME);
Parcel parcel = Parcel.obtain();
originalDevice.writeToParcel(parcel, 0);
parcel.setDataPosition(0);
VirtualDevice device = VirtualDevice.CREATOR.createFromParcel(parcel);
- assertThat(device).isEqualTo(originalDevice);
assertThat(device.getDeviceId()).isEqualTo(VIRTUAL_DEVICE_ID);
assertThat(device.getPersistentDeviceId()).isEqualTo(PERSISTENT_ID);
assertThat(device.getName()).isEqualTo(DEVICE_NAME);
}
+
+ @RequiresFlagsEnabled(Flags.FLAG_VDM_PUBLIC_APIS)
+ @Test
+ public void virtualDevice_getDisplayIds() throws Exception {
+ VirtualDevice virtualDevice =
+ new VirtualDevice(
+ mVirtualDevice, VIRTUAL_DEVICE_ID, /*persistentId=*/null, /*name=*/null);
+
+ when(mVirtualDevice.getDisplayIds()).thenReturn(new int[0]);
+ assertThat(virtualDevice.getDisplayIds()).hasLength(0);
+
+ final int[] displayIds = new int[]{7, 18};
+ when(mVirtualDevice.getDisplayIds()).thenReturn(displayIds);
+ assertThat(virtualDevice.getDisplayIds()).isEqualTo(displayIds);
+ }
+
+ @RequiresFlagsEnabled(Flags.FLAG_VDM_PUBLIC_APIS)
+ @Test
+ public void virtualDevice_hasCustomSensorSupport() throws Exception {
+ VirtualDevice virtualDevice =
+ new VirtualDevice(
+ mVirtualDevice, VIRTUAL_DEVICE_ID, /*persistentId=*/null, /*name=*/null);
+
+ when(mVirtualDevice.getDevicePolicy(POLICY_TYPE_SENSORS)).thenReturn(DEVICE_POLICY_DEFAULT);
+ assertThat(virtualDevice.hasCustomSensorSupport()).isFalse();
+
+ when(mVirtualDevice.getDevicePolicy(POLICY_TYPE_SENSORS)).thenReturn(DEVICE_POLICY_CUSTOM);
+ assertThat(virtualDevice.hasCustomSensorSupport()).isTrue();
+ }
}
diff --git a/services/tests/servicestests/src/com/android/server/companion/virtual/audio/VirtualAudioControllerTest.java b/services/tests/servicestests/src/com/android/server/companion/virtual/audio/VirtualAudioControllerTest.java
index 2bfa44ecb1d6..78655a5dd341 100644
--- a/services/tests/servicestests/src/com/android/server/companion/virtual/audio/VirtualAudioControllerTest.java
+++ b/services/tests/servicestests/src/com/android/server/companion/virtual/audio/VirtualAudioControllerTest.java
@@ -25,7 +25,6 @@ import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
-import android.companion.virtual.VirtualDeviceParams;
import android.companion.virtual.audio.IAudioConfigChangedCallback;
import android.companion.virtual.audio.IAudioRoutingCallback;
import android.content.Context;
@@ -79,11 +78,10 @@ public class VirtualAudioControllerTest {
FLAG_SECURE,
SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS,
/* allowedUsers= */ new ArraySet<>(),
- /* allowedCrossTaskNavigations= */ new ArraySet<>(),
- /* blockedCrossTaskNavigations= */ new ArraySet<>(),
- /* allowedActivities= */ new ArraySet<>(),
- /* blockedActivities= */ new ArraySet<>(),
- VirtualDeviceParams.ACTIVITY_POLICY_DEFAULT_ALLOWED,
+ /* activityLaunchAllowedByDefault= */ true,
+ /* activityPolicyExceptions= */ new ArraySet<>(),
+ /* crossTaskNavigationAllowedByDefault= */ true,
+ /* crossTaskNavigationExceptions= */ new ArraySet<>(),
/* activityListener= */ null,
/* pipBlockedCallback= */ null,
/* activityBlockedCallback= */ null,
diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
index f408ef0394e2..f4dac2c10d0f 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
@@ -1144,6 +1144,10 @@ public class DevicePolicyManagerTest extends DpmTestBase {
eq(UserManager.DISALLOW_ADD_CLONE_PROFILE),
eq(true), eq(UserHandle.SYSTEM));
+ verify(getServices().userManager, times(1)).setUserRestriction(
+ eq(UserManager.DISALLOW_ADD_PRIVATE_PROFILE),
+ eq(true), eq(UserHandle.SYSTEM));
+
verify(mContext.spiedContext, times(1)).sendBroadcastAsUser(
MockUtils.checkIntentAction(DevicePolicyManager.ACTION_DEVICE_OWNER_CHANGED),
MockUtils.checkUserHandle(UserHandle.USER_SYSTEM));
@@ -1422,6 +1426,10 @@ public class DevicePolicyManagerTest extends DpmTestBase {
.setUserRestriction(eq(UserManager.DISALLOW_ADD_CLONE_PROFILE), eq(false),
MockUtils.checkUserHandle(UserHandle.USER_SYSTEM));
+ verify(getServices().userManager)
+ .setUserRestriction(eq(UserManager.DISALLOW_ADD_PRIVATE_PROFILE), eq(false),
+ MockUtils.checkUserHandle(UserHandle.USER_SYSTEM));
+
verify(getServices().userManagerInternal).setDevicePolicyUserRestrictions(
eq(UserHandle.USER_SYSTEM), MockUtils.checkUserRestrictions(),
MockUtils.checkUserRestrictions(UserHandle.USER_SYSTEM), eq(true));
diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/PolicyVersionUpgraderTest.java b/services/tests/servicestests/src/com/android/server/devicepolicy/PolicyVersionUpgraderTest.java
index eb2ee35161ff..d2b921deb0d9 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/PolicyVersionUpgraderTest.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/PolicyVersionUpgraderTest.java
@@ -76,7 +76,7 @@ import javax.xml.parsers.DocumentBuilderFactory;
public class PolicyVersionUpgraderTest extends DpmTestBase {
// NOTE: Only change this value if the corresponding CL also adds a test to test the upgrade
// to the new version.
- private static final int LATEST_TESTED_VERSION = 5;
+ private static final int LATEST_TESTED_VERSION = 6;
public static final String PERMISSIONS_TAG = "admin-can-grant-sensors-permissions";
public static final String DEVICE_OWNER_XML = "device_owner_2.xml";
private ComponentName mFakeAdmin;
@@ -313,7 +313,7 @@ public class PolicyVersionUpgraderTest extends DpmTestBase {
}
@Test
- public void testEffectiveKeepProfilesRunningSet() throws Exception {
+ public void testEffectiveKeepProfilesRunningSetToFalse4To5() throws Exception {
writeVersionToXml(4);
final int userId = UserHandle.USER_SYSTEM;
@@ -327,10 +327,111 @@ public class PolicyVersionUpgraderTest extends DpmTestBase {
Document policies = readPolicies(userId);
Element keepProfilesRunning = (Element) policies.getDocumentElement()
.getElementsByTagName("keep-profiles-running").item(0);
- assertThat(keepProfilesRunning.getAttribute("value")).isEqualTo("false");
+
+ // Default value (false) is not serialized.
+ assertThat(keepProfilesRunning).isNull();
+ }
+ @Test
+ public void testEffectiveKeepProfilesRunningIsToFalse4To6() throws Exception {
+ writeVersionToXml(4);
+
+ final int userId = UserHandle.USER_SYSTEM;
+ mProvider.mUsers = new int[]{userId};
+ preparePoliciesFile(userId, "device_policies.xml");
+
+ mUpgrader.upgradePolicy(6);
+
+ assertThat(readVersionFromXml()).isAtLeast(6);
+
+ Document policies = readPolicies(userId);
+ Element keepProfilesRunning = (Element) policies.getDocumentElement()
+ .getElementsByTagName("keep-profiles-running").item(0);
+
+ // Default value (false) is not serialized.
+ assertThat(keepProfilesRunning).isNull();
+ }
+
+ /**
+ * Verify correct behaviour when upgrading from Android 13
+ */
+ @Test
+ public void testEffectiveKeepProfilesRunningIsToFalse3To6() throws Exception {
+ writeVersionToXml(3);
+
+ final int userId = UserHandle.USER_SYSTEM;
+ mProvider.mUsers = new int[]{userId};
+ preparePoliciesFile(userId, "device_policies.xml");
+
+ mUpgrader.upgradePolicy(6);
+
+ assertThat(readVersionFromXml()).isAtLeast(6);
+
+ Document policies = readPolicies(userId);
+ Element keepProfilesRunning = (Element) policies.getDocumentElement()
+ .getElementsByTagName("keep-profiles-running").item(0);
+
+ // Default value (false) is not serialized.
+ assertThat(keepProfilesRunning).isNull();
}
@Test
+ public void testEffectiveKeepProfilesRunningMissingInV5() throws Exception {
+ writeVersionToXml(5);
+
+ final int userId = UserHandle.USER_SYSTEM;
+ mProvider.mUsers = new int[]{userId};
+ preparePoliciesFile(userId, "device_policies.xml");
+
+ mUpgrader.upgradePolicy(6);
+
+ assertThat(readVersionFromXml()).isAtLeast(6);
+
+ Document policies = readPolicies(userId);
+ Element keepProfilesRunning = (Element) policies.getDocumentElement()
+ .getElementsByTagName("keep-profiles-running").item(0);
+ assertThat(keepProfilesRunning.getAttribute("value")).isEqualTo("true");
+ }
+
+ @Test
+ public void testEffectiveKeepProfilesRunningTrueInV5() throws Exception {
+ writeVersionToXml(5);
+
+ final int userId = UserHandle.USER_SYSTEM;
+ mProvider.mUsers = new int[]{userId};
+ preparePoliciesFile(userId, "device_policies_keep_profiles_running_true.xml");
+
+ mUpgrader.upgradePolicy(6);
+
+ assertThat(readVersionFromXml()).isAtLeast(6);
+
+ Document policies = readPolicies(userId);
+ Element keepProfilesRunning = (Element) policies.getDocumentElement()
+ .getElementsByTagName("keep-profiles-running").item(0);
+ assertThat(keepProfilesRunning.getAttribute("value")).isEqualTo("true");
+ }
+
+ @Test
+ public void testEffectiveKeepProfilesRunningFalseInV5() throws Exception {
+ writeVersionToXml(5);
+
+ final int userId = UserHandle.USER_SYSTEM;
+ mProvider.mUsers = new int[]{userId};
+ preparePoliciesFile(userId, "device_policies_keep_profiles_running_false.xml");
+
+ mUpgrader.upgradePolicy(6);
+
+ assertThat(readVersionFromXml()).isAtLeast(6);
+
+ Document policies = readPolicies(userId);
+ Element keepProfilesRunning = (Element) policies.getDocumentElement()
+ .getElementsByTagName("keep-profiles-running").item(0);
+
+ // Default value (false) is not serialized.
+ assertThat(keepProfilesRunning).isNull();
+ }
+
+
+ @Test
public void isLatestVersionTested() {
assertThat(DevicePolicyManagerService.DPMS_VERSION).isEqualTo(LATEST_TESTED_VERSION);
}
diff --git a/services/tests/servicestests/src/com/android/server/pm/UserManagerTest.java b/services/tests/servicestests/src/com/android/server/pm/UserManagerTest.java
index ecd35a55e291..b22798e6eaed 100644
--- a/services/tests/servicestests/src/com/android/server/pm/UserManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/UserManagerTest.java
@@ -1174,6 +1174,24 @@ public final class UserManagerTest {
}
}
+ // Make sure the creation of a private profile fails if DISALLOW_ADD_PRIVATE_PROFILE is true.
+ @MediumTest
+ @Test
+ public void testCreateProfileForUser_disallowAddPrivateProfile() {
+ final int mainUserId = ActivityManager.getCurrentUser();
+ final UserHandle mainUserHandle = asHandle(mainUserId);
+ mUserManager.setUserRestriction(UserManager.DISALLOW_ADD_PRIVATE_PROFILE,
+ true, mainUserHandle);
+ try {
+ UserInfo privateProfileInfo = createProfileForUser("Private",
+ UserManager.USER_TYPE_PROFILE_PRIVATE, mainUserId);
+ assertThat(privateProfileInfo).isNull();
+ } finally {
+ mUserManager.setUserRestriction(UserManager.DISALLOW_ADD_PRIVATE_PROFILE, false,
+ mainUserHandle);
+ }
+ }
+
@MediumTest
@Test
public void testAddRestrictedProfile() throws Exception {
diff --git a/services/tests/servicestests/src/com/android/server/pm/UserRestrictionsUtilsTest.java b/services/tests/servicestests/src/com/android/server/pm/UserRestrictionsUtilsTest.java
index a387d4a8b2bc..9907bd6f38b6 100644
--- a/services/tests/servicestests/src/com/android/server/pm/UserRestrictionsUtilsTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/UserRestrictionsUtilsTest.java
@@ -72,6 +72,8 @@ public class UserRestrictionsUtilsTest extends AndroidTestCase {
public void testCanDeviceOwnerChange() {
assertFalse(UserRestrictionsUtils.canDeviceOwnerChange(UserManager.DISALLOW_RECORD_AUDIO));
assertFalse(UserRestrictionsUtils.canDeviceOwnerChange(UserManager.DISALLOW_WALLPAPER));
+ assertFalse(UserRestrictionsUtils.canDeviceOwnerChange(
+ UserManager.DISALLOW_ADD_PRIVATE_PROFILE));
assertTrue(UserRestrictionsUtils.canDeviceOwnerChange(UserManager.DISALLOW_ADD_USER));
assertTrue(UserRestrictionsUtils.canDeviceOwnerChange(UserManager.DISALLOW_USER_SWITCH));
}
@@ -83,6 +85,8 @@ public class UserRestrictionsUtilsTest extends AndroidTestCase {
UserManager.DISALLOW_WALLPAPER, true));
assertFalse(UserRestrictionsUtils.canProfileOwnerChange(
UserManager.DISALLOW_USER_SWITCH, true));
+ assertFalse(UserRestrictionsUtils.canProfileOwnerChange(
+ UserManager.DISALLOW_ADD_PRIVATE_PROFILE, true));
assertTrue(UserRestrictionsUtils.canProfileOwnerChange(
UserManager.DISALLOW_ADD_USER, true));
assertTrue(UserRestrictionsUtils.canProfileOwnerChange(
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/ZenModeHelperTest.java b/services/tests/uiservicestests/src/com/android/server/notification/ZenModeHelperTest.java
index e540068e6bc6..e22c10489d4d 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/ZenModeHelperTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/ZenModeHelperTest.java
@@ -2470,6 +2470,143 @@ public class ZenModeHelperTest extends UiServiceTestCase {
assertEquals(12345, mZenModeEventLogger.getPackageUid(4));
}
+ @Test
+ public void testUpdateConsolidatedPolicy_defaultRulesOnly() {
+ setupZenConfig();
+
+ // When there's one automatic rule active and it doesn't specify a policy, test that the
+ // resulting consolidated policy is one that matches the default rule settings.
+ AutomaticZenRule zenRule = new AutomaticZenRule("name",
+ null,
+ new ComponentName(CUSTOM_PKG_NAME, "ScheduleConditionProvider"),
+ ZenModeConfig.toScheduleConditionId(new ScheduleInfo()),
+ null,
+ NotificationManager.INTERRUPTION_FILTER_PRIORITY, true);
+ String id = mZenModeHelper.addAutomaticZenRule(mContext.getPackageName(), zenRule, "test",
+ Process.SYSTEM_UID, true);
+
+ // enable the rule
+ mZenModeHelper.setAutomaticZenRuleState(id,
+ new Condition(zenRule.getConditionId(), "", STATE_TRUE),
+ Process.SYSTEM_UID, true);
+
+ // inspect the consolidated policy. Based on setupZenConfig() values.
+ assertFalse(mZenModeHelper.mConsolidatedPolicy.allowAlarms());
+ assertFalse(mZenModeHelper.mConsolidatedPolicy.allowMedia());
+ assertFalse(mZenModeHelper.mConsolidatedPolicy.allowSystem());
+ assertTrue(mZenModeHelper.mConsolidatedPolicy.allowReminders());
+ assertTrue(mZenModeHelper.mConsolidatedPolicy.allowCalls());
+ assertEquals(PRIORITY_SENDERS_STARRED, mZenModeHelper.mConsolidatedPolicy.allowCallsFrom());
+ assertTrue(mZenModeHelper.mConsolidatedPolicy.allowMessages());
+ assertTrue(mZenModeHelper.mConsolidatedPolicy.allowConversations());
+ assertTrue(mZenModeHelper.mConsolidatedPolicy.allowRepeatCallers());
+ assertFalse(mZenModeHelper.mConsolidatedPolicy.showBadges());
+ }
+
+ @Test
+ public void testUpdateConsolidatedPolicy_customPolicyOnly() {
+ setupZenConfig();
+
+ // when there's only one automatic rule active and it has a custom policy, make sure that's
+ // what the consolidated policy reflects whether or not it's stricter than what the default
+ // would specify.
+ ZenPolicy customPolicy = new ZenPolicy.Builder()
+ .allowAlarms(true) // more lenient than default
+ .allowMedia(true) // more lenient than default
+ .allowRepeatCallers(false) // more restrictive than default
+ .allowCalls(ZenPolicy.PEOPLE_TYPE_NONE) // more restrictive than default
+ .showBadges(true) // more lenient
+ .showPeeking(false) // more restrictive
+ .build();
+
+ AutomaticZenRule zenRule = new AutomaticZenRule("name",
+ null,
+ new ComponentName(CUSTOM_PKG_NAME, "ScheduleConditionProvider"),
+ ZenModeConfig.toScheduleConditionId(new ScheduleInfo()),
+ customPolicy,
+ NotificationManager.INTERRUPTION_FILTER_PRIORITY, true);
+ String id = mZenModeHelper.addAutomaticZenRule(mContext.getPackageName(), zenRule, "test",
+ Process.SYSTEM_UID, true);
+
+ // enable the rule; this will update the consolidated policy
+ mZenModeHelper.setAutomaticZenRuleState(id,
+ new Condition(zenRule.getConditionId(), "", STATE_TRUE),
+ Process.SYSTEM_UID, true);
+
+ // since this is the only active rule, the consolidated policy should match the custom
+ // policy for every field specified, and take default values for unspecified things
+ assertTrue(mZenModeHelper.mConsolidatedPolicy.allowAlarms()); // custom
+ assertTrue(mZenModeHelper.mConsolidatedPolicy.allowMedia()); // custom
+ assertFalse(mZenModeHelper.mConsolidatedPolicy.allowSystem()); // default
+ assertTrue(mZenModeHelper.mConsolidatedPolicy.allowReminders()); // default
+ assertFalse(mZenModeHelper.mConsolidatedPolicy.allowCalls()); // custom
+ assertTrue(mZenModeHelper.mConsolidatedPolicy.allowMessages()); // default
+ assertTrue(mZenModeHelper.mConsolidatedPolicy.allowConversations()); // default
+ assertFalse(mZenModeHelper.mConsolidatedPolicy.allowRepeatCallers()); // custom
+ assertTrue(mZenModeHelper.mConsolidatedPolicy.showBadges()); // custom
+ assertFalse(mZenModeHelper.mConsolidatedPolicy.showPeeking()); // custom
+ }
+
+ @Test
+ public void testUpdateConsolidatedPolicy_defaultAndCustomActive() {
+ setupZenConfig();
+
+ // when there are two rules active, one inheriting the default policy and one setting its
+ // own custom policy, they should be merged to form the most restrictive combination.
+
+ // rule 1: no custom policy
+ AutomaticZenRule zenRule = new AutomaticZenRule("name",
+ null,
+ new ComponentName(CUSTOM_PKG_NAME, "ScheduleConditionProvider"),
+ ZenModeConfig.toScheduleConditionId(new ScheduleInfo()),
+ null,
+ NotificationManager.INTERRUPTION_FILTER_PRIORITY, true);
+ String id = mZenModeHelper.addAutomaticZenRule(mContext.getPackageName(), zenRule, "test",
+ Process.SYSTEM_UID, true);
+
+ // enable rule 1
+ mZenModeHelper.setAutomaticZenRuleState(id,
+ new Condition(zenRule.getConditionId(), "", STATE_TRUE),
+ Process.SYSTEM_UID, true);
+
+ // custom policy for rule 2
+ ZenPolicy customPolicy = new ZenPolicy.Builder()
+ .allowAlarms(true) // more lenient than default
+ .allowMedia(true) // more lenient than default
+ .allowRepeatCallers(false) // more restrictive than default
+ .allowCalls(ZenPolicy.PEOPLE_TYPE_NONE) // more restrictive than default
+ .showBadges(true) // more lenient
+ .showPeeking(false) // more restrictive
+ .build();
+
+ AutomaticZenRule zenRule2 = new AutomaticZenRule("name2",
+ null,
+ new ComponentName(CUSTOM_PKG_NAME, "ScheduleConditionProvider"),
+ ZenModeConfig.toScheduleConditionId(new ScheduleInfo()),
+ customPolicy,
+ NotificationManager.INTERRUPTION_FILTER_PRIORITY, true);
+ String id2 = mZenModeHelper.addAutomaticZenRule(mContext.getPackageName(), zenRule2,
+ "test", Process.SYSTEM_UID, true);
+
+ // enable rule 2; this will update the consolidated policy
+ mZenModeHelper.setAutomaticZenRuleState(id2,
+ new Condition(zenRule2.getConditionId(), "", STATE_TRUE),
+ Process.SYSTEM_UID, true);
+
+ // now both rules should be on, and the consolidated policy should reflect the most
+ // restrictive option of each of the two
+ assertFalse(mZenModeHelper.mConsolidatedPolicy.allowAlarms()); // default stricter
+ assertFalse(mZenModeHelper.mConsolidatedPolicy.allowMedia()); // default stricter
+ assertFalse(mZenModeHelper.mConsolidatedPolicy.allowSystem()); // default, unset in custom
+ assertTrue(mZenModeHelper.mConsolidatedPolicy.allowReminders()); // default
+ assertFalse(mZenModeHelper.mConsolidatedPolicy.allowCalls()); // custom stricter
+ assertTrue(mZenModeHelper.mConsolidatedPolicy.allowMessages()); // default, unset in custom
+ assertTrue(mZenModeHelper.mConsolidatedPolicy.allowConversations()); // default
+ assertFalse(mZenModeHelper.mConsolidatedPolicy.allowRepeatCallers()); // custom stricter
+ assertFalse(mZenModeHelper.mConsolidatedPolicy.showBadges()); // default stricter
+ assertFalse(mZenModeHelper.mConsolidatedPolicy.showPeeking()); // custom stricter
+ }
+
private void setupZenConfig() {
mZenModeHelper.mZenMode = Global.ZEN_MODE_OFF;
mZenModeHelper.mConfig.allowAlarms = false;
diff --git a/services/tests/vibrator/src/com/android/server/vibrator/HapticFeedbackCustomizationTest.java b/services/tests/vibrator/src/com/android/server/vibrator/HapticFeedbackCustomizationTest.java
index 10b49c67e8bb..bc826a3cf4a6 100644
--- a/services/tests/vibrator/src/com/android/server/vibrator/HapticFeedbackCustomizationTest.java
+++ b/services/tests/vibrator/src/com/android/server/vibrator/HapticFeedbackCustomizationTest.java
@@ -30,7 +30,6 @@ import static org.mockito.Mockito.when;
import android.content.res.Resources;
import android.os.VibrationEffect;
-import android.os.Vibrator;
import android.os.VibratorInfo;
import android.util.AtomicFile;
import android.util.SparseArray;
@@ -73,12 +72,10 @@ public class HapticFeedbackCustomizationTest {
VibrationEffect.createWaveform(new long[] {123}, new int[] {254}, -1);
@Mock private Resources mResourcesMock;
- @Mock private Vibrator mVibratorMock;
@Mock private VibratorInfo mVibratorInfoMock;
@Before
public void setUp() {
- when(mVibratorMock.getInfo()).thenReturn(mVibratorInfoMock);
when(mVibratorInfoMock.areVibrationFeaturesSupported(any())).thenReturn(true);
}
@@ -220,17 +217,17 @@ public class HapticFeedbackCustomizationTest {
public void testParseCustomizations_noCustomizationFile_returnsNull() throws Exception {
setCustomizationFilePath("");
- assertThat(HapticFeedbackCustomization.loadVibrations(mResourcesMock, mVibratorMock))
+ assertThat(HapticFeedbackCustomization.loadVibrations(mResourcesMock, mVibratorInfoMock))
.isNull();
setCustomizationFilePath(null);
- assertThat(HapticFeedbackCustomization.loadVibrations(mResourcesMock, mVibratorMock))
+ assertThat(HapticFeedbackCustomization.loadVibrations(mResourcesMock, mVibratorInfoMock))
.isNull();
setCustomizationFilePath("non_existent_file.xml");
- assertThat(HapticFeedbackCustomization.loadVibrations(mResourcesMock, mVibratorMock))
+ assertThat(HapticFeedbackCustomization.loadVibrations(mResourcesMock, mVibratorInfoMock))
.isNull();
}
@@ -387,7 +384,7 @@ public class HapticFeedbackCustomizationTest {
String xml, SparseArray<VibrationEffect> expectedCustomizations) throws Exception {
setupCustomizationFile(xml);
assertThat(expectedCustomizations.contentEquals(
- HapticFeedbackCustomization.loadVibrations(mResourcesMock, mVibratorMock)))
+ HapticFeedbackCustomization.loadVibrations(mResourcesMock, mVibratorInfoMock)))
.isTrue();
}
@@ -395,13 +392,15 @@ public class HapticFeedbackCustomizationTest {
setupCustomizationFile(xml);
assertThrows("Expected haptic feedback customization to fail for " + xml,
CustomizationParserException.class,
- () -> HapticFeedbackCustomization.loadVibrations(mResourcesMock, mVibratorMock));
+ () -> HapticFeedbackCustomization.loadVibrations(
+ mResourcesMock, mVibratorInfoMock));
}
private void assertParseCustomizationsFails() throws Exception {
assertThrows("Expected haptic feedback customization to fail",
CustomizationParserException.class,
- () -> HapticFeedbackCustomization.loadVibrations(mResourcesMock, mVibratorMock));
+ () -> HapticFeedbackCustomization.loadVibrations(
+ mResourcesMock, mVibratorInfoMock));
}
private void setupCustomizationFile(String xml) throws Exception {
diff --git a/services/tests/vibrator/src/com/android/server/vibrator/HapticFeedbackVibrationProviderTest.java b/services/tests/vibrator/src/com/android/server/vibrator/HapticFeedbackVibrationProviderTest.java
index cae811e9bb35..a91bd2b55f76 100644
--- a/services/tests/vibrator/src/com/android/server/vibrator/HapticFeedbackVibrationProviderTest.java
+++ b/services/tests/vibrator/src/com/android/server/vibrator/HapticFeedbackVibrationProviderTest.java
@@ -31,8 +31,10 @@ import static org.mockito.Mockito.when;
import android.content.Context;
import android.content.res.Resources;
+import android.hardware.vibrator.IVibrator;
+import android.os.VibrationAttributes;
import android.os.VibrationEffect;
-import android.os.test.FakeVibrator;
+import android.os.VibratorInfo;
import android.util.AtomicFile;
import android.util.SparseArray;
@@ -58,7 +60,7 @@ public class HapticFeedbackVibrationProviderTest {
VibrationEffect.startComposition().addPrimitive(PRIMITIVE_CLICK, 0.3497f).compose();
private Context mContext = InstrumentationRegistry.getContext();
- private FakeVibrator mVibrator = new FakeVibrator(mContext);
+ private VibratorInfo mVibratorInfo = VibratorInfo.EMPTY_VIBRATOR_INFO;
@Mock private Resources mResourcesMock;
@@ -66,14 +68,14 @@ public class HapticFeedbackVibrationProviderTest {
public void testNonExistentCustomization_useDefault() throws Exception {
// No customization file is set.
HapticFeedbackVibrationProvider hapticProvider =
- new HapticFeedbackVibrationProvider(mResourcesMock, mVibrator);
+ new HapticFeedbackVibrationProvider(mResourcesMock, mVibratorInfo);
assertThat(hapticProvider.getVibrationForHapticFeedback(CONTEXT_CLICK))
.isEqualTo(VibrationEffect.get(EFFECT_TICK));
// The customization file specifies no customization.
setupCustomizationFile("<haptic-feedback-constants></haptic-feedback-constants>");
- hapticProvider = new HapticFeedbackVibrationProvider(mResourcesMock, mVibrator);
+ hapticProvider = new HapticFeedbackVibrationProvider(mResourcesMock, mVibratorInfo);
assertThat(hapticProvider.getVibrationForHapticFeedback(CONTEXT_CLICK))
.isEqualTo(VibrationEffect.get(EFFECT_TICK));
@@ -83,7 +85,7 @@ public class HapticFeedbackVibrationProviderTest {
public void testExceptionParsingCustomizations_useDefault() throws Exception {
setupCustomizationFile("<bad-xml></bad-xml>");
HapticFeedbackVibrationProvider hapticProvider =
- new HapticFeedbackVibrationProvider(mResourcesMock, mVibrator);
+ new HapticFeedbackVibrationProvider(mResourcesMock, mVibratorInfo);
assertThat(hapticProvider.getVibrationForHapticFeedback(CONTEXT_CLICK))
.isEqualTo(VibrationEffect.get(EFFECT_TICK));
@@ -96,7 +98,7 @@ public class HapticFeedbackVibrationProviderTest {
customizations.put(CONTEXT_CLICK, PRIMITIVE_CLICK_EFFECT);
HapticFeedbackVibrationProvider hapticProvider =
- new HapticFeedbackVibrationProvider(mResourcesMock, mVibrator, customizations);
+ new HapticFeedbackVibrationProvider(mResourcesMock, mVibratorInfo, customizations);
// The override for `CONTEXT_CLICK` is used.
assertThat(hapticProvider.getVibrationForHapticFeedback(CONTEXT_CLICK))
@@ -109,11 +111,15 @@ public class HapticFeedbackVibrationProviderTest {
@Test
public void testDoNotUseInvalidCustomizedVibration() throws Exception {
mockVibratorPrimitiveSupport(new int[] {});
- SparseArray<VibrationEffect> customizations = new SparseArray<>();
- customizations.put(CONTEXT_CLICK, PRIMITIVE_CLICK_EFFECT);
+ String xml = "<haptic-feedback-constants>"
+ + "<constant id=\"" + CONTEXT_CLICK + "\">"
+ + PRIMITIVE_CLICK_EFFECT
+ + "</constant>"
+ + "</haptic-feedback-constants>";
+ setupCustomizationFile(xml);
HapticFeedbackVibrationProvider hapticProvider =
- new HapticFeedbackVibrationProvider(mResourcesMock, mVibrator, customizations);
+ new HapticFeedbackVibrationProvider(mResourcesMock, mVibratorInfo);
// The override for `CONTEXT_CLICK` is not used because the vibration is not supported.
assertThat(hapticProvider.getVibrationForHapticFeedback(CONTEXT_CLICK))
@@ -132,14 +138,14 @@ public class HapticFeedbackVibrationProviderTest {
// Test with a customization available for `TEXT_HANDLE_MOVE`.
HapticFeedbackVibrationProvider hapticProvider =
- new HapticFeedbackVibrationProvider(mResourcesMock, mVibrator, customizations);
+ new HapticFeedbackVibrationProvider(mResourcesMock, mVibratorInfo, customizations);
assertThat(hapticProvider.getVibrationForHapticFeedback(TEXT_HANDLE_MOVE)).isNull();
// Test with no customization available for `TEXT_HANDLE_MOVE`.
hapticProvider =
new HapticFeedbackVibrationProvider(
- mResourcesMock, mVibrator, /* hapticCustomizations= */ null);
+ mResourcesMock, mVibratorInfo, /* hapticCustomizations= */ null);
assertThat(hapticProvider.getVibrationForHapticFeedback(TEXT_HANDLE_MOVE)).isNull();
}
@@ -153,7 +159,7 @@ public class HapticFeedbackVibrationProviderTest {
// Test with a customization available for `TEXT_HANDLE_MOVE`.
HapticFeedbackVibrationProvider hapticProvider =
- new HapticFeedbackVibrationProvider(mResourcesMock, mVibrator, customizations);
+ new HapticFeedbackVibrationProvider(mResourcesMock, mVibratorInfo, customizations);
assertThat(hapticProvider.getVibrationForHapticFeedback(TEXT_HANDLE_MOVE))
.isEqualTo(PRIMITIVE_CLICK_EFFECT);
@@ -161,7 +167,7 @@ public class HapticFeedbackVibrationProviderTest {
// Test with no customization available for `TEXT_HANDLE_MOVE`.
hapticProvider =
new HapticFeedbackVibrationProvider(
- mResourcesMock, mVibrator, /* hapticCustomizations= */ null);
+ mResourcesMock, mVibratorInfo, /* hapticCustomizations= */ null);
assertThat(hapticProvider.getVibrationForHapticFeedback(TEXT_HANDLE_MOVE))
.isEqualTo(VibrationEffect.get(EFFECT_TEXTURE_TICK));
@@ -176,14 +182,14 @@ public class HapticFeedbackVibrationProviderTest {
customizations.put(SAFE_MODE_ENABLED, PRIMITIVE_CLICK_EFFECT);
HapticFeedbackVibrationProvider hapticProvider =
- new HapticFeedbackVibrationProvider(mResourcesMock, mVibrator, customizations);
+ new HapticFeedbackVibrationProvider(mResourcesMock, mVibratorInfo, customizations);
assertThat(hapticProvider.getVibrationForHapticFeedback(SAFE_MODE_ENABLED))
.isEqualTo(PRIMITIVE_CLICK_EFFECT);
mockSafeModeEnabledVibration(null);
hapticProvider =
- new HapticFeedbackVibrationProvider(mResourcesMock, mVibrator, customizations);
+ new HapticFeedbackVibrationProvider(mResourcesMock, mVibratorInfo, customizations);
assertThat(hapticProvider.getVibrationForHapticFeedback(SAFE_MODE_ENABLED))
.isEqualTo(PRIMITIVE_CLICK_EFFECT);
@@ -193,20 +199,9 @@ public class HapticFeedbackVibrationProviderTest {
public void testNoValidCustomizationPresentForSafeModeEnabled_resourceBasedVibrationUsed()
throws Exception {
mockSafeModeEnabledVibration(10, 20, 30, 40);
- SparseArray<VibrationEffect> customizations = new SparseArray<>();
- customizations.put(SAFE_MODE_ENABLED, PRIMITIVE_CLICK_EFFECT);
-
- // Test with a customization that is not supported by the vibrator.
HapticFeedbackVibrationProvider hapticProvider =
- new HapticFeedbackVibrationProvider(mResourcesMock, mVibrator, customizations);
-
- assertThat(hapticProvider.getVibrationForHapticFeedback(SAFE_MODE_ENABLED))
- .isEqualTo(VibrationEffect.createWaveform(new long[] {10, 20, 30, 40}, -1));
-
- // Test with no customizations.
- hapticProvider =
new HapticFeedbackVibrationProvider(
- mResourcesMock, mVibrator, /* hapticCustomizations= */ null);
+ mResourcesMock, mVibratorInfo, /* hapticCustomizations= */ null);
assertThat(hapticProvider.getVibrationForHapticFeedback(SAFE_MODE_ENABLED))
.isEqualTo(VibrationEffect.createWaveform(new long[] {10, 20, 30, 40}, -1));
@@ -216,25 +211,44 @@ public class HapticFeedbackVibrationProviderTest {
public void testNoValidCustomizationAndResourcePresentForSafeModeEnabled_noVibrationUsed()
throws Exception {
mockSafeModeEnabledVibration(null);
- SparseArray<VibrationEffect> customizations = new SparseArray<>();
- customizations.put(SAFE_MODE_ENABLED, PRIMITIVE_CLICK_EFFECT);
-
- // Test with a customization that is not supported by the vibrator.
HapticFeedbackVibrationProvider hapticProvider =
- new HapticFeedbackVibrationProvider(mResourcesMock, mVibrator, customizations);
+ new HapticFeedbackVibrationProvider(
+ mResourcesMock, mVibratorInfo, /* hapticCustomizations= */ null);
assertThat(hapticProvider.getVibrationForHapticFeedback(SAFE_MODE_ENABLED)).isNull();
+ }
- // Test with no customizations.
- hapticProvider =
- new HapticFeedbackVibrationProvider(
- mResourcesMock, mVibrator, /* hapticCustomizations= */ null);
+ @Test
+ public void testVibrationAttribute_forNotBypassingIntensitySettings() {
+ HapticFeedbackVibrationProvider hapticProvider =
+ new HapticFeedbackVibrationProvider(mResourcesMock, mVibratorInfo);
- assertThat(hapticProvider.getVibrationForHapticFeedback(SAFE_MODE_ENABLED)).isNull();
+ VibrationAttributes attrs = hapticProvider.getVibrationAttributesForHapticFeedback(
+ SAFE_MODE_ENABLED, /* bypassVibrationIntensitySetting= */ false);
+
+ assertThat(attrs.getFlags() & VibrationAttributes.FLAG_BYPASS_USER_VIBRATION_INTENSITY_OFF)
+ .isEqualTo(0);
+ }
+
+ @Test
+ public void testVibrationAttribute_forByassingIntensitySettings() {
+ HapticFeedbackVibrationProvider hapticProvider =
+ new HapticFeedbackVibrationProvider(mResourcesMock, mVibratorInfo);
+
+ VibrationAttributes attrs = hapticProvider.getVibrationAttributesForHapticFeedback(
+ SAFE_MODE_ENABLED, /* bypassVibrationIntensitySetting= */ true);
+
+ assertThat(attrs.getFlags() & VibrationAttributes.FLAG_BYPASS_USER_VIBRATION_INTENSITY_OFF)
+ .isNotEqualTo(0);
}
private void mockVibratorPrimitiveSupport(int... supportedPrimitives) {
- mVibrator = new FakeVibrator(mContext, supportedPrimitives);
+ VibratorInfo.Builder builder = new VibratorInfo.Builder(/* id= */ 1)
+ .setCapabilities(IVibrator.CAP_COMPOSE_EFFECTS);
+ for (int primitive : supportedPrimitives) {
+ builder.setSupportedPrimitive(primitive, 10);
+ }
+ mVibratorInfo = builder.build();
}
private void mockHapticTextSupport(boolean supported) {
diff --git a/services/tests/vibrator/src/com/android/server/vibrator/VibratorManagerServiceTest.java b/services/tests/vibrator/src/com/android/server/vibrator/VibratorManagerServiceTest.java
index 4e3a893954a2..c25f0cb91caa 100644
--- a/services/tests/vibrator/src/com/android/server/vibrator/VibratorManagerServiceTest.java
+++ b/services/tests/vibrator/src/com/android/server/vibrator/VibratorManagerServiceTest.java
@@ -22,6 +22,7 @@ import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertThrows;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
@@ -30,6 +31,7 @@ import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.inOrder;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
@@ -45,6 +47,7 @@ import android.content.ContentResolver;
import android.content.Context;
import android.content.ContextWrapper;
import android.content.pm.PackageManagerInternal;
+import android.content.res.Resources;
import android.hardware.input.IInputManager;
import android.hardware.input.InputManager;
import android.hardware.input.InputManagerGlobal;
@@ -79,8 +82,10 @@ import android.os.vibrator.VibrationConfig;
import android.os.vibrator.VibrationEffectSegment;
import android.provider.Settings;
import android.util.ArraySet;
+import android.util.SparseArray;
import android.util.SparseBooleanArray;
import android.view.Display;
+import android.view.HapticFeedbackConstants;
import android.view.InputDevice;
import androidx.test.InstrumentationRegistry;
@@ -169,6 +174,8 @@ public class VibratorManagerServiceTest {
private final Map<Integer, FakeVibratorControllerProvider> mVibratorProviders = new HashMap<>();
+ private SparseArray<VibrationEffect> mHapticFeedbackVibrationMap = new SparseArray<>();
+
private VibratorManagerService mService;
private Context mContextSpy;
private TestLooper mTestLooper;
@@ -309,6 +316,12 @@ public class VibratorManagerServiceTest {
mExternalVibratorService =
(VibratorManagerService.ExternalVibratorService) serviceInstance;
}
+
+ HapticFeedbackVibrationProvider createHapticFeedbackVibrationProvider(
+ Resources resources, VibratorInfo vibratorInfo) {
+ return new HapticFeedbackVibrationProvider(
+ resources, vibratorInfo, mHapticFeedbackVibrationMap);
+ }
});
return mService;
}
@@ -623,6 +636,18 @@ public class VibratorManagerServiceTest {
}
@Test
+ public void vibrate_withoutVibratePermission_throwsSecurityException() {
+ denyPermission(android.Manifest.permission.VIBRATE);
+ VibratorManagerService service = createSystemReadyService();
+
+ assertThrows("Expected vibrating without permission to fail!",
+ SecurityException.class,
+ () -> vibrate(service,
+ VibrationEffect.createPredefined(VibrationEffect.EFFECT_CLICK),
+ VibrationAttributes.createForUsage(VibrationAttributes.USAGE_TOUCH)));
+ }
+
+ @Test
public void vibrate_withRingtone_usesRingerModeSettings() throws Exception {
mockVibrators(1);
FakeVibratorControllerProvider fakeVibrator = mVibratorProviders.get(1);
@@ -1274,6 +1299,60 @@ public class VibratorManagerServiceTest {
}
@Test
+ public void performHapticFeedback_doesNotRequirePermission() throws Exception {
+ denyPermission(android.Manifest.permission.VIBRATE);
+ mHapticFeedbackVibrationMap.put(
+ HapticFeedbackConstants.KEYBOARD_TAP,
+ VibrationEffect.createPredefined(VibrationEffect.EFFECT_CLICK));
+ mockVibrators(1);
+ FakeVibratorControllerProvider fakeVibrator = mVibratorProviders.get(1);
+ fakeVibrator.setSupportedEffects(VibrationEffect.EFFECT_CLICK);
+ VibratorManagerService service = createSystemReadyService();
+
+ HalVibration vibration =
+ performHapticFeedbackAndWaitUntilFinished(
+ service, HapticFeedbackConstants.KEYBOARD_TAP, /* always= */ true);
+
+ List<VibrationEffectSegment> playedSegments = fakeVibrator.getAllEffectSegments();
+ assertEquals(1, playedSegments.size());
+ PrebakedSegment segment = (PrebakedSegment) playedSegments.get(0);
+ assertEquals(VibrationEffect.EFFECT_CLICK, segment.getEffectId());
+ assertEquals(VibrationAttributes.USAGE_TOUCH, vibration.callerInfo.attrs.getUsage());
+ }
+
+ @Test
+ public void performHapticFeedback_doesNotVibrateWhenVibratorInfoNotReady() throws Exception {
+ denyPermission(android.Manifest.permission.VIBRATE);
+ mHapticFeedbackVibrationMap.put(
+ HapticFeedbackConstants.KEYBOARD_TAP,
+ VibrationEffect.createPredefined(VibrationEffect.EFFECT_CLICK));
+ mockVibrators(1);
+ FakeVibratorControllerProvider fakeVibrator = mVibratorProviders.get(1);
+ fakeVibrator.setVibratorInfoLoadSuccessful(false);
+ fakeVibrator.setSupportedEffects(VibrationEffect.EFFECT_CLICK);
+ VibratorManagerService service = createService();
+
+ performHapticFeedbackAndWaitUntilFinished(
+ service, HapticFeedbackConstants.KEYBOARD_TAP, /* always= */ true);
+
+ assertTrue(fakeVibrator.getAllEffectSegments().isEmpty());
+ }
+
+ @Test
+ public void performHapticFeedback_doesNotVibrateForInvalidConstant() throws Exception {
+ denyPermission(android.Manifest.permission.VIBRATE);
+ mockVibrators(1);
+ VibratorManagerService service = createSystemReadyService();
+
+ // These are bad haptic feedback IDs, so expect no vibration played.
+ performHapticFeedbackAndWaitUntilFinished(service, /* constant= */ -1, /* always= */ false);
+ performHapticFeedbackAndWaitUntilFinished(
+ service, HapticFeedbackConstants.NO_HAPTICS, /* always= */ true);
+
+ assertTrue(mVibratorProviders.get(1).getAllEffectSegments().isEmpty());
+ }
+
+ @Test
public void vibrate_withIntensitySettings_appliesSettingsToScaleVibrations() throws Exception {
int defaultNotificationIntensity =
mVibrator.getDefaultVibrationIntensity(VibrationAttributes.USAGE_NOTIFICATION);
@@ -2231,6 +2310,18 @@ public class VibratorManagerServiceTest {
mContextSpy.getContentResolver(), settingName, value, UserHandle.USER_CURRENT);
}
+ private HalVibration performHapticFeedbackAndWaitUntilFinished(VibratorManagerService service,
+ int constant, boolean always) throws InterruptedException {
+ HalVibration vib =
+ service.performHapticFeedbackInternal(UID, Display.DEFAULT_DISPLAY, PACKAGE_NAME,
+ constant, always, "some reason", service);
+ if (vib != null) {
+ vib.waitForEnd();
+ }
+
+ return vib;
+ }
+
private void vibrateAndWaitUntilFinished(VibratorManagerService service, VibrationEffect effect,
VibrationAttributes attrs) throws InterruptedException {
vibrateAndWaitUntilFinished(service, CombinedVibration.createParallel(effect), attrs);
@@ -2239,8 +2330,8 @@ public class VibratorManagerServiceTest {
private void vibrateAndWaitUntilFinished(VibratorManagerService service,
CombinedVibration effect, VibrationAttributes attrs) throws InterruptedException {
HalVibration vib =
- service.vibrateInternal(UID, Display.DEFAULT_DISPLAY, PACKAGE_NAME, effect, attrs,
- "some reason", service);
+ service.vibrateWithPermissionCheck(UID, Display.DEFAULT_DISPLAY, PACKAGE_NAME,
+ effect, attrs, "some reason", service);
if (vib != null) {
vib.waitForEnd();
}
@@ -2271,4 +2362,9 @@ public class VibratorManagerServiceTest {
}
return predicateResult;
}
+
+ private void denyPermission(String permission) {
+ doThrow(new SecurityException()).when(mContextSpy)
+ .enforceCallingOrSelfPermission(eq(permission), anyString());
+ }
}
diff --git a/services/tests/wmtests/src/com/android/server/policy/ShortcutLoggingTests.java b/services/tests/wmtests/src/com/android/server/policy/ShortcutLoggingTests.java
index 8fadecd0dc38..e13dc3eea729 100644
--- a/services/tests/wmtests/src/com/android/server/policy/ShortcutLoggingTests.java
+++ b/services/tests/wmtests/src/com/android/server/policy/ShortcutLoggingTests.java
@@ -65,6 +65,12 @@ public class ShortcutLoggingTests extends ShortcutKeyTestBase {
KeyboardLogEvent.RECENT_APPS, KeyEvent.KEYCODE_TAB, ALT_ON},
{"BACK key -> Go back", new int[]{KeyEvent.KEYCODE_BACK}, KeyboardLogEvent.BACK,
KeyEvent.KEYCODE_BACK, 0},
+ {"Meta + `(grave) -> Go back", new int[]{META_KEY, KeyEvent.KEYCODE_GRAVE},
+ KeyboardLogEvent.BACK, KeyEvent.KEYCODE_GRAVE, META_ON},
+ {"Meta + Left arrow -> Go back", new int[]{META_KEY, KeyEvent.KEYCODE_DPAD_LEFT},
+ KeyboardLogEvent.BACK, KeyEvent.KEYCODE_DPAD_LEFT, META_ON},
+ {"Meta + Del -> Go back", new int[]{META_KEY, KeyEvent.KEYCODE_DEL},
+ KeyboardLogEvent.BACK, KeyEvent.KEYCODE_DEL, META_ON},
{"APP_SWITCH key -> Open App switcher", new int[]{KeyEvent.KEYCODE_APP_SWITCH},
KeyboardLogEvent.APP_SWITCH, KeyEvent.KEYCODE_APP_SWITCH, 0},
{"ASSIST key -> Launch assistant", new int[]{KeyEvent.KEYCODE_ASSIST},
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityStartInterceptorTest.java b/services/tests/wmtests/src/com/android/server/wm/ActivityStartInterceptorTest.java
index bcb0c6b5c269..0989db4c25ac 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityStartInterceptorTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityStartInterceptorTest.java
@@ -59,6 +59,7 @@ import android.os.UserHandle;
import android.os.UserManager;
import android.platform.test.annotations.Presubmit;
import android.testing.DexmakerShareClassLoaderRule;
+import android.util.Pair;
import android.util.SparseArray;
import androidx.test.filters.SmallTest;
@@ -128,6 +129,8 @@ public class ActivityStartInterceptorTest {
private ActivityManagerInternal mAmInternal;
@Mock
private LockTaskController mLockTaskController;
+ @Mock
+ private TaskDisplayArea mTaskDisplayArea;
private ActivityStartInterceptor mInterceptor;
private ActivityInfo mAInfo = new ActivityInfo();
@@ -139,8 +142,8 @@ public class ActivityStartInterceptorTest {
public void setUp() throws RemoteException {
MockitoAnnotations.initMocks(this);
mService.mAmInternal = mAmInternal;
- mInterceptor = new ActivityStartInterceptor(
- mService, mSupervisor, mRootWindowContainer, mContext);
+ mService.mRootWindowContainer = mRootWindowContainer;
+ mInterceptor = new ActivityStartInterceptor(mService, mSupervisor, mContext);
mInterceptor.setStates(TEST_USER_ID, TEST_REAL_CALLING_PID, TEST_REAL_CALLING_UID,
TEST_START_FLAGS, TEST_CALLING_PACKAGE, null);
@@ -201,7 +204,7 @@ public class ActivityStartInterceptorTest {
.thenReturn(PLATFORM_PACKAGE_NAME);
// THEN calling intercept returns true
- assertTrue(mInterceptor.intercept(null, null, mAInfo, null, null, null, 0, 0, null));
+ assertTrue(mInterceptor.intercept(null, null, mAInfo, null, null, null, 0, 0, null, null));
// THEN the returned intent is the admin support intent
assertEquals(ADMIN_SUPPORT_INTENT, mInterceptor.mIntent);
@@ -212,7 +215,7 @@ public class ActivityStartInterceptorTest {
final String suspendingPackage = "com.test.suspending.package";
final SuspendDialogInfo dialogInfo = suspendPackage(suspendingPackage);
// THEN calling intercept returns true
- assertTrue(mInterceptor.intercept(null, null, mAInfo, null, null, null, 0, 0, null));
+ assertTrue(mInterceptor.intercept(null, null, mAInfo, null, null, null, 0, 0, null, null));
// Check intent parameters
assertEquals(dialogInfo,
@@ -243,7 +246,7 @@ public class ActivityStartInterceptorTest {
TEST_USER_ID, TEST_PACKAGE_NAME, LOCK_TASK_LAUNCH_MODE_DEFAULT))
.thenReturn(false);
- assertTrue(mInterceptor.intercept(null, null, mAInfo, null, null, null, 0, 0, null));
+ assertTrue(mInterceptor.intercept(null, null, mAInfo, null, null, null, 0, 0, null, null));
assertTrue(BlockedAppActivity.createIntent(TEST_USER_ID, TEST_PACKAGE_NAME)
.filterEquals(mInterceptor.mIntent));
@@ -257,7 +260,8 @@ public class ActivityStartInterceptorTest {
when(mDevicePolicyManager.isKeepProfilesRunningEnabled()).thenReturn(true);
// THEN calling intercept returns false because package also has to be suspended.
- assertFalse(mInterceptor.intercept(null, null, mAInfo, null, null, null, 0, 0, null));
+ assertFalse(
+ mInterceptor.intercept(null, null, mAInfo, null, null, null, 0, 0, null, null));
}
@Test
@@ -268,7 +272,7 @@ public class ActivityStartInterceptorTest {
when(mDevicePolicyManager.isKeepProfilesRunningEnabled()).thenReturn(false);
// THEN calling intercept returns true
- assertTrue(mInterceptor.intercept(null, null, mAInfo, null, null, null, 0, 0, null));
+ assertTrue(mInterceptor.intercept(null, null, mAInfo, null, null, null, 0, 0, null, null));
// THEN the returned intent is the quiet mode intent
assertTrue(UnlaunchableAppActivity.createInQuietModeDialogIntent(TEST_USER_ID)
@@ -284,7 +288,7 @@ public class ActivityStartInterceptorTest {
when(mDevicePolicyManager.isKeepProfilesRunningEnabled()).thenReturn(true);
// THEN calling intercept returns true
- assertTrue(mInterceptor.intercept(null, null, mAInfo, null, null, null, 0, 0, null));
+ assertTrue(mInterceptor.intercept(null, null, mAInfo, null, null, null, 0, 0, null, null));
// THEN the returned intent is the quiet mode intent
assertTrue(UnlaunchableAppActivity.createInQuietModeDialogIntent(TEST_USER_ID)
@@ -300,7 +304,7 @@ public class ActivityStartInterceptorTest {
when(mDevicePolicyManager.isKeepProfilesRunningEnabled()).thenReturn(false);
// THEN calling intercept returns true
- assertTrue(mInterceptor.intercept(null, null, mAInfo, null, null, null, 0, 0, null));
+ assertTrue(mInterceptor.intercept(null, null, mAInfo, null, null, null, 0, 0, null, null));
// THEN the returned intent is the quiet mode intent
assertTrue(UnlaunchableAppActivity.createInQuietModeDialogIntent(TEST_USER_ID)
@@ -313,7 +317,7 @@ public class ActivityStartInterceptorTest {
when(mAmInternal.shouldConfirmCredentials(TEST_USER_ID)).thenReturn(true);
// THEN calling intercept returns true
- mInterceptor.intercept(null, null, mAInfo, null, null, null, 0, 0, null);
+ mInterceptor.intercept(null, null, mAInfo, null, null, null, 0, 0, null, null);
// THEN the returned intent is the confirm credentials intent
assertTrue(CONFIRM_CREDENTIALS_INTENT.filterEquals(mInterceptor.mIntent));
@@ -329,7 +333,7 @@ public class ActivityStartInterceptorTest {
mAInfo.flags |= ActivityInfo.FLAG_SHOW_WHEN_LOCKED;
// THEN calling intercept returns true
- mInterceptor.intercept(originalIntent, null, mAInfo, null, null, null, 0, 0, null);
+ mInterceptor.intercept(originalIntent, null, mAInfo, null, null, null, 0, 0, null, null);
// THEN the returned intent is original intent
assertSame(originalIntent, mInterceptor.mIntent);
@@ -345,7 +349,7 @@ public class ActivityStartInterceptorTest {
mAInfo.directBootAware = false;
// THEN calling intercept returns true
- mInterceptor.intercept(null, null, mAInfo, null, null, null, 0, 0, null);
+ mInterceptor.intercept(null, null, mAInfo, null, null, null, 0, 0, null, null);
// THEN the returned intent is the confirm credentials intent
assertTrue(CONFIRM_CREDENTIALS_INTENT.filterEquals(mInterceptor.mIntent));
@@ -362,7 +366,7 @@ public class ActivityStartInterceptorTest {
mAInfo.directBootAware = true;
// THEN calling intercept returns true
- mInterceptor.intercept(originalIntent, null, mAInfo, null, null, null, 0, 0, null);
+ mInterceptor.intercept(originalIntent, null, mAInfo, null, null, null, 0, 0, null, null);
// THEN the returned intent is original intent
assertSame(originalIntent, mInterceptor.mIntent);
@@ -375,7 +379,7 @@ public class ActivityStartInterceptorTest {
.thenReturn("This app is bad");
// THEN calling intercept returns true
- assertTrue(mInterceptor.intercept(null, null, mAInfo, null, null, null, 0, 0, null));
+ assertTrue(mInterceptor.intercept(null, null, mAInfo, null, null, null, 0, 0, null, null));
// THEN the returned intent is the harmful app warning intent
assertEquals(HarmfulAppWarningActivity.class.getName(),
@@ -383,11 +387,40 @@ public class ActivityStartInterceptorTest {
}
@Test
+ public void testHomeIntentInterception() {
+ // GIVEN a primary home intent and a display area that doesn't support it but supports
+ // secondary home activities
+ Intent originalIntent = new Intent(Intent.ACTION_MAIN);
+ originalIntent.addCategory(Intent.CATEGORY_HOME);
+
+ Intent expectedIntent = new Intent(Intent.ACTION_MAIN);
+ expectedIntent.addCategory(Intent.CATEGORY_SECONDARY_HOME);
+ expectedIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+
+ final int secondaryDisplayId = 7;
+ when(mTaskDisplayArea.getDisplayId()).thenReturn(secondaryDisplayId);
+ when(mRootWindowContainer.shouldPlacePrimaryHomeOnDisplay(eq(secondaryDisplayId)))
+ .thenReturn(false);
+ when(mRootWindowContainer.shouldPlaceSecondaryHomeOnDisplayArea(eq(mTaskDisplayArea)))
+ .thenReturn(true);
+ when(mRootWindowContainer.resolveSecondaryHomeActivity(
+ eq(TEST_USER_ID), eq(mTaskDisplayArea)))
+ .thenReturn(Pair.create(null, expectedIntent));
+
+ // THEN calling intercept returns true
+ assertTrue(mInterceptor.intercept(originalIntent, null, mAInfo, null, null, null, 0, 0,
+ null, mTaskDisplayArea));
+
+ // THEN the returned intent is the secondary home intent
+ assertSame(expectedIntent, mInterceptor.mIntent);
+ }
+
+ @Test
public void testNoInterception() {
// GIVEN that none of the interception conditions are met
// THEN calling intercept returns false
- assertFalse(mInterceptor.intercept(null, null, mAInfo, null, null, null, 0, 0, null));
+ assertFalse(mInterceptor.intercept(null, null, mAInfo, null, null, null, 0, 0, null, null));
}
public void addMockInterceptorCallback(
@@ -420,7 +453,7 @@ public class ActivityStartInterceptorTest {
new Intent("android.test.foo"),
ActivityOptions.makeBasic().setLaunchDisplayId(3));
- assertTrue(mInterceptor.intercept(null, null, mAInfo, null, null, null, 0, 0, null));
+ assertTrue(mInterceptor.intercept(null, null, mAInfo, null, null, null, 0, 0, null, null));
assertEquals("android.test.foo", mInterceptor.mIntent.getAction());
assertEquals(3, mInterceptor.mActivityOptions.getLaunchDisplayId());
}
@@ -429,7 +462,7 @@ public class ActivityStartInterceptorTest {
public void testInterceptionCallback_singleCallbackReturnsNull() {
addMockInterceptorCallback(null, null);
- assertFalse(mInterceptor.intercept(null, null, mAInfo, null, null, null, 0, 0, null));
+ assertFalse(mInterceptor.intercept(null, null, mAInfo, null, null, null, 0, 0, null, null));
}
@Test
@@ -437,7 +470,7 @@ public class ActivityStartInterceptorTest {
addMockInterceptorCallback(null, null);
addMockInterceptorCallback(new Intent("android.test.second"), null);
- assertTrue(mInterceptor.intercept(null, null, mAInfo, null, null, null, 0, 0, null));
+ assertTrue(mInterceptor.intercept(null, null, mAInfo, null, null, null, 0, 0, null, null));
assertEquals("android.test.second", mInterceptor.mIntent.getAction());
}
@@ -447,7 +480,7 @@ public class ActivityStartInterceptorTest {
new Intent("android.test.foo"),
ActivityOptions.makeBasic().setLaunchDisplayId(3), true);
ActivityInfo aInfo = mAInfo;
- assertTrue(mInterceptor.intercept(null, null, aInfo, null, null, null, 0, 0, null));
+ assertTrue(mInterceptor.intercept(null, null, aInfo, null, null, null, 0, 0, null, null));
assertEquals("android.test.foo", mInterceptor.mIntent.getAction());
assertEquals(3, mInterceptor.mActivityOptions.getLaunchDisplayId());
assertEquals(aInfo, mInterceptor.mAInfo); // mAInfo should not be resolved
@@ -459,7 +492,7 @@ public class ActivityStartInterceptorTest {
new Intent("android.test.foo"),
ActivityOptions.makeBasic().setLaunchDisplayId(3));
ActivityInfo aInfo = mAInfo;
- assertTrue(mInterceptor.intercept(null, null, aInfo, null, null, null, 0, 0, null));
+ assertTrue(mInterceptor.intercept(null, null, aInfo, null, null, null, 0, 0, null, null));
assertEquals("android.test.foo", mInterceptor.mIntent.getAction());
assertEquals(3, mInterceptor.mActivityOptions.getLaunchDisplayId());
assertNotEquals(aInfo, mInterceptor.mAInfo); // mAInfo should be resolved after intercept
@@ -488,7 +521,7 @@ public class ActivityStartInterceptorTest {
when(packageManagerMock.getSdkSandboxPackageName()).thenReturn(sandboxPackageNameMock);
Intent intent = new Intent().setAction(ACTION_START_SANDBOXED_ACTIVITY);
- mInterceptor.intercept(intent, null, mAInfo, null, null, null, 0, 0, null);
+ mInterceptor.intercept(intent, null, mAInfo, null, null, null, 0, 0, null, null);
verify(spyCallback, times(1)).onInterceptActivityLaunch(
any(ActivityInterceptorCallback.ActivityInterceptorInfo.class));
@@ -505,7 +538,7 @@ public class ActivityStartInterceptorTest {
when(packageManagerMock.getSdkSandboxPackageName()).thenReturn(sandboxPackageNameMock);
Intent intent = new Intent().setPackage(sandboxPackageNameMock);
- mInterceptor.intercept(intent, null, mAInfo, null, null, null, 0, 0, null);
+ mInterceptor.intercept(intent, null, mAInfo, null, null, null, 0, 0, null, null);
verify(spyCallback, times(1)).onInterceptActivityLaunch(
any(ActivityInterceptorCallback.ActivityInterceptorInfo.class));
@@ -522,7 +555,7 @@ public class ActivityStartInterceptorTest {
when(packageManagerMock.getSdkSandboxPackageName()).thenReturn(sandboxPackageNameMock);
Intent intent = new Intent().setComponent(new ComponentName(sandboxPackageNameMock, ""));
- mInterceptor.intercept(intent, null, mAInfo, null, null, null, 0, 0, null);
+ mInterceptor.intercept(intent, null, mAInfo, null, null, null, 0, 0, null, null);
verify(spyCallback, times(1)).onInterceptActivityLaunch(
any(ActivityInterceptorCallback.ActivityInterceptorInfo.class));
@@ -539,23 +572,23 @@ public class ActivityStartInterceptorTest {
when(packageManagerMock.getSdkSandboxPackageName()).thenReturn(sandboxPackageNameMock);
// Intent: null
- mInterceptor.intercept(null, null, mAInfo, null, null, null, 0, 0, null);
+ mInterceptor.intercept(null, null, mAInfo, null, null, null, 0, 0, null, null);
// Action: null, Package: null, ComponentName: null
Intent intent = new Intent();
- mInterceptor.intercept(intent, null, mAInfo, null, null, null, 0, 0, null);
+ mInterceptor.intercept(intent, null, mAInfo, null, null, null, 0, 0, null, null);
// Wrong Action
intent = new Intent().setAction(Intent.ACTION_VIEW);
- mInterceptor.intercept(intent, null, mAInfo, null, null, null, 0, 0, null);
+ mInterceptor.intercept(intent, null, mAInfo, null, null, null, 0, 0, null, null);
// Wrong Package
intent = new Intent().setPackage("Random");
- mInterceptor.intercept(intent, null, mAInfo, null, null, null, 0, 0, null);
+ mInterceptor.intercept(intent, null, mAInfo, null, null, null, 0, 0, null, null);
// Wrong ComponentName's package
intent = new Intent().setComponent(new ComponentName("Random", ""));
- mInterceptor.intercept(intent, null, mAInfo, null, null, null, 0, 0, null);
+ mInterceptor.intercept(intent, null, mAInfo, null, null, null, 0, 0, null, null);
verify(spyCallback, never()).onInterceptActivityLaunch(
any(ActivityInterceptorCallback.ActivityInterceptorInfo.class));
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 cb92cc5cff67..ae87e38d8faf 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java
@@ -1662,9 +1662,10 @@ public class ActivityStarterTests extends WindowTestsBase {
@Test
public void testResultCanceledWhenNotAllowedStartingActivity() {
+ final Task task = new TaskBuilder(mSupervisor).build();
final ActivityStarter starter = prepareStarter(0, false);
final ActivityRecord targetRecord = new ActivityBuilder(mAtm).build();
- final ActivityRecord sourceRecord = new ActivityBuilder(mAtm).build();
+ final ActivityRecord sourceRecord = new ActivityBuilder(mAtm).setTask(task).build();
targetRecord.resultTo = sourceRecord;
// Abort the activity start and ensure the sourceRecord gets the result (RESULT_CANCELED).
diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyTests.java
index dd90e0450280..bf86563e3d86 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyTests.java
@@ -16,6 +16,7 @@
package com.android.server.wm;
+import static android.inputmethodservice.InputMethodService.ENABLE_HIDE_IME_CAPTION_BAR;
import static android.view.DisplayCutout.NO_CUTOUT;
import static android.view.InsetsSource.ID_IME;
import static android.view.RoundedCorners.NO_ROUNDED_CORNERS;
@@ -427,11 +428,11 @@ public class DisplayPolicyTests extends WindowTestsBase {
@SetupWindows(addWindows = { W_NAVIGATION_BAR, W_INPUT_METHOD })
@Test
public void testImeMinimalSourceFrame() {
+ Assume.assumeFalse("Behavior no longer needed with ENABLE_HIDE_IME_CAPTION_BAR",
+ ENABLE_HIDE_IME_CAPTION_BAR);
+
final DisplayPolicy displayPolicy = mDisplayContent.getDisplayPolicy();
- final DisplayInfo displayInfo = new DisplayInfo();
- displayInfo.logicalWidth = 1000;
- displayInfo.logicalHeight = 2000;
- displayInfo.rotation = ROTATION_0;
+ final DisplayInfo displayInfo = mDisplayContent.getDisplayInfo();
WindowManager.LayoutParams attrs = mNavBarWindow.mAttrs;
displayPolicy.addWindowLw(mNavBarWindow, attrs);
@@ -466,10 +467,6 @@ public class DisplayPolicyTests extends WindowTestsBase {
@Test
public void testImeInsetsGivenContentFrame() {
final DisplayPolicy displayPolicy = mDisplayContent.getDisplayPolicy();
- final DisplayInfo displayInfo = new DisplayInfo();
- displayInfo.logicalWidth = 1000;
- displayInfo.logicalHeight = 2000;
- displayInfo.rotation = ROTATION_0;
mDisplayContent.setInputMethodWindowLocked(mImeWindow);
mImeWindow.getControllableInsetProvider().setServerVisible(true);
diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayRotationTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayRotationTests.java
index c4302db16b98..915b387ddb75 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DisplayRotationTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DisplayRotationTests.java
@@ -583,6 +583,7 @@ public class DisplayRotationTests {
enableOrientationSensor();
+ clearInvocations(sMockWm);
mOrientationSensorListener.onSensorChanged(createSensorEvent(Surface.ROTATION_90));
assertTrue(waitForUiHandler());
@@ -627,6 +628,7 @@ public class DisplayRotationTests {
when(mDisplayRotationImmersiveAppCompatPolicyMock.isRotationLockEnforced(
Surface.ROTATION_90)).thenReturn(false);
+ clearInvocations(sMockWm);
// And then ActivityRecord.setRequestedOrientation calls onSetRequestedOrientation.
mTarget.onSetRequestedOrientation();
@@ -864,6 +866,7 @@ public class DisplayRotationTests {
assertEquals(Surface.ROTATION_270, mTarget.rotationForOrientation(
SCREEN_ORIENTATION_UNSPECIFIED, Surface.ROTATION_0));
+ clearInvocations(sMockWm);
// ... until half-fold
mTarget.foldStateChanged(DeviceStateController.DeviceState.HALF_FOLDED);
assertTrue(waitForUiHandler());
@@ -899,6 +902,7 @@ public class DisplayRotationTests {
assertEquals(Surface.ROTATION_270, mTarget.rotationForOrientation(
SCREEN_ORIENTATION_UNSPECIFIED, Surface.ROTATION_0));
+ clearInvocations(sMockWm);
// ... half-fold -> still no rotation
mTarget.foldStateChanged(DeviceStateController.DeviceState.HALF_FOLDED);
assertTrue(waitForUiHandler());
@@ -1194,12 +1198,12 @@ public class DisplayRotationTests {
}
@Test
- public void testIsFixedToUserRotation_displayContentOrientationFixed() throws Exception {
+ public void testIsFixedToUserRotation_displayShouldNotRotateWithContent() throws Exception {
mBuilder.build();
- when(mMockDisplayContent.isDisplayOrientationFixed()).thenReturn(true);
+ when(mMockDisplayContent.shouldRotateWithContent()).thenReturn(false);
assertFalse("Display rotation should respect app requested orientation if"
- + " the display has fixed orientation.", mTarget.isFixedToUserRotation());
+ + " the display does not rotate with content.", mTarget.isFixedToUserRotation());
}
@Test
@@ -1453,6 +1457,7 @@ public class DisplayRotationTests {
.thenReturn(mock(TaskDisplayArea.class));
when(mMockDisplayContent.getWindowConfiguration())
.thenReturn(new WindowConfiguration());
+ when(mMockDisplayContent.shouldRotateWithContent()).thenReturn(true);
Field field = DisplayContent.class
.getDeclaredField("mFixedRotationTransitionListener");
diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayWindowPolicyControllerTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayWindowPolicyControllerTests.java
index 5dfb901a7c1e..30a89412d946 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DisplayWindowPolicyControllerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DisplayWindowPolicyControllerTests.java
@@ -44,7 +44,6 @@ import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
-import java.util.List;
import java.util.Set;
/**
@@ -106,7 +105,6 @@ public class DisplayWindowPolicyControllerTests extends WindowTestsBase {
assertEquals(uidAmount, mDwpc.mRunningUids.size());
assertTrue(mDwpc.mRunningUids.contains(TEST_USER_0_ID) == expectedUid0);
assertTrue(mDwpc.mRunningUids.contains(TEST_USER_1_ID) == expectedUid1);
-
}
private ActivityRecord launchActivityOnDisplay(DisplayContent display, int uid) {
@@ -197,6 +195,11 @@ public class DisplayWindowPolicyControllerTests extends WindowTestsBase {
@Test
public void testCanActivityBeLaunched_requiredDisplayCategory() {
+ doReturn(null).when(mWm.mDisplayManagerInternal)
+ .getDisplayWindowPolicyController(anyInt());
+ mSecondaryDisplay = createNewDisplay();
+ assertFalse(mSecondaryDisplay.mDwpcHelper.hasController());
+
ActivityStarter starter = new ActivityStarter(mock(ActivityStartController.class), mAtm,
mSupervisor, mock(ActivityStartInterceptor.class));
final Task task = new TaskBuilder(mSupervisor).setDisplay(mSecondaryDisplay).build();
@@ -233,20 +236,14 @@ public class DisplayWindowPolicyControllerTests extends WindowTestsBase {
public boolean canActivityBeLaunched(@NonNull ActivityInfo activity, Intent intent,
@WindowConfiguration.WindowingMode int windowingMode, int launchingFromDisplayId,
boolean isNewTask) {
- return false;
+ return canContainActivity(activity, windowingMode, launchingFromDisplayId, isNewTask);
}
@Override
- public boolean canContainActivities(@NonNull List<ActivityInfo> activities,
- @WindowConfiguration.WindowingMode int windowingMode) {
- final int activityCount = activities.size();
- for (int i = 0; i < activityCount; i++) {
- final ActivityInfo aInfo = activities.get(i);
- if (aInfo.getComponentName().equals(DISALLOWED_ACTIVITY)) {
- return false;
- }
- }
- return true;
+ protected boolean canContainActivity(@NonNull ActivityInfo activity,
+ @WindowConfiguration.WindowingMode int windowingMode, int launchingFromDisplayId,
+ boolean isNewTask) {
+ return !activity.getComponentName().equals(DISALLOWED_ACTIVITY);
}
@Override
diff --git a/services/tests/wmtests/src/com/android/server/wm/LetterboxConfigurationPersisterTest.java b/services/tests/wmtests/src/com/android/server/wm/LetterboxConfigurationPersisterTest.java
index 06033c7ebf75..3fcec963593c 100644
--- a/services/tests/wmtests/src/com/android/server/wm/LetterboxConfigurationPersisterTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/LetterboxConfigurationPersisterTest.java
@@ -184,7 +184,7 @@ public class LetterboxConfigurationPersisterTest {
LETTERBOX_HORIZONTAL_REACHABILITY_POSITION_LEFT);
firstPersister.setLetterboxPositionForVerticalReachability(false,
LETTERBOX_VERTICAL_REACHABILITY_POSITION_TOP);
- waitForCompletion(mPersisterQueue);
+ waitForCompletion(firstPersisterQueue);
final int newPositionForHorizontalReachability =
firstPersister.getLetterboxPositionForHorizontalReachability(false);
final int newPositionForVerticalReachability =
diff --git a/services/tests/wmtests/src/com/android/server/wm/LetterboxConfigurationTest.java b/services/tests/wmtests/src/com/android/server/wm/LetterboxConfigurationTest.java
index e1fc0cfdc317..80e169d8d579 100644
--- a/services/tests/wmtests/src/com/android/server/wm/LetterboxConfigurationTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/LetterboxConfigurationTest.java
@@ -250,4 +250,42 @@ public class LetterboxConfigurationTest {
times(expectedTime)).setLetterboxPositionForVerticalReachability(halfFoldPose,
expected);
}
+
+ @Test
+ public void test_letterboxPositionWhenReachabilityEnabledIsReset() {
+ // Check that horizontal reachability is set with correct arguments
+ mLetterboxConfiguration.resetPersistentLetterboxPositionForHorizontalReachability();
+ verify(mLetterboxConfigurationPersister).setLetterboxPositionForHorizontalReachability(
+ false /* forBookMode */,
+ LETTERBOX_HORIZONTAL_REACHABILITY_POSITION_CENTER);
+ verify(mLetterboxConfigurationPersister).setLetterboxPositionForHorizontalReachability(
+ true /* forBookMode */,
+ LETTERBOX_HORIZONTAL_REACHABILITY_POSITION_LEFT);
+
+ // Check that vertical reachability is set with correct arguments
+ mLetterboxConfiguration.resetPersistentLetterboxPositionForVerticalReachability();
+ verify(mLetterboxConfigurationPersister).setLetterboxPositionForVerticalReachability(
+ false /* forTabletopMode */,
+ LETTERBOX_VERTICAL_REACHABILITY_POSITION_CENTER);
+ verify(mLetterboxConfigurationPersister).setLetterboxPositionForVerticalReachability(
+ true /* forTabletopMode */,
+ LETTERBOX_VERTICAL_REACHABILITY_POSITION_TOP);
+ }
+
+ @Test
+ public void test_lettterboxPositionWhenReachabilityEnabledIsSet() {
+ // Check that horizontal reachability is set with correct arguments
+ mLetterboxConfiguration.setPersistentLetterboxPositionForHorizontalReachability(
+ false /* forBookMode */, LETTERBOX_HORIZONTAL_REACHABILITY_POSITION_LEFT);
+ verify(mLetterboxConfigurationPersister).setLetterboxPositionForHorizontalReachability(
+ false /* forBookMode */,
+ LETTERBOX_HORIZONTAL_REACHABILITY_POSITION_LEFT);
+
+ // Check that vertical reachability is set with correct arguments
+ mLetterboxConfiguration.setPersistentLetterboxPositionForVerticalReachability(
+ false /* forTabletopMode */, LETTERBOX_VERTICAL_REACHABILITY_POSITION_TOP);
+ verify(mLetterboxConfigurationPersister).setLetterboxPositionForVerticalReachability(
+ false /* forTabletopMode */,
+ LETTERBOX_VERTICAL_REACHABILITY_POSITION_TOP);
+ }
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskLaunchParamsModifierTests.java b/services/tests/wmtests/src/com/android/server/wm/TaskLaunchParamsModifierTests.java
index 739737eb318d..07cfbf094e5d 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskLaunchParamsModifierTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskLaunchParamsModifierTests.java
@@ -678,6 +678,39 @@ public class TaskLaunchParamsModifierTests extends WindowTestsBase {
WINDOWING_MODE_FULLSCREEN);
}
+ @Test
+ public void testInheritsSourceTaskWindowingModeWhenActivityIsInDifferentWindowingMode() {
+ final TestDisplayContent fullscreenDisplay = createNewDisplayContent(
+ WINDOWING_MODE_FULLSCREEN);
+ final ActivityRecord source = createSourceActivity(fullscreenDisplay);
+ source.setWindowingMode(WINDOWING_MODE_PINNED);
+ source.getTask().setWindowingMode(WINDOWING_MODE_FREEFORM);
+
+ assertEquals(RESULT_CONTINUE,
+ new CalculateRequestBuilder().setSource(source).calculate());
+
+ assertEquivalentWindowingMode(WINDOWING_MODE_FREEFORM, mResult.mWindowingMode,
+ WINDOWING_MODE_FULLSCREEN);
+ }
+
+ @Test
+ public void testDoesNotInheritsSourceTaskWindowingModeWhenActivityIsInFreeformWindowingMode() {
+ // The activity could end up in different windowing mode state after calling finish()
+ // while the task would still hold the WINDOWING_MODE_PINNED state, or in other words
+ // be still in the Picture in Picture mode.
+ final TestDisplayContent fullscreenDisplay = createNewDisplayContent(
+ WINDOWING_MODE_FULLSCREEN);
+ final ActivityRecord source = createSourceActivity(fullscreenDisplay);
+ source.setWindowingMode(WINDOWING_MODE_FREEFORM);
+ source.getTask().setWindowingMode(WINDOWING_MODE_PINNED);
+
+ assertEquals(RESULT_CONTINUE,
+ new CalculateRequestBuilder().setSource(source).calculate());
+
+ assertEquivalentWindowingMode(WINDOWING_MODE_FULLSCREEN, mResult.mWindowingMode,
+ WINDOWING_MODE_FULLSCREEN);
+ }
+
@Test
public void testKeepsPictureInPictureLaunchModeInOptions() {
diff --git a/startop/apps/ColorChanging/app/build.gradle b/startop/apps/ColorChanging/app/build.gradle
index ab955aaf90ee..11b14c04f1b9 100644
--- a/startop/apps/ColorChanging/app/build.gradle
+++ b/startop/apps/ColorChanging/app/build.gradle
@@ -14,7 +14,7 @@ android {
buildTypes {
release {
minifyEnabled false
- proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
+ proguardFiles getDefaultProguardFile('proguard-android-optimize.txt')
}
}
}
diff --git a/startop/apps/ColorChanging/app/proguard-rules.pro b/startop/apps/ColorChanging/app/proguard-rules.pro
deleted file mode 100644
index f1b424510da5..000000000000
--- a/startop/apps/ColorChanging/app/proguard-rules.pro
+++ /dev/null
@@ -1,21 +0,0 @@
-# Add project specific ProGuard rules here.
-# You can control the set of applied configuration files using the
-# proguardFiles setting in build.gradle.
-#
-# For more details, see
-# http://developer.android.com/guide/developing/tools/proguard.html
-
-# If your project uses WebView with JS, uncomment the following
-# and specify the fully qualified class name to the JavaScript interface
-# class:
-#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
-# public *;
-#}
-
-# Uncomment this to preserve the line number information for
-# debugging stack traces.
-#-keepattributes SourceFile,LineNumberTable
-
-# If you keep the line number information, uncomment this to
-# hide the original source file name.
-#-renamesourcefileattribute SourceFile
diff --git a/telecomm/java/android/telecom/Call.java b/telecomm/java/android/telecom/Call.java
index e51696e58f57..7d9b3790c1b5 100644
--- a/telecomm/java/android/telecom/Call.java
+++ b/telecomm/java/android/telecom/Call.java
@@ -16,6 +16,7 @@
package android.telecom;
+import android.annotation.FlaggedApi;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -31,6 +32,7 @@ import android.os.Handler;
import android.os.ParcelFileDescriptor;
import com.android.internal.telecom.IVideoProvider;
+import com.android.server.telecom.flags.Flags;
import java.io.IOException;
import java.io.InputStreamReader;
@@ -720,6 +722,7 @@ public final class Call {
* The underlying connection was added as a transactional call via the
* {@link TelecomManager#addCall} API.
*/
+ @FlaggedApi(Flags.FLAG_VOIP_APP_ACTIONS_SUPPORT)
public static final int PROPERTY_IS_TRANSACTIONAL = 0x00008000;
//******************************************************************************************
diff --git a/telecomm/java/android/telecom/CallEndpoint.java b/telecomm/java/android/telecom/CallEndpoint.java
index ed4bf40061e2..a557cafd309a 100644
--- a/telecomm/java/android/telecom/CallEndpoint.java
+++ b/telecomm/java/android/telecom/CallEndpoint.java
@@ -127,7 +127,7 @@ public final class CallEndpoint implements Parcelable {
return false;
}
CallEndpoint endpoint = (CallEndpoint) obj;
- return getEndpointName().toString().contentEquals(endpoint.getEndpointName())
+ return Objects.equals(getEndpointName(), endpoint.getEndpointName())
&& getEndpointType() == endpoint.getEndpointType()
&& getIdentifier().equals(endpoint.getIdentifier());
}
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index 0bb75d87ffc1..0c8603b339d3 100644
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -9456,6 +9456,19 @@ public class CarrierConfigManager {
"carrier_supported_satellite_services_per_provider_bundle";
/**
+ * This config enables modem to scan satellite PLMNs specified as per
+ * {@link #KEY_CARRIER_SUPPORTED_SATELLITE_SERVICES_PER_PROVIDER_BUNDLE} and attach to same
+ * in case cellular networks are not enabled. This will need specific agreement between
+ * satellite provider and the carrier before enabling this flag.
+ *
+ * The default value is false.
+ *
+ * @hide
+ */
+ public static final String KEY_SATELLITE_ATTACH_SUPPORTED_BOOL =
+ "satellite_attach_supported_bool";
+
+ /**
* Indicating whether DUN APN should be disabled when the device is roaming. In that case,
* the default APN (i.e. internet) will be used for tethering.
*
@@ -9881,9 +9894,15 @@ public class CarrierConfigManager {
sDefaults.putBoolean(KEY_USE_ONLY_DIALED_SIM_ECC_LIST_BOOL, false);
sDefaults.putString(KEY_CARRIER_NETWORK_SERVICE_WWAN_PACKAGE_OVERRIDE_STRING, "");
sDefaults.putString(KEY_CARRIER_NETWORK_SERVICE_WLAN_PACKAGE_OVERRIDE_STRING, "");
+ sDefaults.putString(KEY_CARRIER_NETWORK_SERVICE_WLAN_CLASS_OVERRIDE_STRING, "");
+ sDefaults.putString(KEY_CARRIER_NETWORK_SERVICE_WWAN_CLASS_OVERRIDE_STRING, "");
sDefaults.putString(KEY_CARRIER_QUALIFIED_NETWORKS_SERVICE_PACKAGE_OVERRIDE_STRING, "");
+ sDefaults.putString(KEY_CARRIER_QUALIFIED_NETWORKS_SERVICE_CLASS_OVERRIDE_STRING, "");
sDefaults.putString(KEY_CARRIER_DATA_SERVICE_WWAN_PACKAGE_OVERRIDE_STRING, "");
sDefaults.putString(KEY_CARRIER_DATA_SERVICE_WLAN_PACKAGE_OVERRIDE_STRING, "");
+ sDefaults.putString(KEY_CARRIER_DATA_SERVICE_WWAN_CLASS_OVERRIDE_STRING, "");
+ sDefaults.putString(KEY_CARRIER_DATA_SERVICE_WLAN_CLASS_OVERRIDE_STRING, "");
+ sDefaults.putString(KEY_CONFIG_PLANS_PACKAGE_OVERRIDE_STRING, "");
sDefaults.putString(KEY_CARRIER_INSTANT_LETTERING_INVALID_CHARS_STRING, "");
sDefaults.putString(KEY_CARRIER_INSTANT_LETTERING_ESCAPED_CHARS_STRING, "");
sDefaults.putString(KEY_CARRIER_INSTANT_LETTERING_ENCODING_STRING, "");
@@ -10465,6 +10484,7 @@ public class CarrierConfigManager {
sDefaults.putPersistableBundle(
KEY_CARRIER_SUPPORTED_SATELLITE_SERVICES_PER_PROVIDER_BUNDLE,
PersistableBundle.EMPTY);
+ sDefaults.putBoolean(KEY_SATELLITE_ATTACH_SUPPORTED_BOOL, false);
sDefaults.putBoolean(KEY_DISABLE_DUN_APN_WHILE_ROAMING_WITH_PRESET_APN_BOOL, false);
sDefaults.putString(KEY_DEFAULT_PREFERRED_APN_NAME_STRING, "");
sDefaults.putBoolean(KEY_SUPPORTS_CALL_COMPOSER_BOOL, false);
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index 69b1d6333596..234ca918a144 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -2649,10 +2649,6 @@ public class TelephonyManager {
return getCurrentPhoneType();
}
- private int getPhoneTypeFromProperty() {
- return getPhoneTypeFromProperty(getPhoneId());
- }
-
/** {@hide} */
@UnsupportedAppUsage
private int getPhoneTypeFromProperty(int phoneId) {
@@ -2662,10 +2658,6 @@ public class TelephonyManager {
return getPhoneTypeFromNetworkType(phoneId);
}
- private int getPhoneTypeFromNetworkType() {
- return getPhoneTypeFromNetworkType(getPhoneId());
- }
-
/** {@hide} */
private int getPhoneTypeFromNetworkType(int phoneId) {
// When the system property CURRENT_ACTIVE_PHONE, has not been set,
@@ -11564,16 +11556,6 @@ public class TelephonyManager {
}
/**
- * Set TelephonyProperties.icc_operator_numeric for the default phone.
- *
- * @hide
- */
- public void setSimOperatorNumeric(String numeric) {
- int phoneId = getPhoneId();
- setSimOperatorNumericForPhone(phoneId, numeric);
- }
-
- /**
* Set TelephonyProperties.icc_operator_numeric for the given phone.
*
* @hide
@@ -11588,16 +11570,6 @@ public class TelephonyManager {
}
/**
- * Set TelephonyProperties.icc_operator_alpha for the default phone.
- *
- * @hide
- */
- public void setSimOperatorName(String name) {
- int phoneId = getPhoneId();
- setSimOperatorNameForPhone(phoneId, name);
- }
-
- /**
* Set TelephonyProperties.icc_operator_alpha for the given phone.
*
* @hide
@@ -11850,17 +11822,6 @@ public class TelephonyManager {
}
/**
- * Set baseband version for the default phone.
- *
- * @param version baseband version
- * @hide
- */
- public void setBasebandVersion(String version) {
- int phoneId = getPhoneId();
- setBasebandVersionForPhone(phoneId, version);
- }
-
- /**
* Set baseband version by phone id.
*
* @param phoneId for which baseband version is set
@@ -11898,18 +11859,6 @@ public class TelephonyManager {
}
/**
- * Set phone type for the default phone.
- *
- * @param type phone type
- *
- * @hide
- */
- public void setPhoneType(int type) {
- int phoneId = getPhoneId();
- setPhoneType(phoneId, type);
- }
-
- /**
* Set phone type by phone id.
*
* @param phoneId for which phone type is set
@@ -11927,19 +11876,6 @@ public class TelephonyManager {
}
/**
- * Get OTASP number schema for the default phone.
- *
- * @param defaultValue default value
- * @return OTA SP number schema
- *
- * @hide
- */
- public String getOtaSpNumberSchema(String defaultValue) {
- int phoneId = getPhoneId();
- return getOtaSpNumberSchemaForPhone(phoneId, defaultValue);
- }
-
- /**
* Get OTASP number schema by phone id.
*
* @param phoneId for which OTA SP number schema is get
@@ -11959,19 +11895,6 @@ public class TelephonyManager {
}
/**
- * Get SMS receive capable from system property for the default phone.
- *
- * @param defaultValue default value
- * @return SMS receive capable
- *
- * @hide
- */
- public boolean getSmsReceiveCapable(boolean defaultValue) {
- int phoneId = getPhoneId();
- return getSmsReceiveCapableForPhone(phoneId, defaultValue);
- }
-
- /**
* Get SMS receive capable from system property by phone id.
*
* @param phoneId for which SMS receive capable is get
@@ -11989,19 +11912,6 @@ public class TelephonyManager {
}
/**
- * Get SMS send capable from system property for the default phone.
- *
- * @param defaultValue default value
- * @return SMS send capable
- *
- * @hide
- */
- public boolean getSmsSendCapable(boolean defaultValue) {
- int phoneId = getPhoneId();
- return getSmsSendCapableForPhone(phoneId, defaultValue);
- }
-
- /**
* Get SMS send capable from system property by phone id.
*
* @param phoneId for which SMS send capable is get
@@ -12065,16 +11975,6 @@ public class TelephonyManager {
/**
* Set the alphabetic name of current registered operator.
- * @param name the alphabetic name of current registered operator.
- * @hide
- */
- public void setNetworkOperatorName(String name) {
- int phoneId = getPhoneId();
- setNetworkOperatorNameForPhone(phoneId, name);
- }
-
- /**
- * Set the alphabetic name of current registered operator.
* @param phoneId which phone you want to set
* @param name the alphabetic name of current registered operator.
* @hide
@@ -12108,16 +12008,6 @@ public class TelephonyManager {
/**
* Set the numeric name (MCC+MNC) of current registered operator.
- * @param operator the numeric name (MCC+MNC) of current registered operator
- * @hide
- */
- public void setNetworkOperatorNumeric(String numeric) {
- int phoneId = getPhoneId();
- setNetworkOperatorNumericForPhone(phoneId, numeric);
- }
-
- /**
- * Set the numeric name (MCC+MNC) of current registered operator.
* @param phoneId for which phone type is set
* @param operator the numeric name (MCC+MNC) of current registered operator
* @hide
@@ -12133,16 +12023,6 @@ public class TelephonyManager {
/**
* Set roaming state of the current network, for GSM purposes.
- * @param isRoaming is network in romaing state or not
- * @hide
- */
- public void setNetworkRoaming(boolean isRoaming) {
- int phoneId = getPhoneId();
- setNetworkRoamingForPhone(phoneId, isRoaming);
- }
-
- /**
- * Set roaming state of the current network, for GSM purposes.
* @param phoneId which phone you want to set
* @param isRoaming is network in romaing state or not
* @hide
@@ -12321,21 +12201,6 @@ public class TelephonyManager {
}
/**
- * TODO delete after SuW migrates to new API.
- * @hide
- */
- public String getLocaleFromDefaultSim() {
- try {
- final ITelephony telephony = getITelephony();
- if (telephony != null) {
- return telephony.getSimLocaleForSubscriber(getSubId());
- }
- } catch (RemoteException ex) {
- }
- return null;
- }
-
- /**
* Exception that may be supplied to the callback provided in {@link #requestModemActivityInfo}.
* @hide
*/
diff --git a/telephony/java/android/telephony/satellite/SatelliteManager.java b/telephony/java/android/telephony/satellite/SatelliteManager.java
index 9994002a4a37..5f6c14a36d46 100644
--- a/telephony/java/android/telephony/satellite/SatelliteManager.java
+++ b/telephony/java/android/telephony/satellite/SatelliteManager.java
@@ -44,10 +44,14 @@ import com.android.telephony.Rlog;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.time.Duration;
+import java.util.Arrays;
+import java.util.HashSet;
import java.util.Objects;
+import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Executor;
import java.util.function.Consumer;
+import java.util.stream.Collectors;
/**
* Manages satellite operations such as provisioning, pointing, messaging, location sharing, etc.
@@ -79,6 +83,23 @@ public final class SatelliteManager {
@Nullable private final Context mContext;
/**
+ * Create a new SatelliteManager object pinned to the given subscription ID.
+ * This is needed only to handle carrier specific satellite features.
+ * For eg: requestSatelliteAttachEnabledForCarrier and
+ * requestIsSatelliteAttachEnabledForCarrier
+ *
+ * @return a SatelliteManager that uses the given subId for all satellite activities.
+ * @throws IllegalArgumentException if the subscription is invalid.
+ * @hide
+ */
+ public SatelliteManager createForSubscriptionId(int subId) {
+ if (!SubscriptionManager.isValidSubscriptionId(subId)) {
+ throw new IllegalArgumentException("Invalid subscription ID");
+ }
+ return new SatelliteManager(mContext, subId);
+ }
+
+ /**
* Create an instance of the SatelliteManager.
*
* @param context The context the SatelliteManager belongs to.
@@ -101,26 +122,26 @@ public final class SatelliteManager {
}
/**
- * Exception from the satellite service containing the {@link SatelliteError} error code.
+ * Exception from the satellite service containing the {@link SatelliteResult} error code.
*/
public static class SatelliteException extends Exception {
- @SatelliteError private final int mErrorCode;
+ @SatelliteResult private final int mErrorCode;
/**
* Create a SatelliteException with a given error code.
*
- * @param errorCode The {@link SatelliteError}.
+ * @param errorCode The {@link SatelliteResult}.
*/
- public SatelliteException(@SatelliteError int errorCode) {
+ public SatelliteException(@SatelliteResult int errorCode) {
mErrorCode = errorCode;
}
/**
* Get the error code returned from the satellite service.
*
- * @return The {@link SatelliteError}.
+ * @return The {@link SatelliteResult}.
*/
- @SatelliteError public int getErrorCode() {
+ @SatelliteResult public int getErrorCode() {
return mErrorCode;
}
}
@@ -185,134 +206,134 @@ public final class SatelliteManager {
/**
* The request was successfully processed.
*/
- public static final int SATELLITE_ERROR_NONE = 0;
+ public static final int SATELLITE_RESULT_SUCCESS = 0;
/**
* A generic error which should be used only when other specific errors cannot be used.
*/
- public static final int SATELLITE_ERROR = 1;
+ public static final int SATELLITE_RESULT_ERROR = 1;
/**
* Error received from the satellite server.
*/
- public static final int SATELLITE_SERVER_ERROR = 2;
+ public static final int SATELLITE_RESULT_SERVER_ERROR = 2;
/**
* Error received from the vendor service. This generic error code should be used
* only when the error cannot be mapped to other specific service error codes.
*/
- public static final int SATELLITE_SERVICE_ERROR = 3;
+ public static final int SATELLITE_RESULT_SERVICE_ERROR = 3;
/**
* Error received from satellite modem. This generic error code should be used only when
* the error cannot be mapped to other specific modem error codes.
*/
- public static final int SATELLITE_MODEM_ERROR = 4;
+ public static final int SATELLITE_RESULT_MODEM_ERROR = 4;
/**
* Error received from the satellite network. This generic error code should be used only when
* the error cannot be mapped to other specific network error codes.
*/
- public static final int SATELLITE_NETWORK_ERROR = 5;
+ public static final int SATELLITE_RESULT_NETWORK_ERROR = 5;
/**
* Telephony is not in a valid state to receive requests from clients.
*/
- public static final int SATELLITE_INVALID_TELEPHONY_STATE = 6;
+ public static final int SATELLITE_RESULT_INVALID_TELEPHONY_STATE = 6;
/**
* Satellite modem is not in a valid state to receive requests from clients.
*/
- public static final int SATELLITE_INVALID_MODEM_STATE = 7;
+ public static final int SATELLITE_RESULT_INVALID_MODEM_STATE = 7;
/**
* Either vendor service, or modem, or Telephony framework has received a request with
* invalid arguments from its clients.
*/
- public static final int SATELLITE_INVALID_ARGUMENTS = 8;
+ public static final int SATELLITE_RESULT_INVALID_ARGUMENTS = 8;
/**
* Telephony framework failed to send a request or receive a response from the vendor service
* or satellite modem due to internal error.
*/
- public static final int SATELLITE_REQUEST_FAILED = 9;
+ public static final int SATELLITE_RESULT_REQUEST_FAILED = 9;
/**
* Radio did not start or is resetting.
*/
- public static final int SATELLITE_RADIO_NOT_AVAILABLE = 10;
+ public static final int SATELLITE_RESULT_RADIO_NOT_AVAILABLE = 10;
/**
* The request is not supported by either the satellite modem or the network.
*/
- public static final int SATELLITE_REQUEST_NOT_SUPPORTED = 11;
+ public static final int SATELLITE_RESULT_REQUEST_NOT_SUPPORTED = 11;
/**
* Satellite modem or network has no resources available to handle requests from clients.
*/
- public static final int SATELLITE_NO_RESOURCES = 12;
+ public static final int SATELLITE_RESULT_NO_RESOURCES = 12;
/**
* Satellite service is not provisioned yet.
*/
- public static final int SATELLITE_SERVICE_NOT_PROVISIONED = 13;
+ public static final int SATELLITE_RESULT_SERVICE_NOT_PROVISIONED = 13;
/**
* Satellite service provision is already in progress.
*/
- public static final int SATELLITE_SERVICE_PROVISION_IN_PROGRESS = 14;
+ public static final int SATELLITE_RESULT_SERVICE_PROVISION_IN_PROGRESS = 14;
/**
* The ongoing request was aborted by either the satellite modem or the network.
* This error is also returned when framework decides to abort current send request as one
* of the previous send request failed.
*/
- public static final int SATELLITE_REQUEST_ABORTED = 15;
+ public static final int SATELLITE_RESULT_REQUEST_ABORTED = 15;
/**
* The device/subscriber is barred from accessing the satellite service.
*/
- public static final int SATELLITE_ACCESS_BARRED = 16;
+ public static final int SATELLITE_RESULT_ACCESS_BARRED = 16;
/**
* Satellite modem timeout to receive ACK or response from the satellite network after
* sending a request to the network.
*/
- public static final int SATELLITE_NETWORK_TIMEOUT = 17;
+ public static final int SATELLITE_RESULT_NETWORK_TIMEOUT = 17;
/**
* Satellite network is not reachable from the modem.
*/
- public static final int SATELLITE_NOT_REACHABLE = 18;
+ public static final int SATELLITE_RESULT_NOT_REACHABLE = 18;
/**
* The device/subscriber is not authorized to register with the satellite service provider.
*/
- public static final int SATELLITE_NOT_AUTHORIZED = 19;
+ public static final int SATELLITE_RESULT_NOT_AUTHORIZED = 19;
/**
* The device does not support satellite.
*/
- public static final int SATELLITE_NOT_SUPPORTED = 20;
+ public static final int SATELLITE_RESULT_NOT_SUPPORTED = 20;
/**
* The current request is already in-progress.
*/
- public static final int SATELLITE_REQUEST_IN_PROGRESS = 21;
+ public static final int SATELLITE_RESULT_REQUEST_IN_PROGRESS = 21;
/**
* Satellite modem is currently busy due to which current request cannot be processed.
*/
- public static final int SATELLITE_MODEM_BUSY = 22;
+ public static final int SATELLITE_RESULT_MODEM_BUSY = 22;
/** @hide */
- @IntDef(prefix = {"SATELLITE_"}, value = {
- SATELLITE_ERROR_NONE,
- SATELLITE_ERROR,
- SATELLITE_SERVER_ERROR,
- SATELLITE_SERVICE_ERROR,
- SATELLITE_MODEM_ERROR,
- SATELLITE_NETWORK_ERROR,
- SATELLITE_INVALID_TELEPHONY_STATE,
- SATELLITE_INVALID_MODEM_STATE,
- SATELLITE_INVALID_ARGUMENTS,
- SATELLITE_REQUEST_FAILED,
- SATELLITE_RADIO_NOT_AVAILABLE,
- SATELLITE_REQUEST_NOT_SUPPORTED,
- SATELLITE_NO_RESOURCES,
- SATELLITE_SERVICE_NOT_PROVISIONED,
- SATELLITE_SERVICE_PROVISION_IN_PROGRESS,
- SATELLITE_REQUEST_ABORTED,
- SATELLITE_ACCESS_BARRED,
- SATELLITE_NETWORK_TIMEOUT,
- SATELLITE_NOT_REACHABLE,
- SATELLITE_NOT_AUTHORIZED,
- SATELLITE_NOT_SUPPORTED,
- SATELLITE_REQUEST_IN_PROGRESS,
- SATELLITE_MODEM_BUSY
+ @IntDef(prefix = {"SATELLITE_RESULT_"}, value = {
+ SATELLITE_RESULT_SUCCESS,
+ SATELLITE_RESULT_ERROR,
+ SATELLITE_RESULT_SERVER_ERROR,
+ SATELLITE_RESULT_SERVICE_ERROR,
+ SATELLITE_RESULT_MODEM_ERROR,
+ SATELLITE_RESULT_NETWORK_ERROR,
+ SATELLITE_RESULT_INVALID_TELEPHONY_STATE,
+ SATELLITE_RESULT_INVALID_MODEM_STATE,
+ SATELLITE_RESULT_INVALID_ARGUMENTS,
+ SATELLITE_RESULT_REQUEST_FAILED,
+ SATELLITE_RESULT_RADIO_NOT_AVAILABLE,
+ SATELLITE_RESULT_REQUEST_NOT_SUPPORTED,
+ SATELLITE_RESULT_NO_RESOURCES,
+ SATELLITE_RESULT_SERVICE_NOT_PROVISIONED,
+ SATELLITE_RESULT_SERVICE_PROVISION_IN_PROGRESS,
+ SATELLITE_RESULT_REQUEST_ABORTED,
+ SATELLITE_RESULT_ACCESS_BARRED,
+ SATELLITE_RESULT_NETWORK_TIMEOUT,
+ SATELLITE_RESULT_NOT_REACHABLE,
+ SATELLITE_RESULT_NOT_AUTHORIZED,
+ SATELLITE_RESULT_NOT_SUPPORTED,
+ SATELLITE_RESULT_REQUEST_IN_PROGRESS,
+ SATELLITE_RESULT_MODEM_BUSY
})
@Retention(RetentionPolicy.SOURCE)
- public @interface SatelliteError {}
+ public @interface SatelliteResult {}
/**
* Unknown Non-Terrestrial radio technology. This generic radio technology should be used
@@ -403,7 +424,7 @@ public final class SatelliteManager {
* {@code false} to disable.
* @param enableDemoMode {@code true} to enable demo mode and {@code false} to disable.
* @param executor The executor on which the error code listener will be called.
- * @param resultListener Listener for the {@link SatelliteError} result of the operation.
+ * @param resultListener Listener for the {@link SatelliteResult} result of the operation.
*
* @throws SecurityException if the caller doesn't have required permission.
* @throws IllegalStateException if the Telephony process is not currently available.
@@ -412,7 +433,7 @@ public final class SatelliteManager {
public void requestSatelliteEnabled(boolean enableSatellite, boolean enableDemoMode,
@NonNull @CallbackExecutor Executor executor,
- @SatelliteError @NonNull Consumer<Integer> resultListener) {
+ @SatelliteResult @NonNull Consumer<Integer> resultListener) {
Objects.requireNonNull(executor);
Objects.requireNonNull(resultListener);
@@ -446,7 +467,7 @@ public final class SatelliteManager {
* will return a {@code boolean} with value {@code true} if the satellite modem
* is enabled and {@code false} otherwise.
* If the request is not successful, {@link OutcomeReceiver#onError(Throwable)}
- * will return a {@link SatelliteException} with the {@link SatelliteError}.
+ * will return a {@link SatelliteException} with the {@link SatelliteResult}.
*
* @throws SecurityException if the caller doesn't have required permission.
* @throws IllegalStateException if the Telephony process is not currently available.
@@ -464,7 +485,7 @@ public final class SatelliteManager {
ResultReceiver receiver = new ResultReceiver(null) {
@Override
protected void onReceiveResult(int resultCode, Bundle resultData) {
- if (resultCode == SATELLITE_ERROR_NONE) {
+ if (resultCode == SATELLITE_RESULT_SUCCESS) {
if (resultData.containsKey(KEY_SATELLITE_ENABLED)) {
boolean isSatelliteEnabled =
resultData.getBoolean(KEY_SATELLITE_ENABLED);
@@ -473,8 +494,8 @@ public final class SatelliteManager {
} else {
loge("KEY_SATELLITE_ENABLED does not exist.");
executor.execute(() -> Binder.withCleanCallingIdentity(() ->
- callback.onError(
- new SatelliteException(SATELLITE_REQUEST_FAILED))));
+ callback.onError(new SatelliteException(
+ SATELLITE_RESULT_REQUEST_FAILED))));
}
} else {
executor.execute(() -> Binder.withCleanCallingIdentity(() ->
@@ -501,7 +522,7 @@ public final class SatelliteManager {
* will return a {@code boolean} with value {@code true} if demo mode is enabled
* and {@code false} otherwise.
* If the request is not successful, {@link OutcomeReceiver#onError(Throwable)}
- * will return a {@link SatelliteException} with the {@link SatelliteError}.
+ * will return a {@link SatelliteException} with the {@link SatelliteResult}.
*
* @throws SecurityException if the caller doesn't have required permission.
* @throws IllegalStateException if the Telephony process is not currently available.
@@ -519,7 +540,7 @@ public final class SatelliteManager {
ResultReceiver receiver = new ResultReceiver(null) {
@Override
protected void onReceiveResult(int resultCode, Bundle resultData) {
- if (resultCode == SATELLITE_ERROR_NONE) {
+ if (resultCode == SATELLITE_RESULT_SUCCESS) {
if (resultData.containsKey(KEY_DEMO_MODE_ENABLED)) {
boolean isDemoModeEnabled =
resultData.getBoolean(KEY_DEMO_MODE_ENABLED);
@@ -528,8 +549,8 @@ public final class SatelliteManager {
} else {
loge("KEY_DEMO_MODE_ENABLED does not exist.");
executor.execute(() -> Binder.withCleanCallingIdentity(() ->
- callback.onError(
- new SatelliteException(SATELLITE_REQUEST_FAILED))));
+ callback.onError(new SatelliteException(
+ SATELLITE_RESULT_REQUEST_FAILED))));
}
} else {
executor.execute(() -> Binder.withCleanCallingIdentity(() ->
@@ -556,7 +577,7 @@ public final class SatelliteManager {
* will return a {@code boolean} with value {@code true} if the satellite
* service is supported on the device and {@code false} otherwise.
* If the request is not successful, {@link OutcomeReceiver#onError(Throwable)}
- * will return a {@link SatelliteException} with the {@link SatelliteError}.
+ * will return a {@link SatelliteException} with the {@link SatelliteResult}.
*
* @throws IllegalStateException if the Telephony process is not currently available.
*/
@@ -572,7 +593,7 @@ public final class SatelliteManager {
ResultReceiver receiver = new ResultReceiver(null) {
@Override
protected void onReceiveResult(int resultCode, Bundle resultData) {
- if (resultCode == SATELLITE_ERROR_NONE) {
+ if (resultCode == SATELLITE_RESULT_SUCCESS) {
if (resultData.containsKey(KEY_SATELLITE_SUPPORTED)) {
boolean isSatelliteSupported =
resultData.getBoolean(KEY_SATELLITE_SUPPORTED);
@@ -581,8 +602,8 @@ public final class SatelliteManager {
} else {
loge("KEY_SATELLITE_SUPPORTED does not exist.");
executor.execute(() -> Binder.withCleanCallingIdentity(() ->
- callback.onError(
- new SatelliteException(SATELLITE_REQUEST_FAILED))));
+ callback.onError(new SatelliteException(
+ SATELLITE_RESULT_REQUEST_FAILED))));
}
} else {
executor.execute(() -> Binder.withCleanCallingIdentity(() ->
@@ -608,7 +629,7 @@ public final class SatelliteManager {
* If the request is successful, {@link OutcomeReceiver#onResult(Object)}
* will return the {@link SatelliteCapabilities} of the satellite service.
* If the request is not successful, {@link OutcomeReceiver#onError(Throwable)}
- * will return a {@link SatelliteException} with the {@link SatelliteError}.
+ * will return a {@link SatelliteException} with the {@link SatelliteResult}.
*
* @throws SecurityException if the caller doesn't have required permission.
* @throws IllegalStateException if the Telephony process is not currently available.
@@ -626,7 +647,7 @@ public final class SatelliteManager {
ResultReceiver receiver = new ResultReceiver(null) {
@Override
protected void onReceiveResult(int resultCode, Bundle resultData) {
- if (resultCode == SATELLITE_ERROR_NONE) {
+ if (resultCode == SATELLITE_RESULT_SUCCESS) {
if (resultData.containsKey(KEY_SATELLITE_CAPABILITIES)) {
SatelliteCapabilities capabilities =
resultData.getParcelable(KEY_SATELLITE_CAPABILITIES,
@@ -636,8 +657,8 @@ public final class SatelliteManager {
} else {
loge("KEY_SATELLITE_CAPABILITIES does not exist.");
executor.execute(() -> Binder.withCleanCallingIdentity(() ->
- callback.onError(
- new SatelliteException(SATELLITE_REQUEST_FAILED))));
+ callback.onError(new SatelliteException(
+ SATELLITE_RESULT_REQUEST_FAILED))));
}
} else {
executor.execute(() -> Binder.withCleanCallingIdentity(() ->
@@ -791,16 +812,37 @@ public final class SatelliteManager {
public @interface DatagramType {}
/**
+ * Satellite communication restricted by user.
+ * @hide
+ */
+ public static final int SATELLITE_COMMUNICATION_RESTRICTION_REASON_USER = 0;
+
+ /**
+ * Satellite communication restricted by geolocation. This can be
+ * triggered based upon geofence input provided by carrier to enable or disable satellite.
+ * @hide
+ */
+ public static final int SATELLITE_COMMUNICATION_RESTRICTION_REASON_GEOLOCATION = 1;
+
+ /** @hide */
+ @IntDef(prefix = "SATELLITE_COMMUNICATION_RESTRICTION_REASON_", value = {
+ SATELLITE_COMMUNICATION_RESTRICTION_REASON_USER,
+ SATELLITE_COMMUNICATION_RESTRICTION_REASON_GEOLOCATION
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface SatelliteCommunicationRestrictionReason {}
+
+ /**
* Start receiving satellite transmission updates.
* This can be called by the pointing UI when the user starts pointing to the satellite.
* Modem should continue to report the pointing input as the device or satellite moves.
- * Satellite transmission updates are started only on {@link #SATELLITE_ERROR_NONE}.
+ * Satellite transmission updates are started only on {@link #SATELLITE_RESULT_SUCCESS}.
* All other results indicate that this operation failed.
* Once satellite transmission updates begin, position and datagram transfer state updates
* will be sent through {@link SatelliteTransmissionUpdateCallback}.
*
* @param executor The executor on which the callback and error code listener will be called.
- * @param resultListener Listener for the {@link SatelliteError} result of the operation.
+ * @param resultListener Listener for the {@link SatelliteResult} result of the operation.
* @param callback The callback to notify of satellite transmission updates.
*
* @throws SecurityException if the caller doesn't have required permission.
@@ -809,7 +851,7 @@ public final class SatelliteManager {
@RequiresPermission(Manifest.permission.SATELLITE_COMMUNICATION)
public void startSatelliteTransmissionUpdates(@NonNull @CallbackExecutor Executor executor,
- @SatelliteError @NonNull Consumer<Integer> resultListener,
+ @SatelliteResult @NonNull Consumer<Integer> resultListener,
@NonNull SatelliteTransmissionUpdateCallback callback) {
Objects.requireNonNull(executor);
Objects.requireNonNull(resultListener);
@@ -866,12 +908,12 @@ public final class SatelliteManager {
* Stop receiving satellite transmission updates.
* This can be called by the pointing UI when the user stops pointing to the satellite.
* Satellite transmission updates are stopped and the callback is unregistered only on
- * {@link #SATELLITE_ERROR_NONE}. All other results that this operation failed.
+ * {@link #SATELLITE_RESULT_SUCCESS}. All other results that this operation failed.
*
* @param callback The callback that was passed to {@link
* #startSatelliteTransmissionUpdates(Executor, Consumer, SatelliteTransmissionUpdateCallback)}.
* @param executor The executor on which the error code listener will be called.
- * @param resultListener Listener for the {@link SatelliteError} result of the operation.
+ * @param resultListener Listener for the {@link SatelliteResult} result of the operation.
*
* @throws SecurityException if the caller doesn't have required permission.
* @throws IllegalStateException if the Telephony process is not currently available.
@@ -881,7 +923,7 @@ public final class SatelliteManager {
public void stopSatelliteTransmissionUpdates(
@NonNull SatelliteTransmissionUpdateCallback callback,
@NonNull @CallbackExecutor Executor executor,
- @SatelliteError @NonNull Consumer<Integer> resultListener) {
+ @SatelliteResult @NonNull Consumer<Integer> resultListener) {
Objects.requireNonNull(callback);
Objects.requireNonNull(executor);
Objects.requireNonNull(resultListener);
@@ -905,7 +947,7 @@ public final class SatelliteManager {
} else {
loge("stopSatelliteTransmissionUpdates: No internal callback.");
executor.execute(() -> Binder.withCleanCallingIdentity(
- () -> resultListener.accept(SATELLITE_INVALID_ARGUMENTS)));
+ () -> resultListener.accept(SATELLITE_RESULT_INVALID_ARGUMENTS)));
}
} else {
throw new IllegalStateException("telephony service is null.");
@@ -927,7 +969,7 @@ public final class SatelliteManager {
* request. Even when the cancellation is signaled, Telephony will
* still trigger the callback to return the result of this request.
* @param executor The executor on which the error code listener will be called.
- * @param resultListener Listener for the {@link SatelliteError} result of the operation.
+ * @param resultListener Listener for the {@link SatelliteResult} result of the operation.
*
* @throws SecurityException if the caller doesn't have required permission.
* @throws IllegalStateException if the Telephony process is not currently available.
@@ -937,7 +979,7 @@ public final class SatelliteManager {
public void provisionSatelliteService(@NonNull String token, @NonNull byte[] provisionData,
@Nullable CancellationSignal cancellationSignal,
@NonNull @CallbackExecutor Executor executor,
- @SatelliteError @NonNull Consumer<Integer> resultListener) {
+ @SatelliteResult @NonNull Consumer<Integer> resultListener) {
Objects.requireNonNull(token);
Objects.requireNonNull(executor);
Objects.requireNonNull(resultListener);
@@ -980,7 +1022,7 @@ public final class SatelliteManager {
* This should match with the token passed as input in
* {@link #provisionSatelliteService(String, byte[], CancellationSignal, Executor,
* Consumer)}
- * @param resultListener Listener for the {@link SatelliteError} result of the operation.
+ * @param resultListener Listener for the {@link SatelliteResult} result of the operation.
*
* @throws SecurityException if the caller doesn't have required permission.
* @throws IllegalStateException if the Telephony process is not currently available.
@@ -989,7 +1031,7 @@ public final class SatelliteManager {
public void deprovisionSatelliteService(@NonNull String token,
@NonNull @CallbackExecutor Executor executor,
- @SatelliteError @NonNull Consumer<Integer> resultListener) {
+ @SatelliteResult @NonNull Consumer<Integer> resultListener) {
Objects.requireNonNull(token);
Objects.requireNonNull(executor);
Objects.requireNonNull(resultListener);
@@ -1020,14 +1062,14 @@ public final class SatelliteManager {
* @param executor The executor on which the callback will be called.
* @param callback The callback to handle the satellite provision state changed event.
*
- * @return The {@link SatelliteError} result of the operation.
+ * @return The {@link SatelliteResult} result of the operation.
*
* @throws SecurityException if the caller doesn't have required permission.
* @throws IllegalStateException if the Telephony process is not currently available.
*/
@RequiresPermission(Manifest.permission.SATELLITE_COMMUNICATION)
- @SatelliteError public int registerForSatelliteProvisionStateChanged(
+ @SatelliteResult public int registerForSatelliteProvisionStateChanged(
@NonNull @CallbackExecutor Executor executor,
@NonNull SatelliteProvisionStateCallback callback) {
Objects.requireNonNull(executor);
@@ -1055,7 +1097,7 @@ public final class SatelliteManager {
loge("registerForSatelliteProvisionStateChanged() RemoteException: " + ex);
ex.rethrowFromSystemServer();
}
- return SATELLITE_REQUEST_FAILED;
+ return SATELLITE_RESULT_REQUEST_FAILED;
}
/**
@@ -1102,7 +1144,7 @@ public final class SatelliteManager {
* will return a {@code boolean} with value {@code true} if the device is
* provisioned with a satellite provider and {@code false} otherwise.
* If the request is not successful, {@link OutcomeReceiver#onError(Throwable)}
- * will return a {@link SatelliteException} with the {@link SatelliteError}.
+ * will return a {@link SatelliteException} with the {@link SatelliteResult}.
*
* @throws SecurityException if the caller doesn't have required permission.
* @throws IllegalStateException if the Telephony process is not currently available.
@@ -1120,7 +1162,7 @@ public final class SatelliteManager {
ResultReceiver receiver = new ResultReceiver(null) {
@Override
protected void onReceiveResult(int resultCode, Bundle resultData) {
- if (resultCode == SATELLITE_ERROR_NONE) {
+ if (resultCode == SATELLITE_RESULT_SUCCESS) {
if (resultData.containsKey(KEY_SATELLITE_PROVISIONED)) {
boolean isSatelliteProvisioned =
resultData.getBoolean(KEY_SATELLITE_PROVISIONED);
@@ -1129,8 +1171,8 @@ public final class SatelliteManager {
} else {
loge("KEY_SATELLITE_PROVISIONED does not exist.");
executor.execute(() -> Binder.withCleanCallingIdentity(() ->
- callback.onError(
- new SatelliteException(SATELLITE_REQUEST_FAILED))));
+ callback.onError(new SatelliteException(
+ SATELLITE_RESULT_REQUEST_FAILED))));
}
} else {
executor.execute(() -> Binder.withCleanCallingIdentity(() ->
@@ -1154,14 +1196,14 @@ public final class SatelliteManager {
* @param executor The executor on which the callback will be called.
* @param callback The callback to handle the satellite modem state changed event.
*
- * @return The {@link SatelliteError} result of the operation.
+ * @return The {@link SatelliteResult} result of the operation.
*
* @throws SecurityException if the caller doesn't have required permission.
* @throws IllegalStateException if the Telephony process is not currently available.
*/
@RequiresPermission(Manifest.permission.SATELLITE_COMMUNICATION)
- @SatelliteError public int registerForSatelliteModemStateChanged(
+ @SatelliteResult public int registerForSatelliteModemStateChanged(
@NonNull @CallbackExecutor Executor executor,
@NonNull SatelliteStateCallback callback) {
Objects.requireNonNull(executor);
@@ -1186,7 +1228,7 @@ public final class SatelliteManager {
loge("registerForSatelliteModemStateChanged() RemoteException:" + ex);
ex.rethrowFromSystemServer();
}
- return SATELLITE_REQUEST_FAILED;
+ return SATELLITE_RESULT_REQUEST_FAILED;
}
/**
@@ -1232,14 +1274,14 @@ public final class SatelliteManager {
* @param callback The callback to handle incoming datagrams over satellite.
* This callback with be invoked when a new datagram is received from satellite.
*
- * @return The {@link SatelliteError} result of the operation.
+ * @return The {@link SatelliteResult} result of the operation.
*
* @throws SecurityException if the caller doesn't have required permission.
* @throws IllegalStateException if the Telephony process is not currently available.
*/
@RequiresPermission(Manifest.permission.SATELLITE_COMMUNICATION)
- @SatelliteError public int registerForSatelliteDatagram(
+ @SatelliteResult public int registerForSatelliteDatagram(
@NonNull @CallbackExecutor Executor executor,
@NonNull SatelliteDatagramCallback callback) {
Objects.requireNonNull(executor);
@@ -1280,7 +1322,7 @@ public final class SatelliteManager {
loge("registerForSatelliteDatagram() RemoteException:" + ex);
ex.rethrowFromSystemServer();
}
- return SATELLITE_REQUEST_FAILED;
+ return SATELLITE_RESULT_REQUEST_FAILED;
}
/**
@@ -1327,7 +1369,7 @@ public final class SatelliteManager {
* Consumer)} )}
*
* @param executor The executor on which the result listener will be called.
- * @param resultListener Listener for the {@link SatelliteError} result of the operation.
+ * @param resultListener Listener for the {@link SatelliteResult} result of the operation.
*
* @throws SecurityException if the caller doesn't have required permission.
* @throws IllegalStateException if the Telephony process is not currently available.
@@ -1335,7 +1377,7 @@ public final class SatelliteManager {
@RequiresPermission(Manifest.permission.SATELLITE_COMMUNICATION)
public void pollPendingSatelliteDatagrams(@NonNull @CallbackExecutor Executor executor,
- @SatelliteError @NonNull Consumer<Integer> resultListener) {
+ @SatelliteResult @NonNull Consumer<Integer> resultListener) {
Objects.requireNonNull(executor);
Objects.requireNonNull(resultListener);
@@ -1380,7 +1422,7 @@ public final class SatelliteManager {
* user activity and the application's ability to determine the
* best possible UX experience for the user.
* @param executor The executor on which the result listener will be called.
- * @param resultListener Listener for the {@link SatelliteError} result of the operation.
+ * @param resultListener Listener for the {@link SatelliteResult} result of the operation.
*
* @throws SecurityException if the caller doesn't have required permission.
* @throws IllegalStateException if the Telephony process is not currently available.
@@ -1390,7 +1432,7 @@ public final class SatelliteManager {
public void sendSatelliteDatagram(@DatagramType int datagramType,
@NonNull SatelliteDatagram datagram, boolean needFullScreenPointingUI,
@NonNull @CallbackExecutor Executor executor,
- @SatelliteError @NonNull Consumer<Integer> resultListener) {
+ @SatelliteResult @NonNull Consumer<Integer> resultListener) {
Objects.requireNonNull(datagram);
Objects.requireNonNull(executor);
Objects.requireNonNull(resultListener);
@@ -1426,7 +1468,7 @@ public final class SatelliteManager {
* communication is allowed for the current location and
* {@code false} otherwise.
* If the request is not successful, {@link OutcomeReceiver#onError(Throwable)}
- * will return a {@link SatelliteException} with the {@link SatelliteError}.
+ * will return a {@link SatelliteException} with the {@link SatelliteResult}.
*
* @throws SecurityException if the caller doesn't have required permission.
* @throws IllegalStateException if the Telephony process is not currently available.
@@ -1445,7 +1487,7 @@ public final class SatelliteManager {
ResultReceiver receiver = new ResultReceiver(null) {
@Override
protected void onReceiveResult(int resultCode, Bundle resultData) {
- if (resultCode == SATELLITE_ERROR_NONE) {
+ if (resultCode == SATELLITE_RESULT_SUCCESS) {
if (resultData.containsKey(KEY_SATELLITE_COMMUNICATION_ALLOWED)) {
boolean isSatelliteCommunicationAllowed =
resultData.getBoolean(KEY_SATELLITE_COMMUNICATION_ALLOWED);
@@ -1454,8 +1496,8 @@ public final class SatelliteManager {
} else {
loge("KEY_SATELLITE_COMMUNICATION_ALLOWED does not exist.");
executor.execute(() -> Binder.withCleanCallingIdentity(() ->
- callback.onError(
- new SatelliteException(SATELLITE_REQUEST_FAILED))));
+ callback.onError(new SatelliteException(
+ SATELLITE_RESULT_REQUEST_FAILED))));
}
} else {
executor.execute(() -> Binder.withCleanCallingIdentity(() ->
@@ -1484,7 +1526,7 @@ public final class SatelliteManager {
* If the request is successful, {@link OutcomeReceiver#onResult(Object)}
* will return the time after which the satellite will be visible.
* If the request is not successful, {@link OutcomeReceiver#onError(Throwable)}
- * will return a {@link SatelliteException} with the {@link SatelliteError}.
+ * will return a {@link SatelliteException} with the {@link SatelliteResult}.
*
* @throws SecurityException if the caller doesn't have required permission.
* @throws IllegalStateException if the Telephony process is not currently available.
@@ -1502,7 +1544,7 @@ public final class SatelliteManager {
ResultReceiver receiver = new ResultReceiver(null) {
@Override
protected void onReceiveResult(int resultCode, Bundle resultData) {
- if (resultCode == SATELLITE_ERROR_NONE) {
+ if (resultCode == SATELLITE_RESULT_SUCCESS) {
if (resultData.containsKey(KEY_SATELLITE_NEXT_VISIBILITY)) {
int nextVisibilityDuration =
resultData.getInt(KEY_SATELLITE_NEXT_VISIBILITY);
@@ -1512,8 +1554,8 @@ public final class SatelliteManager {
} else {
loge("KEY_SATELLITE_NEXT_VISIBILITY does not exist.");
executor.execute(() -> Binder.withCleanCallingIdentity(() ->
- callback.onError(
- new SatelliteException(SATELLITE_REQUEST_FAILED))));
+ callback.onError(new SatelliteException(
+ SATELLITE_RESULT_REQUEST_FAILED))));
}
} else {
executor.execute(() -> Binder.withCleanCallingIdentity(() ->
@@ -1559,6 +1601,182 @@ public final class SatelliteManager {
}
}
+ /**
+ * User request to enable or disable carrier supported satellite plmn scan and attach by modem.
+ * <p>
+ * This API should be called by only settings app to pass down the user input for
+ * enabling/disabling satellite. This user input will be persisted across device reboots.
+ * <p>
+ * Satellite will be enabled only when the following conditions are met:
+ * <ul>
+ * <li>Users want to enable it.</li>
+ * <li>There is no satellite communication restriction, which is added by
+ * {@link #addSatelliteAttachRestrictionForCarrier(int, Executor, Consumer)}</li>
+ * <li>The carrier config {@link
+ * android.telephony.CarrierConfigManager#KEY_SATELLITE_ATTACH_SUPPORTED_BOOL} is set to
+ * {@code true}.</li>
+ * </ul>
+ *
+ * @param enableSatellite {@code true} to enable the satellite and {@code false} to disable.
+ * @param executor The executor on which the error code listener will be called.
+ * @param resultListener Listener for the {@link SatelliteError} result of the operation.
+ *
+ * @throws SecurityException if the caller doesn't have required permission.
+ * @throws IllegalStateException if the Telephony process is not currently available.
+ * @hide
+ */
+ @RequiresPermission(Manifest.permission.SATELLITE_COMMUNICATION)
+ public void requestSatelliteAttachEnabledForCarrier(boolean enableSatellite,
+ @NonNull @CallbackExecutor Executor executor,
+ @SatelliteResult @NonNull Consumer<Integer> resultListener) {
+ Objects.requireNonNull(executor);
+ Objects.requireNonNull(resultListener);
+
+ if (enableSatellite) {
+ removeSatelliteAttachRestrictionForCarrier(
+ SATELLITE_COMMUNICATION_RESTRICTION_REASON_USER, executor, resultListener);
+ } else {
+ addSatelliteAttachRestrictionForCarrier(
+ SATELLITE_COMMUNICATION_RESTRICTION_REASON_USER, executor, resultListener);
+ }
+ }
+
+ /**
+ * Request to get whether the carrier supported satellite plmn scan and attach by modem is
+ * enabled by user.
+ *
+ * @param executor The executor on which the callback will be called.
+ * @param callback The callback object to which the result will be delivered.
+ * If the request is successful, {@link OutcomeReceiver#onResult(Object)}
+ * will return a {@code boolean} with value {@code true} if the satellite
+ * is enabled and {@code false} otherwise.
+ * If the request is not successful, {@link OutcomeReceiver#onError(Throwable)}
+ * will return a {@link SatelliteException} with the {@link SatelliteError}.
+ *
+ * @throws SecurityException if the caller doesn't have required permission.
+ * @throws IllegalStateException if the Telephony process is not currently available.
+ * @hide
+ */
+ @RequiresPermission(Manifest.permission.SATELLITE_COMMUNICATION)
+ public void requestIsSatelliteAttachEnabledForCarrier(
+ @NonNull @CallbackExecutor Executor executor,
+ @NonNull OutcomeReceiver<Boolean, SatelliteException> callback) {
+ Objects.requireNonNull(executor);
+ Objects.requireNonNull(callback);
+
+ Set<Integer> restrictionReason = getSatelliteAttachRestrictionReasonsForCarrier();
+ executor.execute(() -> callback.onResult(
+ !restrictionReason.contains(SATELLITE_COMMUNICATION_RESTRICTION_REASON_USER)));
+ }
+
+ /**
+ * Add a restriction reason for disallowing carrier supported satellite plmn scan and attach
+ * by modem.
+ *
+ * @param reason Reason for disallowing satellite communication.
+ * @param executor The executor on which the error code listener will be called.
+ * @param resultListener Listener for the {@link SatelliteError} result of the operation.
+ *
+ * @throws SecurityException if the caller doesn't have required permission.
+ * @throws IllegalStateException if the Telephony process is not currently available.
+ * @hide
+ */
+ @RequiresPermission(Manifest.permission.SATELLITE_COMMUNICATION)
+ public void addSatelliteAttachRestrictionForCarrier(
+ @SatelliteCommunicationRestrictionReason int reason,
+ @NonNull @CallbackExecutor Executor executor,
+ @SatelliteResult @NonNull Consumer<Integer> resultListener) {
+ try {
+ ITelephony telephony = getITelephony();
+ if (telephony != null) {
+ IIntegerConsumer errorCallback = new IIntegerConsumer.Stub() {
+ @Override
+ public void accept(int result) {
+ executor.execute(() -> Binder.withCleanCallingIdentity(
+ () -> resultListener.accept(result)));
+ }
+ };
+ telephony.addSatelliteAttachRestrictionForCarrier(mSubId, reason, errorCallback);
+ } else {
+ throw new IllegalStateException("telephony service is null.");
+ }
+ } catch (RemoteException ex) {
+ loge("addSatelliteAttachRestrictionForCarrier() RemoteException:" + ex);
+ ex.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * Remove a restriction reason for disallowing carrier supported satellite plmn scan and attach
+ * by modem.
+ *
+ * @param reason Reason for disallowing satellite communication.
+ * @param executor The executor on which the error code listener will be called.
+ * @param resultListener Listener for the {@link SatelliteError} result of the operation.
+ *
+ * @throws SecurityException if the caller doesn't have required permission.
+ * @throws IllegalStateException if the Telephony process is not currently available.
+ * @hide
+ */
+ @RequiresPermission(Manifest.permission.SATELLITE_COMMUNICATION)
+ public void removeSatelliteAttachRestrictionForCarrier(
+ @SatelliteCommunicationRestrictionReason int reason,
+ @NonNull @CallbackExecutor Executor executor,
+ @SatelliteResult @NonNull Consumer<Integer> resultListener) {
+ try {
+ ITelephony telephony = getITelephony();
+ if (telephony != null) {
+ IIntegerConsumer errorCallback = new IIntegerConsumer.Stub() {
+ @Override
+ public void accept(int result) {
+ executor.execute(() -> Binder.withCleanCallingIdentity(
+ () -> resultListener.accept(result)));
+ }
+ };
+ telephony.removeSatelliteAttachRestrictionForCarrier(mSubId, reason, errorCallback);
+ } else {
+ throw new IllegalStateException("telephony service is null.");
+ }
+ } catch (RemoteException ex) {
+ loge("removeSatelliteAttachRestrictionForCarrier() RemoteException:" + ex);
+ ex.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * Get reasons for disallowing satellite attach, as requested by
+ * {@link #addSatelliteAttachRestrictionForCarrier(int, Executor, Consumer)}
+ *
+ * @return Set of reasons for disallowing satellite communication.
+ *
+ * @throws SecurityException if the caller doesn't have required permission.
+ * @throws IllegalStateException if the Telephony process is not currently available.
+ * @hide
+ */
+ @RequiresPermission(Manifest.permission.SATELLITE_COMMUNICATION)
+ @SatelliteCommunicationRestrictionReason
+ public @NonNull Set<Integer> getSatelliteAttachRestrictionReasonsForCarrier() {
+ try {
+ ITelephony telephony = getITelephony();
+ if (telephony != null) {
+ int[] receivedArray =
+ telephony.getSatelliteAttachRestrictionReasonsForCarrier(mSubId);
+ if (receivedArray.length == 0) {
+ logd("received set is empty, create empty set");
+ return new HashSet<>();
+ } else {
+ return Arrays.stream(receivedArray).boxed().collect(Collectors.toSet());
+ }
+ } else {
+ throw new IllegalStateException("telephony service is null.");
+ }
+ } catch (RemoteException ex) {
+ loge("getSatelliteAttachRestrictionReasonsForCarrier() RemoteException: " + ex);
+ ex.rethrowFromSystemServer();
+ }
+ return null;
+ }
+
private static ITelephony getITelephony() {
ITelephony binder = ITelephony.Stub.asInterface(TelephonyFrameworkInitializer
.getTelephonyServiceManager()
diff --git a/telephony/java/android/telephony/satellite/SatelliteTransmissionUpdateCallback.java b/telephony/java/android/telephony/satellite/SatelliteTransmissionUpdateCallback.java
index d7d892a7c30a..7ac06b04a8eb 100644
--- a/telephony/java/android/telephony/satellite/SatelliteTransmissionUpdateCallback.java
+++ b/telephony/java/android/telephony/satellite/SatelliteTransmissionUpdateCallback.java
@@ -43,7 +43,7 @@ public interface SatelliteTransmissionUpdateCallback {
*/
void onSendDatagramStateChanged(
@SatelliteManager.SatelliteDatagramTransferState int state, int sendPendingCount,
- @SatelliteManager.SatelliteError int errorCode);
+ @SatelliteManager.SatelliteResult int errorCode);
/**
* Called when satellite datagram receive state changed.
@@ -54,5 +54,5 @@ public interface SatelliteTransmissionUpdateCallback {
*/
void onReceiveDatagramStateChanged(
@SatelliteManager.SatelliteDatagramTransferState int state, int receivePendingCount,
- @SatelliteManager.SatelliteError int errorCode);
+ @SatelliteManager.SatelliteResult int errorCode);
}
diff --git a/telephony/java/android/telephony/satellite/stub/ISatellite.aidl b/telephony/java/android/telephony/satellite/stub/ISatellite.aidl
index ea4e2e2ef1b9..02661de34fb2 100644
--- a/telephony/java/android/telephony/satellite/stub/ISatellite.aidl
+++ b/telephony/java/android/telephony/satellite/stub/ISatellite.aidl
@@ -382,4 +382,64 @@ oneway interface ISatellite {
*/
void requestTimeForNextSatelliteVisibility(in IIntegerConsumer resultCallback,
in IIntegerConsumer callback);
+
+ /**
+ * Set the non-terrestrial PLMN with lower priority than terrestrial networks.
+ * MCC/MNC broadcast by the non-terrestrial networks may not be included in OPLMNwACT file on
+ * SIM profile. Acquisition of satellite based system is lower priority to terrestrial
+ * networks. UE shall make all attempts to acquire terrestrial service prior to camping on
+ * satellite LTE service.
+ *
+ * @param simSlot Indicates the SIM slot to which this API will be applied. The modem will use
+ * this information to determine the relevant carrier.
+ * @param plmnList The list of roaming PLMN used for connecting to satellite networks.
+ * @param resultCallback The callback to receive the error code result of the operation.
+ *
+ * Valid error codes returned:
+ * SatelliteError:NONE
+ * SatelliteError:INVALID_ARGUMENTS
+ * SatelliteError:INVALID_MODEM_STATE
+ * SatelliteError:MODEM_ERR
+ * SatelliteError:NO_RESOURCES
+ * SatelliteError:RADIO_NOT_AVAILABLE
+ * SatelliteError:REQUEST_NOT_SUPPORTED
+ */
+ void setSatellitePlmn(int simSlot, in List<String> plmnList,
+ in IIntegerConsumer resultCallback);
+
+ /**
+ * Enable or disable satellite in the cellular modem associated with a carrier.
+ * Refer setSatellitePlmn for the details of satellite PLMN scanning process.
+ *
+ * @param simSlot Indicates the SIM slot to which this API will be applied. The modem will use
+ * this information to determine the relevant carrier.
+ * @param serial Serial number of request.
+ * @param enable {@code true} to enable satellite, {@code false} to disable satellite.
+ *
+ * Valid errors returned:
+ * SatelliteError:NONE
+ * SatelliteError:INVALID_MODEM_STATE
+ * SatelliteError:MODEM_ERR
+ * SatelliteError:RADIO_NOT_AVAILABLE
+ * SatelliteError:REQUEST_NOT_SUPPORTED
+ */
+ void setSatelliteEnabledForCarrier(int simSlot, boolean satelliteEnabled,
+ in IIntegerConsumer callback);
+
+ /**
+ * Check whether satellite is enabled in the cellular modem associated with a carrier.
+ *
+ * @param simSlot Indicates the SIM slot to which this API will be applied. The modem will use
+ * this information to determine the relevant carrier.
+ * @param serial Serial number of request.
+ *
+ * Valid errors returned:
+ * SatelliteError:NONE
+ * SatelliteError:INVALID_MODEM_STATE
+ * SatelliteError:MODEM_ERR
+ * SatelliteError:RADIO_NOT_AVAILABLE
+ * SatelliteError:REQUEST_NOT_SUPPORTED
+ */
+ void requestIsSatelliteEnabledForCarrier(int simSlot, in IIntegerConsumer resultCallback,
+ in IBooleanConsumer callback);
}
diff --git a/telephony/java/android/telephony/satellite/stub/ISatelliteListener.aidl b/telephony/java/android/telephony/satellite/stub/ISatelliteListener.aidl
index 5e692151c604..d68716291b8e 100644
--- a/telephony/java/android/telephony/satellite/stub/ISatelliteListener.aidl
+++ b/telephony/java/android/telephony/satellite/stub/ISatelliteListener.aidl
@@ -19,7 +19,6 @@ package android.telephony.satellite.stub;
import android.telephony.satellite.stub.NTRadioTechnology;
import android.telephony.satellite.stub.PointingInfo;
import android.telephony.satellite.stub.SatelliteDatagram;
-import android.telephony.satellite.stub.SatelliteError;
import android.telephony.satellite.stub.SatelliteModemState;
/**
diff --git a/telephony/java/android/telephony/satellite/stub/SatelliteImplBase.java b/telephony/java/android/telephony/satellite/stub/SatelliteImplBase.java
index 17d026cc8c1c..6451daf2e752 100644
--- a/telephony/java/android/telephony/satellite/stub/SatelliteImplBase.java
+++ b/telephony/java/android/telephony/satellite/stub/SatelliteImplBase.java
@@ -25,6 +25,7 @@ import com.android.internal.telephony.IBooleanConsumer;
import com.android.internal.telephony.IIntegerConsumer;
import com.android.internal.telephony.util.TelephonyUtils;
+import java.util.List;
import java.util.concurrent.CancellationException;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletionException;
@@ -212,6 +213,34 @@ public class SatelliteImplBase extends SatelliteService {
"requestTimeForNextSatelliteVisibility");
}
+ @Override
+ public void setSatellitePlmn(int simSlot, List<String> plmnList,
+ IIntegerConsumer errorCallback)
+ throws RemoteException {
+ executeMethodAsync(
+ () -> SatelliteImplBase.this
+ .setSatellitePlmn(simSlot, plmnList, errorCallback),
+ "setSatellitePlmn");
+ }
+
+ @Override
+ public void setSatelliteEnabledForCarrier(int simSlot, boolean enableSatellite,
+ IIntegerConsumer errorCallback) throws RemoteException {
+ executeMethodAsync(
+ () -> SatelliteImplBase.this
+ .setSatelliteEnabledForCarrier(simSlot, enableSatellite, errorCallback),
+ "setSatelliteEnabledForCarrier");
+ }
+
+ @Override
+ public void requestIsSatelliteEnabledForCarrier(int simSlot, IIntegerConsumer errorCallback,
+ IBooleanConsumer callback) throws RemoteException {
+ executeMethodAsync(
+ () -> SatelliteImplBase.this
+ .requestIsSatelliteEnabledForCarrier(simSlot, errorCallback, callback),
+ "requestIsSatelliteEnabledForCarrier");
+ }
+
// Call the methods with a clean calling identity on the executor and wait indefinitely for
// the future to return.
private void executeMethodAsync(Runnable r, String errorLogName) throws RemoteException {
@@ -618,4 +647,75 @@ public class SatelliteImplBase extends SatelliteService {
@NonNull IIntegerConsumer callback) {
// stub implementation
}
+
+
+ /**
+ * Set the non-terrestrial PLMN with lower priority than terrestrial networks.
+ * MCC/MNC broadcast by the non-terrestrial networks may not be included in OPLMNwACT file on
+ * SIM profile. Acquisition of satellite based system is lower priority to terrestrial
+ * networks. UE shall make all attempts to acquire terrestrial service prior to camping on
+ * satellite LTE service.
+ * This method must only take effect if {@link #setSatelliteEnabledForCarrier} is {@code true},
+ * and return an error otherwise.
+ *
+ * @param simLogicalSlotIndex Indicates the SIM logical slot index to which this API will be
+ * applied. The modem will use this information to determine the relevant carrier.
+ * @param errorCallback The callback to receive the error code result of the operation.
+ * @param plmnList The list of roaming PLMN used for connecting to satellite networks.
+ *
+ * Valid error codes returned:
+ * SatelliteError:NONE
+ * SatelliteError:INVALID_ARGUMENTS
+ * SatelliteError:INVALID_MODEM_STATE
+ * SatelliteError:MODEM_ERR
+ * SatelliteError:NO_RESOURCES
+ * SatelliteError:RADIO_NOT_AVAILABLE
+ * SatelliteError:REQUEST_NOT_SUPPORTED
+ */
+ public void setSatellitePlmn(@NonNull int simLogicalSlotIndex, @NonNull List<String> plmnList,
+ @NonNull IIntegerConsumer errorCallback) {
+ // stub implementation
+ }
+
+ /**
+ * Request to enable or disable carrier supported satellite plmn scan and attach by modem.
+ * Refer {@link #setSatellitePlmn} for the details of satellite PLMN scanning process.
+ *
+ * @param simLogicalSlotIndex Indicates the SIM logical slot index to which this API will be
+ * applied. The modem will use this information to determine the relevant carrier.
+ * @param satelliteEnabled {@code true} to enable satellite, {@code false} to disable satellite.
+ * @param callback {@code true} to enable satellite, {@code false} to disable satellite.
+ *
+ * Valid errors returned:
+ * SatelliteError:NONE
+ * SatelliteError:INVALID_MODEM_STATE
+ * SatelliteError:MODEM_ERR
+ * SatelliteError:RADIO_NOT_AVAILABLE
+ * SatelliteError:REQUEST_NOT_SUPPORTED
+ */
+ public void setSatelliteEnabledForCarrier(@NonNull int simLogicalSlotIndex,
+ @NonNull boolean satelliteEnabled, @NonNull IIntegerConsumer callback) {
+ // stub implementation
+ }
+
+ /**
+ * Request to get whether the satellite is enabled in the cellular modem associated with a
+ * carrier.
+ *
+ * @param simLogicalSlotIndex Indicates the SIM logical slot index to which this API will be
+ * applied. The modem will use this information to determine the relevant carrier.
+ * @param errorCallback The callback to receive the error code result of the operation.
+ * @param callback {@code true} to satellite enabled, {@code false} to satellite disabled.
+ *
+ * Valid errors returned:
+ * SatelliteError:NONE
+ * SatelliteError:INVALID_MODEM_STATE
+ * SatelliteError:MODEM_ERR
+ * SatelliteError:RADIO_NOT_AVAILABLE
+ * SatelliteError:REQUEST_NOT_SUPPORTED
+ */
+ public void requestIsSatelliteEnabledForCarrier(@NonNull int simLogicalSlotIndex,
+ @NonNull IIntegerConsumer errorCallback, @NonNull IBooleanConsumer callback) {
+ // stub implementation
+ }
}
diff --git a/telephony/java/android/telephony/satellite/stub/SatelliteError.aidl b/telephony/java/android/telephony/satellite/stub/SatelliteResult.aidl
index 6a110a90276f..639b4831cb16 100644
--- a/telephony/java/android/telephony/satellite/stub/SatelliteError.aidl
+++ b/telephony/java/android/telephony/satellite/stub/SatelliteResult.aidl
@@ -20,91 +20,87 @@ package android.telephony.satellite.stub;
* {@hide}
*/
@Backing(type="int")
-enum SatelliteError {
+enum SatelliteResult {
/**
* The request was successfully processed.
*/
- ERROR_NONE = 0,
+ SATELLITE_RESULT_SUCCESS = 0,
/**
* A generic error which should be used only when other specific errors cannot be used.
*/
- SATELLITE_ERROR = 1,
+ SATELLITE_RESULT_ERROR = 1,
/**
* Error received from the satellite server.
*/
- SERVER_ERROR = 2,
+ SATELLITE_RESULT_SERVER_ERROR = 2,
/**
* Error received from the vendor service. This generic error code should be used
* only when the error cannot be mapped to other specific service error codes.
*/
- SERVICE_ERROR = 3,
+ SATELLITE_RESULT_SERVICE_ERROR = 3,
/**
* Error received from satellite modem. This generic error code should be used only when
* the error cannot be mapped to other specific modem error codes.
*/
- MODEM_ERROR = 4,
+ SATELLITE_RESULT_MODEM_ERROR = 4,
/**
* Error received from the satellite network. This generic error code should be used only when
* the error cannot be mapped to other specific network error codes.
*/
- NETWORK_ERROR = 5,
- /**
- * Telephony is not in a valid state to receive requests from clients.
- */
- INVALID_TELEPHONY_STATE = 6,
+ SATELLITE_RESULT_NETWORK_ERROR = 5,
/**
* Satellite modem is not in a valid state to receive requests from clients.
*/
- INVALID_MODEM_STATE = 7,
+ SATELLITE_RESULT_INVALID_MODEM_STATE = 6,
/**
* Either vendor service, or modem, or Telephony framework has received a request with
* invalid arguments from its clients.
*/
- INVALID_ARGUMENTS = 8,
+ SATELLITE_RESULT_INVALID_ARGUMENTS = 7,
/**
* Telephony framework failed to send a request or receive a response from the vendor service
* or satellite modem due to internal error.
*/
- REQUEST_FAILED = 9,
+ SATELLITE_RESULT_REQUEST_FAILED = 8,
/**
* Radio did not start or is resetting.
*/
- RADIO_NOT_AVAILABLE = 10,
+ SATELLITE_RESULT_RADIO_NOT_AVAILABLE = 9,
/**
* The request is not supported by either the satellite modem or the network.
*/
- REQUEST_NOT_SUPPORTED = 11,
+ SATELLITE_RESULT_REQUEST_NOT_SUPPORTED = 10,
/**
* Satellite modem or network has no resources available to handle requests from clients.
*/
- NO_RESOURCES = 12,
+ SATELLITE_RESULT_NO_RESOURCES = 11,
/**
* Satellite service is not provisioned yet.
*/
- SERVICE_NOT_PROVISIONED = 13,
+ SATELLITE_RESULT_SERVICE_NOT_PROVISIONED = 12,
/**
* Satellite service provision is already in progress.
*/
- SERVICE_PROVISION_IN_PROGRESS = 14,
+ SATELLITE_RESULT_SERVICE_PROVISION_IN_PROGRESS = 13,
/**
* The ongoing request was aborted by either the satellite modem or the network.
*/
- REQUEST_ABORTED = 15,
+ SATELLITE_RESULT_REQUEST_ABORTED = 14,
/**
* The device/subscriber is barred from accessing the satellite service.
*/
- SATELLITE_ACCESS_BARRED = 16,
+ SATELLITE_RESULT_ACCESS_BARRED = 15,
/**
* Satellite modem timeout to receive ACK or response from the satellite network after
* sending a request to the network.
*/
- NETWORK_TIMEOUT = 17,
+ SATELLITE_RESULT_NETWORK_TIMEOUT = 16,
/**
* Satellite network is not reachable from the modem.
*/
- SATELLITE_NOT_REACHABLE = 18,
+ SATELLITE_RESULT_NOT_REACHABLE = 17,
/**
* The device/subscriber is not authorized to register with the satellite service provider.
*/
- NOT_AUTHORIZED = 19
+ SATELLITE_RESULT_NOT_AUTHORIZED = 18
}
diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl
index 06071feccf69..3aa5a5a14bc8 100644
--- a/telephony/java/com/android/internal/telephony/ITelephony.aidl
+++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl
@@ -3033,4 +3033,42 @@ interface ITelephony {
@JavaPassthrough(annotation="@android.annotation.RequiresPermission("
+ "android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)")
List<String> getShaIdFromAllowList(String pkgName, int carrierId);
+
+ /**
+ * Add a restriction reason for disallowing satellite communication.
+ *
+ * @param subId The subId of the subscription to request for.
+ * @param reason Reason for disallowing satellite communication for carrier.
+ * @param callback Listener for the {@link SatelliteManager.SatelliteError} result of the
+ * operation.
+ */
+ @JavaPassthrough(annotation="@android.annotation.RequiresPermission("
+ + "android.Manifest.permission.SATELLITE_COMMUNICATION)")
+ void addSatelliteAttachRestrictionForCarrier(int subId, int reason,
+ in IIntegerConsumer callback);
+
+ /**
+ * Remove a restriction reason for disallowing satellite communication.
+ *
+ * @param subId The subId of the subscription to request for.
+ * @param reason Reason for disallowing satellite communication.
+ * @param callback Listener for the {@link SatelliteManager.SatelliteError} result of the
+ * operation.
+ */
+ @JavaPassthrough(annotation="@android.annotation.RequiresPermission("
+ + "android.Manifest.permission.SATELLITE_COMMUNICATION)")
+ void removeSatelliteAttachRestrictionForCarrier(int subId, int reason,
+ in IIntegerConsumer callback);
+
+ /**
+ * Get reasons for disallowing satellite communication, as requested by
+ * {@link #addSatelliteAttachRestrictionForCarrier(int, int)}.
+ *
+ * @param subId The subId of the subscription to request for.
+ *
+ * @return Set of reasons for disallowing satellite communication.
+ */
+ @JavaPassthrough(annotation="@android.annotation.RequiresPermission("
+ + "android.Manifest.permission.SATELLITE_COMMUNICATION)")
+ int[] getSatelliteAttachRestrictionReasonsForCarrier(int subId);
}
diff --git a/tests/ApkVerityTest/ApkVerityTestApp/feature_split/AndroidManifest.xml b/tests/ApkVerityTest/ApkVerityTestApp/feature_split/AndroidManifest.xml
deleted file mode 100644
index 3f1a4f3a26a1..000000000000
--- a/tests/ApkVerityTest/ApkVerityTestApp/feature_split/AndroidManifest.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-<?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.apkverity"
- android:isFeatureSplit="true"
- split="feature_x">
- <application>
- <activity android:name=".feature_x.DummyActivity"/>
- </application>
-</manifest>
diff --git a/tests/ApkVerityTest/src/com/android/apkverity/ApkVerityTest.java b/tests/ApkVerityTest/src/com/android/apkverity/ApkVerityTest.java
deleted file mode 100644
index 482f633e2fe1..000000000000
--- a/tests/ApkVerityTest/src/com/android/apkverity/ApkVerityTest.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.apkverity;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
-
-import android.platform.test.annotations.RootPermissionTest;
-
-import com.android.blockdevicewriter.BlockDeviceWriter;
-import com.android.tradefed.device.DeviceNotAvailableException;
-import com.android.tradefed.device.ITestDevice;
-import com.android.tradefed.log.LogUtil.CLog;
-import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
-import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test;
-import com.android.tradefed.util.CommandResult;
-import com.android.tradefed.util.CommandStatus;
-
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-import java.io.FileNotFoundException;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.HashSet;
-import java.util.Set;
-
-/**
- * This test makes sure app installs with fs-verity signature, and on-access verification works.
- *
- * <p>When an app is installed, all or none of the files should have their corresponding .fsv_sig
- * signature file. Otherwise, install will fail.
- *
- * <p>Once installed, file protected by fs-verity is verified by kernel every time a block is loaded
- * from disk to memory. The file is immutable by design, enforced by filesystem.
- *
- * <p>In order to make sure a block of the file is readable only if the underlying block on disk
- * stay intact, the test needs to bypass the filesystem and tampers with the corresponding physical
- * address against the block device.
- *
- * <p>Requirements to run this test:
- * <ul>
- * <li>Device is rootable</li>
- * <li>The filesystem supports fs-verity</li>
- * <li>The feature flag is enabled</li>
- * </ul>
- */
-@RootPermissionTest
-@RunWith(DeviceJUnit4ClassRunner.class)
-public class ApkVerityTest extends BaseHostJUnit4Test {
- private static final String TARGET_PACKAGE = "com.android.apkverity";
-
- private static final String BASE_APK = "ApkVerityTestApp.apk";
- private static final String BASE_APK_DM = "ApkVerityTestApp.dm";
- private static final String SPLIT_APK = "ApkVerityTestAppSplit.apk";
- private static final String SPLIT_APK_DM = "ApkVerityTestAppSplit.dm";
-
- private static final String INSTALLED_BASE_APK = "base.apk";
- private static final String INSTALLED_BASE_DM = "base.dm";
- private static final String INSTALLED_SPLIT_APK = "split_feature_x.apk";
- private static final String INSTALLED_SPLIT_DM = "split_feature_x.dm";
- private static final String INSTALLED_BASE_APK_FSV_SIG = "base.apk.fsv_sig";
- private static final String INSTALLED_BASE_DM_FSV_SIG = "base.dm.fsv_sig";
- private static final String INSTALLED_SPLIT_APK_FSV_SIG = "split_feature_x.apk.fsv_sig";
- private static final String INSTALLED_SPLIT_DM_FSV_SIG = "split_feature_x.dm.fsv_sig";
-
- private static final String DAMAGING_EXECUTABLE = "/data/local/tmp/block_device_writer";
- private static final String CERT_PATH = "/data/local/tmp/ApkVerityTestCert.der";
-
- /** Only 4K page is supported by fs-verity currently. */
- private static final int FSVERITY_PAGE_SIZE = 4096;
-
- private ITestDevice mDevice;
- private boolean mDmRequireFsVerity;
-
- @Before
- public void setUp() throws DeviceNotAvailableException {
- mDevice = getDevice();
- mDmRequireFsVerity = "true".equals(
- mDevice.getProperty("pm.dexopt.dm.require_fsverity"));
-
- expectRemoteCommandToSucceed("cmd file_integrity append-cert " + CERT_PATH);
- uninstallPackage(TARGET_PACKAGE);
- }
-
- @After
- public void tearDown() throws DeviceNotAvailableException {
- expectRemoteCommandToSucceed("cmd file_integrity remove-last-cert");
- uninstallPackage(TARGET_PACKAGE);
- }
-
- @Test
- public void testFsverityKernelSupports() throws DeviceNotAvailableException {
- ITestDevice.MountPointInfo mountPoint = mDevice.getMountPointInfo("/data");
- expectRemoteCommandToSucceed("test -f /sys/fs/" + mountPoint.type + "/features/verity");
- }
-
- @Test
- public void testInstallBase() throws DeviceNotAvailableException, FileNotFoundException {
- new InstallMultiple()
- .addFileAndSignature(BASE_APK)
- .run();
- assertNotNull(getDevice().getAppPackageInfo(TARGET_PACKAGE));
-
- verifyInstalledFiles(
- INSTALLED_BASE_APK,
- INSTALLED_BASE_APK_FSV_SIG);
- verifyInstalledFilesHaveFsverity(INSTALLED_BASE_APK);
- }
-
- @Test
- public void testInstallBaseWithWrongSignature()
- throws DeviceNotAvailableException, FileNotFoundException {
- new InstallMultiple()
- .addFile(BASE_APK)
- .addFile(SPLIT_APK_DM + ".fsv_sig",
- BASE_APK + ".fsv_sig")
- .runExpectingFailure();
- }
-
- @Test
- public void testInstallBaseWithSplit()
- throws DeviceNotAvailableException, FileNotFoundException {
- new InstallMultiple()
- .addFileAndSignature(BASE_APK)
- .addFileAndSignature(SPLIT_APK)
- .run();
- assertNotNull(getDevice().getAppPackageInfo(TARGET_PACKAGE));
-
- verifyInstalledFiles(
- INSTALLED_BASE_APK,
- INSTALLED_BASE_APK_FSV_SIG,
- INSTALLED_SPLIT_APK,
- INSTALLED_SPLIT_APK_FSV_SIG);
- verifyInstalledFilesHaveFsverity(
- INSTALLED_BASE_APK,
- INSTALLED_SPLIT_APK);
- }
-
- @Test
- public void testInstallBaseWithDm() throws DeviceNotAvailableException, FileNotFoundException {
- new InstallMultiple()
- .addFileAndSignature(BASE_APK)
- .addFileAndSignature(BASE_APK_DM)
- .run();
- assertNotNull(getDevice().getAppPackageInfo(TARGET_PACKAGE));
-
- verifyInstalledFiles(
- INSTALLED_BASE_APK,
- INSTALLED_BASE_APK_FSV_SIG,
- INSTALLED_BASE_DM,
- INSTALLED_BASE_DM_FSV_SIG);
- verifyInstalledFilesHaveFsverity(
- INSTALLED_BASE_APK,
- INSTALLED_BASE_DM);
- }
-
- @Test
- public void testInstallEverything() throws DeviceNotAvailableException, FileNotFoundException {
- new InstallMultiple()
- .addFileAndSignature(BASE_APK)
- .addFileAndSignature(BASE_APK_DM)
- .addFileAndSignature(SPLIT_APK)
- .addFileAndSignature(SPLIT_APK_DM)
- .run();
- assertNotNull(getDevice().getAppPackageInfo(TARGET_PACKAGE));
-
- verifyInstalledFiles(
- INSTALLED_BASE_APK,
- INSTALLED_BASE_APK_FSV_SIG,
- INSTALLED_BASE_DM,
- INSTALLED_BASE_DM_FSV_SIG,
- INSTALLED_SPLIT_APK,
- INSTALLED_SPLIT_APK_FSV_SIG,
- INSTALLED_SPLIT_DM,
- INSTALLED_SPLIT_DM_FSV_SIG);
- verifyInstalledFilesHaveFsverity(
- INSTALLED_BASE_APK,
- INSTALLED_BASE_DM,
- INSTALLED_SPLIT_APK,
- INSTALLED_SPLIT_DM);
- }
-
- @Test
- public void testInstallSplitOnly()
- throws DeviceNotAvailableException, FileNotFoundException {
- new InstallMultiple()
- .addFileAndSignature(BASE_APK)
- .run();
- assertNotNull(getDevice().getAppPackageInfo(TARGET_PACKAGE));
- verifyInstalledFiles(
- INSTALLED_BASE_APK,
- INSTALLED_BASE_APK_FSV_SIG);
-
- new InstallMultiple()
- .inheritFrom(TARGET_PACKAGE)
- .addFileAndSignature(SPLIT_APK)
- .run();
-
- verifyInstalledFiles(
- INSTALLED_BASE_APK,
- INSTALLED_BASE_APK_FSV_SIG,
- INSTALLED_SPLIT_APK,
- INSTALLED_SPLIT_APK_FSV_SIG);
- verifyInstalledFilesHaveFsverity(
- INSTALLED_BASE_APK,
- INSTALLED_SPLIT_APK);
- }
-
- @Test
- public void testInstallSplitOnlyMissingSignature()
- throws DeviceNotAvailableException, FileNotFoundException {
- new InstallMultiple()
- .addFileAndSignature(BASE_APK)
- .run();
- assertNotNull(getDevice().getAppPackageInfo(TARGET_PACKAGE));
- verifyInstalledFiles(
- INSTALLED_BASE_APK,
- INSTALLED_BASE_APK_FSV_SIG);
-
- new InstallMultiple()
- .inheritFrom(TARGET_PACKAGE)
- .addFile(SPLIT_APK)
- .runExpectingFailure();
- }
-
- @Test
- public void testInstallSplitOnlyWithoutBaseSignature()
- throws DeviceNotAvailableException, FileNotFoundException {
- new InstallMultiple()
- .addFile(BASE_APK)
- .run();
- assertNotNull(getDevice().getAppPackageInfo(TARGET_PACKAGE));
- verifyInstalledFiles(INSTALLED_BASE_APK);
-
- new InstallMultiple()
- .inheritFrom(TARGET_PACKAGE)
- .addFileAndSignature(SPLIT_APK)
- .run();
- verifyInstalledFiles(
- INSTALLED_BASE_APK,
- INSTALLED_SPLIT_APK,
- INSTALLED_SPLIT_APK_FSV_SIG);
- }
-
- @Test
- public void testInstallOnlyDmHasFsvSig()
- throws DeviceNotAvailableException, FileNotFoundException {
- new InstallMultiple()
- .addFile(BASE_APK)
- .addFileAndSignature(BASE_APK_DM)
- .addFile(SPLIT_APK)
- .addFileAndSignature(SPLIT_APK_DM)
- .run();
- verifyInstalledFiles(
- INSTALLED_BASE_APK,
- INSTALLED_BASE_DM,
- INSTALLED_BASE_DM_FSV_SIG,
- INSTALLED_SPLIT_APK,
- INSTALLED_SPLIT_DM,
- INSTALLED_SPLIT_DM_FSV_SIG);
- verifyInstalledFilesHaveFsverity(
- INSTALLED_BASE_DM,
- INSTALLED_SPLIT_DM);
- }
-
- @Test
- public void testInstallDmWithoutFsvSig_Base()
- throws DeviceNotAvailableException, FileNotFoundException {
- InstallMultiple installer = new InstallMultiple()
- .addFile(BASE_APK)
- .addFile(BASE_APK_DM)
- .addFile(SPLIT_APK)
- .addFileAndSignature(SPLIT_APK_DM);
- if (mDmRequireFsVerity) {
- installer.runExpectingFailure();
- } else {
- installer.run();
- verifyInstalledFiles(
- INSTALLED_BASE_APK,
- INSTALLED_BASE_DM,
- INSTALLED_SPLIT_APK,
- INSTALLED_SPLIT_DM,
- INSTALLED_SPLIT_DM_FSV_SIG);
- verifyInstalledFilesHaveFsverity(INSTALLED_SPLIT_DM);
- }
- }
-
- @Test
- public void testInstallDmWithoutFsvSig_Split()
- throws DeviceNotAvailableException, FileNotFoundException {
- InstallMultiple installer = new InstallMultiple()
- .addFile(BASE_APK)
- .addFileAndSignature(BASE_APK_DM)
- .addFile(SPLIT_APK)
- .addFile(SPLIT_APK_DM);
- if (mDmRequireFsVerity) {
- installer.runExpectingFailure();
- } else {
- installer.run();
- verifyInstalledFiles(
- INSTALLED_BASE_APK,
- INSTALLED_BASE_DM,
- INSTALLED_BASE_DM_FSV_SIG,
- INSTALLED_SPLIT_APK,
- INSTALLED_SPLIT_DM);
- verifyInstalledFilesHaveFsverity(INSTALLED_BASE_DM);
- }
- }
-
- @Test
- public void testInstallSomeApkIsMissingFsvSig_Base()
- throws DeviceNotAvailableException, FileNotFoundException {
- new InstallMultiple()
- .addFileAndSignature(BASE_APK)
- .addFileAndSignature(BASE_APK_DM)
- .addFile(SPLIT_APK)
- .addFileAndSignature(SPLIT_APK_DM)
- .runExpectingFailure();
- }
-
- @Test
- public void testInstallSomeApkIsMissingFsvSig_Split()
- throws DeviceNotAvailableException, FileNotFoundException {
- new InstallMultiple()
- .addFile(BASE_APK)
- .addFileAndSignature(BASE_APK_DM)
- .addFileAndSignature(SPLIT_APK)
- .addFileAndSignature(SPLIT_APK_DM)
- .runExpectingFailure();
- }
-
- @Test
- public void testInstallBaseWithFsvSigThenSplitWithout()
- throws DeviceNotAvailableException, FileNotFoundException {
- new InstallMultiple()
- .addFileAndSignature(BASE_APK)
- .run();
- assertNotNull(getDevice().getAppPackageInfo(TARGET_PACKAGE));
- verifyInstalledFiles(
- INSTALLED_BASE_APK,
- INSTALLED_BASE_APK_FSV_SIG);
-
- new InstallMultiple()
- .addFile(SPLIT_APK)
- .runExpectingFailure();
- }
-
- @Test
- public void testInstallBaseWithoutFsvSigThenSplitWith()
- throws DeviceNotAvailableException, FileNotFoundException {
- new InstallMultiple()
- .addFile(BASE_APK)
- .run();
- assertNotNull(getDevice().getAppPackageInfo(TARGET_PACKAGE));
- verifyInstalledFiles(INSTALLED_BASE_APK);
-
- new InstallMultiple()
- .addFileAndSignature(SPLIT_APK)
- .runExpectingFailure();
- }
-
- @Test
- public void testFsverityFileIsImmutableAndReadable() throws DeviceNotAvailableException {
- new InstallMultiple().addFileAndSignature(BASE_APK).run();
- String apkPath = getApkPath(TARGET_PACKAGE);
-
- assertNotNull(getDevice().getAppPackageInfo(TARGET_PACKAGE));
- expectRemoteCommandToFail("echo -n '' >> " + apkPath);
- expectRemoteCommandToSucceed("cat " + apkPath + " > /dev/null");
- }
-
- @Test
- public void testFsverityFailToReadModifiedBlockAtFront() throws DeviceNotAvailableException {
- new InstallMultiple().addFileAndSignature(BASE_APK).run();
- String apkPath = getApkPath(TARGET_PACKAGE);
-
- long apkSize = getFileSizeInBytes(apkPath);
- long offsetFirstByte = 0;
-
- // The first two pages should be both readable at first.
- assertTrue(BlockDeviceWriter.canReadByte(mDevice, apkPath, offsetFirstByte));
- if (apkSize > offsetFirstByte + FSVERITY_PAGE_SIZE) {
- assertTrue(BlockDeviceWriter.canReadByte(mDevice, apkPath,
- offsetFirstByte + FSVERITY_PAGE_SIZE));
- }
-
- // Damage the file directly against the block device.
- damageFileAgainstBlockDevice(apkPath, offsetFirstByte);
-
- // Expect actual read from disk to fail but only at damaged page.
- expectReadFromBlockDeviceToFail(apkPath, offsetFirstByte);
- if (apkSize > offsetFirstByte + FSVERITY_PAGE_SIZE) {
- long lastByteOfTheSamePage =
- offsetFirstByte % FSVERITY_PAGE_SIZE + FSVERITY_PAGE_SIZE - 1;
- assertFalse(BlockDeviceWriter.canReadByte(mDevice, apkPath, lastByteOfTheSamePage));
- assertTrue(BlockDeviceWriter.canReadByte(mDevice, apkPath, lastByteOfTheSamePage + 1));
- }
- }
-
- @Test
- public void testFsverityFailToReadModifiedBlockAtBack() throws DeviceNotAvailableException {
- new InstallMultiple().addFileAndSignature(BASE_APK).run();
- String apkPath = getApkPath(TARGET_PACKAGE);
-
- long apkSize = getFileSizeInBytes(apkPath);
- long offsetOfLastByte = apkSize - 1;
-
- // The first two pages should be both readable at first.
- assertTrue(BlockDeviceWriter.canReadByte(mDevice, apkPath, offsetOfLastByte));
- if (offsetOfLastByte - FSVERITY_PAGE_SIZE > 0) {
- assertTrue(BlockDeviceWriter.canReadByte(mDevice, apkPath,
- offsetOfLastByte - FSVERITY_PAGE_SIZE));
- }
-
- // Damage the file directly against the block device.
- damageFileAgainstBlockDevice(apkPath, offsetOfLastByte);
-
- // Expect actual read from disk to fail but only at damaged page.
- expectReadFromBlockDeviceToFail(apkPath, offsetOfLastByte);
- if (offsetOfLastByte - FSVERITY_PAGE_SIZE > 0) {
- long firstByteOfTheSamePage = offsetOfLastByte - offsetOfLastByte % FSVERITY_PAGE_SIZE;
- assertFalse(BlockDeviceWriter.canReadByte(mDevice, apkPath, firstByteOfTheSamePage));
- assertTrue(BlockDeviceWriter.canReadByte(mDevice, apkPath, firstByteOfTheSamePage - 1));
- }
- }
-
- private void verifyInstalledFilesHaveFsverity(String... filenames)
- throws DeviceNotAvailableException {
- // Verify that all files are protected by fs-verity
- String apkPath = getApkPath(TARGET_PACKAGE);
- String appDir = apkPath.substring(0, apkPath.lastIndexOf("/"));
- long kTargetOffset = 0;
- for (String basename : filenames) {
- String path = appDir + "/" + basename;
- damageFileAgainstBlockDevice(path, kTargetOffset);
-
- expectReadFromBlockDeviceToFail(path, kTargetOffset);
- }
- }
-
- private void expectReadFromBlockDeviceToFail(String readPath, long offset)
- throws DeviceNotAvailableException {
- // Retry is sometimes needed to pass the test. Package manager may have FD leaks
- // (see b/122744005 as example) that prevents the file in question to be evicted
- // from filesystem cache. Forcing GC workarounds the problem.
- int retry = 5;
- for (; retry > 0; retry--) {
- BlockDeviceWriter.dropCaches(mDevice);
- if (!BlockDeviceWriter.canReadByte(mDevice, readPath, offset)) {
- break;
- }
- try {
- String openFiles = expectRemoteCommandToSucceed("lsof " + readPath);
- CLog.d("lsof: " + openFiles);
- Thread.sleep(1000);
- forceGCOnOpenFilesProcess(getOpenFilesPIDs(openFiles));
- } catch (InterruptedException e) {
- Thread.currentThread().interrupt();
- return;
- }
- }
- assertTrue("Read from " + readPath + " should fail", retry > 0);
- }
-
- /**
- * This is a helper method that parses the lsof output to get PIDs of process holding FD.
- * Here is an example output of lsof. This method extracts the second columns(PID).
- *
- * Example lsof output:
- * COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
- * .example.app 1063 u0_a38 mem REG 253,6 8599 12826 example.apk
- * .example.app 1063 u0_a38 99r REG 253,6 8599 12826 example.apk
- */
- private Set<String> getOpenFilesPIDs(String lsof) {
- Set<String> openFilesPIDs = new HashSet<>();
- String[] lines = lsof.split("\n");
- for (int i = 1; i < lines.length; i++) {
- openFilesPIDs.add(lines[i].split("\\s+")[1]);
- }
- return openFilesPIDs;
- }
-
- /**
- * This is a helper method that forces GC on processes given their PIDs.
- * That is to execute shell command "kill -10" on PIDs.
- */
- private void forceGCOnOpenFilesProcess(Set<String> openFilesPIDs)
- throws DeviceNotAvailableException {
- for (String openFilePID : openFilesPIDs) {
- mDevice.executeShellV2Command("kill -10 " + openFilePID);
- }
- }
-
- private void verifyInstalledFiles(String... filenames) throws DeviceNotAvailableException {
- String apkPath = getApkPath(TARGET_PACKAGE);
- String appDir = apkPath.substring(0, apkPath.lastIndexOf("/"));
- // Exclude directories since we only care about files.
- HashSet<String> actualFiles = new HashSet<>(Arrays.asList(
- expectRemoteCommandToSucceed("ls -p " + appDir + " | grep -v '/'").split("\n")));
-
- HashSet<String> expectedFiles = new HashSet<>(Arrays.asList(filenames));
- assertEquals(expectedFiles, actualFiles);
- }
-
- private void damageFileAgainstBlockDevice(String path, long offsetOfTargetingByte)
- throws DeviceNotAvailableException {
- assertTrue(path.startsWith("/data/"));
- ITestDevice.MountPointInfo mountPoint = mDevice.getMountPointInfo("/data");
- ArrayList<String> args = new ArrayList<>();
- args.add(DAMAGING_EXECUTABLE);
- if ("f2fs".equals(mountPoint.type)) {
- args.add("--use-f2fs-pinning");
- }
- args.add(mountPoint.filesystem);
- args.add(path);
- args.add(Long.toString(offsetOfTargetingByte));
- expectRemoteCommandToSucceed(String.join(" ", args));
- }
-
- private String getApkPath(String packageName) throws DeviceNotAvailableException {
- String line = expectRemoteCommandToSucceed("pm path " + packageName + " | grep base.apk");
- int index = line.trim().indexOf(":");
- assertTrue(index >= 0);
- return line.substring(index + 1);
- }
-
- private long getFileSizeInBytes(String packageName) throws DeviceNotAvailableException {
- return Long.parseLong(expectRemoteCommandToSucceed("stat -c '%s' " + packageName).trim());
- }
-
- private String expectRemoteCommandToSucceed(String cmd) throws DeviceNotAvailableException {
- CommandResult result = mDevice.executeShellV2Command(cmd);
- assertEquals("`" + cmd + "` failed: " + result.getStderr(), CommandStatus.SUCCESS,
- result.getStatus());
- return result.getStdout();
- }
-
- private void expectRemoteCommandToFail(String cmd) throws DeviceNotAvailableException {
- CommandResult result = mDevice.executeShellV2Command(cmd);
- assertTrue("Unexpected success from `" + cmd + "`: " + result.getStderr(),
- result.getStatus() != CommandStatus.SUCCESS);
- }
-
- private class InstallMultiple extends BaseInstallMultiple<InstallMultiple> {
- InstallMultiple() {
- super(getDevice(), getBuild());
- }
-
- InstallMultiple addFileAndSignature(String filename) {
- try {
- addFile(filename);
- addFile(filename + ".fsv_sig");
- } catch (FileNotFoundException e) {
- fail("Missing test file: " + e);
- }
- return this;
- }
- }
-}
diff --git a/tests/ApkVerityTest/src/com/android/apkverity/BaseInstallMultiple.java b/tests/ApkVerityTest/src/com/android/apkverity/BaseInstallMultiple.java
deleted file mode 100644
index 02e73d157dde..000000000000
--- a/tests/ApkVerityTest/src/com/android/apkverity/BaseInstallMultiple.java
+++ /dev/null
@@ -1,140 +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.apkverity;
-
-import com.android.compatibility.common.tradefed.build.CompatibilityBuildHelper;
-import com.android.tradefed.build.IBuildInfo;
-import com.android.tradefed.device.DeviceNotAvailableException;
-import com.android.tradefed.device.ITestDevice;
-
-import junit.framework.TestCase;
-
-import java.io.File;
-import java.io.FileNotFoundException;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-/**
- * Base class for invoking the install-multiple command via ADB. Subclass this for less typing:
- *
- * <code> private class InstallMultiple extends BaseInstallMultiple&lt;InstallMultiple&gt; { public
- * InstallMultiple() { super(getDevice(), null); } } </code>
- */
-/*package*/ class BaseInstallMultiple<T extends BaseInstallMultiple<?>> {
-
- private final ITestDevice mDevice;
- private final IBuildInfo mBuild;
-
- private final List<String> mArgs = new ArrayList<>();
- private final Map<File, String> mFileToRemoteMap = new HashMap<>();
-
- /*package*/ BaseInstallMultiple(ITestDevice device, IBuildInfo buildInfo) {
- mDevice = device;
- mBuild = buildInfo;
- addArg("-g");
- }
-
- T addArg(String arg) {
- mArgs.add(arg);
- return (T) this;
- }
-
- T addFile(String filename) throws FileNotFoundException {
- return addFile(filename, filename);
- }
-
- T addFile(String filename, String remoteName) throws FileNotFoundException {
- CompatibilityBuildHelper buildHelper = new CompatibilityBuildHelper(mBuild);
- mFileToRemoteMap.put(buildHelper.getTestFile(filename), remoteName);
- return (T) this;
- }
-
- T inheritFrom(String packageName) {
- addArg("-r");
- addArg("-p " + packageName);
- return (T) this;
- }
-
- void run() throws DeviceNotAvailableException {
- run(true);
- }
-
- void runExpectingFailure() throws DeviceNotAvailableException {
- run(false);
- }
-
- private void run(boolean expectingSuccess) throws DeviceNotAvailableException {
- final ITestDevice device = mDevice;
-
- // Create an install session
- final StringBuilder cmd = new StringBuilder();
- cmd.append("pm install-create");
- for (String arg : mArgs) {
- cmd.append(' ').append(arg);
- }
-
- String result = device.executeShellCommand(cmd.toString());
- TestCase.assertTrue(result, result.startsWith("Success"));
-
- final int start = result.lastIndexOf("[");
- final int end = result.lastIndexOf("]");
- int sessionId = -1;
- try {
- if (start != -1 && end != -1 && start < end) {
- sessionId = Integer.parseInt(result.substring(start + 1, end));
- }
- } catch (NumberFormatException e) {
- throw new IllegalStateException("Failed to parse install session: " + result);
- }
- if (sessionId == -1) {
- throw new IllegalStateException("Failed to create install session: " + result);
- }
-
- // Push our files into session. Ideally we'd use stdin streaming,
- // but ddmlib doesn't support it yet.
- for (final Map.Entry<File, String> entry : mFileToRemoteMap.entrySet()) {
- final File file = entry.getKey();
- final String remoteName = entry.getValue();
- final String remotePath = "/data/local/tmp/" + file.getName();
- if (!device.pushFile(file, remotePath)) {
- throw new IllegalStateException("Failed to push " + file);
- }
-
- cmd.setLength(0);
- cmd.append("pm install-write");
- cmd.append(' ').append(sessionId);
- cmd.append(' ').append(remoteName);
- cmd.append(' ').append(remotePath);
-
- result = device.executeShellCommand(cmd.toString());
- TestCase.assertTrue(result, result.startsWith("Success"));
- }
-
- // Everything staged; let's pull trigger
- cmd.setLength(0);
- cmd.append("pm install-commit");
- cmd.append(' ').append(sessionId);
-
- result = device.executeShellCommand(cmd.toString());
- if (expectingSuccess) {
- TestCase.assertTrue(result, result.contains("Success"));
- } else {
- TestCase.assertFalse(result, result.contains("Success"));
- }
- }
-}
diff --git a/tests/ApkVerityTest/testdata/ApkVerityTestApp.dm b/tests/ApkVerityTest/testdata/ApkVerityTestApp.dm
deleted file mode 100644
index e53a86131366..000000000000
--- a/tests/ApkVerityTest/testdata/ApkVerityTestApp.dm
+++ /dev/null
Binary files differ
diff --git a/tests/ApkVerityTest/testdata/ApkVerityTestAppSplit.dm b/tests/ApkVerityTest/testdata/ApkVerityTestAppSplit.dm
deleted file mode 100644
index 75396f1ba730..000000000000
--- a/tests/ApkVerityTest/testdata/ApkVerityTestAppSplit.dm
+++ /dev/null
Binary files differ
diff --git a/tests/ApkVerityTest/testdata/README.md b/tests/ApkVerityTest/testdata/README.md
deleted file mode 100644
index 163cb183a5ad..000000000000
--- a/tests/ApkVerityTest/testdata/README.md
+++ /dev/null
@@ -1,13 +0,0 @@
-This test only runs on rooted / debuggable device.
-
-The test tries to install subsets of base.{apk,dm}, split.{apk,dm} and their
-corresponding .fsv_sig files (generated by build rule). If installed, the
-tests also tries to tamper with the file at absolute disk offset to verify
-if fs-verity is effective.
-
-How to generate dex metadata (.dm)
-==================================
-
- adb shell profman --generate-test-profile=/data/local/tmp/primary.prof
- adb pull /data/local/tmp/primary.prof
- zip foo.dm primary.prof
diff --git a/tests/BatteryStatsPerfTest/src/com/android/internal/os/BatteryUsageStatsPerfTest.java b/tests/BatteryStatsPerfTest/src/com/android/internal/os/BatteryUsageStatsPerfTest.java
index fe2fe0b40891..08430f2f2744 100644
--- a/tests/BatteryStatsPerfTest/src/com/android/internal/os/BatteryUsageStatsPerfTest.java
+++ b/tests/BatteryStatsPerfTest/src/com/android/internal/os/BatteryUsageStatsPerfTest.java
@@ -159,7 +159,7 @@ public class BatteryUsageStatsPerfTest {
private static BatteryUsageStats buildBatteryUsageStats() {
final BatteryUsageStats.Builder builder =
- new BatteryUsageStats.Builder(new String[]{"FOO"}, true, false)
+ new BatteryUsageStats.Builder(new String[]{"FOO"}, true, false, 0)
.setBatteryCapacity(4000)
.setDischargePercentage(20)
.setDischargedPowerRange(1000, 2000)
diff --git a/tests/ChoreographerTests/src/main/java/android/view/choreographertests/AttachedChoreographerTest.java b/tests/ChoreographerTests/src/main/java/android/view/choreographertests/AttachedChoreographerTest.java
index bb0d30af42ee..5460e4e87e2f 100644
--- a/tests/ChoreographerTests/src/main/java/android/view/choreographertests/AttachedChoreographerTest.java
+++ b/tests/ChoreographerTests/src/main/java/android/view/choreographertests/AttachedChoreographerTest.java
@@ -421,7 +421,7 @@ public class AttachedChoreographerTest {
@Test
public void testChoreographerAttachedAfterSetFrameRate() {
- Log.i(TAG, "adyabr: starting testChoreographerAttachedAfterSetFrameRate");
+ Log.i(TAG, "starting testChoreographerAttachedAfterSetFrameRate");
class TransactionGenerator implements SurfaceControl.TransactionCommittedListener {
private SurfaceControl mSc;
diff --git a/tests/FlickerTests/Android.bp b/tests/FlickerTests/Android.bp
index 2ccc0fa9e1e7..a2ae56eaeadc 100644
--- a/tests/FlickerTests/Android.bp
+++ b/tests/FlickerTests/Android.bp
@@ -95,6 +95,7 @@ java_defaults {
"flickertestapplib",
"flickerlib",
"flickerlib-helpers",
+ "flickerlib-trace_processor_shell",
"platform-test-annotations",
"wm-flicker-common-app-helpers",
"wm-shell-flicker-utils",
diff --git a/tests/FlickerTests/AndroidTestTemplate.xml b/tests/FlickerTests/AndroidTestTemplate.xml
index 44a824513b91..878038557cf1 100644
--- a/tests/FlickerTests/AndroidTestTemplate.xml
+++ b/tests/FlickerTests/AndroidTestTemplate.xml
@@ -61,7 +61,9 @@
<option name="shell-timeout" value="6600s"/>
<option name="test-timeout" value="6600s"/>
<option name="hidden-api-checks" value="false"/>
+ <!-- TODO(b/288396763): re-enable when PerfettoListener is fixed
<option name="device-listeners" value="android.device.collectors.PerfettoListener"/>
+ -->
<!-- PerfettoListener related arguments -->
<option name="instrumentation-arg" key="perfetto_config_text_proto" value="true"/>
<option name="instrumentation-arg"
diff --git a/tests/FlickerTests/manifests/AndroidManifest.xml b/tests/FlickerTests/manifests/AndroidManifest.xml
index 1a34d9ea0f83..6bc7cbe88589 100644
--- a/tests/FlickerTests/manifests/AndroidManifest.xml
+++ b/tests/FlickerTests/manifests/AndroidManifest.xml
@@ -44,8 +44,12 @@
<uses-permission android:name="android.permission.MANAGE_ACTIVITY_TASKS" />
<!-- ActivityOptions.makeCustomTaskAnimation() -->
<uses-permission android:name="android.permission.START_TASKS_FROM_RECENTS" />
- <!-- Allow the test to write directly to /sdcard/ -->
- <application android:requestLegacyExternalStorage="true" android:largeHeap="true">
+ <!-- Allow the test to connect to perfetto trace processor -->
+ <uses-permission android:name="android.permission.INTERNET"/>
+ <!-- Allow the test to write directly to /sdcard/ and connect to trace processor -->
+ <application android:requestLegacyExternalStorage="true"
+ android:networkSecurityConfig="@xml/network_security_config"
+ android:largeHeap="true">
<uses-library android:name="android.test.runner"/>
<uses-library android:name="androidx.window.extensions" android:required="false"/>
diff --git a/tests/FlickerTests/res/xml/network_security_config.xml b/tests/FlickerTests/res/xml/network_security_config.xml
new file mode 100644
index 000000000000..4bd9ca049f55
--- /dev/null
+++ b/tests/FlickerTests/res/xml/network_security_config.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2023 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<network-security-config>
+ <domain-config cleartextTrafficPermitted="true">
+ <domain includeSubdomains="true">localhost</domain>
+ </domain-config>
+</network-security-config>
diff --git a/tests/ApkVerityTest/Android.bp b/tests/FsVerityTest/Android.bp
index f026bea80470..53606a32b185 100644
--- a/tests/ApkVerityTest/Android.bp
+++ b/tests/FsVerityTest/Android.bp
@@ -22,7 +22,7 @@ package {
}
java_test_host {
- name: "ApkVerityTest",
+ name: "FsVerityTest",
srcs: ["src/**/*.java"],
libs: [
"tradefed",
@@ -30,8 +30,10 @@ java_test_host {
"compatibility-host-util",
],
static_libs: [
+ "android.security.flags-aconfig-java-host",
"block_device_writer_jar",
"frameworks-base-hostutils",
+ "flag-junit-host",
],
test_suites: [
"general-tests",
@@ -41,14 +43,6 @@ java_test_host {
"block_device_writer",
],
data: [
- ":ApkVerityTestCertDer",
- ":ApkVerityTestApp",
- ":ApkVerityTestAppFsvSig",
- ":ApkVerityTestAppDm",
- ":ApkVerityTestAppDmFsvSig",
- ":ApkVerityTestAppSplit",
- ":ApkVerityTestAppSplitFsvSig",
- ":ApkVerityTestAppSplitDm",
- ":ApkVerityTestAppSplitDmFsvSig",
+ ":FsVerityTestApp",
],
}
diff --git a/tests/ApkVerityTest/AndroidTest.xml b/tests/FsVerityTest/AndroidTest.xml
index 4487cefb4f9c..49cbde0d4611 100644
--- a/tests/ApkVerityTest/AndroidTest.xml
+++ b/tests/FsVerityTest/AndroidTest.xml
@@ -13,7 +13,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
-<configuration description="APK fs-verity integration/regression test">
+<configuration description="fs-verity end-to-end test">
<option name="test-suite-tag" value="apct" />
<object type="module_controller" class="com.android.tradefed.testtype.suite.module.ShippingApiLevelModuleController">
@@ -24,19 +24,9 @@
<!-- This test requires root to write against block device. -->
<target_preparer class="com.android.tradefed.targetprep.RootTargetPreparer" />
- <target_preparer class="com.android.tradefed.targetprep.DeviceSetup">
- <!-- Disable package verifier prevents it holding the target APK's fd that prevents cache
- eviction. -->
- <option name="set-global-setting" key="verifier_verify_adb_installs" value="0" />
- <option name="restore-settings" value="true" />
-
- <!-- Skip in order to prevent reboot that confuses the test flow. -->
- <option name="force-skip-system-props" value="true" />
- </target_preparer>
-
- <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
- <option name="cleanup" value="true" />
- <option name="push" value="ApkVerityTestCert.der->/data/local/tmp/ApkVerityTestCert.der" />
+ <target_preparer class="com.android.tradefed.targetprep.TestAppInstallSetup">
+ <option name="test-file-name" value="FsVerityTestApp.apk"/>
+ <option name="cleanup-apks" value="true"/>
</target_preparer>
<target_preparer class="com.android.compatibility.common.tradefed.targetprep.FilePusher">
@@ -48,9 +38,7 @@
<option name="push" value="block_device_writer->/data/local/tmp/block_device_writer" />
</target_preparer>
- <!-- Skip on HWASan. TODO(b/232288278): Re-enable -->
- <object type="module_controller" class="com.android.tradefed.testtype.suite.module.SkipHWASanModuleController" />
<test class="com.android.compatibility.common.tradefed.testtype.JarHostTest" >
- <option name="jar" value="ApkVerityTest.jar" />
+ <option name="jar" value="FsVerityTest.jar" />
</test>
</configuration>
diff --git a/tests/ApkVerityTest/ApkVerityTestApp/Android.bp b/tests/FsVerityTest/FsVerityTestApp/Android.bp
index adf8f9f9d321..43da3ff9fec1 100644
--- a/tests/ApkVerityTest/ApkVerityTestApp/Android.bp
+++ b/tests/FsVerityTest/FsVerityTestApp/Android.bp
@@ -22,17 +22,8 @@ package {
}
android_test_helper_app {
- name: "ApkVerityTestApp",
- manifest: "AndroidManifest.xml",
- srcs: ["src/**/*.java"],
-}
-
-android_test_helper_app {
- name: "ApkVerityTestAppSplit",
- manifest: "feature_split/AndroidManifest.xml",
- srcs: ["src/**/*.java"],
- aaptflags: [
- "--custom-package com.android.apkverity.feature_x",
- "--package-id 0x80",
- ],
+ name: "FsVerityTestApp",
+ manifest: "AndroidManifest.xml",
+ srcs: ["src/**/*.java"],
+ static_libs: ["compatibility-device-util-axt"],
}
diff --git a/tests/ApkVerityTest/ApkVerityTestApp/AndroidManifest.xml b/tests/FsVerityTest/FsVerityTestApp/AndroidManifest.xml
index 0b3ff77c2cdf..42fe49be66d9 100644
--- a/tests/ApkVerityTest/ApkVerityTestApp/AndroidManifest.xml
+++ b/tests/FsVerityTest/FsVerityTestApp/AndroidManifest.xml
@@ -16,8 +16,12 @@
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="com.android.apkverity">
+ package="com.android.fsverity">
<application>
<activity android:name=".DummyActivity"/>
</application>
+ <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
+ android:targetPackage="com.android.fsverity"
+ android:label="Helper app of fs-verity test">
+ </instrumentation>/>
</manifest>
diff --git a/tests/FsVerityTest/FsVerityTestApp/src/com/android/fsverity/Helper.java b/tests/FsVerityTest/FsVerityTestApp/src/com/android/fsverity/Helper.java
new file mode 100644
index 000000000000..2ed4fec4a93c
--- /dev/null
+++ b/tests/FsVerityTest/FsVerityTestApp/src/com/android/fsverity/Helper.java
@@ -0,0 +1,108 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.fsverity;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.junit.Assert.assertThrows;
+
+import android.content.Context;
+import android.security.FileIntegrityManager;
+import android.util.Log;
+
+import androidx.test.core.app.ApplicationProvider;
+import androidx.test.platform.app.InstrumentationRegistry;
+
+import org.junit.Test;
+
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.RandomAccessFile;
+import java.util.ArrayList;
+import java.util.Arrays;
+
+/**
+ * Test helper that works with the host-side test to set up a test file, and to verify fs-verity
+ * verification is done expectedly.
+ */
+public class Helper {
+ private static final String TAG = "FsVerityTest";
+
+ private static final String FILENAME = "test.file";
+
+ private static final long BLOCK_SIZE = 4096;
+
+ @Test
+ public void prepareTest() throws Exception {
+ Context context = ApplicationProvider.getApplicationContext();
+ android.os.Bundle testArgs = InstrumentationRegistry.getArguments();
+
+ String basename = testArgs.getString("basename");
+ context.deleteFile(basename);
+
+ assertThat(testArgs).isNotNull();
+ int fileSize = Integer.parseInt(testArgs.getString("fileSize"));
+ Log.d(TAG, "Preparing test file with size " + fileSize);
+
+ byte[] bytes = new byte[8192];
+ Arrays.fill(bytes, (byte) '1');
+ try (FileOutputStream os = context.openFileOutput(basename, Context.MODE_PRIVATE)) {
+ for (int i = 0; i < fileSize; i += bytes.length) {
+ if (i + bytes.length > fileSize) {
+ os.write(bytes, 0, fileSize % bytes.length);
+ } else {
+ os.write(bytes);
+ }
+ }
+ }
+
+ // Enable fs-verity
+ FileIntegrityManager fim = context.getSystemService(FileIntegrityManager.class);
+ fim.setupFsVerity(context.getFileStreamPath(basename));
+ }
+
+ @Test
+ public void verifyFileRead() throws Exception {
+ Context context = ApplicationProvider.getApplicationContext();
+
+ // Collect indices that the backing blocks are supposed to be corrupted.
+ android.os.Bundle testArgs = InstrumentationRegistry.getArguments();
+ assertThat(testArgs).isNotNull();
+ String filePath = testArgs.getString("filePath");
+ String csv = testArgs.getString("brokenBlockIndicesCsv");
+ Log.d(TAG, "brokenBlockIndicesCsv: " + csv);
+ String[] strings = csv.split(",");
+ var corrupted = new ArrayList(strings.length);
+ for (int i = 0; i < strings.length; i++) {
+ corrupted.add(Integer.parseInt(strings[i]));
+ }
+
+ // Expect the read to succeed or fail per the prior.
+ try (var file = new RandomAccessFile(filePath, "r")) {
+ long total_blocks = (file.length() + BLOCK_SIZE - 1) / BLOCK_SIZE;
+ for (int i = 0; i < (int) total_blocks; i++) {
+ file.seek(i * BLOCK_SIZE);
+ if (corrupted.contains(i)) {
+ Log.d(TAG, "Expecting read at block #" + i + " to fail");
+ assertThrows(IOException.class, () -> file.read());
+ } else {
+ assertThat(file.readByte()).isEqualTo('1');
+ }
+ }
+ }
+ }
+}
diff --git a/tests/ApkVerityTest/OWNERS b/tests/FsVerityTest/OWNERS
index d67285ede44a..d67285ede44a 100644
--- a/tests/ApkVerityTest/OWNERS
+++ b/tests/FsVerityTest/OWNERS
diff --git a/tests/ApkVerityTest/TEST_MAPPING b/tests/FsVerityTest/TEST_MAPPING
index 72d96148c69f..39944bed3f60 100644
--- a/tests/ApkVerityTest/TEST_MAPPING
+++ b/tests/FsVerityTest/TEST_MAPPING
@@ -1,11 +1,11 @@
{
- "presubmit": [
+ "postsubmit": [
{
- "name": "ApkVerityTest"
+ "name": "FsVerityTest"
},
// nextgen test only runs during postsubmit.
{
- "name": "ApkVerityTest",
+ "name": "FsVerityTest",
"keywords": ["nextgen"]
}
]
diff --git a/tests/ApkVerityTest/block_device_writer/Android.bp b/tests/FsVerityTest/block_device_writer/Android.bp
index 0002447d17f2..0002447d17f2 100644
--- a/tests/ApkVerityTest/block_device_writer/Android.bp
+++ b/tests/FsVerityTest/block_device_writer/Android.bp
diff --git a/tests/ApkVerityTest/block_device_writer/block_device_writer.cpp b/tests/FsVerityTest/block_device_writer/block_device_writer.cpp
index 02dfd732a716..02dfd732a716 100644
--- a/tests/ApkVerityTest/block_device_writer/block_device_writer.cpp
+++ b/tests/FsVerityTest/block_device_writer/block_device_writer.cpp
diff --git a/tests/ApkVerityTest/block_device_writer/src/com/android/blockdevicewriter/BlockDeviceWriter.java b/tests/FsVerityTest/block_device_writer/src/com/android/blockdevicewriter/BlockDeviceWriter.java
index 9be02ec3be86..9be02ec3be86 100644
--- a/tests/ApkVerityTest/block_device_writer/src/com/android/blockdevicewriter/BlockDeviceWriter.java
+++ b/tests/FsVerityTest/block_device_writer/src/com/android/blockdevicewriter/BlockDeviceWriter.java
diff --git a/tests/FsVerityTest/src/com/android/fsverity/FsVerityHostTest.java b/tests/FsVerityTest/src/com/android/fsverity/FsVerityHostTest.java
new file mode 100644
index 000000000000..be479f205ff2
--- /dev/null
+++ b/tests/FsVerityTest/src/com/android/fsverity/FsVerityHostTest.java
@@ -0,0 +1,103 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.fsverity;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.platform.test.annotations.RequiresFlagsEnabled;
+import android.platform.test.annotations.RootPermissionTest;
+import android.platform.test.flag.junit.CheckFlagsRule;
+import android.platform.test.flag.junit.host.HostFlagsValueProvider;
+import android.security.Flags;
+
+import com.android.blockdevicewriter.BlockDeviceWriter;
+import com.android.tradefed.device.ITestDevice;
+import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test;
+import com.android.tradefed.testtype.junit4.DeviceTestRunOptions;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+/**
+ * This test verifies fs-verity works end-to-end. There is a corresponding helper app.
+ *
+ * <p>The helper app uses a FileIntegrityManager API to enable fs-verity to a file. The host test
+ * here * tampers with the file's backing storage, then tells the helper app to read and expect
+ * success/failure on read.
+ *
+ * <p>In order to make sure a block of the file is readable only if the underlying block on disk
+ * stay intact, the test needs to bypass the filesystem and tampers with the corresponding physical
+ * address against the block device.
+ */
+@RootPermissionTest
+@RunWith(DeviceJUnit4ClassRunner.class)
+@RequiresFlagsEnabled(Flags.FLAG_FSVERITY_API)
+public class FsVerityHostTest extends BaseHostJUnit4Test {
+ private static final String TARGET_PACKAGE = "com.android.fsverity";
+
+ private static final String BASENAME = "test.file";
+ private static final String TARGET_PATH = "/data/data/" + TARGET_PACKAGE + "/files/" + BASENAME;
+
+ @Rule
+ public final CheckFlagsRule mCheckFlagsRule =
+ HostFlagsValueProvider.createCheckFlagsRule(this::getDevice);
+
+ @Test
+ public void testFsVeritySmallFile() throws Exception {
+ prepareTest(10000);
+
+ ITestDevice device = getDevice();
+ BlockDeviceWriter.damageFileAgainstBlockDevice(device, TARGET_PATH, 0);
+ BlockDeviceWriter.damageFileAgainstBlockDevice(device, TARGET_PATH, 8192);
+ BlockDeviceWriter.dropCaches(device);
+
+ verifyRead(TARGET_PATH, "0,2");
+ }
+
+ @Test
+ public void testFsVerityLargerFileWithOneMoreMerkleTreeLevel() throws Exception {
+ prepareTest(128 * 4096 + 1);
+
+ ITestDevice device = getDevice();
+ BlockDeviceWriter.damageFileAgainstBlockDevice(device, TARGET_PATH, 4096);
+ BlockDeviceWriter.damageFileAgainstBlockDevice(device, TARGET_PATH, 100 * 4096);
+ BlockDeviceWriter.damageFileAgainstBlockDevice(device, TARGET_PATH, 128 * 4096 + 1);
+ BlockDeviceWriter.dropCaches(device);
+
+ verifyRead(TARGET_PATH, "1,100,128");
+ }
+
+ private void prepareTest(int fileSize) throws Exception {
+ DeviceTestRunOptions options = new DeviceTestRunOptions(TARGET_PACKAGE);
+ options.setTestClassName(TARGET_PACKAGE + ".Helper");
+ options.setTestMethodName("prepareTest");
+ options.addInstrumentationArg("basename", BASENAME);
+ options.addInstrumentationArg("fileSize", String.valueOf(fileSize));
+ assertThat(runDeviceTests(options)).isTrue();
+ }
+
+ private void verifyRead(String path, String indicesCsv) throws Exception {
+ DeviceTestRunOptions options = new DeviceTestRunOptions(TARGET_PACKAGE);
+ options.setTestClassName(TARGET_PACKAGE + ".Helper");
+ options.setTestMethodName("verifyFileRead");
+ options.addInstrumentationArg("brokenBlockIndicesCsv", indicesCsv);
+ options.addInstrumentationArg("filePath", TARGET_PATH);
+ assertThat(runDeviceTests(options)).isTrue();
+ }
+}
diff --git a/tests/ApkVerityTest/testdata/Android.bp b/tests/FsVerityTest/testdata/Android.bp
index ccfc4c99a347..2d578d36423d 100644
--- a/tests/ApkVerityTest/testdata/Android.bp
+++ b/tests/FsVerityTest/testdata/Android.bp
@@ -37,51 +37,3 @@ filegroup {
name: "ApkVerityTestCertDer",
srcs: ["ApkVerityTestCert.der"],
}
-
-filegroup {
- name: "ApkVerityTestAppDm",
- srcs: ["ApkVerityTestApp.dm"],
-}
-
-filegroup {
- name: "ApkVerityTestAppSplitDm",
- srcs: ["ApkVerityTestAppSplit.dm"],
-}
-
-genrule_defaults {
- name: "apk_verity_sig_gen_default",
- tools: ["fsverity"],
- tool_files: [":ApkVerityTestKeyPem", ":ApkVerityTestCertPem"],
- cmd: "$(location fsverity) sign $(in) $(out) " +
- "--key=$(location :ApkVerityTestKeyPem) " +
- "--cert=$(location :ApkVerityTestCertPem) " +
- "> /dev/null",
-}
-
-genrule {
- name: "ApkVerityTestAppFsvSig",
- defaults: ["apk_verity_sig_gen_default"],
- srcs: [":ApkVerityTestApp"],
- out: ["ApkVerityTestApp.apk.fsv_sig"],
-}
-
-genrule {
- name: "ApkVerityTestAppDmFsvSig",
- defaults: ["apk_verity_sig_gen_default"],
- srcs: [":ApkVerityTestAppDm"],
- out: ["ApkVerityTestApp.dm.fsv_sig"],
-}
-
-genrule {
- name: "ApkVerityTestAppSplitFsvSig",
- defaults: ["apk_verity_sig_gen_default"],
- srcs: [":ApkVerityTestAppSplit"],
- out: ["ApkVerityTestAppSplit.apk.fsv_sig"],
-}
-
-genrule {
- name: "ApkVerityTestAppSplitDmFsvSig",
- defaults: ["apk_verity_sig_gen_default"],
- srcs: [":ApkVerityTestAppSplitDm"],
- out: ["ApkVerityTestAppSplit.dm.fsv_sig"],
-}
diff --git a/tests/ApkVerityTest/testdata/ApkVerityTestCert.der b/tests/FsVerityTest/testdata/ApkVerityTestCert.der
index fe9029b53aa1..fe9029b53aa1 100644
--- a/tests/ApkVerityTest/testdata/ApkVerityTestCert.der
+++ b/tests/FsVerityTest/testdata/ApkVerityTestCert.der
Binary files differ
diff --git a/tests/ApkVerityTest/testdata/ApkVerityTestCert.pem b/tests/FsVerityTest/testdata/ApkVerityTestCert.pem
index 6c0b7b1f635a..6c0b7b1f635a 100644
--- a/tests/ApkVerityTest/testdata/ApkVerityTestCert.pem
+++ b/tests/FsVerityTest/testdata/ApkVerityTestCert.pem
diff --git a/tests/ApkVerityTest/testdata/ApkVerityTestKey.pem b/tests/FsVerityTest/testdata/ApkVerityTestKey.pem
index f0746c162421..f0746c162421 100644
--- a/tests/ApkVerityTest/testdata/ApkVerityTestKey.pem
+++ b/tests/FsVerityTest/testdata/ApkVerityTestKey.pem
diff --git a/tests/SurfaceViewBufferTests/Android.bp b/tests/SurfaceViewBufferTests/Android.bp
index dc75f00e7cdc..38313f85c31d 100644
--- a/tests/SurfaceViewBufferTests/Android.bp
+++ b/tests/SurfaceViewBufferTests/Android.bp
@@ -23,7 +23,10 @@ package {
android_test {
name: "SurfaceViewBufferTests",
- srcs: ["**/*.java","**/*.kt"],
+ srcs: [
+ "**/*.java",
+ "**/*.kt",
+ ],
manifest: "AndroidManifest.xml",
test_config: "AndroidTest.xml",
platform_apis: true,
@@ -41,6 +44,7 @@ android_test {
"kotlin-stdlib",
"kotlinx-coroutines-android",
"flickerlib",
+ "flickerlib-trace_processor_shell",
"truth-prebuilt",
"cts-wm-util",
"CtsSurfaceValidatorLib",
@@ -60,7 +64,7 @@ cc_library_shared {
"libandroid",
],
include_dirs: [
- "system/core/include"
+ "system/core/include",
],
stl: "libc++_static",
cflags: [
diff --git a/tests/SurfaceViewBufferTests/AndroidManifest.xml b/tests/SurfaceViewBufferTests/AndroidManifest.xml
index 78415e8641eb..798c67a320ce 100644
--- a/tests/SurfaceViewBufferTests/AndroidManifest.xml
+++ b/tests/SurfaceViewBufferTests/AndroidManifest.xml
@@ -29,9 +29,12 @@
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
<!-- Save failed test bitmap images !-->
<uses-permission android:name="android.Manifest.permission.WRITE_EXTERNAL_STORAGE"/>
+ <!-- Allow the test to connect to perfetto trace processor -->
+ <uses-permission android:name="android.permission.INTERNET"/>
<application android:allowBackup="false"
- android:supportsRtl="true">
+ android:supportsRtl="true"
+ android:networkSecurityConfig="@xml/network_security_config">
<activity android:name=".MainActivity"
android:taskAffinity="com.android.test.MainActivity"
android:theme="@style/AppTheme"
diff --git a/tests/SurfaceViewBufferTests/res/xml/network_security_config.xml b/tests/SurfaceViewBufferTests/res/xml/network_security_config.xml
new file mode 100644
index 000000000000..4bd9ca049f55
--- /dev/null
+++ b/tests/SurfaceViewBufferTests/res/xml/network_security_config.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2023 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<network-security-config>
+ <domain-config cleartextTrafficPermitted="true">
+ <domain includeSubdomains="true">localhost</domain>
+ </domain-config>
+</network-security-config>
diff --git a/tests/SurfaceViewBufferTests/src/com/android/test/SurfaceTracingTestBase.kt b/tests/SurfaceViewBufferTests/src/com/android/test/SurfaceTracingTestBase.kt
index a38019d67376..b03b7335b08b 100644
--- a/tests/SurfaceViewBufferTests/src/com/android/test/SurfaceTracingTestBase.kt
+++ b/tests/SurfaceViewBufferTests/src/com/android/test/SurfaceTracingTestBase.kt
@@ -21,11 +21,9 @@ import android.graphics.Color
import android.graphics.Rect
import android.util.Log
import androidx.test.ext.junit.rules.ActivityScenarioRule
-import android.tools.common.flicker.subject.layers.LayerSubject
import android.tools.common.traces.surfaceflinger.LayersTrace
-import android.tools.device.traces.io.ResultWriter
-import android.tools.device.traces.monitors.surfaceflinger.LayersTraceMonitor
import android.tools.device.traces.monitors.withSFTracing
+import android.tools.device.traces.monitors.PerfettoTraceMonitor
import junit.framework.Assert
import org.junit.After
import org.junit.Before
@@ -33,6 +31,7 @@ import org.junit.Rule
import java.io.FileOutputStream
import java.io.IOException
import java.util.concurrent.CountDownLatch
+import perfetto.protos.PerfettoConfig.SurfaceFlingerLayersConfig
open class SurfaceTracingTestBase(useBlastAdapter: Boolean) :
SurfaceViewBufferTestBase(useBlastAdapter) {
@@ -43,7 +42,7 @@ open class SurfaceTracingTestBase(useBlastAdapter: Boolean) :
@Before
override fun setup() {
super.setup()
- stopLayerTrace()
+ PerfettoTraceMonitor.stopAllSessions()
addSurfaceView()
}
@@ -83,10 +82,6 @@ open class SurfaceTracingTestBase(useBlastAdapter: Boolean) :
instrumentation.waitForIdleSync()
}
- private fun stopLayerTrace() {
- LayersTraceMonitor().stop(ResultWriter())
- }
-
fun checkPixels(bounds: Rect, @ColorInt color: Int) {
val screenshot = instrumentation.getUiAutomation().takeScreenshot()
val pixels = IntArray(screenshot.width * screenshot.height)
@@ -106,14 +101,19 @@ open class SurfaceTracingTestBase(useBlastAdapter: Boolean) :
Log.e("SurfaceViewBufferTests", "Error writing bitmap to file", e)
}
}
- Assert.assertEquals("Checking $bounds found mismatch $i,$j",
- Color.valueOf(color), Color.valueOf(actualColor))
+ 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
+ private val TRACE_FLAGS = listOf(
+ SurfaceFlingerLayersConfig.TraceFlag.TRACE_FLAG_BUFFERS,
+ SurfaceFlingerLayersConfig.TraceFlag.TRACE_FLAG_VIRTUAL_DISPLAYS,
+ )
}
} \ No newline at end of file
diff --git a/tests/TaskOrganizerTest/Android.bp b/tests/TaskOrganizerTest/Android.bp
index 9b72d359aae6..bf12f423f145 100644
--- a/tests/TaskOrganizerTest/Android.bp
+++ b/tests/TaskOrganizerTest/Android.bp
@@ -25,7 +25,10 @@ package {
android_test {
name: "TaskOrganizerTest",
- srcs: ["**/*.java","**/*.kt"],
+ srcs: [
+ "**/*.java",
+ "**/*.kt",
+ ],
manifest: "AndroidManifest.xml",
test_config: "AndroidTest.xml",
platform_apis: true,
@@ -39,6 +42,7 @@ android_test {
"kotlin-stdlib",
"kotlinx-coroutines-android",
"flickerlib",
+ "flickerlib-trace_processor_shell",
"truth-prebuilt",
],
-} \ No newline at end of file
+}
diff --git a/tests/TaskOrganizerTest/AndroidManifest.xml b/tests/TaskOrganizerTest/AndroidManifest.xml
index 1f1bd3ef7d81..cbeb246eb86c 100644
--- a/tests/TaskOrganizerTest/AndroidManifest.xml
+++ b/tests/TaskOrganizerTest/AndroidManifest.xml
@@ -16,9 +16,11 @@
<uses-permission android:name="android.permission.CHANGE_CONFIGURATION"/>
<uses-permission android:name="android.permission.MANAGE_ACTIVITY_TASKS"/>
<uses-permission android:name="android.permission.INTERACT_ACROSS_USERS_FULL"/>
+ <!-- Allow the test to connect to perfetto trace processor -->
+ <uses-permission android:name="android.permission.INTERNET"/>
<!-- Enable / Disable tracing !-->
<uses-permission android:name="android.permission.DUMP" />
- <application>
+ <application android:networkSecurityConfig="@xml/network_security_config">
<activity android:name="TaskOrganizerMultiWindowTest"
android:label="TaskOrganizer MW Test"
android:exported="true"
diff --git a/tests/TaskOrganizerTest/res/xml/network_security_config.xml b/tests/TaskOrganizerTest/res/xml/network_security_config.xml
new file mode 100644
index 000000000000..e450a993da28
--- /dev/null
+++ b/tests/TaskOrganizerTest/res/xml/network_security_config.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+~ Copyright (C) 2023 The Android Open Source Project
+~
+~ Licensed under the Apache License, Version 2.0 (the "License");
+~ you may not use this file except in compliance with the License.
+~ You may obtain a copy of the License at
+~
+~ http://www.apache.org/licenses/LICENSE-2.0
+~
+~ Unless required by applicable law or agreed to in writing, software
+~ distributed under the License is distributed on an "AS IS" BASIS,
+~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+~ See the License for the specific language governing permissions and
+~ limitations under the License.
+-->
+<network-security-config>
+ <domain-config cleartextTrafficPermitted="true">
+ <domain includeSubdomains="true">localhost</domain>
+ </domain-config>
+</network-security-config> \ 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 6f4f7b13af66..2c7905d552f1 100644
--- a/tests/TaskOrganizerTest/src/com/android/test/taskembed/ResizeTasksSyncTest.kt
+++ b/tests/TaskOrganizerTest/src/com/android/test/taskembed/ResizeTasksSyncTest.kt
@@ -22,8 +22,6 @@ import androidx.test.platform.app.InstrumentationRegistry
import androidx.test.runner.AndroidJUnit4
import android.tools.common.datatypes.Size
import android.tools.common.flicker.subject.layers.LayersTraceSubject
-import android.tools.device.traces.io.ResultWriter
-import android.tools.device.traces.monitors.surfaceflinger.LayersTraceMonitor
import android.tools.device.traces.monitors.withSFTracing
import org.junit.After
import org.junit.Before
@@ -41,16 +39,13 @@ class ResizeTasksSyncTest {
@get:Rule
var scenarioRule: ActivityScenarioRule<TaskOrganizerMultiWindowTest> =
ActivityScenarioRule<TaskOrganizerMultiWindowTest>(
- TaskOrganizerMultiWindowTest::class.java)
+ TaskOrganizerMultiWindowTest::class.java
+ )
protected val instrumentation: Instrumentation = InstrumentationRegistry.getInstrumentation()
@Before
fun setup() {
- val monitor = LayersTraceMonitor()
- if (monitor.isEnabled) {
- monitor.stop(ResultWriter())
- }
val firstTaskBounds = Rect(0, 0, 1080, 1000)
val secondTaskBounds = Rect(0, 1000, 1080, 2000)
@@ -71,7 +66,7 @@ class ResizeTasksSyncTest {
val firstBounds = Rect(0, 0, 1080, 800)
val secondBounds = Rect(0, 1000, 1080, 1800)
- val trace = withSFTracing(TRACE_FLAGS) {
+ val trace = withSFTracing() {
lateinit var resizeReadyLatch: CountDownLatch
scenarioRule.getScenario().onActivity {
resizeReadyLatch = it.resizeTaskView(firstBounds, secondBounds)
@@ -106,7 +101,6 @@ class ResizeTasksSyncTest {
}
companion object {
- private const val TRACE_FLAGS = 0x1 // TRACE_CRITICAL
private const val FIRST_ACTIVITY = "Activity1"
private const val SECOND_ACTIVITY = "Activity2"
}
diff --git a/tools/hoststubgen/.gitignore b/tools/hoststubgen/.gitignore
new file mode 100644
index 000000000000..6453bdef8cee
--- /dev/null
+++ b/tools/hoststubgen/.gitignore
@@ -0,0 +1,3 @@
+out/
+*-out/
+*.log
diff --git a/tools/hoststubgen/OWNERS b/tools/hoststubgen/OWNERS
new file mode 100644
index 000000000000..a8c5321307d1
--- /dev/null
+++ b/tools/hoststubgen/OWNERS
@@ -0,0 +1,3 @@
+omakoto@google.com
+jsharkey@google.com
+jaggies@google.com
diff --git a/tools/hoststubgen/README.md b/tools/hoststubgen/README.md
new file mode 100644
index 000000000000..b0a126292063
--- /dev/null
+++ b/tools/hoststubgen/README.md
@@ -0,0 +1,76 @@
+# HostStubGen
+
+## Overview
+
+This directory contains tools / sample code / investigation for host side test support.
+
+
+## Directories and files
+
+- `hoststubgen/`
+ Contains source code of the "hoststubgen" tool and relevant code
+
+ - `framework-policy-override.txt`
+ This file contains "policy overrides", which allows to control what goes to stub/impl without
+ having to touch the target java files. This allows quicker iteration, because you can skip
+ having to rebuild framework.jar.
+
+ - `src/`
+
+ HostStubGen tool source code.
+
+ - `annotations-src/` See `Android.bp`.
+ - `helper-framework-buildtime-src/` See `Android.bp`.
+ - `helper-framework-runtime-src/` See `Android.bp`.
+ - `helper-runtime-src/` See `Android.bp`.
+
+ - `test-tiny-framework/` See `README.md` in it.
+
+ - `test-framework` See `README.md` in it.
+
+- `scripts`
+ - `run-host-test.sh`
+
+ Run a host side test. Use it instead of `atest` for now. (`atest` works "mostly" but it has
+ problems.)
+
+ - `dump-jar.sh`
+
+ A script to dump the content of `*.class` and `*.jar` files.
+
+ - `run-all-tests.sh`
+
+ Run all tests. Many tests may fail, but at least this should run til the end.
+ (It should print `run-all-tests.sh finished` at the end)
+
+## Build and run
+
+### Building `HostStubGen` binary
+
+```
+m hoststubgen
+```
+
+### Run the tests
+
+- Run all relevant tests and test scripts. Some of thests are still expected to fail,
+ but this should print "finished, with no unexpected failures" at the end.
+
+ However, because some of the script it executes depend on internal file paths to Soong's
+ intermediate directory, some of it might fail when something changes in the build system.
+
+ We need proper build system integration to fix them.
+```
+$ ./scripts/run-all-tests.sh
+```
+
+- See also `README.md` in `test-*` directories.
+
+## TODOs, etc
+
+ - Make sure the parent's visibility is not smaller than the member's.
+
+- @HostSideTestNativeSubstitutionClass should automatically add class-keep to the substitute class.
+ (or at least check it.)
+
+ - The `HostStubGenTest-framework-test-host-test-lib` jar somehow contain all ASM classes? Figure out where the dependency is coming from.
diff --git a/tools/hoststubgen/TEST_MAPPING b/tools/hoststubgen/TEST_MAPPING
new file mode 100644
index 000000000000..970362611f53
--- /dev/null
+++ b/tools/hoststubgen/TEST_MAPPING
@@ -0,0 +1,6 @@
+{
+ // TODO: Change to presubmit.
+ "postsubmit": [
+ { "name": "tiny-framework-dump-test" }
+ ]
+}
diff --git a/tools/hoststubgen/common.sh b/tools/hoststubgen/common.sh
new file mode 100644
index 000000000000..b49ee39a3142
--- /dev/null
+++ b/tools/hoststubgen/common.sh
@@ -0,0 +1,116 @@
+# Copyright (C) 2023 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+set -e # Exit at failure
+shopt -s globstar # Enable double-star wildcards (**)
+
+cd "${0%/*}" # Move to the script dir
+
+fail() {
+ echo "Error: $*" 1>&2
+ exit 1
+}
+
+# Print the arguments and then execute.
+run() {
+ echo "Running: $*" 1>&2
+ "$@"
+}
+
+# Concatenate the second and subsequent args with the first arg as a separator.
+# e.g. `join : a b c` -> prints `a:b:c`
+join() {
+ local IFS="$1"
+ shift
+ echo "$*"
+}
+
+abspath() {
+ for name in "${@}"; do
+ readlink -f $name
+ done
+}
+
+m() {
+ if (( $SKIP_BUILD )) ; then
+ echo "Skipping build: $*" 1>&2
+ return 0
+ fi
+ run ${ANDROID_BUILD_TOP}/build/soong/soong_ui.bash --make-mode "$@"
+}
+
+# Extract given jar files
+extract() {
+ for f in "${@}"; do
+ local out=$f.ext
+ run rm -fr $out
+ run mkdir -p $out
+
+ # It's too noisy, so only show the first few lines.
+ {
+ # Hmm unzipping kotlin jar files may produce a warning? Let's just add `|| true`...
+ run unzip $f -d $out || true
+ } |& sed -e '5,$d'
+ echo ' (omitting remaining output)'
+
+ done
+}
+
+# Find all *.java files in $1, and print them as Java class names.
+# For example, if there's a file `src/com/android/test/Test.java`, and you run
+# `list_all_classes_under_dir src`, then it'll print `com.android.test.Test`.
+list_all_classes_under_dir() {
+ local dir="$1"
+ ( # Use a subshell, so we won't change the current directory on the caller side.
+ cd "$dir"
+
+ # List the java files, but replace the slashes with dots, and remove the `.java` suffix.
+ ls **/*.java | sed -e 's!/!.!g' -e 's!.java$!!'
+ )
+}
+
+checkenv() {
+ # Make sure $ANDROID_BUILD_TOP is set.
+ : ${ANDROID_BUILD_TOP:?}
+
+ # Make sure ANDROID_BUILD_TOP doesn't contain whitespace.
+ set ${ANDROID_BUILD_TOP}
+ if [[ $# != 1 ]] ; then
+ fail "\$ANDROID_BUILD_TOP cannot contain whitespace."
+ fi
+}
+
+checkenv
+
+JAVAC=${JAVAC:-javac}
+JAVA=${JAVA:-java}
+JAR=${JAR:-jar}
+
+JAVAC_OPTS=${JAVAC_OPTS:--Xmaxerrs 99999 -Xlint:none}
+
+SOONG_INT=$ANDROID_BUILD_TOP/out/soong/.intermediates
+
+JUNIT_TEST_MAIN_CLASS=com.android.hoststubgen.hosthelper.HostTestSuite
+
+run_junit_test_jar() {
+ local jar="$1"
+ echo "Starting test: $jar ..."
+ run cd "${jar%/*}"
+
+ run $JAVA $JAVA_OPTS \
+ -cp $jar \
+ org.junit.runner.JUnitCore \
+ $main_class || return 1
+ return 0
+}
diff --git a/tools/hoststubgen/hoststubgen/.gitignore b/tools/hoststubgen/hoststubgen/.gitignore
new file mode 100644
index 000000000000..0f384074ed7f
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/.gitignore
@@ -0,0 +1 @@
+framework-all-stub-out \ No newline at end of file
diff --git a/tools/hoststubgen/hoststubgen/Android.bp b/tools/hoststubgen/hoststubgen/Android.bp
new file mode 100644
index 000000000000..a617876a6da0
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/Android.bp
@@ -0,0 +1,303 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_base_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_base_license"],
+}
+
+// This library contains the standard hoststubgen annotations.
+java_library {
+ name: "hoststubgen-annotations",
+ srcs: [
+ "annotations-src/**/*.java",
+ ],
+ host_supported: true,
+
+ // Seems like we need it to avoid circular deps.
+ // Copied it from "app-compat-annotations".
+ sdk_version: "core_current",
+ visibility: ["//visibility:public"],
+}
+
+// This library contains helper classes used in the host side test environment at runtime.
+// This library is _not_ specific to Android APIs.
+java_library_host {
+ name: "hoststubgen-helper-runtime",
+ srcs: [
+ "helper-runtime-src/**/*.java",
+ ],
+ libs: [
+ "junit",
+ "ow2-asm",
+ "ow2-asm-analysis",
+ "ow2-asm-commons",
+ "ow2-asm-tree",
+ "ow2-asm-util",
+ ],
+ static_libs: [
+ "guava",
+ ],
+ jarjar_rules: "jarjar-rules.txt",
+ visibility: ["//visibility:public"],
+}
+
+// Host-side stub generator tool.
+java_binary_host {
+ name: "hoststubgen",
+ main_class: "com.android.hoststubgen.Main",
+ srcs: ["src/**/*.kt"],
+ static_libs: [
+ "hoststubgen-helper-runtime",
+ "ow2-asm",
+ "ow2-asm-analysis",
+ "ow2-asm-commons",
+ "ow2-asm-tree",
+ "ow2-asm-util",
+ ],
+ visibility: ["//visibility:public"],
+}
+
+// File that contains the standard command line argumetns to hoststubgen.
+filegroup {
+ name: "hoststubgen-standard-options",
+ srcs: [
+ "hoststubgen-standard-options.txt",
+ ],
+ visibility: ["//visibility:public"],
+}
+
+hoststubgen_common_options = "$(location hoststubgen) " +
+ // "--in-jar $(location :framework-all) " +
+ // "--policy-override-file $(location framework-policy-override.txt) " +
+ "@$(location :hoststubgen-standard-options) " +
+
+ "--out-stub-jar $(location host_stub.jar) " +
+ "--out-impl-jar $(location host_impl.jar) " +
+
+ // "--keep-all-classes " + // Used it for an experiment. See KeepAllClassesFilter.
+ "--gen-keep-all-file $(location hoststubgen_keep_all.txt) " +
+ "--gen-input-dump-file $(location hoststubgen_dump.txt) " +
+ ""
+
+// Common defaults for stub generation.
+// This one is not specific to Android APIs.
+genrule_defaults {
+ name: "hoststubgen-command-defaults",
+ tools: ["hoststubgen"],
+ srcs: [
+ ":hoststubgen-standard-options",
+ ],
+ // Create two jar files.
+ out: [
+ "host_stub.jar",
+ "host_impl.jar",
+
+ // Following files are created just as FYI.
+ "hoststubgen_keep_all.txt",
+ "hoststubgen_dump.txt",
+ ],
+ // visibility: ["//visibility:public"],
+}
+
+// Generate the stub/impl from framework-all, with hidden APIs.
+java_genrule_host {
+ name: "framework-all-hidden-api-host",
+ defaults: ["hoststubgen-command-defaults"],
+ cmd: hoststubgen_common_options +
+ "--in-jar $(location :framework-all) " +
+ "--policy-override-file $(location framework-policy-override.txt) ",
+ srcs: [
+ ":framework-all",
+ "framework-policy-override.txt",
+ ],
+ visibility: ["//visibility:private"],
+}
+
+// Extract the stub jar from "framework-all-host" for subsequent build rules.
+java_genrule_host {
+ name: "framework-all-hidden-api-host-stub",
+ cmd: "cp $(in) $(out)",
+ srcs: [
+ ":framework-all-hidden-api-host{host_stub.jar}",
+ ],
+ out: [
+ "host_stub.jar",
+ ],
+ visibility: ["//visibility:public"],
+}
+
+// Extract the impl jar from "framework-all-host" for subsequent build rules.
+java_genrule_host {
+ name: "framework-all-hidden-api-host-impl",
+ cmd: "cp $(in) $(out)",
+ srcs: [
+ ":framework-all-hidden-api-host{host_impl.jar}",
+ ],
+ out: [
+ "host_impl.jar",
+ ],
+ visibility: ["//visibility:public"],
+}
+
+// Generate the stub/impl from framework-all, with only public/system/test APIs, without
+// hidden APIs.
+java_genrule_host {
+ name: "framework-all-test-api-host",
+ defaults: ["hoststubgen-command-defaults"],
+ cmd: hoststubgen_common_options +
+ "--intersect-stub-jar $(location :android_test_stubs_current{.jar}) " +
+ "--in-jar $(location :framework-all) " +
+ "--policy-override-file $(location framework-policy-override.txt) ",
+ srcs: [
+ ":framework-all",
+ ":android_test_stubs_current{.jar}",
+ "framework-policy-override.txt",
+ ],
+ visibility: ["//visibility:private"],
+}
+
+// Extract the stub jar from "framework-all-test-api-host" for subsequent build rules.
+java_genrule_host {
+ name: "framework-all-test-api-host-stub",
+ cmd: "cp $(in) $(out)",
+ srcs: [
+ ":framework-all-test-api-host{host_stub.jar}",
+ ],
+ out: [
+ "host_stub.jar",
+ ],
+ visibility: ["//visibility:public"],
+}
+
+// Extract the impl jar from "framework-all-test-api-host" for subsequent build rules.
+java_genrule_host {
+ name: "framework-all-test-api-host-impl",
+ cmd: "cp $(in) $(out)",
+ srcs: [
+ ":framework-all-test-api-host{host_impl.jar}",
+ ],
+ out: [
+ "host_impl.jar",
+ ],
+ visibility: ["//visibility:public"],
+}
+
+// This library contains helper classes to build hostside tests/targets.
+// This essentially contains dependencies from tests that we can't actually use the real ones.
+// For example, the actual AndroidTestCase and AndroidJUnit4 don't run on the host side (yet),
+// so we pup "fake" implementations here.
+// Ideally this library should be empty.
+java_library_host {
+ name: "hoststubgen-helper-framework-buildtime",
+ srcs: [
+ "helper-framework-buildtime-src/**/*.java",
+ ],
+ libs: [
+ // We need it to pull in some of the framework classes used in this library,
+ // such as Context.java.
+ "framework-all-hidden-api-host-impl",
+ "junit",
+ ],
+ visibility: ["//visibility:public"],
+}
+
+// This module contains "fake" libcore/dalvik classes, framework native substitution, etc,
+// that are needed at runtime.
+java_library_host {
+ name: "hoststubgen-helper-framework-runtime",
+ srcs: [
+ "helper-framework-runtime-src/**/*.java",
+ ],
+ libs: [
+ "hoststubgen-helper-runtime",
+ "framework-all-hidden-api-host-impl",
+ ],
+ visibility: ["//visibility:public"],
+}
+
+// Defaults for host side test modules.
+// We need two rules for each test.
+// 1. A "-test-lib" jar, which compiles the test against the stub jar.
+// This one is only used by the second rule, so it should be "private.
+// 2. A "-test" jar, which includes 1 + the runtime (impl) jars.
+
+// This and next ones are for tests using framework-app, with hidden APIs.
+java_defaults {
+ name: "hosttest-with-framework-all-hidden-api-test-lib-defaults",
+ installable: false,
+ libs: [
+ "framework-all-hidden-api-host-stub",
+ ],
+ static_libs: [
+ "hoststubgen-helper-framework-buildtime",
+ "framework-annotations-lib",
+ ],
+ visibility: ["//visibility:private"],
+}
+
+// Default rules to include `libandroid_runtime`. For now, it's empty, but we'll use it
+// once we start using JNI.
+java_defaults {
+ name: "hosttest-with-libandroid_runtime",
+ jni_libs: [
+ // "libandroid_runtime",
+
+ // TODO: Figure out how to build them automatically.
+ // Following ones are depended by libandroid_runtime.
+ // Without listing them here, not only we won't get them under
+ // $ANDROID_HOST_OUT/testcases/*/lib64, but also not under
+ // $ANDROID_HOST_OUT/lib64, so we'd fail to load them at runtime.
+ // ($ANDROID_HOST_OUT/lib/ gets all of them though.)
+ // "libcutils",
+ // "libharfbuzz_ng",
+ // "libminikin",
+ // "libz",
+ // "libbinder",
+ // "libhidlbase",
+ // "libvintf",
+ // "libicu",
+ // "libutils",
+ // "libtinyxml2",
+ ],
+}
+
+java_defaults {
+ name: "hosttest-with-framework-all-hidden-api-test-defaults",
+ defaults: ["hosttest-with-libandroid_runtime"],
+ installable: false,
+ test_config: "AndroidTest-host.xml",
+ static_libs: [
+ "hoststubgen-helper-runtime",
+ "hoststubgen-helper-framework-runtime",
+ "framework-all-hidden-api-host-impl",
+ ],
+}
+
+// This and next ones are for tests using framework-app, with public/system/test APIs,
+// without hidden APIs.
+java_defaults {
+ name: "hosttest-with-framework-all-test-api-test-lib-defaults",
+ installable: false,
+ libs: [
+ "framework-all-test-api-host-stub",
+ ],
+ static_libs: [
+ "hoststubgen-helper-framework-buildtime",
+ "framework-annotations-lib",
+ ],
+ visibility: ["//visibility:private"],
+}
+
+java_defaults {
+ name: "hosttest-with-framework-all-test-api-test-defaults",
+ defaults: ["hosttest-with-libandroid_runtime"],
+ installable: false,
+ test_config: "AndroidTest-host.xml",
+ static_libs: [
+ "hoststubgen-helper-runtime",
+ "hoststubgen-helper-framework-runtime",
+ "framework-all-test-api-host-impl",
+ ],
+}
diff --git a/tools/hoststubgen/hoststubgen/annotations-src/android/hosttest/annotation/HostSideTestClassLoadHook.java b/tools/hoststubgen/hoststubgen/annotations-src/android/hosttest/annotation/HostSideTestClassLoadHook.java
new file mode 100644
index 000000000000..a774336a897c
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/annotations-src/android/hosttest/annotation/HostSideTestClassLoadHook.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.hosttest.annotation;
+
+import static java.lang.annotation.ElementType.TYPE;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * THIS ANNOTATION IS EXPERIMENTAL. REACH OUT TO g/ravenwood BEFORE USING IT, OR YOU HAVE ANY
+ * QUESTIONS ABOUT IT.
+ *
+ * Add this with a fully-specified method name (e.g. {@code "com.package.Class.methodName"})
+ * of a callback to get a callback at the class load time.
+ *
+ * The method must be {@code public static} with a single argument that takes
+ * {@link java.lang.Class}.
+ */
+@Target({TYPE})
+@Retention(RetentionPolicy.CLASS)
+public @interface HostSideTestClassLoadHook {
+ String value();
+}
diff --git a/tools/hoststubgen/hoststubgen/annotations-src/android/hosttest/annotation/HostSideTestKeep.java b/tools/hoststubgen/hoststubgen/annotations-src/android/hosttest/annotation/HostSideTestKeep.java
new file mode 100644
index 000000000000..06ad1c266a14
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/annotations-src/android/hosttest/annotation/HostSideTestKeep.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.hosttest.annotation;
+
+import static java.lang.annotation.ElementType.CONSTRUCTOR;
+import static java.lang.annotation.ElementType.FIELD;
+import static java.lang.annotation.ElementType.METHOD;
+import static java.lang.annotation.ElementType.TYPE;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * THIS ANNOTATION IS EXPERIMENTAL. REACH OUT TO g/ravenwood BEFORE USING IT, OR YOU HAVE ANY
+ * QUESTIONS ABOUT IT.
+ *
+ * Mark a class, field or a method as "Stub", meaning tests can _not_ see the APIs, but they
+ * can indirectly be used on the host side.
+ * When applied to a class, it will _not_ affect the visibility of its members. They need to be
+ * individually marked.
+ *
+ * <p>In order to expose a class and all its members, use {@link HostSideTestWholeClassStub}
+ * instead.
+ * @hide
+ */
+@Target({TYPE, FIELD, METHOD, CONSTRUCTOR})
+@Retention(RetentionPolicy.CLASS)
+public @interface HostSideTestKeep {
+}
diff --git a/tools/hoststubgen/hoststubgen/annotations-src/android/hosttest/annotation/HostSideTestNativeSubstitutionClass.java b/tools/hoststubgen/hoststubgen/annotations-src/android/hosttest/annotation/HostSideTestNativeSubstitutionClass.java
new file mode 100644
index 000000000000..9c8138351eb5
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/annotations-src/android/hosttest/annotation/HostSideTestNativeSubstitutionClass.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.hosttest.annotation;
+
+import static java.lang.annotation.ElementType.TYPE;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * THIS ANNOTATION IS EXPERIMENTAL. REACH OUT TO g/ravenwood BEFORE USING IT, OR YOU HAVE ANY
+ * QUESTIONS ABOUT IT.
+ *
+ * If a class has this annotation, all its native methods will be delegated to another class.
+ * (See {@link android.os.Parcel} as an example.)
+ */
+@Target({TYPE})
+@Retention(RetentionPolicy.CLASS)
+public @interface HostSideTestNativeSubstitutionClass {
+ String value();
+}
diff --git a/tools/hoststubgen/hoststubgen/annotations-src/android/hosttest/annotation/HostSideTestRemove.java b/tools/hoststubgen/hoststubgen/annotations-src/android/hosttest/annotation/HostSideTestRemove.java
new file mode 100644
index 000000000000..46e5078fb05d
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/annotations-src/android/hosttest/annotation/HostSideTestRemove.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.hosttest.annotation;
+
+import static java.lang.annotation.ElementType.CONSTRUCTOR;
+import static java.lang.annotation.ElementType.FIELD;
+import static java.lang.annotation.ElementType.METHOD;
+import static java.lang.annotation.ElementType.TYPE;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * THIS ANNOTATION IS EXPERIMENTAL. REACH OUT TO g/ravenwood BEFORE USING IT, OR YOU HAVE ANY
+ * QUESTIONS ABOUT IT.
+ *
+ * Mark an item as "remove", so this cannot be used on the host side even indirectly.
+ * This is the default behavior.
+ *
+ * @hide
+ */
+@Target({TYPE, FIELD, METHOD, CONSTRUCTOR})
+@Retention(RetentionPolicy.CLASS)
+public @interface HostSideTestRemove {
+}
diff --git a/tools/hoststubgen/hoststubgen/annotations-src/android/hosttest/annotation/HostSideTestStub.java b/tools/hoststubgen/hoststubgen/annotations-src/android/hosttest/annotation/HostSideTestStub.java
new file mode 100644
index 000000000000..cabdfe0eeb77
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/annotations-src/android/hosttest/annotation/HostSideTestStub.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.hosttest.annotation;
+
+import static java.lang.annotation.ElementType.CONSTRUCTOR;
+import static java.lang.annotation.ElementType.FIELD;
+import static java.lang.annotation.ElementType.METHOD;
+import static java.lang.annotation.ElementType.TYPE;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * THIS ANNOTATION IS EXPERIMENTAL. REACH OUT TO g/ravenwood BEFORE USING IT, OR YOU HAVE ANY
+ * QUESTIONS ABOUT IT.
+ *
+ * Mark a class, field or a method as "Stub", meaning tests can see the APIs.
+ * When applied to a class, it will _not_ affect the visibility of its members. They need to be
+ * individually marked.
+ *
+ * <p>In order to expose a class and all its members, use {@link HostSideTestWholeClassStub}
+ * instead.
+ *
+ * @hide
+ */
+@Target({TYPE, FIELD, METHOD, CONSTRUCTOR})
+@Retention(RetentionPolicy.CLASS)
+public @interface HostSideTestStub {
+}
diff --git a/tools/hoststubgen/hoststubgen/annotations-src/android/hosttest/annotation/HostSideTestSubstitute.java b/tools/hoststubgen/hoststubgen/annotations-src/android/hosttest/annotation/HostSideTestSubstitute.java
new file mode 100644
index 000000000000..510a67e0aaed
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/annotations-src/android/hosttest/annotation/HostSideTestSubstitute.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.hosttest.annotation;
+
+import static java.lang.annotation.ElementType.METHOD;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * THIS ANNOTATION IS EXPERIMENTAL. REACH OUT TO g/ravenwood BEFORE USING IT, OR YOU HAVE ANY
+ * QUESTIONS ABOUT IT.
+ *
+ * If a method has this annotation, we'll replace it with another method on the host side.
+ *
+ * See {@link android.util.LruCache#getEldest()} and its substitution.
+ *
+ * @hide
+ */
+@Target({METHOD})
+@Retention(RetentionPolicy.CLASS)
+public @interface HostSideTestSubstitute {
+ // TODO We should add "_host" as default. We're not doing it yet, because extractign the default
+ // value with ASM doesn't seem trivial. (? not sure.)
+ String suffix();
+}
diff --git a/tools/hoststubgen/hoststubgen/annotations-src/android/hosttest/annotation/HostSideTestThrow.java b/tools/hoststubgen/hoststubgen/annotations-src/android/hosttest/annotation/HostSideTestThrow.java
new file mode 100644
index 000000000000..cd1bef4be505
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/annotations-src/android/hosttest/annotation/HostSideTestThrow.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.hosttest.annotation;
+
+import static java.lang.annotation.ElementType.CONSTRUCTOR;
+import static java.lang.annotation.ElementType.METHOD;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * THIS ANNOTATION IS EXPERIMENTAL. REACH OUT TO g/ravenwood BEFORE USING IT, OR YOU HAVE ANY
+ * QUESTIONS ABOUT IT.
+ *
+ * If a method has this annotation, it will throw on the host side.
+ *
+ * @hide
+ */
+@Target({METHOD, CONSTRUCTOR})
+@Retention(RetentionPolicy.CLASS)
+public @interface HostSideTestThrow {
+}
diff --git a/tools/hoststubgen/hoststubgen/annotations-src/android/hosttest/annotation/HostSideTestWholeClassKeep.java b/tools/hoststubgen/hoststubgen/annotations-src/android/hosttest/annotation/HostSideTestWholeClassKeep.java
new file mode 100644
index 000000000000..3d1ddea2cbb7
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/annotations-src/android/hosttest/annotation/HostSideTestWholeClassKeep.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.hosttest.annotation;
+
+import static java.lang.annotation.ElementType.TYPE;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * THIS ANNOTATION IS EXPERIMENTAL. REACH OUT TO g/ravenwood BEFORE USING IT, OR YOU HAVE ANY
+ * QUESTIONS ABOUT IT.
+ *
+ * Same as {@link HostSideTestKeep} but it'll change the visibility of all its members too.
+ * @hide
+ */
+@Target({TYPE})
+@Retention(RetentionPolicy.CLASS)
+public @interface HostSideTestWholeClassKeep {
+}
diff --git a/tools/hoststubgen/hoststubgen/annotations-src/android/hosttest/annotation/HostSideTestWholeClassStub.java b/tools/hoststubgen/hoststubgen/annotations-src/android/hosttest/annotation/HostSideTestWholeClassStub.java
new file mode 100644
index 000000000000..1824f6f01516
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/annotations-src/android/hosttest/annotation/HostSideTestWholeClassStub.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.hosttest.annotation;
+
+import static java.lang.annotation.ElementType.TYPE;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * THIS ANNOTATION IS EXPERIMENTAL. REACH OUT TO g/ravenwood BEFORE USING IT, OR YOU HAVE ANY
+ * QUESTIONS ABOUT IT.
+ *
+ * Same as {@link HostSideTestStub} but it'll change the visibility of all its members too.
+ *
+ * @hide
+ */
+@Target({TYPE})
+@Retention(RetentionPolicy.CLASS)
+public @interface HostSideTestWholeClassStub {
+}
diff --git a/tools/hoststubgen/hoststubgen/annotations-src/android/hosttest/annotation/tests/HostSideTestSuppress.java b/tools/hoststubgen/hoststubgen/annotations-src/android/hosttest/annotation/tests/HostSideTestSuppress.java
new file mode 100644
index 000000000000..b10f0ff1a4b1
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/annotations-src/android/hosttest/annotation/tests/HostSideTestSuppress.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.hosttest.annotation.tests;
+
+import static java.lang.annotation.ElementType.FIELD;
+import static java.lang.annotation.ElementType.METHOD;
+import static java.lang.annotation.ElementType.TYPE;
+
+import java.lang.annotation.Target;
+
+/**
+ * Use this annotation to skip certain tests for host side tests.
+ *
+ * TODO: Actually use it in the test runner.
+ */
+@Target({TYPE, FIELD, METHOD})
+public @interface HostSideTestSuppress {
+}
diff --git a/tools/hoststubgen/hoststubgen/framework-policy-override.txt b/tools/hoststubgen/hoststubgen/framework-policy-override.txt
new file mode 100644
index 000000000000..295498da02e4
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/framework-policy-override.txt
@@ -0,0 +1,98 @@
+# --------------------------------------------------------------------------------------------------
+# This file contains rules to process `framework-all.jar` to generate the host side test "stub" and
+# "impl" jars, without using Java annotations.
+#
+# Useful when:
+# - The class is auto-generated and annotations can't be added.
+# (We need to figure out what to do on auto-generated classes.)
+# - Want to quickly change filter rules without having to rebuild framework.jar.
+#
+# Using this file, one can control the visibility of APIs on a per-class, per-field and per-method
+# basis, but in most cases, per-class directives would be sufficient. That is:
+#
+# - To put the entire class, including its members and nested classes, in the "stub" jar,
+# so that the test / target code can use the API, use `stubclass`.
+#
+# class package.class stubclass
+#
+# - To put the entire class, including its members and nested classes, in the "impl" jar,
+# but not in the "stub" jar, use `keepclass`. Use this when you don't want to expose an API to
+# tests/target directly, but it's still needed at runtime, because it's used by other "stub" APIs
+# directly or indirectly.
+#
+# class package.class keepclass
+#
+# All other classes will be removed from both the stub jar and impl jar.
+#
+# --------------------------------------------------------------------------------------------------
+
+# --------------------------------------------------------------------------------------------------
+# Directions on auto-generated classes, where we can't use Java annotations (yet).
+# --------------------------------------------------------------------------------------------------
+class android.Manifest stubclass
+class android.R stubclass
+class android.os.PersistableBundleProto keepclass
+
+# This is in module-utils, where using a HostStubGen annotation would be complicated, so we
+# add a direction here rather than using a java annotation.
+# The build file says it's deprecated, anyway...? Figure out what to do with it.
+class com.android.internal.util.Preconditions keepclass
+
+# --------------------------------------------------------------------------------------------------
+# Actual framework classes
+# --------------------------------------------------------------------------------------------------
+
+# Put basic exception classes in the "impl" jar.
+# We don't put them in stub yet (until something actually needs them).
+class android.os.DeadObjectException keepclass
+class android.os.DeadSystemRuntimeException keepclass
+class android.os.NetworkOnMainThreadException keepclass
+class android.os.RemoteException keepclass
+class android.os.ServiceSpecificException keepclass
+class android.util.AndroidException keepclass
+class android.util.AndroidRuntimeException keepclass
+class android.os.DeadSystemException keepclass
+
+
+# For now, we only want to expose ArrayMap and Log, but they and their tests depend on
+# more classes.
+
+class android.util.ArrayMap stubclass
+
+# Used by ArrayMap. No need to put them in the stub, but we need them in impl.
+class android.util.MapCollections keepclass
+class android.util.ContainerHelpers keepclass
+class com.android.internal.util.XmlUtils keepclass
+class com.android.internal.util.FastMath keepclass
+class android.util.MathUtils keepclass
+
+
+class android.util.Log stubclass
+class android.util.Slog stubclass
+# We don't use Log's native code, yet. Instead, the following line enables the Java substitution.
+# Comment it out to disable Java substitution of Log's native methods.
+class android.util.Log !com.android.hoststubgen.nativesubstitution.Log_host
+
+# Used by log
+class com.android.internal.util.FastPrintWriter keepclass
+class com.android.internal.util.LineBreakBufferedWriter keepclass
+
+
+# Expose Context because it's referred to by AndroidTestCase, but don't need to expose any of
+# its members.
+class android.content.Context keep
+
+# Expose Parcel, Parcel and there relevant classes, which are used by ArrayMapTets.
+class android.os.Parcelable StubClass
+class android.os.Parcel StubClass
+class android.os.Parcel !com.android.hoststubgen.nativesubstitution.Parcel_host
+
+class android.os.IBinder stubClass
+class android.os.IInterface stubclass
+
+class android.os.BadParcelableException stubclass
+class android.os.BadTypeParcelableException stubclass
+
+class android.os.BaseBundle stubclass
+class android.os.Bundle stubclass
+class android.os.PersistableBundle stubclass
diff --git a/tools/hoststubgen/hoststubgen/helper-framework-buildtime-src/android/test/AndroidTestCase.java b/tools/hoststubgen/hoststubgen/helper-framework-buildtime-src/android/test/AndroidTestCase.java
new file mode 100644
index 000000000000..e6d38668335a
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/helper-framework-buildtime-src/android/test/AndroidTestCase.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.test;
+
+import android.content.Context;
+
+import junit.framework.TestCase;
+
+public class AndroidTestCase extends TestCase {
+ protected Context mContext;
+ public Context getContext() {
+ throw new RuntimeException("[ravenwood] Class Context is not supported yet.");
+ }
+}
diff --git a/tools/hoststubgen/hoststubgen/helper-framework-buildtime-src/androidx/annotation/NonNull.java b/tools/hoststubgen/hoststubgen/helper-framework-buildtime-src/androidx/annotation/NonNull.java
new file mode 100644
index 000000000000..51c5d9a05e52
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/helper-framework-buildtime-src/androidx/annotation/NonNull.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 androidx.annotation;
+
+// [ravenwood] TODO: Find the actual androidx jar containing it.s
+
+import static java.lang.annotation.ElementType.FIELD;
+import static java.lang.annotation.ElementType.METHOD;
+import static java.lang.annotation.ElementType.PARAMETER;
+import static java.lang.annotation.RetentionPolicy.SOURCE;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+/**
+ * Denotes that a parameter, field or method return value can never be null.
+ * <p>
+ * This is a marker annotation and it has no specific attributes.
+ *
+ * @paramDoc This value cannot be {@code null}.
+ * @returnDoc This value cannot be {@code null}.
+ * @hide
+ */
+@Retention(SOURCE)
+@Target({METHOD, PARAMETER, FIELD})
+public @interface NonNull {
+}
diff --git a/tools/hoststubgen/hoststubgen/helper-framework-buildtime-src/androidx/annotation/Nullable.java b/tools/hoststubgen/hoststubgen/helper-framework-buildtime-src/androidx/annotation/Nullable.java
new file mode 100644
index 000000000000..f1f0e8b43f16
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/helper-framework-buildtime-src/androidx/annotation/Nullable.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 androidx.annotation;
+
+// [ravenwood] TODO: Find the actual androidx jar containing it.s
+
+import static java.lang.annotation.ElementType.FIELD;
+import static java.lang.annotation.ElementType.METHOD;
+import static java.lang.annotation.ElementType.PARAMETER;
+import static java.lang.annotation.RetentionPolicy.SOURCE;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+/**
+ * Denotes that a parameter, field or method return value can be null.
+ * <p>
+ * When decorating a method call parameter, this denotes that the parameter can
+ * legitimately be null and the method will gracefully deal with it. Typically
+ * used on optional parameters.
+ * <p>
+ * When decorating a method, this denotes the method might legitimately return
+ * null.
+ * <p>
+ * This is a marker annotation and it has no specific attributes.
+ *
+ * @paramDoc This value may be {@code null}.
+ * @returnDoc This value may be {@code null}.
+ * @hide
+ */
+@Retention(SOURCE)
+@Target({METHOD, PARAMETER, FIELD})
+public @interface Nullable {
+}
diff --git a/tools/hoststubgen/hoststubgen/helper-framework-buildtime-src/androidx/test/ext/junit/runners/AndroidJUnit4.java b/tools/hoststubgen/hoststubgen/helper-framework-buildtime-src/androidx/test/ext/junit/runners/AndroidJUnit4.java
new file mode 100644
index 000000000000..0c82e4e268d3
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/helper-framework-buildtime-src/androidx/test/ext/junit/runners/AndroidJUnit4.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.test.ext.junit.runners;
+
+import org.junit.runners.BlockJUnit4ClassRunner;
+import org.junit.runners.model.InitializationError;
+
+// TODO: We need to simulate the androidx test runner.
+// https://source.corp.google.com/piper///depot/google3/third_party/android/androidx_test/ext/junit/java/androidx/test/ext/junit/runners/AndroidJUnit4.java
+// https://source.corp.google.com/piper///depot/google3/third_party/android/androidx_test/runner/android_junit_runner/java/androidx/test/internal/runner/junit4/AndroidJUnit4ClassRunner.java
+
+public class AndroidJUnit4 extends BlockJUnit4ClassRunner {
+ public AndroidJUnit4(Class<?> testClass) throws InitializationError {
+ super(testClass);
+ }
+}
diff --git a/tools/hoststubgen/hoststubgen/helper-framework-buildtime-src/androidx/test/filters/FlakyTest.java b/tools/hoststubgen/hoststubgen/helper-framework-buildtime-src/androidx/test/filters/FlakyTest.java
new file mode 100644
index 000000000000..2470d8390f5d
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/helper-framework-buildtime-src/androidx/test/filters/FlakyTest.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 androidx.test.filters;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Designates a test as being flaky (non-deterministic).
+ *
+ * <p>Can then be used to filter tests on execution using -e annotation or -e notAnnotation as
+ * desired.
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ElementType.METHOD, ElementType.TYPE})
+public @interface FlakyTest {
+ /**
+ * An optional bug number associated with the test. -1 Means that no bug number is associated with
+ * the flaky annotation.
+ *
+ * @return int
+ */
+ int bugId() default -1;
+
+ /**
+ * Details, such as the reason of why the test is flaky.
+ *
+ * @return String
+ */
+ String detail() default "";
+}
diff --git a/tools/hoststubgen/hoststubgen/helper-framework-buildtime-src/androidx/test/filters/LargeTest.java b/tools/hoststubgen/hoststubgen/helper-framework-buildtime-src/androidx/test/filters/LargeTest.java
new file mode 100644
index 000000000000..578d7dc73647
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/helper-framework-buildtime-src/androidx/test/filters/LargeTest.java
@@ -0,0 +1,44 @@
+/*
+ * 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 androidx.test.filters;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Annotation to assign a large test size qualifier to a test. This annotation can be used at a
+ * method or class level.
+ *
+ * <p>Test size qualifiers are a great way to structure test code and are used to assign a test to a
+ * test suite of similar run time.
+ *
+ * <p>Execution time: &gt;1000ms
+ *
+ * <p>Large tests should be focused on testing integration of all application components. These
+ * tests fully participate in the system and may make use of all resources such as databases, file
+ * systems and network. As a rule of thumb most functional UI tests are large tests.
+ *
+ * <p>Note: This class replaces the deprecated Android platform size qualifier <a
+ * href="{@docRoot}reference/android/test/suitebuilder/annotation/LargeTest.html"><code>
+ * android.test.suitebuilder.annotation.LargeTest</code></a> and is the recommended way to annotate
+ * tests written with the AndroidX Test Library.
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ElementType.METHOD, ElementType.TYPE})
+public @interface LargeTest {}
diff --git a/tools/hoststubgen/hoststubgen/helper-framework-buildtime-src/androidx/test/filters/MediumTest.java b/tools/hoststubgen/hoststubgen/helper-framework-buildtime-src/androidx/test/filters/MediumTest.java
new file mode 100644
index 000000000000..dfdaa53ee6ac
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/helper-framework-buildtime-src/androidx/test/filters/MediumTest.java
@@ -0,0 +1,45 @@
+/*
+ * 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 androidx.test.filters;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Annotation to assign a medium test size qualifier to a test. This annotation can be used at a
+ * method or class level.
+ *
+ * <p>Test size qualifiers are a great way to structure test code and are used to assign a test to a
+ * test suite of similar run time.
+ *
+ * <p>Execution time: &lt;1000ms
+ *
+ * <p>Medium tests should be focused on a very limited subset of components or a single component.
+ * Resource access to the file system through well defined interfaces like databases,
+ * ContentProviders, or Context is permitted. Network access should be restricted, (long-running)
+ * blocking operations should be avoided and use mock objects instead.
+ *
+ * <p>Note: This class replaces the deprecated Android platform size qualifier <a
+ * href="{@docRoot}reference/android/test/suitebuilder/annotation/MediumTest.html"><code>
+ * android.test.suitebuilder.annotation.MediumTest</code></a> and is the recommended way to annotate
+ * tests written with the AndroidX Test Library.
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ElementType.METHOD, ElementType.TYPE})
+public @interface MediumTest {}
diff --git a/tools/hoststubgen/hoststubgen/helper-framework-buildtime-src/androidx/test/filters/RequiresDevice.java b/tools/hoststubgen/hoststubgen/helper-framework-buildtime-src/androidx/test/filters/RequiresDevice.java
new file mode 100644
index 000000000000..3d3ee3318bfa
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/helper-framework-buildtime-src/androidx/test/filters/RequiresDevice.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 androidx.test.filters;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Indicates that a specific test should not be run on emulator.
+ *
+ * <p>It will be executed only if the test is running on the physical android device.
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ElementType.TYPE, ElementType.METHOD})
+public @interface RequiresDevice {}
diff --git a/tools/hoststubgen/hoststubgen/helper-framework-buildtime-src/androidx/test/filters/SdkSuppress.java b/tools/hoststubgen/hoststubgen/helper-framework-buildtime-src/androidx/test/filters/SdkSuppress.java
new file mode 100644
index 000000000000..dd65ddb382dc
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/helper-framework-buildtime-src/androidx/test/filters/SdkSuppress.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 androidx.test.filters;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Indicates that a specific test or class requires a minimum or maximum API Level to execute.
+ *
+ * <p>Test(s) will be skipped when executed on android platforms less/more than specified level
+ * (inclusive).
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ElementType.TYPE, ElementType.METHOD})
+public @interface SdkSuppress {
+ /** The minimum API level to execute (inclusive) */
+ int minSdkVersion() default 1;
+ /** The maximum API level to execute (inclusive) */
+ int maxSdkVersion() default Integer.MAX_VALUE;
+ /**
+ * The {@link android.os.Build.VERSION.CODENAME} to execute on. This is intended to be used to run
+ * on a pre-release SDK, where the {@link android.os.Build.VERSION.SDK_INT} has not yet been
+ * finalized. This is treated as an OR operation with respect to the minSdkVersion and
+ * maxSdkVersion attributes.
+ *
+ * <p>For example, to filter a test so it runs on only the prerelease R SDK: <code>
+ * {@literal @}SdkSuppress(minSdkVersion = Build.VERSION_CODES.R, codeName = "R")
+ * </code>
+ */
+ String codeName() default "unset";
+}
diff --git a/tools/hoststubgen/hoststubgen/helper-framework-buildtime-src/androidx/test/filters/SmallTest.java b/tools/hoststubgen/hoststubgen/helper-framework-buildtime-src/androidx/test/filters/SmallTest.java
new file mode 100644
index 000000000000..dd32df44effe
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/helper-framework-buildtime-src/androidx/test/filters/SmallTest.java
@@ -0,0 +1,46 @@
+/*
+ * 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 androidx.test.filters;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Annotation to assign a small test size qualifier to a test. This annotation can be used at a
+ * method or class level.
+ *
+ * <p>Test size qualifiers are a great way to structure test code and are used to assign a test to a
+ * test suite of similar run time.
+ *
+ * <p>Execution time: &lt;200ms
+ *
+ * <p>Small tests should be run very frequently. Focused on units of code to verify specific logical
+ * conditions. These tests should runs in an isolated environment and use mock objects for external
+ * dependencies. Resource access (such as file system, network, or databases) are not permitted.
+ * Tests that interact with hardware, make binder calls, or that facilitate android instrumentation
+ * should not use this annotation.
+ *
+ * <p>Note: This class replaces the deprecated Android platform size qualifier <a
+ * href="http://developer.android.com/reference/android/test/suitebuilder/annotation/SmallTest.html">
+ * android.test.suitebuilder.annotation.SmallTest</a> and is the recommended way to annotate tests
+ * written with the AndroidX Test Library.
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ElementType.METHOD, ElementType.TYPE})
+public @interface SmallTest {}
diff --git a/tools/hoststubgen/hoststubgen/helper-framework-buildtime-src/androidx/test/filters/Suppress.java b/tools/hoststubgen/hoststubgen/helper-framework-buildtime-src/androidx/test/filters/Suppress.java
new file mode 100644
index 000000000000..88e636c2dd77
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/helper-framework-buildtime-src/androidx/test/filters/Suppress.java
@@ -0,0 +1,36 @@
+/*
+ * 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 androidx.test.filters;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Use this annotation on test classes or test methods that should not be included in a test suite.
+ * If the annotation appears on the class then no tests in that class will be included. If the
+ * annotation appears only on a test method then only that method will be excluded.
+ *
+ * <p>Note: This class replaces the deprecated Android platform annotation <a
+ * href="http://developer.android.com/reference/android/test/suitebuilder/annotation/Suppress.html">
+ * android.test.suitebuilder.annotation.Suppress</a> and is the recommended way to suppress tests
+ * written with the AndroidX Test Library.
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ElementType.METHOD, ElementType.TYPE})
+public @interface Suppress {}
diff --git a/tools/hoststubgen/hoststubgen/helper-framework-buildtime-src/androidx/test/runner/AndroidJUnit4.java b/tools/hoststubgen/hoststubgen/helper-framework-buildtime-src/androidx/test/runner/AndroidJUnit4.java
new file mode 100644
index 000000000000..e1379390f98b
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/helper-framework-buildtime-src/androidx/test/runner/AndroidJUnit4.java
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package androidx.test.runner;
+
+import org.junit.runners.model.InitializationError;
+
+public class AndroidJUnit4 extends androidx.test.ext.junit.runners.AndroidJUnit4 {
+ public AndroidJUnit4(Class<?> testClass) throws InitializationError {
+ super(testClass);
+ }
+}
diff --git a/tools/hoststubgen/hoststubgen/helper-framework-runtime-src/framework/com/android/hoststubgen/nativesubstitution/Log_host.java b/tools/hoststubgen/hoststubgen/helper-framework-runtime-src/framework/com/android/hoststubgen/nativesubstitution/Log_host.java
new file mode 100644
index 000000000000..ee55c7ac6ae2
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/helper-framework-runtime-src/framework/com/android/hoststubgen/nativesubstitution/Log_host.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.hoststubgen.nativesubstitution;
+
+import android.util.Log;
+import android.util.Log.Level;
+
+import java.io.PrintStream;
+
+public class Log_host {
+
+ public static boolean isLoggable(String tag, @Level int level) {
+ return true;
+ }
+
+ public static int println_native(int bufID, int priority, String tag, String msg) {
+ final PrintStream out = System.out;
+ final String buffer;
+ switch (bufID) {
+ case Log.LOG_ID_MAIN: buffer = "main"; break;
+ case Log.LOG_ID_RADIO: buffer = "radio"; break;
+ case Log.LOG_ID_EVENTS: buffer = "event"; break;
+ case Log.LOG_ID_SYSTEM: buffer = "system"; break;
+ case Log.LOG_ID_CRASH: buffer = "crash"; break;
+ default: buffer = "buf:" + bufID; break;
+ };
+
+ final String prio;
+ switch (priority) {
+ case Log.VERBOSE: prio = "V"; break;
+ case Log.DEBUG: prio = "D"; break;
+ case Log.INFO: prio = "I"; break;
+ case Log.WARN: prio = "W"; break;
+ case Log.ERROR: prio = "E"; break;
+ case Log.ASSERT: prio = "A"; break;
+ default: prio = "prio:" + priority; break;
+ };
+
+ for (String s : msg.split("\\n")) {
+ out.println(String.format("logd: [%s] %s %s: %s", buffer, prio, tag, s));
+ }
+ return msg.length();
+ }
+
+ public static int logger_entry_max_payload_native() {
+ return 4068; // [ravenwood] This is what people use in various places.
+ }
+}
diff --git a/tools/hoststubgen/hoststubgen/helper-framework-runtime-src/framework/com/android/hoststubgen/nativesubstitution/Parcel_host.java b/tools/hoststubgen/hoststubgen/helper-framework-runtime-src/framework/com/android/hoststubgen/nativesubstitution/Parcel_host.java
new file mode 100644
index 000000000000..d749f076f3b5
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/helper-framework-runtime-src/framework/com/android/hoststubgen/nativesubstitution/Parcel_host.java
@@ -0,0 +1,404 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.hoststubgen.nativesubstitution;
+
+import android.os.IBinder;
+
+import java.io.FileDescriptor;
+import java.nio.ByteBuffer;
+import java.nio.charset.StandardCharsets;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.atomic.AtomicLong;
+
+/**
+ * Tentative, partial implementation of the Parcel native methods, using Java's
+ * {@link ByteBuffer}. It turned out there's enough semantics differences between Parcel
+ * and {@link ByteBuffer}, so it didn't actually work.
+ * (e.g. Parcel seems to allow moving the data position to be beyond its size? Which
+ * {@link ByteBuffer} wouldn't allow...)
+ */
+public class Parcel_host {
+ private Parcel_host() {
+ }
+
+ private static final AtomicLong sNextId = new AtomicLong(0);
+
+ private static final Map<Long, Parcel_host> sInstances = new ConcurrentHashMap<>();
+
+ private boolean mDeleted = false;
+
+ private byte[] mBuffer;
+ private int mSize;
+ private int mPos;
+
+ private boolean mSensitive;
+ private boolean mAllowFds;
+
+ // TODO Use the actual value from Parcel.java.
+ private static final int OK = 0;
+
+ private void validate() {
+ if (mDeleted) {
+ // TODO: Put more info
+ throw new RuntimeException("Parcel already destroyed");
+ }
+ }
+
+ private static Parcel_host getInstance(long id) {
+ Parcel_host p = sInstances.get(id);
+ if (p == null) {
+ // TODO: Put more info
+ throw new RuntimeException("Parcel doesn't exist with id=" + id);
+ }
+ p.validate();
+ return p;
+ }
+
+ public static long nativeCreate() {
+ final long id = sNextId.getAndIncrement();
+ final Parcel_host p = new Parcel_host();
+ sInstances.put(id, p);
+ p.init();
+ return id;
+ }
+
+ private void init() {
+ mBuffer = new byte[0];
+ mSize = 0;
+ mPos = 0;
+ mSensitive = false;
+ mAllowFds = false;
+ }
+
+ private void updateSize() {
+ if (mSize < mPos) {
+ mSize = mPos;
+ }
+ }
+
+ public static void nativeDestroy(long nativePtr) {
+ getInstance(nativePtr).mDeleted = true;
+ sInstances.remove(nativePtr);
+ }
+
+ public static void nativeFreeBuffer(long nativePtr) {
+ getInstance(nativePtr).freeBuffer();
+ }
+
+ public void freeBuffer() {
+ init();
+ }
+
+ private int getCapacity() {
+ return mBuffer.length;
+ }
+
+ private void ensureMoreCapacity(int size) {
+ ensureCapacity(mPos + size);
+ }
+
+ private void ensureCapacity(int targetSize) {
+ if (targetSize <= getCapacity()) {
+ return;
+ }
+ var newSize = getCapacity() * 2;
+ if (newSize < targetSize) {
+ newSize = targetSize;
+ }
+ forceSetCapacity(newSize);
+ }
+
+ private void forceSetCapacity(int newSize) {
+ var newBuf = new byte[newSize];
+
+ // Copy
+ System.arraycopy(mBuffer, 0, newBuf, 0, Math.min(newSize, getCapacity()));
+
+ this.mBuffer = newBuf;
+ }
+
+ private void ensureDataAvailable(int requestSize) {
+ if (mSize - mPos < requestSize) {
+ throw new RuntimeException(String.format(
+ "Pacel data underflow. size=%d, pos=%d, request=%d", mSize, mPos, requestSize));
+ }
+ }
+
+ public static void nativeMarkSensitive(long nativePtr) {
+ getInstance(nativePtr).mSensitive = true;
+ }
+ public static void nativeMarkForBinder(long nativePtr, IBinder binder) {
+ throw new RuntimeException("Not implemented yet");
+ }
+ public static boolean nativeIsForRpc(long nativePtr) {
+ throw new RuntimeException("Not implemented yet");
+ }
+ public static int nativeDataSize(long nativePtr) {
+ return getInstance(nativePtr).mSize;
+ }
+ public static int nativeDataAvail(long nativePtr) {
+ var p = getInstance(nativePtr);
+ return p.mSize - p.mPos;
+ }
+ public static int nativeDataPosition(long nativePtr) {
+ return getInstance(nativePtr).mPos;
+ }
+ public static int nativeDataCapacity(long nativePtr) {
+ return getInstance(nativePtr).mBuffer.length;
+ }
+ public static void nativeSetDataSize(long nativePtr, int size) {
+ var p = getInstance(nativePtr);
+ p.ensureCapacity(size);
+ getInstance(nativePtr).mSize = size;
+ }
+ public static void nativeSetDataPosition(long nativePtr, int pos) {
+ var p = getInstance(nativePtr);
+ // TODO: Should this change the size or the capacity??
+ p.mPos = pos;
+ }
+ public static void nativeSetDataCapacity(long nativePtr, int size) {
+ var p = getInstance(nativePtr);
+ if (p.getCapacity() < size) {
+ p.forceSetCapacity(size);
+ }
+ }
+
+ public static boolean nativePushAllowFds(long nativePtr, boolean allowFds) {
+ var p = getInstance(nativePtr);
+ var prev = p.mAllowFds;
+ p.mAllowFds = allowFds;
+ return prev;
+ }
+ public static void nativeRestoreAllowFds(long nativePtr, boolean lastValue) {
+ getInstance(nativePtr).mAllowFds = lastValue;
+ }
+
+ public static void nativeWriteByteArray(long nativePtr, byte[] b, int offset, int len) {
+ nativeWriteBlob(nativePtr, b, offset, len);
+ }
+
+ public static void nativeWriteBlob(long nativePtr, byte[] b, int offset, int len) {
+ var p = getInstance(nativePtr);
+
+ if (b == null) {
+ nativeWriteInt(nativePtr, -1);
+ } else {
+ final var alignedSize = align4(b.length);
+
+ nativeWriteInt(nativePtr, b.length);
+
+ p.ensureMoreCapacity(alignedSize);
+
+ System.arraycopy(b, offset, p.mBuffer, p.mPos, len);
+ p.mPos += alignedSize;
+ p.updateSize();
+ }
+ }
+
+ public static int nativeWriteInt(long nativePtr, int value) {
+ var p = getInstance(nativePtr);
+ p.ensureMoreCapacity(Integer.BYTES);
+
+ p.mBuffer[p.mPos++] = (byte) ((value >> 24) & 0xff);
+ p.mBuffer[p.mPos++] = (byte) ((value >> 16) & 0xff);
+ p.mBuffer[p.mPos++] = (byte) ((value >> 8) & 0xff);
+ p.mBuffer[p.mPos++] = (byte) ((value >> 0) & 0xff);
+
+ p.updateSize();
+
+ return OK;
+ }
+
+ public static int nativeWriteLong(long nativePtr, long value) {
+ nativeWriteInt(nativePtr, (int) (value >>> 32));
+ nativeWriteInt(nativePtr, (int) (value));
+ return OK;
+ }
+ public static int nativeWriteFloat(long nativePtr, float val) {
+ return nativeWriteInt(nativePtr, Float.floatToIntBits(val));
+ }
+ public static int nativeWriteDouble(long nativePtr, double val) {
+ return nativeWriteLong(nativePtr, Double.doubleToLongBits(val));
+ }
+ public static void nativeSignalExceptionForError(int error) {
+ throw new RuntimeException("Not implemented yet");
+ }
+
+ private static int align4(int val) {
+ return ((val + 3) / 4) * 4;
+ }
+
+ public static void nativeWriteString8(long nativePtr, String val) {
+ if (val == null) {
+ nativeWriteBlob(nativePtr, null, 0, 0);
+ } else {
+ var bytes = val.getBytes(StandardCharsets.UTF_8);
+ nativeWriteBlob(nativePtr, bytes, 0, bytes.length);
+ }
+ }
+ public static void nativeWriteString16(long nativePtr, String val) {
+ // Just reuse String8
+ nativeWriteString8(nativePtr, val);
+ }
+ public static void nativeWriteStrongBinder(long nativePtr, IBinder val) {
+ throw new RuntimeException("Not implemented yet");
+ }
+ public static void nativeWriteFileDescriptor(long nativePtr, FileDescriptor val) {
+ throw new RuntimeException("Not implemented yet");
+ }
+
+ public static byte[] nativeCreateByteArray(long nativePtr) {
+ return nativeReadBlob(nativePtr);
+ }
+
+ public static boolean nativeReadByteArray(long nativePtr, byte[] dest, int destLen) {
+ if (dest == null) {
+ return false;
+ }
+ var data = nativeReadBlob(nativePtr);
+ if (data == null) {
+ System.err.println("Percel has NULL, which is unexpected."); // TODO: Is this correct?
+ return false;
+ }
+ // TODO: Make sure the check logic is correct.
+ if (data.length != destLen) {
+ System.err.println("Byte array size mismatch: expected="
+ + data.length + " given=" + destLen);
+ return false;
+ }
+ return true;
+ }
+
+ public static byte[] nativeReadBlob(long nativePtr) {
+ final var size = nativeReadInt(nativePtr);
+ if (size == -1) {
+ return null;
+ }
+ var p = getInstance(nativePtr);
+ p.ensureDataAvailable(size);
+
+ var bytes = new byte[size];
+ System.arraycopy(p.mBuffer, p.mPos, bytes, 0, size);
+
+ p.mPos += align4(size);
+
+ return bytes;
+ }
+ public static int nativeReadInt(long nativePtr) {
+ var p = getInstance(nativePtr);
+
+ p.ensureDataAvailable(Integer.BYTES);
+
+ var ret = (((p.mBuffer[p.mPos++] & 0xff) << 24)
+ | ((p.mBuffer[p.mPos++] & 0xff) << 16)
+ | ((p.mBuffer[p.mPos++] & 0xff) << 8)
+ | ((p.mBuffer[p.mPos++] & 0xff) << 0));
+
+ return ret;
+ }
+ public static long nativeReadLong(long nativePtr) {
+ return (((long) nativeReadInt(nativePtr)) << 32)
+ | (((long) nativeReadInt(nativePtr)) & 0xffff_ffffL);
+ }
+
+ public static float nativeReadFloat(long nativePtr) {
+ return Float.intBitsToFloat(nativeReadInt(nativePtr));
+ }
+
+ public static double nativeReadDouble(long nativePtr) {
+ return Double.longBitsToDouble(nativeReadLong(nativePtr));
+ }
+
+ public static String nativeReadString8(long nativePtr) {
+ final var bytes = nativeReadBlob(nativePtr);
+ if (bytes == null) {
+ return null;
+ }
+ return new String(bytes, StandardCharsets.UTF_8);
+ }
+ public static String nativeReadString16(long nativePtr) {
+ return nativeReadString8(nativePtr);
+ }
+ public static IBinder nativeReadStrongBinder(long nativePtr) {
+ throw new RuntimeException("Not implemented yet");
+ }
+ public static FileDescriptor nativeReadFileDescriptor(long nativePtr) {
+ throw new RuntimeException("Not implemented yet");
+ }
+
+ public static byte[] nativeMarshall(long nativePtr) {
+ throw new RuntimeException("Not implemented yet");
+ }
+ public static void nativeUnmarshall(
+ long nativePtr, byte[] data, int offset, int length) {
+ throw new RuntimeException("Not implemented yet");
+ }
+ public static int nativeCompareData(long thisNativePtr, long otherNativePtr) {
+ throw new RuntimeException("Not implemented yet");
+ }
+ public static boolean nativeCompareDataInRange(
+ long ptrA, int offsetA, long ptrB, int offsetB, int length) {
+ throw new RuntimeException("Not implemented yet");
+ }
+ public static void nativeAppendFrom(
+ long thisNativePtr, long otherNativePtr, int srcOffset, int length) {
+ var dst = getInstance(thisNativePtr);
+ var src = getInstance(otherNativePtr);
+
+ dst.ensureMoreCapacity(length);
+
+ System.arraycopy(src.mBuffer, srcOffset, dst.mBuffer, dst.mPos, length);
+ dst.mPos += length; // TODO: 4 byte align?
+ dst.updateSize();
+
+ // TODO: Update the other's position?
+ }
+
+ public static boolean nativeHasFileDescriptors(long nativePtr) {
+ // Assume false for now, because we don't support writing FDs yet.
+ return false;
+ }
+ public static boolean nativeHasFileDescriptorsInRange(
+ long nativePtr, int offset, int length) {
+ // Assume false for now, because we don't support writing FDs yet.
+ return false;
+ }
+ public static void nativeWriteInterfaceToken(long nativePtr, String interfaceName) {
+ throw new RuntimeException("Not implemented yet");
+ }
+ public static void nativeEnforceInterface(long nativePtr, String interfaceName) {
+ throw new RuntimeException("Not implemented yet");
+ }
+
+ public static boolean nativeReplaceCallingWorkSourceUid(
+ long nativePtr, int workSourceUid) {
+ throw new RuntimeException("Not implemented yet");
+ }
+ public static int nativeReadCallingWorkSourceUid(long nativePtr) {
+ throw new RuntimeException("Not implemented yet");
+ }
+
+ public static long nativeGetOpenAshmemSize(long nativePtr) {
+ throw new RuntimeException("Not implemented yet");
+ }
+ public static long getGlobalAllocSize() {
+ throw new RuntimeException("Not implemented yet");
+ }
+ public static long getGlobalAllocCount() {
+ throw new RuntimeException("Not implemented yet");
+ }
+}
diff --git a/tools/hoststubgen/hoststubgen/helper-framework-runtime-src/framework/com/android/hoststubgen/nativesubstitution/SystemProperties_host.java b/tools/hoststubgen/hoststubgen/helper-framework-runtime-src/framework/com/android/hoststubgen/nativesubstitution/SystemProperties_host.java
new file mode 100644
index 000000000000..1ec1d5f307e1
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/helper-framework-runtime-src/framework/com/android/hoststubgen/nativesubstitution/SystemProperties_host.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.hoststubgen.nativesubstitution;
+
+public class SystemProperties_host {
+ public static String native_get(String key, String def) {
+ throw new RuntimeException("Not implemented yet");
+ }
+ public static int native_get_int(String key, int def) {
+ throw new RuntimeException("Not implemented yet");
+ }
+ public static long native_get_long(String key, long def) {
+ throw new RuntimeException("Not implemented yet");
+ }
+ public static boolean native_get_boolean(String key, boolean def) {
+ throw new RuntimeException("Not implemented yet");
+ }
+
+ public static long native_find(String name) {
+ throw new RuntimeException("Not implemented yet");
+ }
+ public static String native_get(long handle) {
+ throw new RuntimeException("Not implemented yet");
+ }
+ public static int native_get_int(long handle, int def) {
+ throw new RuntimeException("Not implemented yet");
+ }
+ public static long native_get_long(long handle, long def) {
+ throw new RuntimeException("Not implemented yet");
+ }
+ public static boolean native_get_boolean(long handle, boolean def) {
+ throw new RuntimeException("Not implemented yet");
+ }
+ public static void native_set(String key, String def) {
+ throw new RuntimeException("Not implemented yet");
+ }
+ public static void native_add_change_callback() {
+ throw new RuntimeException("Not implemented yet");
+ }
+ public static void native_report_sysprop_change() {
+ throw new RuntimeException("Not implemented yet");
+ }
+}
diff --git a/tools/hoststubgen/hoststubgen/helper-framework-runtime-src/framework/com/android/hoststubgen/runtimehelper/ClassLoadHook.java b/tools/hoststubgen/hoststubgen/helper-framework-runtime-src/framework/com/android/hoststubgen/runtimehelper/ClassLoadHook.java
new file mode 100644
index 000000000000..4c2d3c404b76
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/helper-framework-runtime-src/framework/com/android/hoststubgen/runtimehelper/ClassLoadHook.java
@@ -0,0 +1,182 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.hoststubgen.runtimehelper;
+
+import com.android.hoststubgen.hosthelper.HostTestException;
+
+import java.io.File;
+import java.io.PrintStream;
+import java.lang.reflect.Modifier;
+import java.util.ArrayList;
+import java.util.Arrays;
+
+/**
+ * Standard class to handle class load hook.
+ *
+ * We use this to initialize the environment necessary for some classes. (e.g. load native libs.)
+ */
+public class ClassLoadHook {
+ private static PrintStream out = System.out;
+
+ /**
+ * If true, we won't load `libandroid_runtime`
+ *
+ * <p>Looks like there's some complexity in running a host test with JNI with `atest`,
+ * so we need a way to remove the dependency.
+ */
+ private static final boolean SKIP_LOADING_LIBANDROID = "1".equals(System.getenv(
+ "HOSTTEST_SKIP_LOADING_LIBANDROID"));
+
+ public static final String CORE_NATIVE_CLASSES = "core_native_classes";
+ public static final String ICU_DATA_PATH = "icu.data.path";
+ public static final String KEYBOARD_PATHS = "keyboard_paths";
+ public static final String GRAPHICS_NATIVE_CLASSES = "graphics_native_classes";
+
+ public static final String VALUE_N_A = "**n/a**";
+ public static final String LIBANDROID_RUNTIME_NAME = "libandroid_runtime";
+
+ private static String sInitialDir = new File("").getAbsolutePath();
+
+ static {
+ log("Initialized. Current dir=" + sInitialDir);
+ }
+
+ private ClassLoadHook() {
+ }
+
+ /**
+ * Called when classes with
+ * {@code @HostSideTestClassLoadHook("com.android.hoststubgen.runtimehelper.ClassLoadHook.onClassLoaded") }
+ * are loaded.
+ */
+ public static void onClassLoaded(Class<?> clazz) {
+ System.out.println("Framework class loaded: " + clazz.getCanonicalName());
+
+ if (android.util.Log.class == clazz) {
+ loadFrameworkNativeCode();
+ }
+ }
+
+ private static void log(String message) {
+ out.println("ClassLoadHook: " + message);
+ }
+
+ private static void log(String fmt, Object... args) {
+ log(String.format(fmt, args));
+ }
+
+ private static void ensurePropertyNotSet(String key) {
+ if (System.getProperty(key) != null) {
+ throw new HostTestException("System property \"" + key + "\" is set unexpectedly");
+ }
+ }
+
+ private static void setProperty(String key, String value) {
+ System.setProperty(key, value);
+ log("Property set: %s=\"%s\"", key, value);
+ }
+
+ private static void dumpSystemProperties() {
+ for (var prop : System.getProperties().entrySet()) {
+ log(" %s=\"%s\"", prop.getKey(), prop.getValue());
+ }
+ }
+
+ private static void loadJniLibrary(String name) {
+ final String path = sInitialDir + "/lib64/" + name + ".so";
+ System.out.println("Loading " + path + " ...");
+ System.load(path);
+ System.out.println("Done loading " + path);
+ }
+
+ private static boolean sLoadFrameworkNativeCodeCalled = false;
+
+ /**
+ * Load `libandroid_runtime` if needed.
+ */
+ private static void loadFrameworkNativeCode() {
+ // This is called from class-initializers, so no synchronization is needed.
+ if (sLoadFrameworkNativeCodeCalled) {
+ // This method has already been called before.s
+ return;
+ }
+ sLoadFrameworkNativeCodeCalled = true;
+
+ // libandroid_runtime uses Java's system properties to decide what JNI methods to set up.
+ // Set up these properties for host-side tests.
+
+ if ("1".equals(System.getenv("HOSTTEST_DUMP_PROPERTIES"))) {
+ log("Java system properties:");
+ dumpSystemProperties();
+ }
+
+ if (SKIP_LOADING_LIBANDROID) {
+ log("Skip loading " + LIBANDROID_RUNTIME_NAME);
+ }
+
+ // Make sure these properties are not set.
+ ensurePropertyNotSet(CORE_NATIVE_CLASSES);
+ ensurePropertyNotSet(ICU_DATA_PATH);
+ ensurePropertyNotSet(KEYBOARD_PATHS);
+ ensurePropertyNotSet(GRAPHICS_NATIVE_CLASSES);
+
+ // Tell libandroid what JNI to use.
+ final var jniClasses = getCoreNativeClassesToUse();
+ if (jniClasses.isEmpty()) {
+ log("No classes require JNI methods, skip loading " + LIBANDROID_RUNTIME_NAME);
+ return;
+ }
+ setProperty(CORE_NATIVE_CLASSES, jniClasses);
+ setProperty(GRAPHICS_NATIVE_CLASSES, "");
+ setProperty(ICU_DATA_PATH, VALUE_N_A);
+ setProperty(KEYBOARD_PATHS, VALUE_N_A);
+
+ loadJniLibrary(LIBANDROID_RUNTIME_NAME);
+ }
+
+ /**
+ * @return if a given method is a native method or not.
+ */
+ private static boolean isNativeMethod(Class<?> clazz, String methodName, Class<?>... argTypes) {
+ try {
+ final var method = clazz.getMethod(methodName, argTypes);
+ return Modifier.isNative(method.getModifiers());
+ } catch (NoSuchMethodException e) {
+ throw new HostTestException(String.format(
+ "Class %s doesn't have method %s with args %s",
+ clazz.getCanonicalName(),
+ methodName,
+ Arrays.toString(argTypes)), e);
+ }
+ }
+
+ /**
+ * Create a list of classes as comma-separated that require JNI methods to be set up.
+ *
+ * <p>This list is used by frameworks/base/core/jni/LayoutlibLoader.cpp to decide
+ * what JNI methods to set up.
+ */
+ private static String getCoreNativeClassesToUse() {
+ final var coreNativeClassesToLoad = new ArrayList<String>();
+
+ if (isNativeMethod(android.util.Log.class, "isLoggable",
+ String.class, int.class)) {
+ coreNativeClassesToLoad.add("android.util.Log");
+ }
+
+ return String.join(",", coreNativeClassesToLoad);
+ }
+}
diff --git a/tools/hoststubgen/hoststubgen/helper-framework-runtime-src/libcore-fake/dalvik/system/VMRuntime.java b/tools/hoststubgen/hoststubgen/helper-framework-runtime-src/libcore-fake/dalvik/system/VMRuntime.java
new file mode 100644
index 000000000000..7d2b00d9420d
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/helper-framework-runtime-src/libcore-fake/dalvik/system/VMRuntime.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package dalvik.system;
+
+// [ravenwood] It's in libart, so until we get ART to work, we need to use a fake.
+// The original is here:
+// $ANDROID_BUILD_TOP/libcore/libart/src/main/java/dalvik/system/VMRuntime.java
+
+import java.lang.reflect.Array;
+
+public class VMRuntime {
+ private static final VMRuntime THE_ONE = new VMRuntime();
+
+ private VMRuntime() {
+ }
+
+ public static VMRuntime getRuntime() {
+ return THE_ONE;
+ }
+
+ public boolean is64Bit() {
+ return true;
+ }
+
+ public static boolean is64BitAbi(String abi) {
+ return true;
+ }
+
+ public Object newUnpaddedArray(Class<?> componentType, int minLength) {
+ return Array.newInstance(componentType, minLength);
+ }
+}
diff --git a/tools/hoststubgen/hoststubgen/helper-framework-runtime-src/libcore-fake/libcore/util/EmptyArray.java b/tools/hoststubgen/hoststubgen/helper-framework-runtime-src/libcore-fake/libcore/util/EmptyArray.java
new file mode 100644
index 000000000000..a1ae35a88656
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/helper-framework-runtime-src/libcore-fake/libcore/util/EmptyArray.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package libcore.util;
+
+import java.lang.annotation.Annotation;
+
+// [ravenwood] Copied from libcore. TODO: Figure out what to do with libcore.
+public class EmptyArray {
+ private EmptyArray() {}
+
+ public static final boolean[] BOOLEAN = new boolean[0];
+
+ public static final byte[] BYTE = new byte[0];
+
+ public static final char[] CHAR = new char[0];
+
+ public static final double[] DOUBLE = new double[0];
+
+ public static final float[] FLOAT = new float[0];
+
+ public static final int[] INT = new int[0];
+
+ public static final long[] LONG = new long[0];
+
+ public static final Class<?>[] CLASS = new Class[0];
+
+ public static final Object[] OBJECT = new Object[0];
+
+ public static final String[] STRING = new String[0];
+
+ public static final Throwable[] THROWABLE = new Throwable[0];
+
+ public static final StackTraceElement[] STACK_TRACE_ELEMENT = new StackTraceElement[0];
+
+ public static final java.lang.reflect.Type[] TYPE = new java.lang.reflect.Type[0];
+
+ public static final java.lang.reflect.TypeVariable[] TYPE_VARIABLE =
+ new java.lang.reflect.TypeVariable[0];
+ public static final Annotation[] ANNOTATION = new Annotation[0];
+
+}
diff --git a/tools/hoststubgen/hoststubgen/helper-framework-runtime-src/libcore-fake/libcore/util/SneakyThrow.java b/tools/hoststubgen/hoststubgen/helper-framework-runtime-src/libcore-fake/libcore/util/SneakyThrow.java
new file mode 100644
index 000000000000..e142c46bc311
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/helper-framework-runtime-src/libcore-fake/libcore/util/SneakyThrow.java
@@ -0,0 +1,33 @@
+/*
+ * 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 libcore.util;
+
+// [ravenwood] Copied from libcore. TODO: Figure out what to do with libcore.
+
+public class SneakyThrow {
+
+ private SneakyThrow() {
+ }
+
+ public static void sneakyThrow(Throwable t) {
+ SneakyThrow.<RuntimeException>sneakyThrow_(t);
+ }
+
+ private static <T extends Throwable> void sneakyThrow_(Throwable t) throws T {
+ throw (T) t;
+ }
+}
diff --git a/tools/hoststubgen/hoststubgen/helper-runtime-src/com/android/hoststubgen/hosthelper/HostStubGenProcessedKeepClass.java b/tools/hoststubgen/hoststubgen/helper-runtime-src/com/android/hoststubgen/hosthelper/HostStubGenProcessedKeepClass.java
new file mode 100644
index 000000000000..4c37579ac917
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/helper-runtime-src/com/android/hoststubgen/hosthelper/HostStubGenProcessedKeepClass.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.hoststubgen.hosthelper;
+
+import static java.lang.annotation.ElementType.TYPE;
+
+import org.objectweb.asm.Type;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Annotation added to all "stub" classes generated by HostStubGen.
+ */
+@Target({TYPE})
+@Retention(RetentionPolicy.RUNTIME)
+public @interface HostStubGenProcessedKeepClass {
+ String CLASS_INTERNAL_NAME = Type.getInternalName(HostStubGenProcessedKeepClass.class);
+ String CLASS_DESCRIPTOR = "L" + CLASS_INTERNAL_NAME + ";";
+}
diff --git a/tools/hoststubgen/hoststubgen/helper-runtime-src/com/android/hoststubgen/hosthelper/HostStubGenProcessedStubClass.java b/tools/hoststubgen/hoststubgen/helper-runtime-src/com/android/hoststubgen/hosthelper/HostStubGenProcessedStubClass.java
new file mode 100644
index 000000000000..34e0030f548a
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/helper-runtime-src/com/android/hoststubgen/hosthelper/HostStubGenProcessedStubClass.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.hoststubgen.hosthelper;
+
+import static java.lang.annotation.ElementType.TYPE;
+
+import org.objectweb.asm.Type;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Annotation added to all "stub" classes generated by HostStubGen.
+ */
+@Target({TYPE})
+@Retention(RetentionPolicy.RUNTIME)
+public @interface HostStubGenProcessedStubClass {
+ String CLASS_INTERNAL_NAME = Type.getInternalName(HostStubGenProcessedStubClass.class);
+ String CLASS_DESCRIPTOR = "L" + CLASS_INTERNAL_NAME + ";";
+}
diff --git a/tools/hoststubgen/hoststubgen/helper-runtime-src/com/android/hoststubgen/hosthelper/HostTestException.java b/tools/hoststubgen/hoststubgen/helper-runtime-src/com/android/hoststubgen/hosthelper/HostTestException.java
new file mode 100644
index 000000000000..c54c2c111229
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/helper-runtime-src/com/android/hoststubgen/hosthelper/HostTestException.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.hoststubgen.hosthelper;
+
+public class HostTestException extends RuntimeException {
+ public HostTestException(String message) {
+ super(message);
+ }
+
+ public HostTestException(String message, Throwable inner) {
+ super(message, inner);
+ }
+}
diff --git a/tools/hoststubgen/hoststubgen/helper-runtime-src/com/android/hoststubgen/hosthelper/HostTestSuite.java b/tools/hoststubgen/hoststubgen/helper-runtime-src/com/android/hoststubgen/hosthelper/HostTestSuite.java
new file mode 100644
index 000000000000..29f7be008eef
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/helper-runtime-src/com/android/hoststubgen/hosthelper/HostTestSuite.java
@@ -0,0 +1,102 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.hoststubgen.hosthelper;
+
+import com.google.common.reflect.ClassPath;
+import com.google.common.reflect.ClassPath.ClassInfo;
+
+import junit.framework.JUnit4TestAdapter;
+import junit.framework.TestSuite;
+
+import java.util.regex.Pattern;
+
+/**
+ * A very simple Junit {@link TestSuite} builder that finds all classes that look like test classes.
+ *
+ * We use it to run ravenwood test jars from the command line.
+ */
+public class HostTestSuite {
+ private static final String CLASS_NAME_REGEX_ENV = "HOST_TEST_CLASS_NAME_REGEX";
+
+ /**
+ * Called by junit, and return all test-looking classes as a suite.
+ */
+ public static TestSuite suite() {
+ TestSuite suite = new TestSuite();
+
+ final Pattern classNamePattern;
+ final var filterRegex = System.getenv(CLASS_NAME_REGEX_ENV);
+ if (filterRegex == null) {
+ classNamePattern = Pattern.compile("");
+ } else {
+ classNamePattern = Pattern.compile(filterRegex);
+ }
+ try {
+ // We use guava to list all classes.
+ ClassPath cp = ClassPath.from(HostTestSuite.class.getClassLoader());
+
+ for (var classInfo : cp.getAllClasses()) {
+ Class<?> clazz = asTestClass(classInfo);
+ if (clazz != null) {
+ if (classNamePattern.matcher(clazz.getSimpleName()).find()) {
+ System.out.println("Test class found " + clazz.getName());
+ } else {
+ System.out.println("Skipping test class (for $"
+ + CLASS_NAME_REGEX_ENV + "): " + clazz.getName());
+ }
+ suite.addTest(new JUnit4TestAdapter(clazz));
+ }
+ }
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ return suite;
+ }
+
+ /**
+ * Decide whether a class looks like a test class or not, and if so, return it as a Class
+ * instance.
+ */
+ private static Class<?> asTestClass(ClassInfo classInfo) {
+ try {
+ final Class<?> clazz = classInfo.load();
+
+ // Does it extend junit.framework.TestCase?
+ if (junit.framework.TestCase.class.isAssignableFrom(clazz)) {
+ // Ignore classes in JUnit itself, or the android(x) test lib.
+ if (classInfo.getName().startsWith("junit.")
+ || classInfo.getName().startsWith("org.junit.")
+ || classInfo.getName().startsWith("android.test.")
+ || classInfo.getName().startsWith("androidx.test.")) {
+ return null; // Ignore junit classes.
+ }
+ return clazz;
+ }
+ // Does it have any "@Test" method?
+ for (var method : clazz.getMethods()) {
+ for (var an : method.getAnnotations()) {
+ if (an.annotationType() == org.junit.Test.class) {
+ return clazz;
+ }
+ }
+ }
+ return null;
+ } catch (java.lang.NoClassDefFoundError e) {
+ // Ignore unloadable classes.
+ return null;
+ }
+ }
+}
diff --git a/tools/hoststubgen/hoststubgen/helper-runtime-src/com/android/hoststubgen/hosthelper/HostTestUtils.java b/tools/hoststubgen/hoststubgen/helper-runtime-src/com/android/hoststubgen/hosthelper/HostTestUtils.java
new file mode 100644
index 000000000000..f7719a6e55b2
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/helper-runtime-src/com/android/hoststubgen/hosthelper/HostTestUtils.java
@@ -0,0 +1,197 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.hoststubgen.hosthelper;
+
+import org.objectweb.asm.Type;
+
+import java.io.PrintStream;
+import java.lang.StackWalker.Option;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.util.HashMap;
+
+import javax.annotation.concurrent.GuardedBy;
+
+/**
+ * Utilities used in the host side test environment.
+ */
+public class HostTestUtils {
+ private HostTestUtils() {
+ }
+
+ public static final String CLASS_INTERNAL_NAME = Type.getInternalName(HostTestUtils.class);
+
+ /** If true, we won't print method call log. */
+ private static final boolean SKIP_METHOD_LOG = "1".equals(System.getenv(
+ "HOSTTEST_SKIP_METHOD_LOG"));
+
+ /** If true, we won't perform non-stub method direct call check. */
+ private static final boolean SKIP_NON_STUB_METHOD_CHECK = "1".equals(System.getenv(
+ "HOSTTEST_SKIP_NON_STUB_METHOD_CHECK"));
+
+
+ /**
+ * Method call log will be printed to it.
+ */
+ public static PrintStream logPrintStream = System.out;
+
+ /**
+ * Called from methods with FilterPolicy.Throw.
+ */
+ public static void onThrowMethodCalled() {
+ // TODO: Maybe add call tracking?
+ throw new RuntimeException("This method is not supported on the host side");
+ }
+
+ /**
+ * Called from methods with FilterPolicy.Log.
+ */
+ public static void logMethodCall(
+ String methodClass,
+ String methodName,
+ String methodDescriptor
+ ) {
+ if (SKIP_METHOD_LOG) {
+ return;
+ }
+ logPrintStream.println("# " + methodClass + "." + methodName + methodDescriptor);
+ }
+
+ private static final StackWalker sStackWalker =
+ StackWalker.getInstance(Option.RETAIN_CLASS_REFERENCE);
+
+ /**
+ * Return a {@link StackWalker} that supports {@link StackWalker#getCallerClass()}.
+ */
+ public static StackWalker getStackWalker() {
+ return sStackWalker;
+ }
+
+ /**
+ * Cache used by {@link #isClassAllowedToCallNonStubMethods}.
+ */
+ @GuardedBy("sAllowedClasses")
+ private static final HashMap<Class, Boolean> sAllowedClasses = new HashMap();
+
+ /**
+ * Return true if a given class is allowed to access non-stub methods -- that is, if the class
+ * is in the hoststubgen generated JARs. (not in the test jar.)
+ */
+ private static boolean isClassAllowedToCallNonStubMethods(Class<?> clazz) {
+ synchronized (sAllowedClasses) {
+ var cached = sAllowedClasses.get(clazz);
+ if (cached != null) {
+ return cached;
+ }
+ }
+ // All processed classes have this annotation.
+ var allowed = clazz.getAnnotation(HostStubGenProcessedKeepClass.class) != null;
+
+ // Java classes should be able to access any methods. (via callbacks, etc.)
+ if (!allowed) {
+ if (clazz.getPackageName().startsWith("java.")
+ || clazz.getPackageName().startsWith("javax.")) {
+ allowed = true;
+ }
+ }
+ synchronized (sAllowedClasses) {
+ sAllowedClasses.put(clazz, allowed);
+ }
+ return allowed;
+ }
+
+ /**
+ * Called when non-stub methods are called. We do a host-unsupported method direct call check
+ * in here.
+ */
+ public static void onNonStubMethodCalled(
+ String methodClass,
+ String methodName,
+ String methodDescriptor,
+ Class<?> callerClass) {
+ if (SKIP_NON_STUB_METHOD_CHECK) {
+ return;
+ }
+ if (isClassAllowedToCallNonStubMethods(callerClass)) {
+ return; // Generated class is allowed to call framework class.
+ }
+ logPrintStream.println("! " + methodClass + "." + methodName + methodDescriptor
+ + " called by " + callerClass.getCanonicalName());
+ }
+
+ /**
+ * Called when any top level class (not nested classes) in the impl jar is loaded.
+ *
+ * When HostStubGen inject a class-load hook, it's always a call to this method, with the
+ * actual method name as the second argument.
+ *
+ * This method discovers the hook method with reflections and call it.
+ *
+ * TODO: Add a unit test.
+ */
+ public static void onClassLoaded(Class<?> loadedClass, String callbackMethod) {
+ logPrintStream.println("! Class loaded: " + loadedClass.getCanonicalName()
+ + " calling hook " + callbackMethod);
+
+ // Forward the call to callbackMethod.
+ final int lastPeriod = callbackMethod.lastIndexOf(".");
+ final String className = callbackMethod.substring(0, lastPeriod);
+ final String methodName = callbackMethod.substring(lastPeriod + 1);
+
+ if (lastPeriod < 0 || className.isEmpty() || methodName.isEmpty()) {
+ throw new HostTestException(String.format(
+ "Unable to find class load hook: malformed method name \"%s\"",
+ callbackMethod));
+ }
+
+ Class<?> clazz = null;
+ try {
+ clazz = Class.forName(className);
+ } catch (Exception e) {
+ throw new HostTestException(String.format(
+ "Unable to find class load hook: Class %s not found", className), e);
+ }
+ if (!Modifier.isPublic(clazz.getModifiers())) {
+ throw new HostTestException(String.format(
+ "Unable to find class load hook: Class %s must be public", className));
+ }
+
+ Method method = null;
+ try {
+ method = clazz.getMethod(methodName, Class.class);
+ } catch (Exception e) {
+ throw new HostTestException(String.format(
+ "Unable to find class load hook: class %s doesn't have method %s"
+ + " (method must take exactly one parameter of type Class, and public static)",
+ className,
+ methodName), e);
+ }
+ if (!(Modifier.isPublic(method.getModifiers())
+ && Modifier.isStatic(method.getModifiers()))) {
+ throw new HostTestException(String.format(
+ "Unable to find class load hook: Method %s in class %s must be public static",
+ methodName, className));
+ }
+ try {
+ method.invoke(null, loadedClass);
+ } catch (Exception e) {
+ throw new HostTestException(String.format(
+ "Unable to invoke class load hook %s.%s",
+ className,
+ methodName), e);
+ }
+ }
+}
diff --git a/tools/hoststubgen/hoststubgen/hoststubgen-standard-options.txt b/tools/hoststubgen/hoststubgen/hoststubgen-standard-options.txt
new file mode 100644
index 000000000000..828d2a3e01c6
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/hoststubgen-standard-options.txt
@@ -0,0 +1,39 @@
+# File containing standard options to HostStubGen
+
+--debug
+
+# Uncomment below lines to enable each feature.
+--enable-non-stub-method-check
+# --no-non-stub-method-check
+
+# --enable-method-logging
+
+
+# Standard annotations.
+# Note, each line is a single argument, so we need newlines after each `--xxx-annotation`.
+--stub-annotation
+ android.hosttest.annotation.HostSideTestStub
+
+--keep-annotation
+ android.hosttest.annotation.HostSideTestKeep
+
+--stub-class-annotation
+ android.hosttest.annotation.HostSideTestWholeClassStub
+
+--keep-class-annotation
+ android.hosttest.annotation.HostSideTestWholeClassKeep
+
+--throw-annotation
+ android.hosttest.annotation.HostSideTestThrow
+
+--remove-annotation
+ android.hosttest.annotation.HostSideTestRemove
+
+--substitute-annotation
+ android.hosttest.annotation.HostSideTestSubstitute
+
+--native-substitute-annotation
+ android.hosttest.annotation.HostSideTestNativeSubstitutionClass
+
+--class-load-hook-annotation
+ android.hosttest.annotation.HostSideTestClassLoadHook
diff --git a/tools/hoststubgen/hoststubgen/jarjar-rules.txt b/tools/hoststubgen/hoststubgen/jarjar-rules.txt
new file mode 100644
index 000000000000..4e61ba6f67b3
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/jarjar-rules.txt
@@ -0,0 +1,2 @@
+# Rename guava
+rule com.google.common.** com.android.hoststubgen.x.@0 \ No newline at end of file
diff --git a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/Exceptions.kt b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/Exceptions.kt
new file mode 100644
index 000000000000..207ba52685f8
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/Exceptions.kt
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.hoststubgen
+
+/**
+ * We will not print the stack trace for exceptions implementing it.
+ */
+interface UserErrorException
+
+/**
+ * Exceptions about parsing class files.
+ */
+class ClassParseException(message: String) : Exception(message)
+
+/**
+ * Use it for internal exception that really shouldn't happen.
+ */
+class HostStubGenInternalException(message: String) : Exception(message)
+
+/**
+ * Exceptions about the content in a jar file.
+ */
+class InvalidJarFileException(message: String) : Exception(message), UserErrorException
+
+/**
+ * Exceptions missing classes, fields, methods, etc.
+ */
+class UnknownApiException(message: String) : Exception(message), UserErrorException
+
+/**
+ * Exceptions related to invalid annotations -- e.g. more than one visibility annotation
+ * on a single API.
+ */
+class InvalidAnnotationException(message: String) : Exception(message), UserErrorException
+
diff --git a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/HostStubGen.kt b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/HostStubGen.kt
new file mode 100644
index 000000000000..8db4b6961376
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/HostStubGen.kt
@@ -0,0 +1,402 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.hoststubgen
+
+import com.android.hoststubgen.asm.ClassNodes
+import com.android.hoststubgen.filters.AnnotationBasedFilter
+import com.android.hoststubgen.filters.ClassWidePolicyPropagatingFilter
+import com.android.hoststubgen.filters.ConstantFilter
+import com.android.hoststubgen.filters.FilterPolicy
+import com.android.hoststubgen.filters.ImplicitOutputFilter
+import com.android.hoststubgen.filters.KeepAllClassesFilter
+import com.android.hoststubgen.filters.OutputFilter
+import com.android.hoststubgen.filters.StubIntersectingFilter
+import com.android.hoststubgen.filters.createFilterFromTextPolicyFile
+import com.android.hoststubgen.filters.printAsTextPolicy
+import com.android.hoststubgen.visitors.BaseAdapter
+import org.objectweb.asm.ClassReader
+import org.objectweb.asm.ClassVisitor
+import org.objectweb.asm.ClassWriter
+import org.objectweb.asm.tree.ClassNode
+import org.objectweb.asm.util.CheckClassAdapter
+import java.io.BufferedInputStream
+import java.io.FileOutputStream
+import java.io.InputStream
+import java.io.OutputStream
+import java.io.PrintWriter
+import java.util.zip.ZipEntry
+import java.util.zip.ZipFile
+import java.util.zip.ZipOutputStream
+
+/**
+ * Actual main class.
+ */
+class HostStubGen(val options: HostStubGenOptions) {
+ fun run() {
+ val errors = HostStubGenErrors()
+
+ // Load all classes.
+ val allClasses = loadClassStructures(options.inJar)
+
+ // Dump the classes, if specified.
+ options.inputJarDumpFile?.let {
+ PrintWriter(it).use { pw -> allClasses.dump(pw) }
+ log.i("Dump file created at $it")
+ }
+
+ options.inputJarAsKeepAllFile?.let {
+ PrintWriter(it).use {
+ pw -> allClasses.forEach {
+ classNode -> printAsTextPolicy(pw, classNode)
+ }
+ }
+ log.i("Dump file created at $it")
+ }
+
+ // Build the filters.
+ val filter = buildFilter(errors, allClasses, options)
+
+ // Transform the jar.
+ convert(
+ options.inJar,
+ options.outStubJar,
+ options.outImplJar,
+ filter,
+ options.enableClassChecker,
+ allClasses,
+ errors,
+ )
+ }
+
+ /**
+ * Load all the classes, without code.
+ */
+ private fun loadClassStructures(inJar: String): ClassNodes {
+ log.i("Reading class structure from $inJar ...")
+ val start = System.currentTimeMillis()
+
+ val allClasses = ClassNodes()
+
+ log.withIndent {
+ ZipFile(inJar).use { inZip ->
+ val inEntries = inZip.entries()
+
+ while (inEntries.hasMoreElements()) {
+ val entry = inEntries.nextElement()
+
+ BufferedInputStream(inZip.getInputStream(entry)).use { bis ->
+ if (entry.name.endsWith(".class")) {
+ val cr = ClassReader(bis)
+ val cn = ClassNode()
+ cr.accept(cn, ClassReader.SKIP_CODE or ClassReader.SKIP_DEBUG
+ or ClassReader.SKIP_FRAMES)
+ if (!allClasses.addClass(cn)) {
+ log.w("Duplicate class found: ${cn.name}")
+ }
+ } else if (entry.name.endsWith(".dex")) {
+ // Seems like it's an ART jar file. We can't process it.
+ // It's a fatal error.
+ throw InvalidJarFileException(
+ "$inJar is not a desktop jar file. It contains a *.dex file.")
+ } else {
+ // Unknown file type. Skip.
+ while (bis.available() > 0) {
+ bis.skip((1024 * 1024).toLong())
+ }
+ }
+ }
+ }
+ }
+ }
+ if (allClasses.size == 0) {
+ log.w("$inJar contains no *.class files.")
+ }
+
+ val end = System.currentTimeMillis()
+ log.v("Done reading class structure in %.1f second(s).", (end - start) / 1000.0)
+ return allClasses
+ }
+
+ /**
+ * Build the filter, which decides what classes/methods/fields should be put in stub or impl
+ * jars, and "how". (e.g. with substitution?)
+ */
+ private fun buildFilter(
+ errors: HostStubGenErrors,
+ allClasses: ClassNodes,
+ options: HostStubGenOptions,
+ ): OutputFilter {
+ // We build a "chain" of multiple filters here.
+ //
+ // The filters are build in from "inside", meaning the first filter created here is
+ // the last filter used, so it has the least precedence.
+ //
+ // So, for example, the "remove" annotation, which is handled by AnnotationBasedFilter,
+ // can override a class-wide annotation, which is handled by
+ // ClassWidePolicyPropagatingFilter, and any annotations can be overridden by the
+ // text-file based filter, which is handled by parseTextFilterPolicyFile.
+
+ // The first filter is for the default policy from the command line options.
+ var filter: OutputFilter = ConstantFilter(options.defaultPolicy, "default-by-options")
+
+ // Next, we need a filter that resolves "class-wide" policies.
+ // This is used when a member (methods, fields, nested classes) don't get any polices
+ // from upper filters. e.g. when a method has no annotations, then this filter will apply
+ // the class-wide policy, if any. (if not, we'll fall back to the above filter.)
+ val classWidePropagator = ClassWidePolicyPropagatingFilter(filter)
+
+ // Next, Java annotation based filter.
+ filter = AnnotationBasedFilter(
+ errors,
+ allClasses,
+ options.stubAnnotations,
+ options.keepAnnotations,
+ options.stubClassAnnotations,
+ options.keepClassAnnotations,
+ options.throwAnnotations,
+ options.removeAnnotations,
+ options.substituteAnnotations,
+ options.nativeSubstituteAnnotations,
+ options.classLoadHookAnnotations,
+ classWidePropagator
+ )
+
+ // Next, "text based" filter, which allows to override polices without touching
+ // the target code.
+ options.policyOverrideFile?.let {
+ filter = createFilterFromTextPolicyFile(it, allClasses, filter)
+ }
+
+ // If `--intersect-stub-jar` is provided, load from these jar files too.
+ // We use this to restrict stub APIs to public/system/test APIs,
+ // by intersecting with a stub jar file created by metalava.
+ if (options.intersectStubJars.size > 0) {
+ val intersectingJars = loadIntersectingJars(options.intersectStubJars)
+
+ filter = StubIntersectingFilter(errors, intersectingJars, filter)
+ }
+
+ // Apply the implicit filter.
+ filter = ImplicitOutputFilter(errors, allClasses, filter)
+
+ // Optionally keep all classes.
+ if (options.keepAllClasses) {
+ filter = KeepAllClassesFilter(filter)
+ }
+
+ return filter
+ }
+
+ /**
+ * Load jar files specified with "--intersect-stub-jar".
+ */
+ private fun loadIntersectingJars(filenames: Set<String>): Map<String, ClassNodes> {
+ val intersectingJars = mutableMapOf<String, ClassNodes>()
+
+ filenames.forEach { filename ->
+ intersectingJars[filename] = loadClassStructures(filename)
+ }
+ return intersectingJars
+ }
+
+ /**
+ * Convert a JAR file into "stub" and "impl" JAR files.
+ */
+ private fun convert(
+ inJar: String,
+ outStubJar: String,
+ outImplJar: String,
+ filter: OutputFilter,
+ enableChecker: Boolean,
+ classes: ClassNodes,
+ errors: HostStubGenErrors,
+ ) {
+ log.i("Converting %s into [stub: %s, impl: %s] ...", inJar, outStubJar, outImplJar)
+ log.i("Checker is %s", if (enableChecker) "enabled" else "disabled")
+
+ val start = System.currentTimeMillis()
+
+ log.withIndent {
+ // Open the input jar file and process each entry.
+ ZipFile(inJar).use { inZip ->
+ ZipOutputStream(FileOutputStream(outStubJar)).use { stubOutStream ->
+ ZipOutputStream(FileOutputStream(outImplJar)).use { implOutStream ->
+ val inEntries = inZip.entries()
+ while (inEntries.hasMoreElements()) {
+ val entry = inEntries.nextElement()
+ convertSingleEntry(inZip, entry, stubOutStream, implOutStream,
+ filter, enableChecker, classes, errors)
+ }
+ log.i("Converted all entries.")
+ }
+ }
+ log.i("Created stub: $outStubJar")
+ log.i("Created impl: $outImplJar")
+ }
+ }
+ val end = System.currentTimeMillis()
+ log.v("Done transforming the jar in %.1f second(s).", (end - start) / 1000.0)
+ }
+
+ /**
+ * Convert a single ZIP entry, which may or may not be a class file.
+ */
+ private fun convertSingleEntry(
+ inZip: ZipFile,
+ entry: ZipEntry,
+ stubOutStream: ZipOutputStream,
+ implOutStream: ZipOutputStream,
+ filter: OutputFilter,
+ enableChecker: Boolean,
+ classes: ClassNodes,
+ errors: HostStubGenErrors,
+ ) {
+ log.d("Entry: %s", entry.name)
+ log.withIndent {
+ val name = entry.name
+
+ // Just ignore all the directories. (TODO: make sure it's okay)
+ if (name.endsWith("/")) {
+ return
+ }
+
+ // If it's a class, convert it.
+ if (name.endsWith(".class")) {
+ processSingleClass(inZip, entry, stubOutStream, implOutStream, filter,
+ enableChecker, classes, errors)
+ return
+ }
+
+ // Handle other file types...
+
+ // - *.uau seems to contain hidden API information.
+ // - *_compat_config.xml is also about compat-framework.
+ if (name.endsWith(".uau") ||
+ name.endsWith("_compat_config.xml")) {
+ log.d("Not needed: %s", entry.name)
+ return
+ }
+
+ // Unknown type, we just copy it to both output zip files.
+ // TODO: We probably shouldn't do it for stub jar?
+ log.v("Copying: %s", entry.name)
+ copyZipEntry(inZip, entry, stubOutStream)
+ copyZipEntry(inZip, entry, implOutStream)
+ }
+ }
+
+ /**
+ * Copy a single ZIP entry to the output.
+ */
+ private fun copyZipEntry(
+ inZip: ZipFile,
+ entry: ZipEntry,
+ out: ZipOutputStream,
+ ) {
+ BufferedInputStream(inZip.getInputStream(entry)).use { bis ->
+ // Copy unknown entries as is to the impl out. (but not to the stub out.)
+ val outEntry = ZipEntry(entry.name)
+ out.putNextEntry(outEntry)
+ while (bis.available() > 0) {
+ out.write(bis.read())
+ }
+ out.closeEntry()
+ }
+ }
+
+ /**
+ * Convert a single class to "stub" and "impl".
+ */
+ private fun processSingleClass(
+ inZip: ZipFile,
+ entry: ZipEntry,
+ stubOutStream: ZipOutputStream,
+ implOutStream: ZipOutputStream,
+ filter: OutputFilter,
+ enableChecker: Boolean,
+ classes: ClassNodes,
+ errors: HostStubGenErrors,
+ ) {
+ val className = entry.name.replaceFirst("\\.class$".toRegex(), "")
+ val classPolicy = filter.getPolicyForClass(className)
+ if (classPolicy.policy == FilterPolicy.Remove) {
+ log.d("Removing class: %s %s", className, classPolicy)
+ return
+ }
+ // Generate stub first.
+ if (classPolicy.policy.needsInStub) {
+ log.v("Creating stub class: %s Policy: %s", className, classPolicy)
+ log.withIndent {
+ BufferedInputStream(inZip.getInputStream(entry)).use { bis ->
+ val newEntry = ZipEntry(entry.name)
+ stubOutStream.putNextEntry(newEntry)
+ convertClass(/*forImpl=*/false, bis, stubOutStream, filter, enableChecker,
+ classes, errors)
+ stubOutStream.closeEntry()
+ }
+ }
+ }
+ log.v("Creating impl class: %s Policy: %s", className, classPolicy)
+ if (classPolicy.policy.needsInImpl) {
+ log.withIndent {
+ BufferedInputStream(inZip.getInputStream(entry)).use { bis ->
+ val newEntry = ZipEntry(entry.name)
+ implOutStream.putNextEntry(newEntry)
+ convertClass(/*forImpl=*/true, bis, implOutStream, filter, enableChecker,
+ classes, errors)
+ implOutStream.closeEntry()
+ }
+ }
+ }
+ }
+
+ /**
+ * Convert a single class to either "stub" or "impl".
+ */
+ private fun convertClass(
+ forImpl: Boolean,
+ input: InputStream,
+ out: OutputStream,
+ filter: OutputFilter,
+ enableChecker: Boolean,
+ classes: ClassNodes,
+ errors: HostStubGenErrors,
+ ) {
+ val cr = ClassReader(input)
+
+ // COMPUTE_FRAMES wouldn't be happy if code uses
+ val flags = ClassWriter.COMPUTE_MAXS // or ClassWriter.COMPUTE_FRAMES
+ val cw = ClassWriter(flags)
+
+ // Connect to the class writer
+ var outVisitor: ClassVisitor = cw
+ if (enableChecker) {
+ outVisitor = CheckClassAdapter(outVisitor)
+ }
+ val visitorOptions = BaseAdapter.Options(
+ enablePreTrace = options.enablePreTrace,
+ enablePostTrace = options.enablePostTrace,
+ enableMethodLogging = options.enablePreTrace,
+ enableNonStubMethodCallDetection = options.enableNonStubMethodCallDetection,
+ errors = errors,
+ )
+ outVisitor = BaseAdapter.getVisitor(classes, outVisitor, filter, forImpl, visitorOptions)
+
+ cr.accept(outVisitor, ClassReader.EXPAND_FRAMES)
+ val data = cw.toByteArray()
+ out.write(data)
+ }
+}
diff --git a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/HostStubGenErrors.kt b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/HostStubGenErrors.kt
new file mode 100644
index 000000000000..9df04892ddbd
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/HostStubGenErrors.kt
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.hoststubgen
+
+class HostStubGenErrors {
+ fun onErrorFound(message: String) {
+ // For now, we just throw as soon as any error is found, but eventually we should keep
+ // all errors and print them at the end.
+ throw RuntimeException(message)
+ }
+} \ No newline at end of file
diff --git a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/HostStubGenLogger.kt b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/HostStubGenLogger.kt
new file mode 100644
index 000000000000..5e71a3690700
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/HostStubGenLogger.kt
@@ -0,0 +1,198 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.hoststubgen
+
+import java.io.OutputStream
+import java.io.PrintStream
+
+val log: HostStubGenLogger = HostStubGenLogger()
+
+/** Logging level */
+enum class LogLevel {
+ None,
+ Error,
+ Warn,
+ Info,
+ Verbose,
+ Debug,
+}
+
+/** Simple logging class. */
+class HostStubGenLogger(
+ private var out: PrintStream = System.out!!,
+ var level: LogLevel = LogLevel.Info,
+) {
+ companion object {
+ private val sNullPrintStream: PrintStream = PrintStream(OutputStream.nullOutputStream())
+ }
+
+ private var indentLevel: Int = 0
+ get() = field
+ set(value) {
+ field = value
+ indent = " ".repeat(value)
+ }
+ private var indent: String = ""
+
+ fun indent() {
+ indentLevel++
+ }
+
+ fun unindent() {
+ if (indentLevel <= 0) {
+ throw IllegalStateException("Unbalanced unindent() call.")
+ }
+ indentLevel--
+ }
+
+ inline fun <T> withIndent(block: () -> T): T {
+ try {
+ indent()
+ return block()
+ } finally {
+ unindent()
+ }
+ }
+
+ fun isEnabled(level: LogLevel): Boolean {
+ return level.ordinal <= this.level.ordinal
+ }
+
+ private fun println(message: String) {
+ out.print(indent)
+ out.println(message)
+ }
+
+ /** Log an error. */
+ fun e(message: String) {
+ if (level.ordinal < LogLevel.Error.ordinal) {
+ return
+ }
+ println(message)
+ }
+
+ /** Log an error. */
+ fun e(format: String, vararg args: Any?) {
+ if (level.ordinal < LogLevel.Error.ordinal) {
+ return
+ }
+ e(String.format(format, *args))
+ }
+
+ /** Log a warning. */
+ fun w(message: String) {
+ if (level.ordinal < LogLevel.Warn.ordinal) {
+ return
+ }
+ println(message)
+ }
+
+ /** Log a warning. */
+ fun w(format: String, vararg args: Any?) {
+ if (level.ordinal < LogLevel.Warn.ordinal) {
+ return
+ }
+ w(String.format(format, *args))
+ }
+
+ /** Log an info message. */
+ fun i(message: String) {
+ if (level.ordinal < LogLevel.Info.ordinal) {
+ return
+ }
+ println(message)
+ }
+
+ /** Log a debug message. */
+ fun i(format: String, vararg args: Any?) {
+ if (level.ordinal < LogLevel.Warn.ordinal) {
+ return
+ }
+ i(String.format(format, *args))
+ }
+
+ /** Log a verbose message. */
+ fun v(message: String) {
+ if (level.ordinal < LogLevel.Verbose.ordinal) {
+ return
+ }
+ println(message)
+ }
+
+ /** Log a verbose message. */
+ fun v(format: String, vararg args: Any?) {
+ if (level.ordinal < LogLevel.Verbose.ordinal) {
+ return
+ }
+ v(String.format(format, *args))
+ }
+
+ /** Log a debug message. */
+ fun d(message: String) {
+ if (level.ordinal < LogLevel.Debug.ordinal) {
+ return
+ }
+ println(message)
+ }
+
+ /** Log a debug message. */
+ fun d(format: String, vararg args: Any?) {
+ if (level.ordinal < LogLevel.Warn.ordinal) {
+ return
+ }
+ d(String.format(format, *args))
+ }
+
+ inline fun forVerbose(block: () -> Unit) {
+ if (isEnabled(LogLevel.Verbose)) {
+ block()
+ }
+ }
+
+ inline fun forDebug(block: () -> Unit) {
+ if (isEnabled(LogLevel.Debug)) {
+ block()
+ }
+ }
+
+ /** Return a stream for error. */
+ fun getErrorPrintStream(): PrintStream {
+ if (level.ordinal < LogLevel.Error.ordinal) {
+ return sNullPrintStream
+ }
+
+ // TODO Apply indent
+ return PrintStream(out)
+ }
+
+ /** Return a stream for verbose messages. */
+ fun getVerbosePrintStream(): PrintStream {
+ if (level.ordinal < LogLevel.Verbose.ordinal) {
+ return sNullPrintStream
+ }
+ // TODO Apply indent
+ return PrintStream(out)
+ }
+
+ /** Return a stream for debug messages. */
+ fun getInfoPrintStream(): PrintStream {
+ if (level.ordinal < LogLevel.Info.ordinal) {
+ return sNullPrintStream
+ }
+ // TODO Apply indent
+ return PrintStream(out)
+ }
+} \ No newline at end of file
diff --git a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/HostStubGenOptions.kt b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/HostStubGenOptions.kt
new file mode 100644
index 000000000000..9a54ecffc8c2
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/HostStubGenOptions.kt
@@ -0,0 +1,307 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.hoststubgen
+
+import com.android.hoststubgen.filters.FilterPolicy
+import java.io.BufferedReader
+import java.io.File
+import java.io.FileReader
+
+/**
+ * Options that can be set from command line arguments.
+ */
+class HostStubGenOptions(
+ /** Input jar file*/
+ var inJar: String = "",
+
+ /** Output stub jar file */
+ var outStubJar: String = "",
+
+ /** Output implementation jar file */
+ var outImplJar: String = "",
+
+ var inputJarDumpFile: String? = null,
+
+ var inputJarAsKeepAllFile: String? = null,
+
+ var stubAnnotations: MutableSet<String> = mutableSetOf(),
+ var keepAnnotations: MutableSet<String> = mutableSetOf(),
+ var throwAnnotations: MutableSet<String> = mutableSetOf(),
+ var removeAnnotations: MutableSet<String> = mutableSetOf(),
+ var stubClassAnnotations: MutableSet<String> = mutableSetOf(),
+ var keepClassAnnotations: MutableSet<String> = mutableSetOf(),
+
+ var substituteAnnotations: MutableSet<String> = mutableSetOf(),
+ var nativeSubstituteAnnotations: MutableSet<String> = mutableSetOf(),
+ var classLoadHookAnnotations: MutableSet<String> = mutableSetOf(),
+
+ var intersectStubJars: MutableSet<String> = mutableSetOf(),
+
+ var policyOverrideFile: String? = null,
+
+ var defaultPolicy: FilterPolicy = FilterPolicy.Remove,
+ var keepAllClasses: Boolean = false,
+
+ var logLevel: LogLevel = LogLevel.Info,
+
+ var cleanUpOnError: Boolean = false,
+
+ var enableClassChecker: Boolean = false,
+ var enablePreTrace: Boolean = false,
+ var enablePostTrace: Boolean = false,
+
+ var enableMethodLogging: Boolean = false,
+
+ var enableNonStubMethodCallDetection: Boolean = true,
+) {
+ companion object {
+
+ private fun String.ensureFileExists(): String {
+ if (!File(this).exists()) {
+ throw InputFileNotFoundException(this)
+ }
+ return this
+ }
+
+ fun parseArgs(args: Array<String>): HostStubGenOptions {
+ val ret = HostStubGenOptions()
+
+ val ai = ArgIterator(expandAtFiles(args))
+
+ var allAnnotations = mutableSetOf<String>()
+
+ fun ensureUniqueAnnotation(name: String): String {
+ if (!allAnnotations.add(name)) {
+ throw DuplicateAnnotationException(ai.current)
+ }
+ return name
+ }
+
+ while (true) {
+ val arg = ai.nextArgOptional()
+ if (arg == null) {
+ break
+ }
+
+ when (arg) {
+ // TODO: Write help
+ "-h", "--h" -> TODO("Help is not implemented yet")
+
+ "-v", "--verbose" -> ret.logLevel = LogLevel.Verbose
+ "-d", "--debug" -> ret.logLevel = LogLevel.Debug
+ "-q", "--quiet" -> ret.logLevel = LogLevel.None
+
+ "--in-jar" -> ret.inJar = ai.nextArgRequired(arg).ensureFileExists()
+ "--out-stub-jar" -> ret.outStubJar = ai.nextArgRequired(arg)
+ "--out-impl-jar" -> ret.outImplJar = ai.nextArgRequired(arg)
+
+ "--policy-override-file" ->
+ ret.policyOverrideFile = ai.nextArgRequired(arg).ensureFileExists()
+
+ "--clean-up-on-error" -> ret.cleanUpOnError = true
+ "--no-clean-up-on-error" -> ret.cleanUpOnError = false
+
+ "--default-remove" -> ret.defaultPolicy = FilterPolicy.Remove
+ "--default-throw" -> ret.defaultPolicy = FilterPolicy.Throw
+ "--default-keep" -> ret.defaultPolicy = FilterPolicy.Keep
+ "--default-stub" -> ret.defaultPolicy = FilterPolicy.Stub
+
+ "--keep-all-classes" -> ret.keepAllClasses = true
+ "--no-keep-all-classes" -> ret.keepAllClasses = false
+
+ "--stub-annotation" ->
+ ret.stubAnnotations += ensureUniqueAnnotation(ai.nextArgRequired(arg))
+
+ "--keep-annotation" ->
+ ret.keepAnnotations += ensureUniqueAnnotation(ai.nextArgRequired(arg))
+
+ "--stub-class-annotation" ->
+ ret.stubClassAnnotations += ensureUniqueAnnotation(ai.nextArgRequired(arg))
+
+ "--keep-class-annotation" ->
+ ret.keepClassAnnotations += ensureUniqueAnnotation(ai.nextArgRequired(arg))
+
+ "--throw-annotation" ->
+ ret.throwAnnotations += ensureUniqueAnnotation(ai.nextArgRequired(arg))
+
+ "--remove-annotation" ->
+ ret.removeAnnotations += ensureUniqueAnnotation(ai.nextArgRequired(arg))
+
+ "--substitute-annotation" ->
+ ret.substituteAnnotations += ensureUniqueAnnotation(ai.nextArgRequired(arg))
+
+ "--native-substitute-annotation" ->
+ ret.nativeSubstituteAnnotations +=
+ ensureUniqueAnnotation(ai.nextArgRequired(arg))
+
+ "--class-load-hook-annotation" ->
+ ret.classLoadHookAnnotations +=
+ ensureUniqueAnnotation(ai.nextArgRequired(arg))
+
+ "--intersect-stub-jar" ->
+ ret.intersectStubJars += ai.nextArgRequired(arg).ensureFileExists()
+
+ "--gen-keep-all-file" ->
+ ret.inputJarAsKeepAllFile = ai.nextArgRequired(arg)
+
+ // Following options are for debugging.
+ "--enable-class-checker" -> ret.enableClassChecker = true
+ "--no-class-checker" -> ret.enableClassChecker = false
+
+ "--enable-pre-trace" -> ret.enablePreTrace = true
+ "--no-pre-trace" -> ret.enablePreTrace = false
+
+ "--enable-post-trace" -> ret.enablePostTrace = true
+ "--no-post-trace" -> ret.enablePostTrace = false
+
+ "--enable-method-logging" -> ret.enableMethodLogging = true
+ "--no-method-logging" -> ret.enableMethodLogging = false
+
+ "--enable-non-stub-method-check" -> ret.enableNonStubMethodCallDetection = true
+ "--no-non-stub-method-check" -> ret.enableNonStubMethodCallDetection = false
+
+ "--gen-input-dump-file" -> ret.inputJarDumpFile = ai.nextArgRequired(arg)
+
+ else -> throw ArgumentsException("Unknown option: $arg")
+ }
+ }
+ if (ret.inJar.isEmpty()) {
+ throw ArgumentsException("Required option missing: --in-jar")
+ }
+ if (ret.outStubJar.isEmpty()) {
+ throw ArgumentsException("Required option missing: --out-stub-jar")
+ }
+ if (ret.outImplJar.isEmpty()) {
+ throw ArgumentsException("Required option missing: --out-impl-jar")
+ }
+
+ return ret
+ }
+
+ /**
+ * Scan the arguments, and if any of them starts with an `@`, then load from the file
+ * and use its content as arguments.
+ *
+ * In this file, each line is treated as a single argument.
+ *
+ * The file can contain '#' as comments.
+ */
+ private fun expandAtFiles(args: Array<String>): List<String> {
+ val ret = mutableListOf<String>()
+
+ args.forEach { arg ->
+ if (!arg.startsWith('@')) {
+ ret += arg
+ return@forEach
+ }
+ // Read from the file, and add each line to the result.
+ val filename = arg.substring(1).ensureFileExists()
+
+ log.v("Expanding options file $filename")
+
+ BufferedReader(FileReader(filename)).use { reader ->
+ while (true) {
+ var line = reader.readLine()
+ if (line == null) {
+ break // EOF
+ }
+
+ line = normalizeTextLine(line)
+ if (line.isNotEmpty()) {
+ ret += line
+ }
+ }
+ }
+ }
+ return ret
+ }
+ }
+
+ open class ArgumentsException(message: String?) : Exception(message), UserErrorException
+
+ /** Thrown when the same annotation is used with different annotation arguments. */
+ class DuplicateAnnotationException(annotationName: String?) :
+ ArgumentsException("Duplicate annotation specified: '$annotationName'")
+
+ /** Thrown when an input file does not exist. */
+ class InputFileNotFoundException(filename: String) :
+ ArgumentsException("File '$filename' not found")
+
+ private class ArgIterator(
+ private val args: List<String>,
+ private var currentIndex: Int = -1
+ ) {
+ val current: String
+ get() = args.get(currentIndex)
+
+ /**
+ * Get the next argument, or [null] if there's no more arguments.
+ */
+ fun nextArgOptional(): String? {
+ if ((currentIndex + 1) >= args.size) {
+ return null
+ }
+ return args.get(++currentIndex)
+ }
+
+ /**
+ * Get the next argument, or throw if
+ */
+ fun nextArgRequired(argName: String): String {
+ nextArgOptional().let {
+ if (it == null) {
+ throw ArgumentsException("Missing parameter for option $argName")
+ }
+ if (it.isEmpty()) {
+ throw ArgumentsException("Parameter can't be empty for option $argName")
+ }
+ return it
+ }
+ }
+ }
+
+ override fun toString(): String {
+ return """
+ HostStubGenOptions{
+ inJar='$inJar',
+ outStubJar='$outStubJar',
+ outImplJar='$outImplJar',
+ inputJarDumpFile=$inputJarDumpFile,
+ inputJarAsKeepAllFile=$inputJarAsKeepAllFile,
+ stubAnnotations=$stubAnnotations,
+ keepAnnotations=$keepAnnotations,
+ throwAnnotations=$throwAnnotations,
+ removeAnnotations=$removeAnnotations,
+ stubClassAnnotations=$stubClassAnnotations,
+ keepClassAnnotations=$keepClassAnnotations,
+ substituteAnnotations=$substituteAnnotations,
+ nativeSubstituteAnnotations=$nativeSubstituteAnnotations,
+ classLoadHookAnnotations=$classLoadHookAnnotations,
+ intersectStubJars=$intersectStubJars,
+ policyOverrideFile=$policyOverrideFile,
+ defaultPolicy=$defaultPolicy,
+ keepAllClasses=$keepAllClasses,
+ logLevel=$logLevel,
+ cleanUpOnError=$cleanUpOnError,
+ enableClassChecker=$enableClassChecker,
+ enablePreTrace=$enablePreTrace,
+ enablePostTrace=$enablePostTrace,
+ enableMethodLogging=$enableMethodLogging,
+ enableNonStubMethodCallDetection=$enableNonStubMethodCallDetection,
+ }
+ """.trimIndent()
+ }
+}
diff --git a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/Main.kt b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/Main.kt
new file mode 100644
index 000000000000..0321d9db03ed
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/Main.kt
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+@file:JvmName("Main")
+
+package com.android.hoststubgen
+
+const val COMMAND_NAME = "HostStubGen"
+
+/**
+ * Entry point.
+ */
+fun main(args: Array<String>) {
+ var success = false
+ var clanupOnError = false
+ try {
+ // Parse the command line arguments.
+ val options = HostStubGenOptions.parseArgs(args)
+ clanupOnError = options.cleanUpOnError
+
+ log.level = options.logLevel
+
+ log.v("HostStubGen started")
+ log.v("Options: $options")
+
+ // Run.
+ HostStubGen(options).run()
+
+ success = true
+ } catch (e: Exception) {
+ log.e("$COMMAND_NAME: Error: ${e.message}")
+ if (e !is UserErrorException) {
+ e.printStackTrace(log.getErrorPrintStream())
+ }
+ if (clanupOnError) {
+ TODO("clanupOnError is not implemented yet")
+ }
+ }
+
+ log.v("HostStubGen finished")
+
+ System.exit(if (success) 0 else 1 )
+}
diff --git a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/Utils.kt b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/Utils.kt
new file mode 100644
index 000000000000..9fbd6d09bfb0
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/Utils.kt
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.hoststubgen
+
+/**
+ * A regex that maches whitespate.
+ */
+val whitespaceRegex = """\s+""".toRegex()
+
+/**
+ * Remove the comment ('#' and following) and surrounding whitespace from a line.
+ */
+fun normalizeTextLine(s: String): String {
+ // Remove # and after. (comment)
+ val pos = s.indexOf('#')
+ val uncommented = if (pos < 0) s else s.substring(0, pos)
+
+ // Remove surrounding whitespace.
+ return uncommented.trim()
+}
diff --git a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/asm/AsmUtils.kt b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/asm/AsmUtils.kt
new file mode 100644
index 000000000000..a51bdcf0c793
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/asm/AsmUtils.kt
@@ -0,0 +1,177 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.hoststubgen.asm
+
+import com.android.hoststubgen.ClassParseException
+import com.android.hoststubgen.HostStubGenInternalException
+import org.objectweb.asm.MethodVisitor
+import org.objectweb.asm.Opcodes
+import org.objectweb.asm.Type
+import org.objectweb.asm.tree.AnnotationNode
+import org.objectweb.asm.tree.ClassNode
+
+
+/** Name of the class initializer method. */
+val CLASS_INITIALIZER_NAME = "<clinit>"
+
+/** Descriptor of the class initializer method. */
+val CLASS_INITIALIZER_DESC = "()V"
+
+/**
+ * Find any of [anyAnnotations] from the list of visible / invisible annotations.
+ */
+fun findAnyAnnotation(
+ anyAnnotations: Set<String>,
+ visibleAnnotations: List<AnnotationNode>?,
+ invisibleAnnotations: List<AnnotationNode>?,
+ ): AnnotationNode? {
+ for (an in visibleAnnotations ?: emptyList()) {
+ if (anyAnnotations.contains(an.desc)) {
+ return an
+ }
+ }
+ for (an in invisibleAnnotations ?: emptyList()) {
+ if (anyAnnotations.contains(an.desc)) {
+ return an
+ }
+ }
+ return null
+}
+
+fun findAnnotationValueAsString(an: AnnotationNode, propertyName: String): String? {
+ for (i in 0..(an.values?.size ?: 0) - 2 step 2) {
+ val name = an.values[i]
+
+ if (name != propertyName) {
+ continue
+ }
+ val value = an.values[i + 1]
+ if (value is String) {
+ return value
+ }
+ throw ClassParseException(
+ "The type of '$name' in annotation \"${an.desc}\" must be String" +
+ ", but is ${value?.javaClass?.canonicalName}")
+ }
+ return null
+}
+
+private val removeLastElement = """[./][^./]*$""".toRegex()
+
+fun getPackageNameFromClassName(className: String): String {
+ return className.replace(removeLastElement, "")
+}
+
+fun resolveClassName(className: String, packageName: String): String {
+ if (className.contains('.') || className.contains('/')) {
+ return className
+ }
+ return "$packageName.$className"
+}
+
+fun String.toJvmClassName(): String {
+ return this.replace('.', '/')
+}
+
+fun String.toHumanReadableClassName(): String {
+ return this.replace('/', '.')
+}
+
+fun String.toHumanReadableMethodName(): String {
+ return this.replace('/', '.')
+}
+
+private val numericalInnerClassName = """.*\$\d+$""".toRegex()
+
+fun isAnonymousInnerClass(cn: ClassNode): Boolean {
+ // TODO: Is there a better way?
+ return cn.name.matches(numericalInnerClassName)
+}
+
+/**
+ * Take a class name. If it's a nested class, then return the name of its direct outer class name.
+ * Otherwise, return null.
+ */
+fun getDirectOuterClassName(className: String): String? {
+ val pos = className.indexOf('$')
+ if (pos < 0) {
+ return null
+ }
+ return className.substring(0, pos)
+}
+
+/**
+ * Write bytecode to push all the method arguments to the stack.
+ * The number of arguments and their type are taken from [methodDescriptor].
+ */
+fun writeByteCodeToPushArguments(methodDescriptor: String, writer: MethodVisitor) {
+ var i = -1
+ Type.getArgumentTypes(methodDescriptor).forEach { type ->
+ i++
+
+ // See https://en.wikipedia.org/wiki/List_of_Java_bytecode_instructions
+
+ // Note, long and double will consume two local variable spaces, so the extra `i++`.
+ when (type) {
+ Type.VOID_TYPE -> throw HostStubGenInternalException("VOID_TYPE not expected")
+ Type.BOOLEAN_TYPE, Type.INT_TYPE, Type.SHORT_TYPE, Type.CHAR_TYPE
+ -> writer.visitVarInsn(Opcodes.ILOAD, i)
+ Type.LONG_TYPE -> writer.visitVarInsn(Opcodes.LLOAD, i++)
+ Type.FLOAT_TYPE -> writer.visitVarInsn(Opcodes.FLOAD, i)
+ Type.DOUBLE_TYPE -> writer.visitVarInsn(Opcodes.DLOAD, i++)
+ else -> writer.visitVarInsn(Opcodes.ALOAD, i)
+ }
+ }
+}
+
+/**
+ * Write bytecode to "RETURN" that matches the method's return type, according to
+ * [methodDescriptor].
+ */
+fun writeByteCodeToReturn(methodDescriptor: String, writer: MethodVisitor) {
+ Type.getReturnType(methodDescriptor).let { type ->
+ // See https://en.wikipedia.org/wiki/List_of_Java_bytecode_instructions
+ when (type) {
+ Type.VOID_TYPE -> writer.visitInsn(Opcodes.RETURN)
+ Type.BOOLEAN_TYPE, Type.INT_TYPE, Type.SHORT_TYPE, Type.CHAR_TYPE
+ -> writer.visitInsn(Opcodes.IRETURN)
+ Type.LONG_TYPE -> writer.visitInsn(Opcodes.LRETURN)
+ Type.FLOAT_TYPE -> writer.visitInsn(Opcodes.FRETURN)
+ Type.DOUBLE_TYPE -> writer.visitInsn(Opcodes.DRETURN)
+ else -> writer.visitInsn(Opcodes.ARETURN)
+ }
+ }
+}
+
+/**
+ * Return the "visibility" modifier from an `access` integer.
+ *
+ * (see https://docs.oracle.com/javase/specs/jvms/se9/html/jvms-4.html#jvms-4.1-200-E.1)
+ */
+fun getVisibilityModifier(access: Int): Int {
+ return access and (Opcodes.ACC_PUBLIC or Opcodes.ACC_PRIVATE or Opcodes.ACC_PROTECTED)
+}
+
+/**
+ * Return true if an `access` integer is "private" or "package private".
+ */
+fun isVisibilityPrivateOrPackagePrivate(access: Int): Boolean {
+ return when (getVisibilityModifier(access)) {
+ 0 -> true // Package private.
+ Opcodes.ACC_PRIVATE -> true
+ else -> false
+ }
+}
diff --git a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/asm/ClassNodes.kt b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/asm/ClassNodes.kt
new file mode 100644
index 000000000000..4df0bfc4a8d1
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/asm/ClassNodes.kt
@@ -0,0 +1,149 @@
+package com.android.hoststubgen.asm
+
+import com.android.hoststubgen.ClassParseException
+import org.objectweb.asm.tree.AnnotationNode
+import org.objectweb.asm.tree.ClassNode
+import org.objectweb.asm.tree.FieldNode
+import org.objectweb.asm.tree.MethodNode
+import org.objectweb.asm.tree.TypeAnnotationNode
+import java.io.PrintWriter
+import java.util.Arrays
+
+/**
+ * Stores all classes loaded from a jar file, in a form of [ClassNode]
+ */
+class ClassNodes {
+ val mAllClasses: MutableMap<String, ClassNode> = HashMap()
+
+ /**
+ * Total number of classes registered.
+ */
+ val size: Int
+ get() = mAllClasses.size
+
+ /** Add a [ClassNode] */
+ fun addClass(cn: ClassNode): Boolean {
+ if (mAllClasses.containsKey(cn.name)) {
+ return false
+ }
+ mAllClasses[cn.name.toJvmClassName()] = cn
+ return true
+ }
+
+ /** Get a class's [ClassNodes] (which may not exist) */
+ fun findClass(name: String): ClassNode? {
+ return mAllClasses[name.toJvmClassName()]
+ }
+
+ /** Get a class's [ClassNodes] (which must exists) */
+ fun getClass(name: String): ClassNode {
+ return findClass(name) ?: throw ClassParseException("Class $name not found")
+ }
+
+ /** Find a field, which may not exist. */
+ fun findField(
+ className: String,
+ fieldName: String,
+ ): FieldNode? {
+ return findClass(className)?.fields?.firstOrNull { it.name == fieldName }?.let { fn ->
+ return fn
+ }
+ }
+
+ /** Find a method, which may not exist. */
+ fun findMethod(
+ className: String,
+ methodName: String,
+ descriptor: String,
+ ): MethodNode? {
+ return findClass(className)?.methods
+ ?.firstOrNull { it.name == methodName && it.desc == descriptor }?.let { mn ->
+ return mn
+ }
+ }
+
+ /** @return true if a class has a class initializer. */
+ fun hasClassInitializer(className: String): Boolean {
+ return findMethod(className, CLASS_INITIALIZER_NAME, CLASS_INITIALIZER_DESC) != null
+ }
+
+ /** Run the lambda on each class in alphabetical order. */
+ fun forEach(consumer: (classNode: ClassNode) -> Unit) {
+ val keys = mAllClasses.keys.toTypedArray()
+ Arrays.sort(keys)
+
+ for (name in keys) {
+ consumer(mAllClasses[name]!!)
+ }
+ }
+
+ /**
+ * Dump all classes.
+ */
+ fun dump(pw: PrintWriter) {
+ forEach { classNode -> dumpClass(pw, classNode) }
+ }
+
+ private fun dumpClass(pw: PrintWriter, cn: ClassNode) {
+ pw.printf("Class: %s [access: %x]\n", cn.name, cn.access)
+ dumpAnnotations(pw, " ",
+ cn.visibleTypeAnnotations, cn.invisibleTypeAnnotations,
+ cn.visibleAnnotations, cn.invisibleAnnotations,
+ )
+
+ for (f in cn.fields ?: emptyList()) {
+ pw.printf(" Field: %s [sig: %s] [desc: %s] [access: %x]\n",
+ f.name, f.signature, f.desc, f.access)
+ dumpAnnotations(pw, " ",
+ f.visibleTypeAnnotations, f.invisibleTypeAnnotations,
+ f.visibleAnnotations, f.invisibleAnnotations,
+ )
+ }
+ for (m in cn.methods ?: emptyList()) {
+ pw.printf(" Method: %s [sig: %s] [desc: %s] [access: %x]\n",
+ m.name, m.signature, m.desc, m.access)
+ dumpAnnotations(pw, " ",
+ m.visibleTypeAnnotations, m.invisibleTypeAnnotations,
+ m.visibleAnnotations, m.invisibleAnnotations,
+ )
+ }
+ }
+
+ private fun dumpAnnotations(
+ pw: PrintWriter,
+ prefix: String,
+ visibleTypeAnnotations: List<TypeAnnotationNode>?,
+ invisibleTypeAnnotations: List<TypeAnnotationNode>?,
+ visibleAnnotations: List<AnnotationNode>?,
+ invisibleAnnotations: List<AnnotationNode>?,
+ ) {
+ for (an in visibleTypeAnnotations ?: emptyList()) {
+ pw.printf("%sTypeAnnotation(vis): %s\n", prefix, an.desc)
+ }
+ for (an in invisibleTypeAnnotations ?: emptyList()) {
+ pw.printf("%sTypeAnnotation(inv): %s\n", prefix, an.desc)
+ }
+ for (an in visibleAnnotations ?: emptyList()) {
+ pw.printf("%sAnnotation(vis): %s\n", prefix, an.desc)
+ if (an.values == null) {
+ continue
+ }
+ var i = 0
+ while (i < an.values.size - 1) {
+ pw.printf("%s - %s -> %s \n", prefix, an.values[i], an.values[i + 1])
+ i += 2
+ }
+ }
+ for (an in invisibleAnnotations ?: emptyList()) {
+ pw.printf("%sAnnotation(inv): %s\n", prefix, an.desc)
+ if (an.values == null) {
+ continue
+ }
+ var i = 0
+ while (i < an.values.size - 1) {
+ pw.printf("%s - %s -> %s \n", prefix, an.values[i], an.values[i + 1])
+ i += 2
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/AnnotationBasedFilter.kt b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/AnnotationBasedFilter.kt
new file mode 100644
index 000000000000..454569d2f1c5
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/AnnotationBasedFilter.kt
@@ -0,0 +1,401 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.hoststubgen.filters
+
+import com.android.hoststubgen.ClassParseException
+import com.android.hoststubgen.HostStubGenErrors
+import com.android.hoststubgen.HostStubGenInternalException
+import com.android.hoststubgen.InvalidAnnotationException
+import com.android.hoststubgen.asm.ClassNodes
+import com.android.hoststubgen.asm.findAnnotationValueAsString
+import com.android.hoststubgen.asm.findAnyAnnotation
+import com.android.hoststubgen.asm.toHumanReadableMethodName
+import com.android.hoststubgen.asm.toJvmClassName
+import com.android.hoststubgen.log
+import org.objectweb.asm.tree.AnnotationNode
+import org.objectweb.asm.tree.ClassNode
+
+// TODO: Detect invalid cases, such as...
+// - Class's visibility is lower than the members'.
+// - HostSideTestSubstituteWith is set, but it doesn't have @Stub or @Keep
+
+/**
+ * [OutputFilter] using Java annotations.
+ */
+class AnnotationBasedFilter(
+ private val errors: HostStubGenErrors,
+ private val classes: ClassNodes,
+ stubAnnotations_: Set<String>,
+ keepAnnotations_: Set<String>,
+ stubClassAnnotations_: Set<String>,
+ keepClassAnnotations_: Set<String>,
+ throwAnnotations_: Set<String>,
+ removeAnnotations_: Set<String>,
+ substituteAnnotations_: Set<String>,
+ nativeSubstituteAnnotations_: Set<String>,
+ classLoadHookAnnotations_: Set<String>,
+ fallback: OutputFilter,
+) : DelegatingFilter(fallback) {
+ private var stubAnnotations = convertToInternalNames(stubAnnotations_)
+ private var keepAnnotations = convertToInternalNames(keepAnnotations_)
+ private var stubClassAnnotations = convertToInternalNames(stubClassAnnotations_)
+ private var keepClassAnnotations = convertToInternalNames(keepClassAnnotations_)
+ private var throwAnnotations = convertToInternalNames(throwAnnotations_)
+ private var removeAnnotations = convertToInternalNames(removeAnnotations_)
+ private var substituteAnnotations = convertToInternalNames(substituteAnnotations_)
+ private var nativeSubstituteAnnotations = convertToInternalNames(nativeSubstituteAnnotations_)
+ private var classLoadHookAnnotations = convertToInternalNames(classLoadHookAnnotations_)
+
+ /** Annotations that control API visibility. */
+ private var visibilityAnnotations: Set<String> = convertToInternalNames(
+ stubAnnotations_ +
+ keepAnnotations_ +
+ stubClassAnnotations_ +
+ keepClassAnnotations_ +
+ throwAnnotations_ +
+ removeAnnotations_)
+
+ /**
+ * All the annotations we use. Note, this one is in a [convertToJvmNames] format unlike
+ * other ones, because of how it's used.
+ */
+ private var allAnnotations: Set<String> = convertToJvmNames(
+ stubAnnotations_ +
+ keepAnnotations_ +
+ stubClassAnnotations_ +
+ keepClassAnnotations_ +
+ throwAnnotations_ +
+ removeAnnotations_ +
+ substituteAnnotations_ +
+ nativeSubstituteAnnotations_ +
+ classLoadHookAnnotations_)
+
+ private val substitutionHelper = SubstitutionHelper()
+
+ private val reasonAnnotation = "annotation"
+ private val reasonClassAnnotation = "class-annotation"
+
+ /**
+ * Throw if an item has more than one visibility annotations.
+ *
+ * name1 - 4 are only used in exception messages. We take them as separate strings
+ * to avoid unnecessary string concatenations.
+ */
+ private fun detectInvalidAnnotations(
+ visibles: List<AnnotationNode>?,
+ invisibles: List<AnnotationNode>?,
+ type: String,
+ name1: String,
+ name2: String,
+ name3: String,
+ ) {
+ var count = 0
+ for (an in visibles ?: emptyList()) {
+ if (visibilityAnnotations.contains(an.desc)) {
+ count++
+ }
+ }
+ for (an in invisibles ?: emptyList()) {
+ if (visibilityAnnotations.contains(an.desc)) {
+ count++
+ }
+ }
+ if (count > 1) {
+ val description = if (name2 == "" && name3 == "") {
+ "$type $name1"
+ } else {
+ "$type $name1.$name2$name3"
+ }
+ throw InvalidAnnotationException(
+ "Found more than one visibility annotations on $description")
+ }
+ }
+
+ /**
+ * Find a visibility annotation.
+ *
+ * name1 - 4 are only used in exception messages.
+ */
+ private fun findAnnotation(
+ visibles: List<AnnotationNode>?,
+ invisibles: List<AnnotationNode>?,
+ type: String,
+ name1: String,
+ name2: String = "",
+ name3: String = "",
+ ): FilterPolicyWithReason? {
+ detectInvalidAnnotations(visibles, invisibles, type, name1, name2, name3)
+
+ findAnyAnnotation(stubAnnotations, visibles, invisibles)?.let {
+ return FilterPolicy.Stub.withReason(reasonAnnotation)
+ }
+ findAnyAnnotation(stubClassAnnotations, visibles, invisibles)?.let {
+ return FilterPolicy.StubClass.withReason(reasonClassAnnotation)
+ }
+ findAnyAnnotation(keepAnnotations, visibles, invisibles)?.let {
+ return FilterPolicy.Keep.withReason(reasonAnnotation)
+ }
+ findAnyAnnotation(keepClassAnnotations, visibles, invisibles)?.let {
+ return FilterPolicy.KeepClass.withReason(reasonClassAnnotation)
+ }
+ findAnyAnnotation(throwAnnotations, visibles, invisibles)?.let {
+ return FilterPolicy.Throw.withReason(reasonAnnotation)
+ }
+ findAnyAnnotation(removeAnnotations, visibles, invisibles)?.let {
+ return FilterPolicy.Remove.withReason(reasonAnnotation)
+ }
+ return null
+ }
+
+ override fun getPolicyForClass(className: String): FilterPolicyWithReason {
+ val cn = classes.getClass(className)
+
+ findAnnotation(
+ cn.visibleAnnotations,
+ cn.invisibleAnnotations,
+ "class",
+ className)?.let {
+ return it
+ }
+
+ // If it's any of the annotations, then always keep it.
+ if (allAnnotations.contains(className)) {
+ return FilterPolicy.KeepClass.withReason("HostStubGen Annotation")
+ }
+
+ return super.getPolicyForClass(className)
+ }
+
+ override fun getPolicyForField(
+ className: String,
+ fieldName: String
+ ): FilterPolicyWithReason {
+ val cn = classes.getClass(className)
+
+ cn.fields?.firstOrNull { it.name == fieldName }?.let {fn ->
+ findAnnotation(
+ fn.visibleAnnotations,
+ fn.invisibleAnnotations,
+ "field",
+ className,
+ fieldName
+ )?.let { policy ->
+ // If the item has an annotation, then use it.
+ return policy
+ }
+ }
+ return super.getPolicyForField(className, fieldName)
+ }
+
+ override fun getPolicyForMethod(
+ className: String,
+ methodName: String,
+ descriptor: String
+ ): FilterPolicyWithReason {
+ val cn = classes.getClass(className)
+
+ cn.methods?.firstOrNull { it.name == methodName && it.desc == descriptor }?.let { mn ->
+ // @SubstituteWith is going to complicate the policy here, so we ask helper
+ // what to do.
+ substitutionHelper.getPolicyFromSubstitution(cn, mn.name, mn.desc)?.let {
+ return it
+ }
+
+ // If there's no substitution, then we check the annotation.
+ findAnnotation(
+ mn.visibleAnnotations,
+ mn.invisibleAnnotations,
+ "method",
+ className,
+ methodName,
+ descriptor
+ )?.let { policy ->
+ return policy
+ }
+ }
+ return super.getPolicyForMethod(className, methodName, descriptor)
+ }
+
+ override fun getRenameTo(
+ className: String,
+ methodName: String,
+ descriptor: String
+ ): String? {
+ val cn = classes.getClass(className)
+
+ // If the method has a "substitute with" annotation, then return its "value" parameter.
+ cn.methods?.firstOrNull { it.name == methodName && it.desc == descriptor }?.let { mn ->
+ return substitutionHelper.getRenameTo(cn, mn.name, mn.desc)
+ }
+ return null
+ }
+
+ override fun getNativeSubstitutionClass(className: String): String? {
+ classes.getClass(className).let { cn ->
+ findAnyAnnotation(nativeSubstituteAnnotations,
+ cn.visibleAnnotations, cn.invisibleAnnotations)?.let { an ->
+ return getAnnotationField(an, "value")?.toJvmClassName()
+ }
+ }
+ return null
+ }
+
+ override fun getClassLoadHook(className: String): String? {
+ classes.getClass(className).let { cn ->
+ findAnyAnnotation(classLoadHookAnnotations,
+ cn.visibleAnnotations, cn.invisibleAnnotations)?.let { an ->
+ return getAnnotationField(an, "value")?.toHumanReadableMethodName()
+ }
+ }
+ return null
+ }
+
+ private data class MethodKey(val name: String, val desc: String)
+
+ /**
+ * In order to handle substitution, we need to build a reverse mapping of substitution
+ * methods.
+ *
+ * This class automatically builds such a map internally that the above methods can
+ * take advantage of.
+ */
+ private inner class SubstitutionHelper {
+ private var currentClass: ClassNode? = null
+
+ private var policiesFromSubstitution = mutableMapOf<MethodKey, FilterPolicyWithReason>()
+ private var substituteToMethods = mutableMapOf<MethodKey, String>()
+
+ fun getPolicyFromSubstitution(cn: ClassNode, methodName: String, descriptor: String):
+ FilterPolicyWithReason? {
+ setClass(cn)
+ return policiesFromSubstitution[MethodKey(methodName, descriptor)]
+ }
+
+ fun getRenameTo(cn: ClassNode, methodName: String, descriptor: String): String? {
+ setClass(cn)
+ return substituteToMethods[MethodKey(methodName, descriptor)]
+ }
+
+ /**
+ * Every time we see a different class, we scan all its methods for substitution attributes,
+ * and compute (implicit) policies caused by them.
+ *
+ * For example, for the following methods:
+ *
+ * @Stub
+ * @Substitute(suffix = "_host")
+ * private void foo() {
+ * // This isn't supported on the host side.
+ * }
+ * private void foo_host() {
+ * // Host side implementation
+ * }
+ *
+ * We internally handle them as:
+ *
+ * foo() -> Remove
+ * foo_host() -> Stub, and then rename it to foo().
+ */
+ private fun setClass(cn: ClassNode) {
+ if (currentClass == cn) {
+ return
+ }
+ // If the class is changing, we'll rebuild the internal structure.
+ currentClass = cn
+
+ policiesFromSubstitution.clear()
+ substituteToMethods.clear()
+
+ for (mn in cn.methods ?: emptyList()) {
+ findAnyAnnotation(substituteAnnotations,
+ mn.visibleAnnotations,
+ mn.invisibleAnnotations)?.let { an ->
+
+ // Find the policy for this method.
+ val policy = outermostFilter.getPolicyForMethod(cn.name, mn.name, mn.desc)
+ .policy.resolveClassWidePolicy()
+ // Make sure it's either Stub or Keep.
+ if (!(policy.needsInStub || policy.needsInImpl)) {
+ // TODO: Use the real annotation names in the message
+ errors.onErrorFound("@SubstituteWith must have either @Stub or @Keep")
+ return@let
+ }
+ if (!policy.isUsableWithMethods) {
+ throw HostStubGenInternalException("Policy $policy shouldn't show up here")
+ }
+
+ val suffix = getAnnotationField(an, "suffix") ?: return@let
+ val renameFrom = mn.name + suffix
+ val renameTo = mn.name
+
+ if (renameFrom == renameTo) {
+ errors.onErrorFound("@SubstituteWith have a different name")
+ return@let
+ }
+
+ // This mn has "SubstituteWith". This means,
+ // 1. Re move the "rename-to" method, so add it to substitutedMethods.
+ policiesFromSubstitution[MethodKey(renameTo, mn.desc)] =
+ FilterPolicy.Remove.withReason("substitute-to")
+
+ // 2. We also keep the from-to in the map.
+ policiesFromSubstitution[MethodKey(renameFrom, mn.desc)] =
+ policy.withReason("substitute-from")
+ substituteToMethods[MethodKey(renameFrom, mn.desc)] = renameTo
+
+ log.v("Substitution found: %s%s -> %s", renameFrom, mn.desc, renameTo)
+ }
+ }
+ }
+ }
+
+ /**
+ * Return the (String) value of 'value' parameter from an annotation.
+ */
+ private fun getAnnotationField(an: AnnotationNode, name: String): String? {
+ try {
+ val suffix = findAnnotationValueAsString(an, name)
+ if (suffix == null) {
+ errors.onErrorFound("Annotation \"${an.desc}\" must have field $name")
+ }
+ return suffix
+ } catch (e: ClassParseException) {
+ errors.onErrorFound(e.message!!)
+ return null
+ }
+ }
+
+ companion object {
+ /**
+ * Convert from human-readable type names (e.g. "com.android.TypeName") to the internal type
+ * names (e.g. "Lcom/android/TypeName).
+ */
+ private fun convertToInternalNames(input: Set<String>): Set<String> {
+ val ret = mutableSetOf<String>()
+ input.forEach { ret.add("L" + it.toJvmClassName() + ";") }
+ return ret
+ }
+
+ /**
+ * Convert from human-readable type names to JVM type names.
+ */
+ private fun convertToJvmNames(input: Set<String>): Set<String> {
+ val ret = mutableSetOf<String>()
+ input.forEach { ret.add(it.toJvmClassName()) }
+ return ret
+ }
+ }
+} \ No newline at end of file
diff --git a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/ClassWidePolicyPropagatingFilter.kt b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/ClassWidePolicyPropagatingFilter.kt
new file mode 100644
index 000000000000..6aac3d88b8b1
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/ClassWidePolicyPropagatingFilter.kt
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.hoststubgen.filters
+
+import com.android.hoststubgen.asm.getDirectOuterClassName
+
+/**
+ * This is used as the second last fallback filter. This filter propagates the class-wide policy
+ * (obtained from [outermostFilter]) to the fields and methods.
+ */
+class ClassWidePolicyPropagatingFilter(
+ fallback: OutputFilter,
+ ) : DelegatingFilter(fallback) {
+
+ private fun getClassWidePolicy(className: String, resolve: Boolean): FilterPolicyWithReason? {
+ var currentClass = className
+
+ while (true) {
+ outermostFilter.getPolicyForClass(className).let { policy ->
+ if (policy.policy.isClassWidePolicy) {
+ val p = if (resolve) policy.policy.resolveClassWidePolicy() else policy.policy
+
+ return p.withReason(policy.reason).wrapReason("class-wide in $currentClass")
+ }
+ // If the class's policy is remove, then remove it.
+ if (policy.policy == FilterPolicy.Remove) {
+ return FilterPolicy.Remove.withReason("class-wide in $currentClass")
+ }
+ }
+
+ // Next, look at the outer class...
+ val outer = getDirectOuterClassName(currentClass)
+ if (outer == null) {
+ return null
+ }
+ currentClass = outer
+ }
+ }
+
+ override fun getPolicyForClass(className: String): FilterPolicyWithReason {
+ // If it's a nested class, use the outer class's policy.
+ getDirectOuterClassName(className)?.let { outerName ->
+ getClassWidePolicy(outerName, resolve = false)?.let { policy ->
+ return policy
+ }
+ }
+
+ return super.getPolicyForClass(className)
+ }
+
+ override fun getPolicyForField(
+ className: String,
+ fieldName: String
+ ): FilterPolicyWithReason {
+ return getClassWidePolicy(className, resolve = true)
+ ?: super.getPolicyForField(className, fieldName)
+ }
+
+ override fun getPolicyForMethod(
+ className: String,
+ methodName: String,
+ descriptor: String
+ ): FilterPolicyWithReason {
+ return getClassWidePolicy(className, resolve = true)
+ ?: super.getPolicyForMethod(className, methodName, descriptor)
+ }
+} \ No newline at end of file
diff --git a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/ConstantFilter.kt b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/ConstantFilter.kt
new file mode 100644
index 000000000000..33010baaf894
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/ConstantFilter.kt
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.hoststubgen.filters
+
+import com.android.hoststubgen.HostStubGenInternalException
+
+
+/**
+ * [OutputFilter] with a given policy. Used to represent the default policy.
+ *
+ * This is used as the last fallback filter.
+ *
+ * @param policy the policy. Cannot be a "substitute" policy.
+ */
+class ConstantFilter(
+ policy: FilterPolicy,
+ val reason: String
+) : OutputFilter() {
+ val classPolicy: FilterPolicy
+ val fieldPolicy: FilterPolicy
+ val methodPolicy: FilterPolicy
+
+ init {
+ if (policy.isSubstitute) {
+ throw HostStubGenInternalException(
+ "ConstantFilter doesn't allow substitution policies.")
+ }
+ if (policy.isClassWidePolicy) {
+ // We prevent it, because there's no point in using class-wide policies because
+ // all members get othe same policy too anyway.
+ throw HostStubGenInternalException(
+ "ConstantFilter doesn't allow class-wide policies.")
+ }
+ methodPolicy = policy
+
+ // TODO: Need to think about the realistic default behavior.
+ classPolicy = if (policy != FilterPolicy.Throw) policy else FilterPolicy.Remove
+ fieldPolicy = classPolicy
+ }
+
+ override fun getPolicyForClass(className: String): FilterPolicyWithReason {
+ return classPolicy.withReason(reason)
+ }
+
+ override fun getPolicyForField(className: String, fieldName: String): FilterPolicyWithReason {
+ return fieldPolicy.withReason(reason)
+ }
+
+ override fun getPolicyForMethod(
+ className: String,
+ methodName: String,
+ descriptor: String,
+ ): FilterPolicyWithReason {
+ return methodPolicy.withReason(reason)
+ }
+}
diff --git a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/DelegatingFilter.kt b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/DelegatingFilter.kt
new file mode 100644
index 000000000000..f0763c4ba097
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/DelegatingFilter.kt
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.hoststubgen.filters
+
+/**
+ * Base class for an [OutputFilter] that uses another filter as a fallback.
+ */
+abstract class DelegatingFilter(
+ // fallback shouldn't be used by subclasses, so make it private.
+ // They should instead be calling into `super` or `outermostFilter`.
+ private val fallback: OutputFilter
+) : OutputFilter() {
+ init {
+ fallback.outermostFilter = this
+ }
+
+ override var outermostFilter: OutputFilter = this
+ get() = field
+ set(value) {
+ field = value
+ // Propagate the inner filters.
+ fallback.outermostFilter = value
+ }
+
+ override fun getPolicyForClass(className: String): FilterPolicyWithReason {
+ return fallback.getPolicyForClass(className)
+ }
+
+ override fun getPolicyForField(
+ className: String,
+ fieldName: String
+ ): FilterPolicyWithReason {
+ return fallback.getPolicyForField(className, fieldName)
+ }
+
+ override fun getPolicyForMethod(
+ className: String,
+ methodName: String,
+ descriptor: String
+ ): FilterPolicyWithReason {
+ return fallback.getPolicyForMethod(className, methodName, descriptor)
+ }
+
+ override fun getRenameTo(
+ className: String,
+ methodName: String,
+ descriptor: String
+ ): String? {
+ return fallback.getRenameTo(className, methodName, descriptor)
+ }
+
+ override fun getNativeSubstitutionClass(className: String): String? {
+ return fallback.getNativeSubstitutionClass(className)
+ }
+
+ override fun getClassLoadHook(className: String): String? {
+ return fallback.getClassLoadHook(className)
+ }
+}
diff --git a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/FilterPolicy.kt b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/FilterPolicy.kt
new file mode 100644
index 000000000000..f11ac2f7325d
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/FilterPolicy.kt
@@ -0,0 +1,133 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.hoststubgen.filters
+
+enum class FilterPolicy {
+ /**
+ * Keep the item in the stub jar file, so tests can use it.
+ */
+ Stub,
+
+ /**
+ * Keep the item in the impl jar file, but not in the stub file. Tests cannot use it directly,
+ * but indirectly.
+ */
+ Keep,
+
+ /**
+ * Only used for types. Keep the class in the stub, and also all its members.
+ * But each member can have another annotations to override it.
+ */
+ StubClass,
+
+ /**
+ * Only used for types. Keep the class in the impl, not in the stub, and also all its members.
+ * But each member can have another annotations to override it.
+ */
+ KeepClass,
+
+ /**
+ * Same as [Stub], but replace it with a "substitution" method. Only usable with methods.
+ */
+ SubstituteAndStub,
+
+ /**
+ * Same as [Keep], but replace it with a "substitution" method. Only usable with methods.
+ */
+ SubstituteAndKeep,
+
+ /**
+ * Only usable with methods. The item will be kept in the impl jar file, but when called,
+ * it'll throw.
+ */
+ Throw,
+
+ /**
+ * Remove the item completely.
+ */
+ Remove;
+
+ val isSubstitute: Boolean
+ get() = this == SubstituteAndStub || this == SubstituteAndKeep
+
+ val needsInStub: Boolean
+ get() = this == Stub || this == StubClass || this == SubstituteAndStub
+
+ val needsInImpl: Boolean
+ get() = this != Remove
+
+ /** Returns whether a policy can be used with classes */
+ val isUsableWithClasses: Boolean
+ get() {
+ return when (this) {
+ Stub, StubClass, Keep, KeepClass, Remove -> true
+ else -> false
+ }
+ }
+
+ /** Returns whether a policy can be used with fields. */
+ val isUsableWithFields: Boolean
+ get() {
+ return when (this) {
+ Stub, Keep, Remove -> true
+ else -> false
+ }
+ }
+
+ /** Returns whether a policy can be used with methods */
+ val isUsableWithMethods: Boolean
+ get() {
+ return when (this) {
+ StubClass, KeepClass -> false
+ else -> true
+ }
+ }
+
+ /** Returns whether a policy is a class-wide one. */
+ val isClassWidePolicy: Boolean
+ get() {
+ return when (this) {
+ StubClass, KeepClass -> true
+ else -> false
+ }
+ }
+
+ fun getSubstitutionBasePolicy(): FilterPolicy {
+ return when (this) {
+ SubstituteAndKeep -> Keep
+ SubstituteAndStub -> Stub
+ else -> this
+ }
+ }
+
+ /**
+ * Convert {Stub,Keep}Class to the corresponding Stub or Keep.
+ */
+ fun resolveClassWidePolicy(): FilterPolicy {
+ return when (this) {
+ StubClass -> Stub
+ KeepClass -> Keep
+ else -> this
+ }
+ }
+
+ /**
+ * Create a [FilterPolicyWithReason] with a given reason.
+ */
+ fun withReason(reason: String): FilterPolicyWithReason {
+ return FilterPolicyWithReason(this, reason)
+ }
+} \ No newline at end of file
diff --git a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/FilterPolicyWithReason.kt b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/FilterPolicyWithReason.kt
new file mode 100644
index 000000000000..b64a2f5fd8a5
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/FilterPolicyWithReason.kt
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.hoststubgen.filters
+
+/**
+ * Captures a [FilterPolicy] with a human-readable reason.
+ */
+data class FilterPolicyWithReason (
+ val policy: FilterPolicy,
+ val reason: String = "",
+) {
+ /**
+ * Return a new [FilterPolicy] with an updated reason, while keeping the original reason
+ * as an "inner-reason".
+ */
+ fun wrapReason(reason: String): FilterPolicyWithReason {
+ return FilterPolicyWithReason(policy, "$reason [inner-reason: ${this.reason}]")
+ }
+
+ /**
+ * If the visibility is lower than "Keep" (meaning if it's "remove"),
+ * then return a new [FilterPolicy] with "Keep".
+ * Otherwise, return itself
+ */
+ fun promoteToKeep(promotionReason: String): FilterPolicyWithReason {
+ if (policy.needsInImpl) {
+ return this
+ }
+ val newPolicy = if (policy.isClassWidePolicy) FilterPolicy.KeepClass else FilterPolicy.Keep
+
+ return FilterPolicyWithReason(newPolicy,
+ "$promotionReason [original remove reason: ${this.reason}]")
+ }
+
+ /**
+ * If the visibility is above "Keep" (meaning if it's "stub"),
+ * then return a new [FilterPolicy] with "Keep".
+ * Otherwise, return itself
+ */
+ fun demoteToKeep(promotionReason: String): FilterPolicyWithReason {
+ if (!policy.needsInStub) {
+ return this
+ }
+ val newPolicy = if (policy.isClassWidePolicy) FilterPolicy.KeepClass else FilterPolicy.Keep
+
+ return FilterPolicyWithReason(newPolicy,
+ "$promotionReason [original stub reason: ${this.reason}]")
+ }
+
+ override fun toString(): String {
+ return "[$policy - reason: $reason]"
+ }
+} \ No newline at end of file
diff --git a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/ImplicitOutputFilter.kt b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/ImplicitOutputFilter.kt
new file mode 100644
index 000000000000..9c372ff68e37
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/ImplicitOutputFilter.kt
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.hoststubgen.filters
+
+import com.android.hoststubgen.HostStubGenErrors
+import com.android.hoststubgen.HostStubGenInternalException
+import com.android.hoststubgen.asm.isAnonymousInnerClass
+import com.android.hoststubgen.log
+import com.android.hoststubgen.asm.ClassNodes
+import com.android.hoststubgen.asm.isVisibilityPrivateOrPackagePrivate
+
+/**
+ * Filter implementing "implicit" rules, such as:
+ * - "keep all anonymous inner classes if the outer class is keep".
+ * (But anonymous inner classes should never be in "stub")
+ * - For classes in stub, make sure private parameterless constructors are also in stub, if any.
+ */
+class ImplicitOutputFilter(
+ private val errors: HostStubGenErrors,
+ private val classes: ClassNodes,
+ fallback: OutputFilter
+) : DelegatingFilter(fallback) {
+ private fun getClassImplicitPolicy(className: String): FilterPolicyWithReason? {
+ // TODO: This check should be cached.
+ val cn = classes.getClass(className)
+
+ if (isAnonymousInnerClass(cn)) {
+ log.forDebug {
+// log.d(" anon-inner class: ${className} outer: ${cn.outerClass} ")
+ }
+ if (cn.outerClass == null) {
+ throw HostStubGenInternalException(
+ "outerClass is null for anonymous inner class")
+ }
+ // If the outer class needs to be in impl, it should be in impl too.
+ val outerPolicy = outermostFilter.getPolicyForClass(cn.outerClass)
+ if (outerPolicy.policy.needsInImpl) {
+ return FilterPolicy.KeepClass.withReason("anonymous-inner-class")
+ }
+ }
+ return null
+ }
+
+ override fun getPolicyForClass(className: String): FilterPolicyWithReason {
+ // Use the implicit policy, if any.
+ getClassImplicitPolicy(className)?.let { return it }
+
+ return super.getPolicyForClass(className)
+ }
+
+ override fun getPolicyForMethod(
+ className: String,
+ methodName: String,
+ descriptor: String
+ ): FilterPolicyWithReason {
+ val fallback = super.getPolicyForMethod(className, methodName, descriptor)
+
+ // If the class is in the stub, then we need to put the private constructor in the stub too,
+ // to prevent the class from getting instantiated.
+ if (outermostFilter.getPolicyForClass(className).policy.needsInStub &&
+ !fallback.policy.needsInStub &&
+ (methodName == "<init>") && // Constructor?
+ (descriptor == "()V")) { // Has zero parameters?
+ classes.findMethod(className, methodName, descriptor)?.let { mn ->
+ if (isVisibilityPrivateOrPackagePrivate(mn.access)) {
+ return FilterPolicy.Stub.withReason("private constructor in stub class")
+ }
+ }
+ }
+
+ return fallback
+ }
+} \ No newline at end of file
diff --git a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/InMemoryOutputFilter.kt b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/InMemoryOutputFilter.kt
new file mode 100644
index 000000000000..f3551d49bd36
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/InMemoryOutputFilter.kt
@@ -0,0 +1,138 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.hoststubgen.filters
+
+import com.android.hoststubgen.UnknownApiException
+import com.android.hoststubgen.asm.ClassNodes
+import com.android.hoststubgen.asm.toHumanReadableClassName
+import com.android.hoststubgen.asm.toHumanReadableMethodName
+
+// TODO: Validate all input names.
+
+class InMemoryOutputFilter(
+ private val classes: ClassNodes,
+ fallback: OutputFilter,
+) : DelegatingFilter(fallback) {
+ private val mPolicies: MutableMap<String, FilterPolicyWithReason> = mutableMapOf()
+ private val mRenames: MutableMap<String, String> = mutableMapOf()
+ private val mNativeSubstitutionClasses: MutableMap<String, String> = mutableMapOf()
+ private val mClassLoadHooks: MutableMap<String, String> = mutableMapOf()
+
+ private fun getClassKey(className: String): String {
+ return className.toHumanReadableClassName()
+ }
+
+ private fun getFieldKey(className: String, fieldName: String): String {
+ return getClassKey(className) + "." + fieldName
+ }
+
+ private fun getMethodKey(className: String, methodName: String, signature: String): String {
+ return getClassKey(className) + "." + methodName + ";" + signature
+ }
+
+ override fun getPolicyForClass(className: String): FilterPolicyWithReason {
+ return mPolicies[getClassKey(className)] ?: super.getPolicyForClass(className)
+ }
+
+ private fun ensureClassExists(className: String) {
+ if (classes.findClass(className) == null) {
+ throw UnknownApiException("Unknown class $className")
+ }
+ }
+
+ private fun ensureFieldExists(className: String, fieldName: String) {
+ if (classes.findField(className, fieldName) == null) {
+ throw UnknownApiException("Unknown field $className.$fieldName")
+ }
+ }
+
+ private fun ensureMethodExists(
+ className: String,
+ methodName: String,
+ descriptor: String
+ ) {
+ if (classes.findMethod(className, methodName, descriptor) == null) {
+ throw UnknownApiException("Unknown method $className.$methodName$descriptor")
+ }
+ }
+
+ fun setPolicyForClass(className: String, policy: FilterPolicyWithReason) {
+ ensureClassExists(className)
+ mPolicies[getClassKey(className)] = policy
+ }
+
+ override fun getPolicyForField(className: String, fieldName: String): FilterPolicyWithReason {
+ return mPolicies[getFieldKey(className, fieldName)]
+ ?: super.getPolicyForField(className, fieldName)
+ }
+
+ fun setPolicyForField(className: String, fieldName: String, policy: FilterPolicyWithReason) {
+ ensureFieldExists(className, fieldName)
+ mPolicies[getFieldKey(className, fieldName)] = policy
+ }
+
+ override fun getPolicyForMethod(
+ className: String,
+ methodName: String,
+ descriptor: String,
+ ): FilterPolicyWithReason {
+ return mPolicies[getMethodKey(className, methodName, descriptor)]
+ ?: super.getPolicyForMethod(className, methodName, descriptor)
+ }
+
+ fun setPolicyForMethod(
+ className: String,
+ methodName: String,
+ descriptor: String,
+ policy: FilterPolicyWithReason,
+ ) {
+ ensureMethodExists(className, methodName, descriptor)
+ mPolicies[getMethodKey(className, methodName, descriptor)] = policy
+ }
+
+ override fun getRenameTo(className: String, methodName: String, descriptor: String): String? {
+ return mRenames[getMethodKey(className, methodName, descriptor)]
+ ?: super.getRenameTo(className, methodName, descriptor)
+ }
+
+ fun setRenameTo(className: String, methodName: String, descriptor: String, toName: String) {
+ ensureMethodExists(className, methodName, descriptor)
+ ensureMethodExists(className, toName, descriptor)
+ mRenames[getMethodKey(className, methodName, descriptor)] = toName
+ }
+
+ override fun getNativeSubstitutionClass(className: String): String? {
+ return mNativeSubstitutionClasses[getClassKey(className)]
+ ?: super.getNativeSubstitutionClass(className)
+ }
+
+ fun setNativeSubstitutionClass(from: String, to: String) {
+ ensureClassExists(from)
+
+ // Native substitute classes may be provided from other jars, so we can't do this check.
+ // ensureClassExists(to)
+ mNativeSubstitutionClasses[getClassKey(from)] = to.toHumanReadableClassName()
+ }
+
+ override fun getClassLoadHook(className: String): String? {
+ return mClassLoadHooks[getClassKey(className)]
+ ?: super.getClassLoadHook(className)
+ }
+
+ fun setClassLoadHook(className: String, methodName: String) {
+ mClassLoadHooks[getClassKey(className)] = methodName.toHumanReadableMethodName()
+ }
+} \ No newline at end of file
diff --git a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/KeepAllClassesFilter.kt b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/KeepAllClassesFilter.kt
new file mode 100644
index 000000000000..45dd38d10ef5
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/KeepAllClassesFilter.kt
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.hoststubgen.filters
+
+/**
+ * An [OutputFilter] that keeps all classes by default. (but none of its members)
+ *
+ * We're not currently using it, but using it *might* make certain things easier. For example, with
+ * this, all classes would at least be loadable.
+ */
+class KeepAllClassesFilter(fallback: OutputFilter) : DelegatingFilter(fallback) {
+ override fun getPolicyForClass(className: String): FilterPolicyWithReason {
+ // If the default visibility wouldn't keep it, change it to "keep".
+ val f = super.getPolicyForClass(className)
+ return f.promoteToKeep("keep-all-classes")
+ }
+} \ No newline at end of file
diff --git a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/OutputFilter.kt b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/OutputFilter.kt
new file mode 100644
index 000000000000..392ee4b81613
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/OutputFilter.kt
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.hoststubgen.filters
+
+/**
+ * Base class for "filters", which decides what APIs should go to the stub / impl jars.
+ */
+abstract class OutputFilter {
+ /**
+ * Filters are stacked over one another. This fields contains the "outermost" filter in a
+ * filter stack chain.
+ *
+ * Subclasses must use this filter to get a policy, when they need to infer a policy
+ * from the policy of another API.
+ *
+ * For example, [ClassWidePolicyPropagatingFilter] needs to check the policy of the enclosing
+ * class to propagate "class-wide" policies, but when it does so, it can't just use
+ * `this.getPolicyForClass()` because that wouldn't return policies decided by "outer"
+ * filters. Instead, it uses [outermostFilter.getPolicyForClass()].
+ *
+ * Note, [outermostFilter] can be itself, so make sure not to cause infinity recursions when
+ * using it.
+ */
+ open var outermostFilter: OutputFilter = this
+ get() = field
+ set(value) {
+ field = value
+ }
+
+ abstract fun getPolicyForClass(className: String): FilterPolicyWithReason
+
+ abstract fun getPolicyForField(className: String, fieldName: String): FilterPolicyWithReason
+
+ abstract fun getPolicyForMethod(
+ className: String,
+ methodName: String,
+ descriptor: String,
+ ): FilterPolicyWithReason
+
+ /**
+ * If a given method is a substitute-from method, return the substitute-to method name.
+ *
+ * The substitute-to and from methods must have the same signature, in the same class.
+ */
+ open fun getRenameTo(className: String, methodName: String, descriptor: String): String? {
+ return null
+ }
+
+ /**
+ * Return a "native substitution class" name for a given class.
+ *
+ * The result will be in a "human readable" form. (e.g. uses '.'s instead of '/'s)
+ *
+ * (which corresponds to @HostSideTestNativeSubstitutionClass of the standard annotations.)
+ */
+ open fun getNativeSubstitutionClass(className: String): String? {
+ return null
+ }
+
+ /**
+ * Return a "class load hook" method name for a given class.
+ *
+ * (which corresponds to @HostSideTestClassLoadHook of the standard annotations.)
+ */
+ open fun getClassLoadHook(className: String): String? {
+ return null
+ }
+} \ No newline at end of file
diff --git a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/StubIntersectingFilter.kt b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/StubIntersectingFilter.kt
new file mode 100644
index 000000000000..f92a0271d7c7
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/StubIntersectingFilter.kt
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.hoststubgen.filters
+
+import com.android.hoststubgen.HostStubGenErrors
+import com.android.hoststubgen.asm.ClassNodes
+
+private const val REASON = "demoted, not in intersect jars"
+
+/**
+ * An [OutputFilter] that will restrict what to put in stub to only what shows up in "intersecting
+ * jar" files.
+ *
+ * For example, if the Android public API stub jar is provided, then the HostStubGen's output
+ * stub will be restricted to public APIs.
+ */
+class StubIntersectingFilter(
+ private val errors: HostStubGenErrors,
+ /**
+ * If a class / field / method is not in any of these jars, then we will not put it in
+ * stub.
+ */
+ private val intersectingJars: Map<String, ClassNodes>,
+ fallback: OutputFilter,
+) : DelegatingFilter(fallback) {
+ private inline fun exists(predicate: (ClassNodes) -> Boolean): Boolean {
+ intersectingJars.forEach { entry ->
+ if (predicate(entry.value)) {
+ return true
+ }
+ }
+ return false
+ }
+
+ /**
+ * If [origPolicy] is less than "Stub", then return it as-is.
+ *
+ * Otherwise, call [inStubChecker] to see if the API is in any of [intersectingJars].
+ * If yes, then return [origPolicy] as-is. Otherwise, demote to "Keep".
+ */
+ private fun intersectWithStub(
+ origPolicy: FilterPolicyWithReason,
+ inStubChecker: () -> Boolean,
+ ): FilterPolicyWithReason {
+ if (origPolicy.policy.needsInStub) {
+ // Only check the stub jars, when the class is supposed to be in stub otherwise.
+ if (!inStubChecker()) {
+ return origPolicy.demoteToKeep(REASON)
+ }
+ }
+ return origPolicy
+ }
+
+ override fun getPolicyForClass(className: String): FilterPolicyWithReason {
+ return intersectWithStub(super.getPolicyForClass(className)) {
+ exists { classes -> classes.findClass(className) != null }
+ }
+ }
+
+ override fun getPolicyForField(
+ className: String,
+ fieldName: String
+ ): FilterPolicyWithReason {
+ return intersectWithStub(super.getPolicyForField(className, fieldName)) {
+ exists { classes -> classes.findField(className, fieldName) != null }
+ }
+ }
+
+ override fun getPolicyForMethod(
+ className: String,
+ methodName: String,
+ descriptor: String
+ ): FilterPolicyWithReason {
+ return intersectWithStub(super.getPolicyForMethod(className, methodName, descriptor)) {
+ exists { classes -> classes.findMethod(className, methodName, descriptor) != null }
+ }
+ }
+} \ No newline at end of file
diff --git a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/TextFileFilterPolicyParser.kt b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/TextFileFilterPolicyParser.kt
new file mode 100644
index 000000000000..46546e8b9491
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/TextFileFilterPolicyParser.kt
@@ -0,0 +1,213 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.hoststubgen.filters
+
+import com.android.hoststubgen.UserErrorException
+import com.android.hoststubgen.asm.ClassNodes
+import com.android.hoststubgen.log
+import com.android.hoststubgen.normalizeTextLine
+import com.android.hoststubgen.whitespaceRegex
+import org.objectweb.asm.Opcodes
+import org.objectweb.asm.tree.ClassNode
+import java.io.BufferedReader
+import java.io.FileReader
+import java.io.PrintWriter
+import java.util.Objects
+
+/**
+ * Print a class node as a "keep" policy.
+ */
+fun printAsTextPolicy(pw: PrintWriter, cn: ClassNode) {
+ pw.printf("class %s\t%s\n", cn.name, "keep")
+
+ for (f in cn.fields ?: emptyList()) {
+ pw.printf(" field %s\t%s\n", f.name, "keep")
+ }
+ for (m in cn.methods ?: emptyList()) {
+ pw.printf(" method %s\t%s\t%s\n", m.name, m.desc, "keep")
+ }
+}
+
+/** Return true if [access] is either public or protected. */
+private fun isVisible(access: Int): Boolean {
+ return (access and (Opcodes.ACC_PUBLIC or Opcodes.ACC_PROTECTED)) != 0
+}
+
+/**
+ * Exception for a parse error.
+ */
+private class ParseException : Exception, UserErrorException {
+ val hasSourceInfo: Boolean
+
+ constructor(message: String) : super(message) {
+ hasSourceInfo = false
+ }
+
+ constructor(message: String, file: String, line: Int) :
+ super("$message in file $file line $line") {
+ hasSourceInfo = true
+ }
+
+ fun withSourceInfo(filename: String, lineNo: Int): ParseException {
+ if (hasSourceInfo) {
+ return this // Already has source information.
+ } else {
+ return ParseException(this.message ?: "", filename, lineNo)
+ }
+ }
+}
+
+private const val FILTER_REASON = "file-override"
+
+/**
+ * Read a given "policy" file and return as an [OutputFilter]
+ */
+fun createFilterFromTextPolicyFile(
+ filename: String,
+ classes: ClassNodes,
+ fallback: OutputFilter,
+ ): OutputFilter {
+ log.i("Loading offloaded annotations from $filename ...")
+ log.withIndent {
+ val ret = InMemoryOutputFilter(classes, fallback)
+
+ var lineNo = 0
+
+ try {
+ BufferedReader(FileReader(filename)).use { reader ->
+ var className = ""
+
+ while (true) {
+ var line = reader.readLine()
+ if (line == null) {
+ break
+ }
+ lineNo++
+
+ line = normalizeTextLine(line)
+
+ if (line.isEmpty()) {
+ continue // skip empty lines.
+ }
+
+ val fields = line.split(whitespaceRegex).toTypedArray()
+ when (fields[0].lowercase()) {
+ "c", "class" -> {
+ if (fields.size < 3) {
+ throw ParseException("Class ('c') expects 2 fields.")
+ }
+ className = fields[1]
+ if (fields[2].startsWith("!")) {
+ // It's a native-substitution.
+ val toClass = fields[2].substring(1)
+ ret.setNativeSubstitutionClass(className, toClass)
+ } else if (fields[2].startsWith("~")) {
+ // It's a class-load hook
+ val callback = fields[2].substring(1)
+ ret.setClassLoadHook(className, callback)
+ } else {
+ val policy = parsePolicy(fields[2])
+ if (!policy.isUsableWithClasses) {
+ throw ParseException("Class can't have policy '$policy'")
+ }
+ Objects.requireNonNull(className)
+
+ // TODO: Duplicate check, etc
+ ret.setPolicyForClass(className, policy.withReason(FILTER_REASON))
+ }
+ }
+
+ "f", "field" -> {
+ if (fields.size < 3) {
+ throw ParseException("Field ('f') expects 2 fields.")
+ }
+ val name = fields[1]
+ val policy = parsePolicy(fields[2])
+ if (!policy.isUsableWithFields) {
+ throw ParseException("Field can't have policy '$policy'")
+ }
+ Objects.requireNonNull(className)
+
+ // TODO: Duplicate check, etc
+ ret.setPolicyForField(className, name, policy.withReason(FILTER_REASON))
+ }
+
+ "m", "method" -> {
+ if (fields.size < 4) {
+ throw ParseException("Method ('m') expects 3 fields.")
+ }
+ val name = fields[1]
+ val signature = fields[2]
+ val policy = parsePolicy(fields[3])
+
+ if (!policy.isUsableWithMethods) {
+ throw ParseException("Method can't have policy '$policy'")
+ }
+
+ Objects.requireNonNull(className)
+
+ ret.setPolicyForMethod(className, name, signature,
+ policy.withReason(FILTER_REASON))
+ if (policy.isSubstitute) {
+ val fromName = fields[3].substring(1)
+
+ if (fromName == name) {
+ throw ParseException(
+ "Substitution must have a different name")
+ }
+
+ // Set the policy for the "from" method.
+ ret.setPolicyForMethod(className, fromName, signature,
+ policy.getSubstitutionBasePolicy()
+ .withReason(FILTER_REASON))
+
+ // Keep "from" -> "to" mapping.
+ ret.setRenameTo(className, fromName, signature, name)
+ }
+ }
+
+ else -> {
+ throw ParseException("Unknown directive \"${fields[0]}\"")
+ }
+ }
+ }
+ }
+ } catch (e: ParseException) {
+ throw e.withSourceInfo(filename, lineNo)
+ }
+ return ret
+ }
+}
+
+private fun parsePolicy(s: String): FilterPolicy {
+ return when (s.lowercase()) {
+ "s", "stub" -> FilterPolicy.Stub
+ "k", "keep" -> FilterPolicy.Keep
+ "t", "throw" -> FilterPolicy.Throw
+ "r", "remove" -> FilterPolicy.Remove
+ "sc", "stubclass" -> FilterPolicy.StubClass
+ "kc", "keepclass" -> FilterPolicy.KeepClass
+ else -> {
+ if (s.startsWith("@")) {
+ FilterPolicy.SubstituteAndStub
+ } else if (s.startsWith("%")) {
+ FilterPolicy.SubstituteAndKeep
+ } else {
+ throw ParseException("Invalid policy \"$s\"")
+ }
+ }
+ }
+}
diff --git a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/visitors/BaseAdapter.kt b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/visitors/BaseAdapter.kt
new file mode 100644
index 000000000000..3cf9a1d7fb82
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/visitors/BaseAdapter.kt
@@ -0,0 +1,252 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.hoststubgen.visitors
+
+import com.android.hoststubgen.HostStubGenErrors
+import com.android.hoststubgen.asm.ClassNodes
+import com.android.hoststubgen.asm.getPackageNameFromClassName
+import com.android.hoststubgen.asm.resolveClassName
+import com.android.hoststubgen.asm.toJvmClassName
+import com.android.hoststubgen.filters.FilterPolicy
+import com.android.hoststubgen.filters.FilterPolicyWithReason
+import com.android.hoststubgen.filters.OutputFilter
+import com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+import com.android.hoststubgen.hosthelper.HostStubGenProcessedStubClass
+import com.android.hoststubgen.log
+import org.objectweb.asm.ClassVisitor
+import org.objectweb.asm.FieldVisitor
+import org.objectweb.asm.MethodVisitor
+import org.objectweb.asm.Opcodes
+import org.objectweb.asm.util.TraceClassVisitor
+import java.io.PrintWriter
+
+val OPCODE_VERSION = Opcodes.ASM9
+
+abstract class BaseAdapter (
+ protected val classes: ClassNodes,
+ nextVisitor: ClassVisitor,
+ protected val filter: OutputFilter,
+ protected val options: Options,
+) : ClassVisitor(OPCODE_VERSION, nextVisitor) {
+
+ /**
+ * Options to control the behavior.
+ */
+ data class Options (
+ val errors: HostStubGenErrors,
+ val enablePreTrace: Boolean,
+ val enablePostTrace: Boolean,
+ val enableMethodLogging: Boolean,
+ val enableNonStubMethodCallDetection: Boolean,
+ )
+
+ protected lateinit var currentPackageName: String
+ protected lateinit var currentClassName: String
+ protected var nativeSubstitutionClass: String? = null
+ protected lateinit var classPolicy: FilterPolicyWithReason
+
+ /**
+ * Return whether an item with a given policy should be included in the output.
+ */
+ protected abstract fun shouldEmit(policy: FilterPolicy): Boolean
+
+ override fun visit(
+ version: Int,
+ access: Int,
+ name: String,
+ signature: String?,
+ superName: String?,
+ interfaces: Array<String>,
+ ) {
+ super.visit(version, access, name, signature, superName, interfaces)
+ currentClassName = name
+ currentPackageName = getPackageNameFromClassName(name)
+ classPolicy = filter.getPolicyForClass(currentClassName)
+
+ log.d("[%s] visit: %s (package: %s)", this.javaClass.simpleName, name, currentPackageName)
+ log.indent()
+ log.v("Emitting class: %s", name)
+ log.indent()
+
+ filter.getNativeSubstitutionClass(currentClassName)?.let { className ->
+ val fullClassName = resolveClassName(className, currentPackageName).toJvmClassName()
+ log.d(" NativeSubstitutionClass: $fullClassName")
+ if (classes.findClass(fullClassName) == null) {
+ log.w("Native substitution class $fullClassName not found. Class must be " +
+ "available at runtime.")
+ } else {
+ // If the class exists, it must have a KeepClass policy.
+ if (filter.getPolicyForClass(fullClassName).policy != FilterPolicy.KeepClass) {
+ // TODO: Use real annotation name.
+ options.errors.onErrorFound(
+ "Native substitution class $fullClassName should have @Keep.")
+ }
+ }
+
+ nativeSubstitutionClass = fullClassName
+ }
+ // Inject annotations to generated classes.
+ if (classPolicy.policy.needsInStub) {
+ visitAnnotation(HostStubGenProcessedStubClass.CLASS_DESCRIPTOR, true)
+ }
+ if (classPolicy.policy.needsInImpl) {
+ visitAnnotation(HostStubGenProcessedKeepClass.CLASS_DESCRIPTOR, true)
+ }
+ }
+
+ override fun visitEnd() {
+ log.unindent()
+ log.unindent()
+ super.visitEnd()
+ }
+
+ var skipMemberModificationNestCount = 0
+
+ /**
+ * This method allows writing class members without any modifications.
+ */
+ protected inline fun writeRawMembers(callback: () -> Unit) {
+ skipMemberModificationNestCount++
+ try {
+ callback()
+ } finally {
+ skipMemberModificationNestCount--
+ }
+ }
+
+ override fun visitField(
+ access: Int,
+ name: String,
+ descriptor: String,
+ signature: String?,
+ value: Any?,
+ ): FieldVisitor? {
+ if (skipMemberModificationNestCount > 0) {
+ return super.visitField(access, name, descriptor, signature, value)
+ }
+ val policy = filter.getPolicyForField(currentClassName, name)
+ log.d("visitField: %s %s [%x] Policy: %s", name, descriptor, access, policy)
+
+ log.withIndent {
+ if (!shouldEmit(policy.policy)) {
+ log.d("Removing %s %s", name, policy)
+ return null
+ }
+
+ log.v("Emitting field: %s %s %s", name, descriptor, policy)
+ return super.visitField(access, name, descriptor, signature, value)
+ }
+ }
+
+ override fun visitMethod(
+ access: Int,
+ name: String,
+ descriptor: String,
+ signature: String?,
+ exceptions: Array<String>?,
+ ): MethodVisitor? {
+ if (skipMemberModificationNestCount > 0) {
+ return super.visitMethod(access, name, descriptor, signature, exceptions)
+ }
+ val p = filter.getPolicyForMethod(currentClassName, name, descriptor)
+ log.d("visitMethod: %s%s [%x] [%s] Policy: %s", name, descriptor, access, signature, p)
+
+ log.withIndent {
+ // If it's a substitute-to method, then skip.
+ val policy = filter.getPolicyForMethod(currentClassName, name, descriptor)
+ if (policy.policy.isSubstitute) {
+ log.d("Skipping %s%s %s", name, descriptor, policy)
+ return null
+ }
+ if (!shouldEmit(p.policy)) {
+ log.d("Removing %s%s %s", name, descriptor, policy)
+ return null
+ }
+
+ // Maybe rename the method.
+ val newName: String
+ val substituteTo = filter.getRenameTo(currentClassName, name, descriptor)
+ if (substituteTo != null) {
+ newName = substituteTo
+ log.v("Emitting %s.%s%s as %s %s", currentClassName, name, descriptor,
+ newName, policy)
+ } else {
+ log.v("Emitting method: %s%s %s", name, descriptor, policy)
+ newName = name
+ }
+
+ // Let subclass update the flag.
+ // But note, we only use it when calling the super's method,
+ // but not for visitMethodInner(), beucase when subclass wants to change access,
+ // it can do so inside visitMethodInner().
+ val newAccess = updateAccessFlags(access, name, descriptor)
+
+ return visitMethodInner(access, newName, descriptor, signature, exceptions, policy,
+ super.visitMethod(newAccess, newName, descriptor, signature, exceptions))
+ }
+ }
+
+ open fun updateAccessFlags(
+ access: Int,
+ name: String,
+ descriptor: String,
+ ): Int {
+ return access
+ }
+
+ abstract fun visitMethodInner(
+ access: Int,
+ name: String,
+ descriptor: String,
+ signature: String?,
+ exceptions: Array<String>?,
+ policy: FilterPolicyWithReason,
+ superVisitor: MethodVisitor?,
+ ): MethodVisitor?
+
+ companion object {
+ fun getVisitor(
+ classes: ClassNodes,
+ nextVisitor: ClassVisitor,
+ filter: OutputFilter,
+ forImpl: Boolean,
+ options: Options,
+ ): ClassVisitor {
+ var next = nextVisitor
+
+ val verbosePrinter = PrintWriter(log.getVerbosePrintStream())
+
+ // TODO: This doesn't work yet.
+
+ // Inject TraceClassVisitor for debugging.
+ if (options.enablePostTrace) {
+ next = TraceClassVisitor(next, verbosePrinter)
+ }
+ var ret: ClassVisitor
+ if (forImpl) {
+ ret = ImplGeneratingAdapter(classes, next, filter, options)
+ } else {
+ ret = StubGeneratingAdapter(classes, next, filter, options)
+ }
+
+ // Inject TraceClassVisitor for debugging.
+ if (options.enablePreTrace) {
+ ret = TraceClassVisitor(ret, verbosePrinter)
+ }
+ return ret
+ }
+ }
+} \ No newline at end of file
diff --git a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/visitors/BodyReplacingMethodVisitor.kt b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/visitors/BodyReplacingMethodVisitor.kt
new file mode 100644
index 000000000000..8250412b3717
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/visitors/BodyReplacingMethodVisitor.kt
@@ -0,0 +1,354 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.hoststubgen.visitors
+
+import org.objectweb.asm.AnnotationVisitor
+import org.objectweb.asm.Attribute
+import org.objectweb.asm.Handle
+import org.objectweb.asm.Label
+import org.objectweb.asm.MethodVisitor
+import org.objectweb.asm.Opcodes
+import org.objectweb.asm.TypePath
+
+/**
+ * A method visitor that removes everything from method body.
+ *
+ * To inject a method body, override [visitCode] and create the opcodes there.
+ */
+abstract class BodyReplacingMethodVisitor(
+ access: Int,
+ name: String,
+ descriptor: String,
+ signature: String?,
+ exceptions: Array<String>?,
+ next: MethodVisitor?,
+) : MethodVisitor(OPCODE_VERSION, next) {
+ val isVoid: Boolean
+ val isStatic: Boolean
+
+ init {
+ isVoid = descriptor.endsWith(")V")
+ isStatic = access and Opcodes.ACC_STATIC != 0
+ }
+
+ // Following methods are for things that we need to keep.
+ // Since they're all calling the super method, we can just remove them, but we keep them
+ // just to clarify what we're keeping.
+
+ final override fun visitParameter(
+ name: String?,
+ access: Int
+ ) {
+ super.visitParameter(name, access)
+ }
+
+ final override fun visitAnnotationDefault(): AnnotationVisitor? {
+ return super.visitAnnotationDefault()
+ }
+
+ final override fun visitAnnotation(
+ descriptor: String?,
+ visible: Boolean
+ ): AnnotationVisitor? {
+ return super.visitAnnotation(descriptor, visible)
+ }
+
+ final override fun visitTypeAnnotation(
+ typeRef: Int,
+ typePath: TypePath?,
+ descriptor: String?,
+ visible: Boolean
+ ): AnnotationVisitor? {
+ return super.visitTypeAnnotation(typeRef, typePath, descriptor, visible)
+ }
+
+ final override fun visitAnnotableParameterCount(
+ parameterCount: Int,
+ visible: Boolean
+ ) {
+ super.visitAnnotableParameterCount(parameterCount, visible)
+ }
+
+ final override fun visitParameterAnnotation(
+ parameter: Int,
+ descriptor: String?,
+ visible: Boolean
+ ): AnnotationVisitor? {
+ return super.visitParameterAnnotation(parameter, descriptor, visible)
+ }
+
+ final override fun visitAttribute(attribute: Attribute?) {
+ super.visitAttribute(attribute)
+ }
+
+ override fun visitEnd() {
+ super.visitEnd()
+ }
+
+ /**
+ * Control when to emit the code. We use this to ignore all visitXxx method calls caused by
+ * the original method, so we'll remove all the original code.
+ *
+ * Only when visitXxx methods are called from [emitNewCode], we pass-through to the base class,
+ * so the body will be generated.
+ *
+ * (See also https://asm.ow2.io/asm4-guide.pdf section 3.2.1 about the MethovVisitor
+ * call order.)
+ */
+ var emitCode = false
+
+ final override fun visitCode() {
+ super.visitCode()
+
+ try {
+ emitCode = true
+
+ emitNewCode()
+ } finally {
+ emitCode = false
+ }
+ }
+
+ /**
+ * Subclass must implement it and emit code, and call [visitMaxs] at the end.
+ */
+ abstract fun emitNewCode()
+
+ final override fun visitMaxs(
+ maxStack: Int,
+ maxLocals: Int
+ ) {
+ if (emitCode) {
+ super.visitMaxs(maxStack, maxLocals)
+ }
+ }
+
+ // Following methods are called inside a method body, and we don't want to
+ // emit any of them, so they are all no-op.
+
+ final override fun visitFrame(
+ type: Int,
+ numLocal: Int,
+ local: Array<out Any>?,
+ numStack: Int,
+ stack: Array<out Any>?
+ ) {
+ if (emitCode) {
+ super.visitFrame(type, numLocal, local, numStack, stack)
+ }
+ }
+
+ final override fun visitInsn(opcode: Int) {
+ if (emitCode) {
+ super.visitInsn(opcode)
+ }
+ }
+
+ final override fun visitIntInsn(
+ opcode: Int,
+ operand: Int
+ ) {
+ if (emitCode) {
+ super.visitIntInsn(opcode, operand)
+ }
+ }
+
+ final override fun visitVarInsn(
+ opcode: Int,
+ varIndex: Int
+ ) {
+ if (emitCode) {
+ super.visitVarInsn(opcode, varIndex)
+ }
+ }
+
+ final override fun visitTypeInsn(
+ opcode: Int,
+ type: String?
+ ) {
+ if (emitCode) {
+ super.visitTypeInsn(opcode, type)
+ }
+ }
+
+ final override fun visitFieldInsn(
+ opcode: Int,
+ owner: String?,
+ name: String?,
+ descriptor: String?
+ ) {
+ if (emitCode) {
+ super.visitFieldInsn(opcode, owner, name, descriptor)
+ }
+ }
+
+ final override fun visitMethodInsn(
+ opcode: Int,
+ owner: String?,
+ name: String?,
+ descriptor: String?,
+ isInterface: Boolean
+ ) {
+ if (emitCode) {
+ super.visitMethodInsn(opcode, owner, name, descriptor, isInterface)
+ }
+ }
+
+ final override fun visitInvokeDynamicInsn(
+ name: String?,
+ descriptor: String?,
+ bootstrapMethodHandle: Handle?,
+ vararg bootstrapMethodArguments: Any?
+ ) {
+ if (emitCode) {
+ super.visitInvokeDynamicInsn(name, descriptor, bootstrapMethodHandle,
+ *bootstrapMethodArguments)
+ }
+ }
+
+ final override fun visitJumpInsn(
+ opcode: Int,
+ label: Label?
+ ) {
+ if (emitCode) {
+ super.visitJumpInsn(opcode, label)
+ }
+ }
+
+ final override fun visitLabel(label: Label?) {
+ if (emitCode) {
+ super.visitLabel(label)
+ }
+ }
+
+ final override fun visitLdcInsn(value: Any?) {
+ if (emitCode) {
+ super.visitLdcInsn(value)
+ }
+ }
+
+ final override fun visitIincInsn(
+ varIndex: Int,
+ increment: Int
+ ) {
+ if (emitCode) {
+ super.visitIincInsn(varIndex, increment)
+ }
+ }
+
+ final override fun visitTableSwitchInsn(
+ min: Int,
+ max: Int,
+ dflt: Label?,
+ vararg labels: Label?
+ ) {
+ if (emitCode) {
+ super.visitTableSwitchInsn(min, max, dflt, *labels)
+ }
+ }
+
+ final override fun visitLookupSwitchInsn(
+ dflt: Label?,
+ keys: IntArray?,
+ labels: Array<out Label>?
+ ) {
+ if (emitCode) {
+ super.visitLookupSwitchInsn(dflt, keys, labels)
+ }
+ }
+
+ final override fun visitMultiANewArrayInsn(
+ descriptor: String?,
+ numDimensions: Int
+ ) {
+ if (emitCode) {
+ super.visitMultiANewArrayInsn(descriptor, numDimensions)
+ }
+ }
+
+ final override fun visitInsnAnnotation(
+ typeRef: Int,
+ typePath: TypePath?,
+ descriptor: String?,
+ visible: Boolean
+ ): AnnotationVisitor? {
+ if (emitCode) {
+ return super.visitInsnAnnotation(typeRef, typePath, descriptor, visible)
+ }
+ return null
+ }
+
+ final override fun visitTryCatchBlock(
+ start: Label?,
+ end: Label?,
+ handler: Label?,
+ type: String?
+ ) {
+ if (emitCode) {
+ super.visitTryCatchBlock(start, end, handler, type)
+ }
+ }
+
+ final override fun visitTryCatchAnnotation(
+ typeRef: Int,
+ typePath: TypePath?,
+ descriptor: String?,
+ visible: Boolean
+ ): AnnotationVisitor? {
+ if (emitCode) {
+ return super.visitTryCatchAnnotation(typeRef, typePath, descriptor, visible)
+ }
+ return null
+ }
+
+ final override fun visitLocalVariable(
+ name: String?,
+ descriptor: String?,
+ signature: String?,
+ start: Label?,
+ end: Label?,
+ index: Int
+ ) {
+ if (emitCode) {
+ super.visitLocalVariable(name, descriptor, signature, start, end, index)
+ }
+ }
+
+ final override fun visitLocalVariableAnnotation(
+ typeRef: Int,
+ typePath: TypePath?,
+ start: Array<out Label>?,
+ end: Array<out Label>?,
+ index: IntArray?,
+ descriptor: String?,
+ visible: Boolean
+ ): AnnotationVisitor? {
+ if (emitCode) {
+ return super.visitLocalVariableAnnotation(
+ typeRef, typePath, start, end, index, descriptor, visible)
+ }
+ return null
+ }
+
+ final override fun visitLineNumber(
+ line: Int,
+ start: Label?
+ ) {
+ if (emitCode) {
+ super.visitLineNumber(line, start)
+ }
+ }
+}
diff --git a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/visitors/ImplGeneratingAdapter.kt b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/visitors/ImplGeneratingAdapter.kt
new file mode 100644
index 000000000000..ac068861ec8d
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/visitors/ImplGeneratingAdapter.kt
@@ -0,0 +1,370 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.hoststubgen.visitors
+
+import com.android.hoststubgen.asm.CLASS_INITIALIZER_DESC
+import com.android.hoststubgen.asm.CLASS_INITIALIZER_NAME
+import com.android.hoststubgen.asm.ClassNodes
+import com.android.hoststubgen.asm.isVisibilityPrivateOrPackagePrivate
+import com.android.hoststubgen.asm.writeByteCodeToPushArguments
+import com.android.hoststubgen.asm.writeByteCodeToReturn
+import com.android.hoststubgen.filters.FilterPolicy
+import com.android.hoststubgen.filters.FilterPolicyWithReason
+import com.android.hoststubgen.filters.OutputFilter
+import com.android.hoststubgen.hosthelper.HostTestUtils
+import com.android.hoststubgen.log
+import org.objectweb.asm.ClassVisitor
+import org.objectweb.asm.MethodVisitor
+import org.objectweb.asm.Opcodes
+import org.objectweb.asm.Type
+
+/**
+ * An adapter that generates the "impl" class file from an input class file.
+ */
+class ImplGeneratingAdapter(
+ classes: ClassNodes,
+ nextVisitor: ClassVisitor,
+ filter: OutputFilter,
+ options: Options,
+) : BaseAdapter(classes, nextVisitor, filter, options) {
+
+ override fun shouldEmit(policy: FilterPolicy): Boolean {
+ return policy.needsInImpl
+ }
+
+ private var classLoadHookMethod: String? = null
+
+ override fun visit(
+ version: Int,
+ access: Int,
+ name: String,
+ signature: String?,
+ superName: String?,
+ interfaces: Array<String>
+ ) {
+ super.visit(version, access, name, signature, superName, interfaces)
+
+ classLoadHookMethod = filter.getClassLoadHook(currentClassName)
+
+ // classLoadHookMethod is non-null, then we need to inject code to call it
+ // in the class initializer.
+ // If the target class already has a class initializer, then we need to inject code to it.
+ // Otherwise, we need to create one.
+
+ classLoadHookMethod?.let { callback ->
+ log.d(" ClassLoadHook: $callback")
+ if (!classes.hasClassInitializer(currentClassName)) {
+ injectClassLoadHook(callback)
+ }
+ }
+ }
+
+ private fun injectClassLoadHook(callback: String) {
+ writeRawMembers {
+ // Create a class initializer to call onClassLoaded().
+ // Each class can only have at most one class initializer, but the base class
+ // StaticInitMerger will merge it with the existing one, if any.
+ visitMethod(
+ Opcodes.ACC_PRIVATE or Opcodes.ACC_STATIC,
+ "<clinit>",
+ "()V",
+ null,
+ null
+ )!!.let { mv ->
+ // Method prologue
+ mv.visitCode()
+
+ writeClassLoadHookCall(mv)
+ mv.visitInsn(Opcodes.RETURN)
+
+ // Method epilogue
+ mv.visitMaxs(0, 0)
+ mv.visitEnd()
+ }
+ }
+ }
+
+ private fun writeClassLoadHookCall(mv: MethodVisitor) {
+ // First argument: the class type.
+ mv.visitLdcInsn(Type.getType("L" + currentClassName + ";"))
+
+ // Second argument: method name
+ mv.visitLdcInsn(classLoadHookMethod)
+
+ // Call HostTestUtils.onClassLoaded().
+ mv.visitMethodInsn(
+ Opcodes.INVOKESTATIC,
+ HostTestUtils.CLASS_INTERNAL_NAME,
+ "onClassLoaded",
+ "(Ljava/lang/Class;Ljava/lang/String;)V",
+ false
+ )
+ }
+
+ override fun updateAccessFlags(
+ access: Int,
+ name: String,
+ descriptor: String,
+ ): Int {
+ if ((access and Opcodes.ACC_NATIVE) != 0 && nativeSubstitutionClass != null) {
+ return access and Opcodes.ACC_NATIVE.inv()
+ }
+ return access
+ }
+
+ override fun visitMethodInner(
+ access: Int,
+ name: String,
+ descriptor: String,
+ signature: String?,
+ exceptions: Array<String>?,
+ policy: FilterPolicyWithReason,
+ superVisitor: MethodVisitor?,
+ ): MethodVisitor? {
+ // Inject method log, if needed.
+ var innerVisitor = superVisitor
+
+ // If method logging is enabled, inject call to the logging method.
+ if (options.enableMethodLogging) {
+ innerVisitor = LogInjectingMethodAdapter(
+ access,
+ name,
+ descriptor,
+ signature,
+ exceptions,
+ innerVisitor,
+ )
+ }
+
+ // If this class already has a class initializer and a class load hook is needed, then
+ // we inject code.
+ if (classLoadHookMethod != null &&
+ name == CLASS_INITIALIZER_NAME &&
+ descriptor == CLASS_INITIALIZER_DESC) {
+ innerVisitor = ClassLoadHookInjectingMethodAdapter(
+ access,
+ name,
+ descriptor,
+ signature,
+ exceptions,
+ innerVisitor,
+ )
+ }
+
+ // If non-stub method call detection is enabled, then inject a call to the checker.
+ if (options.enableNonStubMethodCallDetection && doesMethodNeedNonStubCallCheck(
+ access, name, descriptor, policy) ) {
+ innerVisitor = NonStubMethodCallDetectingAdapter(
+ access,
+ name,
+ descriptor,
+ signature,
+ exceptions,
+ innerVisitor,
+ )
+ }
+
+ log.withIndent {
+ if ((access and Opcodes.ACC_NATIVE) != 0 && nativeSubstitutionClass != null) {
+ log.v("Rewriting native method...")
+ return NativeSubstitutingMethodAdapter(
+ access, name, descriptor, signature, exceptions, innerVisitor)
+ }
+ if (policy.policy == FilterPolicy.Throw) {
+ log.v("Making method throw...")
+ return ThrowingMethodAdapter(
+ access, name, descriptor, signature, exceptions, innerVisitor)
+ }
+ }
+
+ return innerVisitor
+ }
+
+ fun doesMethodNeedNonStubCallCheck(
+ access: Int,
+ name: String,
+ descriptor: String,
+ policy: FilterPolicyWithReason,
+ ): Boolean {
+ // If a method is in the stub, then no need to check.
+ if (policy.policy.needsInStub) {
+ return false
+ }
+ // If a method is private or package-private, no need to check.
+ // Technically test code can use framework package name, so it's a bit too lenient.
+ if (isVisibilityPrivateOrPackagePrivate(access)) {
+ return false
+ }
+ // TODO: If the method overrides a method that's accessible by tests, then we shouldn't
+ // do the check. (e.g. overrides a stub method or java standard method.)
+
+ return true
+ }
+
+ /**
+ * A method adapter that replaces the method body with a HostTestUtils.onThrowMethodCalled()
+ * call.
+ */
+ private inner class ThrowingMethodAdapter(
+ access: Int,
+ val name: String,
+ descriptor: String,
+ signature: String?,
+ exceptions: Array<String>?,
+ next: MethodVisitor?
+ ) : BodyReplacingMethodVisitor(access, name, descriptor, signature, exceptions, next) {
+ override fun emitNewCode() {
+ visitMethodInsn(Opcodes.INVOKESTATIC,
+ HostTestUtils.CLASS_INTERNAL_NAME,
+ "onThrowMethodCalled",
+ "()V",
+ false)
+
+ // We still need a RETURN opcode for the return type.
+ // For now, let's just inject a `throw`.
+ visitTypeInsn(Opcodes.NEW, "java/lang/RuntimeException")
+ visitInsn(Opcodes.DUP)
+ visitLdcInsn("Unreachable")
+ visitMethodInsn(Opcodes.INVOKESPECIAL, "java/lang/RuntimeException",
+ "<init>", "(Ljava/lang/String;)V", false)
+ visitInsn(Opcodes.ATHROW)
+
+ // visitMaxs(3, if (isStatic) 0 else 1)
+ visitMaxs(0, 0) // We let ASM figure them out.
+ }
+ }
+
+ /**
+ * A method adapter that replaces a native method call with a call to the "native substitution"
+ * class.
+ */
+ private inner class NativeSubstitutingMethodAdapter(
+ access: Int,
+ private val name: String,
+ private val descriptor: String,
+ signature: String?,
+ exceptions: Array<String>?,
+ next: MethodVisitor?
+ ) : MethodVisitor(OPCODE_VERSION, next) {
+ override fun visitCode() {
+ super.visitCode()
+
+ throw RuntimeException("NativeSubstitutingMethodVisitor should be called on " +
+ " native method, where visitCode() shouldn't be called.")
+ }
+
+ override fun visitEnd() {
+ writeByteCodeToPushArguments(descriptor, this)
+
+ visitMethodInsn(Opcodes.INVOKESTATIC,
+ nativeSubstitutionClass,
+ name,
+ descriptor,
+ false)
+
+ writeByteCodeToReturn(descriptor, this)
+
+ visitMaxs(99, 0) // We let ASM figure them out.
+ super.visitEnd()
+ }
+ }
+
+ /**
+ * A method adapter that injects a call to HostTestUtils.logMethodCall() to every method.
+ *
+ * Note, when the target method is a constructor, it may contain calls to `super(...)` or
+ * `this(...)`. The logging code will be injected *before* such calls.
+ */
+ private inner class LogInjectingMethodAdapter(
+ access: Int,
+ val name: String,
+ val descriptor: String,
+ signature: String?,
+ exceptions: Array<String>?,
+ next: MethodVisitor?
+ ) : MethodVisitor(OPCODE_VERSION, next) {
+ override fun visitCode() {
+ super.visitCode()
+ visitLdcInsn(currentClassName)
+ visitLdcInsn(name)
+ visitLdcInsn(descriptor)
+ visitMethodInsn(Opcodes.INVOKESTATIC,
+ HostTestUtils.CLASS_INTERNAL_NAME,
+ "logMethodCall",
+ "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V",
+ false)
+ }
+ }
+
+ /**
+ * Inject a class load hook call.
+ */
+ private inner class ClassLoadHookInjectingMethodAdapter(
+ access: Int,
+ val name: String,
+ val descriptor: String,
+ signature: String?,
+ exceptions: Array<String>?,
+ next: MethodVisitor?
+ ) : MethodVisitor(OPCODE_VERSION, next) {
+ override fun visitCode() {
+ super.visitCode()
+
+ writeClassLoadHookCall(this)
+ }
+ }
+
+ /**
+ * A method adapter that detects calls to non-stub methods.
+ */
+ private inner class NonStubMethodCallDetectingAdapter(
+ access: Int,
+ val name: String,
+ val descriptor: String,
+ signature: String?,
+ exceptions: Array<String>?,
+ next: MethodVisitor?
+ ) : MethodVisitor(OPCODE_VERSION, next) {
+ override fun visitCode() {
+ super.visitCode()
+
+ // First three arguments to HostTestUtils.onNonStubMethodCalled().
+ visitLdcInsn(currentClassName)
+ visitLdcInsn(name)
+ visitLdcInsn(descriptor)
+
+ // Call: HostTestUtils.getStackWalker().getCallerClass().
+ // This push the caller Class in the stack.
+ visitMethodInsn(Opcodes.INVOKESTATIC,
+ HostTestUtils.CLASS_INTERNAL_NAME,
+ "getStackWalker",
+ "()Ljava/lang/StackWalker;",
+ false)
+ visitMethodInsn(Opcodes.INVOKEVIRTUAL,
+ "java/lang/StackWalker",
+ "getCallerClass",
+ "()Ljava/lang/Class;",
+ false)
+
+ // Then call onNonStubMethodCalled().
+ visitMethodInsn(Opcodes.INVOKESTATIC,
+ HostTestUtils.CLASS_INTERNAL_NAME,
+ "onNonStubMethodCalled",
+ "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Class;)V",
+ false)
+ }
+ }
+} \ No newline at end of file
diff --git a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/visitors/StubGeneratingAdapter.kt b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/visitors/StubGeneratingAdapter.kt
new file mode 100644
index 000000000000..37e2a888969d
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/visitors/StubGeneratingAdapter.kt
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.hoststubgen.visitors
+
+import com.android.hoststubgen.asm.ClassNodes
+import com.android.hoststubgen.filters.FilterPolicy
+import com.android.hoststubgen.filters.FilterPolicyWithReason
+import com.android.hoststubgen.filters.OutputFilter
+import com.android.hoststubgen.log
+import org.objectweb.asm.ClassVisitor
+import org.objectweb.asm.MethodVisitor
+import org.objectweb.asm.Opcodes
+
+/**
+ * An adapter that generates the "impl" class file from an input class file.
+ */
+class StubGeneratingAdapter(
+ classes: ClassNodes,
+ nextVisitor: ClassVisitor,
+ filter: OutputFilter,
+ options: Options,
+) : BaseAdapter(classes, nextVisitor, filter, options) {
+
+ override fun shouldEmit(policy: FilterPolicy): Boolean {
+ return policy.needsInStub
+ }
+
+ override fun visitMethodInner(
+ access: Int,
+ name: String,
+ descriptor: String,
+ signature: String?,
+ exceptions: Array<String>?,
+ policy: FilterPolicyWithReason,
+ superVisitor: MethodVisitor?,
+ ): MethodVisitor? {
+ return StubMethodVisitor(access, name, descriptor, signature, exceptions, superVisitor)
+ }
+
+ private inner class StubMethodVisitor(
+ access: Int,
+ val name: String,
+ descriptor: String,
+ signature: String?,
+ exceptions: Array<String>?,
+ next: MethodVisitor?
+ ) : BodyReplacingMethodVisitor(access, name, descriptor, signature, exceptions, next) {
+ override fun emitNewCode() {
+ log.d(" Generating stub method for $currentClassName.$name")
+
+ // Inject the following code:
+ // throw new RuntimeException("Stub!");
+
+ /*
+ NEW java/lang/RuntimeException
+ DUP
+ LDC "not supported on host side"
+ INVOKESPECIAL java/lang/RuntimeException.<init> (Ljava/lang/String;)V
+ ATHROW
+ MAXSTACK = 3
+ MAXLOCALS = 2 <- 1 for this, 1 for return value.
+ */
+ visitTypeInsn(Opcodes.NEW, "java/lang/RuntimeException")
+ visitInsn(Opcodes.DUP)
+ visitLdcInsn("Stub!")
+ visitMethodInsn(Opcodes.INVOKESPECIAL, "java/lang/RuntimeException",
+ "<init>", "(Ljava/lang/String;)V", false)
+ visitInsn(Opcodes.ATHROW)
+ visitMaxs(0, 0) // We let ASM figure them out.
+ }
+ }
+}
diff --git a/tools/hoststubgen/hoststubgen/test-framework/Android.bp b/tools/hoststubgen/hoststubgen/test-framework/Android.bp
new file mode 100644
index 000000000000..2b91cc161b7f
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/test-framework/Android.bp
@@ -0,0 +1,19 @@
+// Copyright (C) 2023 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+build = ["AndroidHostTest.bp"]
diff --git a/tools/hoststubgen/hoststubgen/test-framework/AndroidHostTest.bp b/tools/hoststubgen/hoststubgen/test-framework/AndroidHostTest.bp
new file mode 100644
index 000000000000..e7fb2debfc4e
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/test-framework/AndroidHostTest.bp
@@ -0,0 +1,44 @@
+// Copyright (C) 2023 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// Add `build = ["AndroidHostTest.bp"]` to Android.bp to include this file.
+
+// Compile the test jar, using 2 rules.
+// 1. Build the test against the stub.
+java_library_host {
+ name: "HostStubGenTest-framework-test-host-test-lib",
+ defaults: ["hosttest-with-framework-all-hidden-api-test-lib-defaults"],
+ srcs: [
+ "src/**/*.java",
+ ],
+ static_libs: [
+ "junit",
+ "truth-prebuilt",
+ "mockito",
+
+ // http://cs/h/googleplex-android/platform/superproject/main/+/main:platform_testing/libraries/annotations/src/android/platform/test/annotations/
+ "platform-test-annotations",
+ "hoststubgen-annotations",
+ ],
+}
+
+// 2. Link the above module with necessary runtime dependencies, so it can be executed stand-alone.
+java_test_host {
+ name: "HostStubGenTest-framework-all-test-host-test",
+ defaults: ["hosttest-with-framework-all-hidden-api-test-defaults"],
+ static_libs: [
+ "HostStubGenTest-framework-test-host-test-lib",
+ ],
+ test_suites: ["general-tests"],
+}
diff --git a/tools/hoststubgen/hoststubgen/test-framework/AndroidTest-host.xml b/tools/hoststubgen/hoststubgen/test-framework/AndroidTest-host.xml
new file mode 100644
index 000000000000..f35dcf69ecc9
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/test-framework/AndroidTest-host.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2023 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<!-- [Ravenwood] Copied from $ANDROID_BUILD_TOP/cts/hostsidetests/devicepolicy/AndroidTest.xml -->
+<configuration description="CtsContentTestCases host-side test">
+ <option name="test-suite-tag" value="ravenwood" />
+ <option name="config-descriptor:metadata" key="component" value="framework" />
+ <option name="config-descriptor:metadata" key="parameter" value="not_instant_app" />
+ <option name="config-descriptor:metadata" key="parameter" value="not_multi_abi" />
+ <option name="config-descriptor:metadata" key="parameter" value="not_secondary_user" />
+ <option name="config-descriptor:metadata" key="parameter" value="no_foldable_states" />
+
+ <test class="com.android.tradefed.testtype.IsolatedHostTest" >
+ <option name="jar" value="HostStubGenTest-framework-all-test-host-test.jar" />
+ </test>
+</configuration>
diff --git a/tools/hoststubgen/hoststubgen/test-framework/README.md b/tools/hoststubgen/hoststubgen/test-framework/README.md
new file mode 100644
index 000000000000..20e2f873b152
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/test-framework/README.md
@@ -0,0 +1,27 @@
+# HostStubGen: real framework test
+
+This directory contains tests against the actual framework.jar code. The tests were
+copied from somewhere else in the android tree. We use this directory to quickly run existing
+tests.
+
+## How to run
+
+- With `atest`. This is the proper way to run it, but it may fail due to atest's known problems.
+
+ See the top level README.md on why `--no-bazel-mode` is needed (for now).
+
+```
+$ atest --no-bazel-mode HostStubGenTest-framework-test-host-test
+```
+
+- With `run-ravenwood-test`
+
+```
+$ run-ravenwood-test HostStubGenTest-framework-test-host-test
+```
+
+- Advanced option: `run-test-without-atest.sh` runs the test without using `atest` or `run-ravenwood-test`
+
+```
+$ ./run-test-without-atest.sh
+``` \ No newline at end of file
diff --git a/tools/hoststubgen/hoststubgen/test-framework/run-test-without-atest.sh b/tools/hoststubgen/hoststubgen/test-framework/run-test-without-atest.sh
new file mode 100755
index 000000000000..cfc06a12e881
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/test-framework/run-test-without-atest.sh
@@ -0,0 +1,85 @@
+#!/bin/bash
+# Copyright (C) 2023 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# Run HostStubGenTest-framework-test-host-test directly with JUnit.
+# (without using atest.)
+
+source "${0%/*}"/../../common.sh
+
+
+# Options:
+# -v enable verbose log
+# -d enable debugger
+
+verbose=0
+debug=0
+while getopts "vd" opt; do
+ case "$opt" in
+ v) verbose=1 ;;
+ d) debug=1 ;;
+ esac
+done
+shift $(($OPTIND - 1))
+
+
+if (( $verbose )) ; then
+ JAVA_OPTS="$JAVA_OPTS -verbose:class"
+fi
+
+if (( $debug )) ; then
+ JAVA_OPTS="$JAVA_OPTS -agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=8700"
+fi
+
+#=======================================
+module=HostStubGenTest-framework-all-test-host-test
+module_jar=$ANDROID_BUILD_TOP/out/host/linux-x86/testcases/$module/$module.jar
+run m $module
+
+out=out
+
+rm -fr $out
+mkdir -p $out
+
+
+# Copy and extract the relevant jar files so we can look into them.
+run cp \
+ $module_jar \
+ $SOONG_INT/frameworks/base/tools/hoststubgen/hoststubgen/framework-all-hidden-api-host/linux_glibc_common/gen/*.jar \
+ $out
+
+run extract $out/*.jar
+
+# Result is the number of failed tests.
+result=0
+
+
+# This suite runs all tests in the JAR.
+tests=(com.android.hoststubgen.hosthelper.HostTestSuite)
+
+# Uncomment this to run a specific test.
+# tests=(com.android.hoststubgen.frameworktest.LogTest)
+
+
+for class in ${tests[@]} ; do
+ echo "Running $class ..."
+
+ run cd "${module_jar%/*}"
+ run $JAVA $JAVA_OPTS \
+ -cp $module_jar \
+ org.junit.runner.JUnitCore \
+ $class || result=$(( $result + 1 ))
+done
+
+exit $result
diff --git a/tools/hoststubgen/hoststubgen/test-framework/src/com/android/hoststubgen/frameworktest/ArrayMapTest.java b/tools/hoststubgen/hoststubgen/test-framework/src/com/android/hoststubgen/frameworktest/ArrayMapTest.java
new file mode 100644
index 000000000000..62bbf48955da
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/test-framework/src/com/android/hoststubgen/frameworktest/ArrayMapTest.java
@@ -0,0 +1,737 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.hoststubgen.frameworktest;
+
+// [ravewnwood] Copied from cts/, and commented out unsupported stuff.
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertSame;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import android.os.Bundle;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.util.ArrayMap;
+import android.util.Log;
+
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.AbstractMap;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.NoSuchElementException;
+import java.util.Set;
+import java.util.function.BiFunction;
+
+/**
+ * Some basic tests for {@link android.util.ArrayMap}.
+ */
+@RunWith(AndroidJUnit4.class)
+public class ArrayMapTest {
+ static final boolean DEBUG = false;
+
+ static final int OP_ADD = 1;
+ static final int OP_REM = 2;
+
+ static int[] OPS = new int[]{
+ OP_ADD, OP_ADD, OP_ADD, OP_ADD, OP_ADD, OP_ADD, OP_ADD, OP_ADD, OP_ADD,
+ OP_ADD, OP_ADD, OP_ADD, OP_ADD, OP_ADD, OP_ADD, OP_ADD, OP_ADD, OP_ADD,
+ OP_REM, OP_REM, OP_REM, OP_REM, OP_REM, OP_REM, OP_REM, OP_REM, OP_REM,
+ OP_REM, OP_REM, OP_REM, OP_REM, OP_REM, OP_REM, OP_REM, OP_REM, OP_REM,
+
+ OP_ADD, OP_ADD, OP_ADD, OP_ADD, OP_ADD, OP_ADD, OP_ADD, OP_ADD, OP_ADD,
+ OP_REM, OP_REM, OP_REM, OP_REM, OP_REM, OP_REM, OP_REM, OP_REM, OP_REM,
+
+ OP_ADD, OP_ADD, OP_ADD, OP_ADD, OP_ADD, OP_ADD, OP_ADD, OP_ADD, OP_ADD,
+ OP_REM, OP_REM, OP_REM, OP_REM, OP_REM, OP_REM, OP_REM, OP_REM, OP_REM,
+
+ OP_ADD, OP_ADD, OP_ADD, OP_ADD, OP_ADD, OP_ADD, OP_ADD, OP_ADD, OP_ADD,
+ OP_REM, OP_REM, OP_REM, OP_REM, OP_REM, OP_REM, OP_REM, OP_REM, OP_REM,
+
+ OP_ADD, OP_ADD, OP_ADD, OP_ADD, OP_ADD, OP_ADD, OP_ADD, OP_ADD, OP_ADD,
+ OP_ADD, OP_ADD, OP_ADD, OP_ADD, OP_ADD, OP_ADD, OP_ADD, OP_ADD, OP_ADD,
+ OP_ADD, OP_ADD, OP_ADD,
+ OP_REM, OP_REM, OP_REM, OP_REM, OP_REM, OP_REM, OP_REM, OP_REM, OP_REM,
+ OP_REM, OP_REM, OP_REM,
+ OP_REM, OP_REM, OP_REM, OP_REM, OP_REM, OP_REM, OP_REM, OP_REM, OP_REM,
+ };
+
+ static int[] KEYS = new int[]{
+ // General adding and removing.
+ -1, 1900, 600, 200, 1200, 1500, 1800, 100, 1900,
+ 2100, 300, 800, 600, 1100, 1300, 2000, 1000, 1400,
+ 600, -1, 1900, 600, 300, 2100, 200, 800, 800,
+ 1800, 1500, 1300, 1100, 2000, 1400, 1000, 1200, 1900,
+
+ // Shrink when removing item from end.
+ 100, 200, 300, 400, 500, 600, 700, 800, 900,
+ 900, 800, 700, 600, 500, 400, 300, 200, 100,
+
+ // Shrink when removing item from middle.
+ 100, 200, 300, 400, 500, 600, 700, 800, 900,
+ 900, 800, 700, 600, 500, 400, 200, 300, 100,
+
+ // Shrink when removing item from front.
+ 100, 200, 300, 400, 500, 600, 700, 800, 900,
+ 900, 800, 700, 600, 500, 400, 100, 200, 300,
+
+ // Test hash collisions.
+ 105, 106, 108, 104, 102, 102, 107, 5, 205,
+ 4, 202, 203, 3, 5, 101, 109, 200, 201,
+ 0, -1, 100,
+ 106, 108, 104, 102, 103, 105, 107, 101, 109,
+ -1, 100, 0,
+ 4, 5, 3, 5, 200, 203, 202, 201, 205,
+ };
+
+ public static class ControlledHash implements Parcelable {
+ final int mValue;
+
+ ControlledHash(int value) {
+ mValue = value;
+ }
+
+ @Override
+ public final boolean equals(Object o) {
+ if (o == null) {
+ return false;
+ }
+ return mValue == ((ControlledHash)o).mValue;
+ }
+
+ @Override
+ public final int hashCode() {
+ return mValue/100;
+ }
+
+ @Override
+ public final String toString() {
+ return Integer.toString(mValue);
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeInt(mValue);
+ }
+
+ public static final Parcelable.Creator<ControlledHash> CREATOR
+ = new Parcelable.Creator<ControlledHash>() {
+ public ControlledHash createFromParcel(Parcel in) {
+ return new ControlledHash(in.readInt());
+ }
+
+ public ControlledHash[] newArray(int size) {
+ return new ControlledHash[size];
+ }
+ };
+ }
+
+ private static boolean compare(Object v1, Object v2) {
+ if (v1 == null) {
+ return v2 == null;
+ }
+ if (v2 == null) {
+ return false;
+ }
+ return v1.equals(v2);
+ }
+
+ private static void compareMaps(HashMap map, ArrayMap array) {
+ if (map.size() != array.size()) {
+ fail("Bad size: expected " + map.size() + ", got " + array.size());
+ }
+
+ Set<Entry> mapSet = map.entrySet();
+ for (Map.Entry entry : mapSet) {
+ Object expValue = entry.getValue();
+ Object gotValue = array.get(entry.getKey());
+ if (!compare(expValue, gotValue)) {
+ fail("Bad value: expected " + expValue + ", got " + gotValue
+ + " at key " + entry.getKey());
+ }
+ }
+
+ for (int i = 0; i < array.size(); i++) {
+ Object gotValue = array.valueAt(i);
+ Object key = array.keyAt(i);
+ Object expValue = map.get(key);
+ if (!compare(expValue, gotValue)) {
+ fail("Bad value: expected " + expValue + ", got " + gotValue
+ + " at key " + key);
+ }
+ }
+
+ if (map.entrySet().hashCode() != array.entrySet().hashCode()) {
+ fail("Entry set hash codes differ: map=0x"
+ + Integer.toHexString(map.entrySet().hashCode()) + " array=0x"
+ + Integer.toHexString(array.entrySet().hashCode()));
+ }
+
+ if (!map.entrySet().equals(array.entrySet())) {
+ fail("Failed calling equals on map entry set against array set");
+ }
+
+ if (!array.entrySet().equals(map.entrySet())) {
+ fail("Failed calling equals on array entry set against map set");
+ }
+
+ if (map.keySet().hashCode() != array.keySet().hashCode()) {
+ fail("Key set hash codes differ: map=0x"
+ + Integer.toHexString(map.keySet().hashCode()) + " array=0x"
+ + Integer.toHexString(array.keySet().hashCode()));
+ }
+
+ if (!map.keySet().equals(array.keySet())) {
+ fail("Failed calling equals on map key set against array set");
+ }
+
+ if (!array.keySet().equals(map.keySet())) {
+ fail("Failed calling equals on array key set against map set");
+ }
+
+ if (!map.keySet().containsAll(array.keySet())) {
+ fail("Failed map key set contains all of array key set");
+ }
+
+ if (!array.keySet().containsAll(map.keySet())) {
+ fail("Failed array key set contains all of map key set");
+ }
+
+ if (!array.containsAll(map.keySet())) {
+ fail("Failed array contains all of map key set");
+ }
+
+ if (!map.entrySet().containsAll(array.entrySet())) {
+ fail("Failed map entry set contains all of array entry set");
+ }
+
+ if (!array.entrySet().containsAll(map.entrySet())) {
+ fail("Failed array entry set contains all of map entry set");
+ }
+ }
+
+ private static void validateArrayMap(ArrayMap array) {
+ Set<Map.Entry> entrySet = array.entrySet();
+ int index = 0;
+ Iterator<Entry> entryIt = entrySet.iterator();
+ while (entryIt.hasNext()) {
+ Map.Entry entry = entryIt.next();
+ Object value = entry.getKey();
+ Object realValue = array.keyAt(index);
+ if (!compare(realValue, value)) {
+ fail("Bad array map entry set: expected key " + realValue
+ + ", got " + value + " at index " + index);
+ }
+ value = entry.getValue();
+ realValue = array.valueAt(index);
+ if (!compare(realValue, value)) {
+ fail("Bad array map entry set: expected value " + realValue
+ + ", got " + value + " at index " + index);
+ }
+ index++;
+ }
+
+ index = 0;
+ Set keySet = array.keySet();
+ Iterator keyIt = keySet.iterator();
+ while (keyIt.hasNext()) {
+ Object value = keyIt.next();
+ Object realValue = array.keyAt(index);
+ if (!compare(realValue, value)) {
+ fail("Bad array map key set: expected key " + realValue
+ + ", got " + value + " at index " + index);
+ }
+ index++;
+ }
+
+ index = 0;
+ Collection valueCol = array.values();
+ Iterator valueIt = valueCol.iterator();
+ while (valueIt.hasNext()) {
+ Object value = valueIt.next();
+ Object realValue = array.valueAt(index);
+ if (!compare(realValue, value)) {
+ fail("Bad array map value col: expected value " + realValue
+ + ", got " + value + " at index " + index);
+ }
+ index++;
+ }
+ }
+
+ private static void compareBundles(Bundle bundle1, Bundle bundle2) {
+ Set<String> keySet1 = bundle1.keySet();
+ Iterator<String> iterator1 = keySet1.iterator();
+ while (iterator1.hasNext()) {
+ String key = iterator1.next();
+ int value1 = bundle1.getInt(key);
+ if (bundle2.get(key) == null) {
+ fail("Bad Bundle: bundle2 didn't have expected key " + key);
+ }
+ int value2 = bundle2.getInt(key);
+ if (value1 != value2) {
+ fail("Bad Bundle: at key key " + key + " expected " + value1 + ", got " + value2);
+ }
+ }
+ Set<String> keySet2 = bundle2.keySet();
+ Iterator<String> iterator2 = keySet2.iterator();
+ while (iterator2.hasNext()) {
+ String key = iterator2.next();
+ if (bundle1.get(key) == null) {
+ fail("Bad Bundle: bundle1 didn't have expected key " + key);
+ }
+ int value1 = bundle1.getInt(key);
+ int value2 = bundle2.getInt(key);
+ if (value1 != value2) {
+ fail("Bad Bundle: at key key " + key + " expected " + value1 + ", got " + value2);
+ }
+ }
+ }
+
+ private static void dump(Map map, ArrayMap array) {
+ Log.e("test", "HashMap of " + map.size() + " entries:");
+ Set<Map.Entry> mapSet = map.entrySet();
+ for (Map.Entry entry : mapSet) {
+ Log.e("test", " " + entry.getKey() + " -> " + entry.getValue());
+ }
+ Log.e("test", "ArrayMap of " + array.size() + " entries:");
+ for (int i = 0; i < array.size(); i++) {
+ Log.e("test", " " + array.keyAt(i) + " -> " + array.valueAt(i));
+ }
+ }
+
+ private static void dump(ArrayMap map1, ArrayMap map2) {
+ Log.e("test", "ArrayMap of " + map1.size() + " entries:");
+ for (int i = 0; i < map1.size(); i++) {
+ Log.e("test", " " + map1.keyAt(i) + " -> " + map1.valueAt(i));
+ }
+ Log.e("test", "ArrayMap of " + map2.size() + " entries:");
+ for (int i = 0; i < map2.size(); i++) {
+ Log.e("test", " " + map2.keyAt(i) + " -> " + map2.valueAt(i));
+ }
+ }
+
+ private static void dump(Bundle bundle1, Bundle bundle2) {
+ Log.e("test", "First Bundle of " + bundle1.size() + " entries:");
+ Set<String> keys1 = bundle1.keySet();
+ for (String key : keys1) {
+ Log.e("test", " " + key + " -> " + bundle1.get(key));
+ }
+ Log.e("test", "Second Bundle of " + bundle2.size() + " entries:");
+ Set<String> keys2 = bundle2.keySet();
+ for (String key : keys2) {
+ Log.e("test", " " + key + " -> " + bundle2.get(key));
+ }
+ }
+
+ @Test
+ public void testBasicArrayMap() {
+ HashMap<ControlledHash, Integer> hashMap = new HashMap<>();
+ ArrayMap<ControlledHash, Integer> arrayMap = new ArrayMap<>();
+ Bundle bundle = new Bundle();
+
+ for (int i = 0; i < OPS.length; i++) {
+ Integer oldHash;
+ Integer oldArray;
+ ControlledHash key = KEYS[i] < 0 ? null : new ControlledHash(KEYS[i]);
+ String strKey = KEYS[i] < 0 ? null : Integer.toString(KEYS[i]);
+ switch (OPS[i]) {
+ case OP_ADD:
+ if (DEBUG) Log.i("test", "Adding key: " + key);
+ oldHash = hashMap.put(key, i);
+ oldArray = arrayMap.put(key, i);
+ bundle.putInt(strKey, i);
+ break;
+ case OP_REM:
+ if (DEBUG) Log.i("test", "Removing key: " + key);
+ oldHash = hashMap.remove(key);
+ oldArray = arrayMap.remove(key);
+ bundle.remove(strKey);
+ break;
+ default:
+ fail("Bad operation " + OPS[i] + " @ " + i);
+ return;
+ }
+ if (!compare(oldHash, oldArray)) {
+ String msg = "Bad result: expected " + oldHash + ", got " + oldArray;
+ Log.e("test", msg);
+ dump(hashMap, arrayMap);
+ fail(msg);
+ }
+ try {
+ validateArrayMap(arrayMap);
+ } catch (Throwable e) {
+ Log.e("test", e.getMessage());
+ dump(hashMap, arrayMap);
+ throw e;
+ }
+ try {
+ compareMaps(hashMap, arrayMap);
+ } catch (Throwable e) {
+ Log.e("test", e.getMessage());
+ dump(hashMap, arrayMap);
+ throw e;
+ }
+ Parcel parcel = Parcel.obtain();
+ bundle.writeToParcel(parcel, 0);
+ parcel.setDataPosition(0);
+ Bundle bundle2 = parcel.readBundle();
+ try {
+ compareBundles(bundle, bundle2);
+ } catch (Throwable e) {
+ Log.e("test", e.getMessage());
+ dump(bundle, bundle2);
+ throw e;
+ }
+ }
+
+ arrayMap.put(new ControlledHash(50000), 100);
+ ControlledHash lookup = new ControlledHash(50000);
+ Iterator<ControlledHash> it = arrayMap.keySet().iterator();
+ while (it.hasNext()) {
+ if (it.next().equals(lookup)) {
+ it.remove();
+ }
+ }
+ if (arrayMap.containsKey(lookup)) {
+ String msg = "Bad map iterator: didn't remove test key";
+ Log.e("test", msg);
+ dump(hashMap, arrayMap);
+ fail(msg);
+ }
+ }
+
+ @Test
+ public void testCopyArrayMap() {
+ // map copy constructor test
+ ArrayMap newMap = new ArrayMap<Integer, String>();
+ for (int i = 0; i < 10; ++i) {
+ newMap.put(i, String.valueOf(i));
+ }
+ ArrayMap mapCopy = new ArrayMap(newMap);
+ if (!compare(mapCopy, newMap)) {
+ String msg = "ArrayMap copy constructor failure: expected " +
+ newMap + ", got " + mapCopy;
+ Log.e("test", msg);
+ dump(newMap, mapCopy);
+ fail(msg);
+ return;
+ }
+ }
+
+ @Test
+ public void testEqualsArrayMap() {
+ ArrayMap<Integer, String> map1 = new ArrayMap<>();
+ ArrayMap<Integer, String> map2 = new ArrayMap<>();
+ HashMap<Integer, String> map3 = new HashMap<>();
+ if (!compare(map1, map2) || !compare(map1, map3) || !compare(map3, map2)) {
+ fail("ArrayMap equals failure for empty maps " + map1 + ", " +
+ map2 + ", " + map3);
+ }
+
+ for (int i = 0; i < 10; ++i) {
+ String value = String.valueOf(i);
+ map1.put(i, value);
+ map2.put(i, value);
+ map3.put(i, value);
+ }
+ if (!compare(map1, map2) || !compare(map1, map3) || !compare(map3, map2)) {
+ fail("ArrayMap equals failure for populated maps " + map1 + ", " +
+ map2 + ", " + map3);
+ }
+
+ map1.remove(0);
+ if (compare(map1, map2) || compare(map1, map3) || compare(map3, map1)) {
+ fail("ArrayMap equals failure for map size " + map1 + ", " +
+ map2 + ", " + map3);
+ }
+
+ map1.put(0, "-1");
+ if (compare(map1, map2) || compare(map1, map3) || compare(map3, map1)) {
+ fail("ArrayMap equals failure for map contents " + map1 + ", " +
+ map2 + ", " + map3);
+ }
+ }
+
+// /**
+// * Test creating a malformed array map with duplicated keys and that we will catch this when
+// * unparcelling.
+// */
+// @Test
+// public void testDuplicateKeys() throws NoSuchMethodException,
+// InvocationTargetException, IllegalAccessException, NoSuchFieldException {
+// ArrayMap<String, Object> map1 = new ArrayMap(2);
+//
+// Method appendMethod = ArrayMap.class.getMethod("append", Object.class, Object.class);
+// appendMethod.invoke(map1, Integer.toString(100000), "foo");
+// appendMethod.invoke(map1, Integer.toString(100000), "bar");
+//
+// // Now parcel/unparcel, and verify we get the expected error.
+// Parcel parcel = Parcel.obtain();
+// Method writeArrayMapMethod = Parcel.class.getMethod("writeArrayMap", ArrayMap.class);
+// writeArrayMapMethod.invoke(parcel, map1);
+// parcel.setDataPosition(0);
+// ArrayMap<String, Object> map2 = new ArrayMap(2);
+//
+// try {
+// Parcel.class.getMethod("readArrayMap", ArrayMap.class, ClassLoader.class).invoke(
+// parcel, map2, null);
+// } catch (InvocationTargetException e) {
+// Throwable cause = e.getCause();
+// if (cause instanceof IllegalArgumentException) {
+// // Good!
+// return;
+// }
+// throw e;
+// }
+//
+// String msg = "Didn't throw expected IllegalArgumentException";
+// Log.e("test", msg);
+// dump(map1, map2);
+// fail(msg);
+// }
+
+ private static void checkEntrySetToArray(ArrayMap<?, ?> testMap) {
+ try {
+ testMap.entrySet().toArray();
+ fail();
+ } catch (UnsupportedOperationException expected) {
+ }
+
+ try {
+ Map.Entry<?, ?>[] entries = new Map.Entry[20];
+ testMap.entrySet().toArray(entries);
+ fail();
+ } catch (UnsupportedOperationException expected) {
+ }
+ }
+
+ // http://b/32294038, Test ArrayMap.entrySet().toArray()
+ @Test
+ public void testEntrySetArray() {
+ // Create
+ ArrayMap<Integer, String> testMap = new ArrayMap<>();
+
+ // Test empty
+ checkEntrySetToArray(testMap);
+
+ // Test non-empty
+ for (int i = 0; i < 10; ++i) {
+ testMap.put(i, String.valueOf(i));
+ }
+ checkEntrySetToArray(testMap);
+ }
+
+ @Test
+ public void testCanNotIteratePastEnd_entrySetIterator() {
+ Map<String, String> map = new ArrayMap<>();
+ map.put("key 1", "value 1");
+ map.put("key 2", "value 2");
+ Set<Map.Entry<String, String>> expectedEntriesToIterate = new HashSet<>(Arrays.asList(
+ entryOf("key 1", "value 1"),
+ entryOf("key 2", "value 2")
+ ));
+ Iterator<Map.Entry<String, String>> iterator = map.entrySet().iterator();
+
+ // Assert iteration over the expected two entries in any order
+ assertTrue(iterator.hasNext());
+ Map.Entry<String, String> firstEntry = copyOf(iterator.next());
+ assertTrue(expectedEntriesToIterate.remove(firstEntry));
+
+ assertTrue(iterator.hasNext());
+ Map.Entry<String, String> secondEntry = copyOf(iterator.next());
+ assertTrue(expectedEntriesToIterate.remove(secondEntry));
+
+ assertFalse(iterator.hasNext());
+
+ try {
+ iterator.next();
+ fail();
+ } catch (NoSuchElementException expected) {
+ }
+ }
+
+ private static <K, V> Map.Entry<K, V> entryOf(K key, V value) {
+ return new AbstractMap.SimpleEntry<>(key, value);
+ }
+
+ private static <K, V> Map.Entry<K, V> copyOf(Map.Entry<K, V> entry) {
+ return entryOf(entry.getKey(), entry.getValue());
+ }
+
+ @Test
+ public void testCanNotIteratePastEnd_keySetIterator() {
+ Map<String, String> map = new ArrayMap<>();
+ map.put("key 1", "value 1");
+ map.put("key 2", "value 2");
+ Set<String> expectedKeysToIterate = new HashSet<>(Arrays.asList("key 1", "key 2"));
+ Iterator<String> iterator = map.keySet().iterator();
+
+ // Assert iteration over the expected two keys in any order
+ assertTrue(iterator.hasNext());
+ String firstKey = iterator.next();
+ assertTrue(expectedKeysToIterate.remove(firstKey));
+
+ assertTrue(iterator.hasNext());
+ String secondKey = iterator.next();
+ assertTrue(expectedKeysToIterate.remove(secondKey));
+
+ assertFalse(iterator.hasNext());
+
+ try {
+ iterator.next();
+ fail();
+ } catch (NoSuchElementException expected) {
+ }
+ }
+
+ @Test
+ public void testCanNotIteratePastEnd_valuesIterator() {
+ Map<String, String> map = new ArrayMap<>();
+ map.put("key 1", "value 1");
+ map.put("key 2", "value 2");
+ Set<String> expectedValuesToIterate = new HashSet<>(Arrays.asList("value 1", "value 2"));
+ Iterator<String> iterator = map.values().iterator();
+
+ // Assert iteration over the expected two values in any order
+ assertTrue(iterator.hasNext());
+ String firstValue = iterator.next();
+ assertTrue(expectedValuesToIterate.remove(firstValue));
+
+ assertTrue(iterator.hasNext());
+ String secondValue = iterator.next();
+ assertTrue(expectedValuesToIterate.remove(secondValue));
+
+ assertFalse(iterator.hasNext());
+
+ try {
+ iterator.next();
+ fail();
+ } catch (NoSuchElementException expected) {
+ }
+ }
+
+ @Test
+ public void testForEach() {
+ ArrayMap<String, Integer> map = new ArrayMap<>();
+
+ for (int i = 0; i < 50; ++i) {
+ map.put(Integer.toString(i), i * 10);
+ }
+
+ // Make sure forEach goes through all of the elements.
+ HashMap<String, Integer> seen = new HashMap<>();
+ map.forEach(seen::put);
+ compareMaps(seen, map);
+ }
+
+ /**
+ * The entrySet Iterator returns itself from each call to {@code next()}. This is unusual
+ * behavior for {@link Iterator#next()}; this test ensures that any future change to this
+ * behavior is deliberate.
+ */
+ @Test
+ public void testUnusualBehavior_eachEntryIsSameAsIterator_entrySetIterator() {
+ Map<String, String> map = new ArrayMap<>();
+ map.put("key 1", "value 1");
+ map.put("key 2", "value 2");
+ Iterator<Map.Entry<String, String>> iterator = map.entrySet().iterator();
+
+ assertSame(iterator, iterator.next());
+ assertSame(iterator, iterator.next());
+ }
+
+ @SuppressWarnings("SelfEquals")
+ @Test
+ public void testUnusualBehavior_equalsThrowsAfterRemove_entrySetIterator() {
+ Map<String, String> map = new ArrayMap<>();
+ map.put("key 1", "value 1");
+ map.put("key 2", "value 2");
+ Iterator<Map.Entry<String, String>> iterator = map.entrySet().iterator();
+ iterator.next();
+ iterator.remove();
+ try {
+ iterator.equals(iterator);
+ fail();
+ } catch (IllegalStateException expected) {
+ }
+ }
+
+ private static <T> void assertEqualsBothWays(T a, T b) {
+ assertEquals(a, b);
+ assertEquals(b, a);
+ assertEquals(a.hashCode(), b.hashCode());
+ }
+
+ @Test
+ public void testRemoveAll() {
+ final ArrayMap<Integer, String> map = new ArrayMap<>();
+ for (Integer i : Arrays.asList(0, 1, 2, 3, 4, 5)) {
+ map.put(i, i.toString());
+ }
+
+ final ArrayMap<Integer, String> expectedMap = new ArrayMap<>();
+ for (Integer i : Arrays.asList(2, 4)) {
+ expectedMap.put(i, String.valueOf(i));
+ }
+ map.removeAll(Arrays.asList(0, 1, 3, 5, 6));
+ if (!compare(map, expectedMap)) {
+ fail("ArrayMap removeAll failure, expect " + expectedMap + ", but " + map);
+ }
+
+ map.removeAll(Collections.emptyList());
+ if (!compare(map, expectedMap)) {
+ fail("ArrayMap removeAll failure for empty maps, expect " + expectedMap + ", but " +
+ map);
+ }
+
+ map.removeAll(Arrays.asList(2, 4));
+ if (!map.isEmpty()) {
+ fail("ArrayMap removeAll failure, expect empty, but " + map);
+ }
+ }
+
+ @Test
+ public void testReplaceAll() {
+ final ArrayMap<Integer, Integer> map = new ArrayMap<>();
+ final ArrayMap<Integer, Integer> expectedMap = new ArrayMap<>();
+ final BiFunction<Integer, Integer, Integer> function = (k, v) -> 2 * v;
+ for (Integer i : Arrays.asList(0, 1, 2, 3, 4, 5)) {
+ map.put(i, i);
+ expectedMap.put(i, 2 * i);
+ }
+
+ map.replaceAll(function);
+ if (!compare(map, expectedMap)) {
+ fail("ArrayMap replaceAll failure, expect " + expectedMap + ", but " + map);
+ }
+ }
+} \ No newline at end of file
diff --git a/tools/hoststubgen/hoststubgen/test-framework/src/com/android/hoststubgen/frameworktest/LogTest.java b/tools/hoststubgen/hoststubgen/test-framework/src/com/android/hoststubgen/frameworktest/LogTest.java
new file mode 100644
index 000000000000..56544b4d5151
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/test-framework/src/com/android/hoststubgen/frameworktest/LogTest.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.hoststubgen.frameworktest;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.util.Log;
+import android.util.Slog;
+
+import org.junit.Test;
+
+/**
+ * Some basic tests for {@link android.util.Log}.
+ */
+public class LogTest {
+ @Test
+ public void testBasicLogging() {
+ Log.v("TAG", "Test v log");
+ Log.d("TAG", "Test d log");
+ Log.i("TAG", "Test i log");
+ Log.w("TAG", "Test w log");
+ Log.e("TAG", "Test e log");
+
+ Slog.v("TAG", "Test v slog");
+ Slog.d("TAG", "Test d slog");
+ Slog.i("TAG", "Test i slog");
+ Slog.w("TAG", "Test w slog");
+ Slog.e("TAG", "Test e slog");
+ }
+
+ @Test
+ public void testNativeMethods() {
+ assertThat(Log.isLoggable("mytag", Log.INFO)).isTrue();
+ }
+}
diff --git a/tools/hoststubgen/hoststubgen/test-tiny-framework/Android.bp b/tools/hoststubgen/hoststubgen/test-tiny-framework/Android.bp
new file mode 100644
index 000000000000..8c76a612020f
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/test-tiny-framework/Android.bp
@@ -0,0 +1,141 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_base_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_base_license"],
+}
+
+// A library that simulates framework-all.jar
+java_library {
+ name: "hoststubgen-test-tiny-framework",
+ installable: true,
+ host_supported: true,
+ srcs: ["tiny-framework/src/**/*.java"],
+ static_libs: [
+ "hoststubgen-annotations",
+ ],
+}
+
+// Create stub/impl jars from "hoststubgen-test-tiny-framework", using the following 3 rules.
+java_genrule_host {
+ name: "hoststubgen-test-tiny-framework-host",
+ defaults: ["hoststubgen-command-defaults"],
+ cmd: hoststubgen_common_options +
+ "--in-jar $(location :hoststubgen-test-tiny-framework) " +
+ "--policy-override-file $(location policy-override-tiny-framework.txt) ",
+ srcs: [
+ ":hoststubgen-test-tiny-framework",
+ "policy-override-tiny-framework.txt",
+ ],
+}
+
+java_genrule_host {
+ name: "hoststubgen-test-tiny-framework-host-stub",
+ cmd: "cp $(in) $(out)",
+ srcs: [
+ ":hoststubgen-test-tiny-framework-host{host_stub.jar}",
+ ],
+ out: [
+ "host_stub.jar",
+ ],
+}
+
+java_genrule_host {
+ name: "hoststubgen-test-tiny-framework-host-impl",
+ cmd: "cp $(in) $(out)",
+ srcs: [
+ ":hoststubgen-test-tiny-framework-host{host_impl.jar}",
+ ],
+ out: [
+ "host_impl.jar",
+ ],
+}
+
+// Compile the test jar, using 2 rules.
+// 1. Build the test against the stub.
+java_library_host {
+ name: "hoststubgen-test-tiny-test-lib",
+ srcs: ["tiny-test/src/**/*.java"],
+
+ libs: [
+ "hoststubgen-test-tiny-framework-host-stub",
+ ],
+ static_libs: [
+ "junit",
+ "truth-prebuilt",
+
+ // http://cs/h/googleplex-android/platform/superproject/main/+/main:platform_testing/libraries/annotations/src/android/platform/test/annotations/
+ "platform-test-annotations",
+ ],
+ visibility: ["//visibility:private"],
+}
+
+// 2. Link "hoststubgen-test-tiny-test-lib" with necessary runtime dependencies, so it can be
+// executed stand-alone.
+java_test_host {
+ name: "hoststubgen-test-tiny-test",
+ test_config: "AndroidTest-host.xml",
+ static_libs: [
+ "hoststubgen-test-tiny-test-lib",
+ "hoststubgen-helper-runtime",
+ "hoststubgen-test-tiny-framework-host-impl",
+ ],
+ test_suites: ["general-tests"],
+}
+
+// Dump the original, stub and impl jars as text files.
+// We use them in test-and-update-golden.sh.
+java_genrule_host {
+ name: "hoststubgen-test-tiny-framework-orig-dump",
+ defaults: ["hoststubgen-jar-dump-defaults"],
+ srcs: [
+ ":hoststubgen-test-tiny-framework",
+ ],
+ out: [
+ "01-hoststubgen-test-tiny-framework-orig-dump.txt",
+ ],
+ visibility: ["//visibility:private"],
+}
+
+java_genrule_host {
+ name: "hoststubgen-test-tiny-framework-host-stub-dump",
+ defaults: ["hoststubgen-jar-dump-defaults"],
+ srcs: [
+ ":hoststubgen-test-tiny-framework-host-stub",
+ ],
+ out: [
+ "02-hoststubgen-test-tiny-framework-host-stub-dump.txt",
+ ],
+ visibility: ["//visibility:private"],
+}
+
+java_genrule_host {
+ name: "hoststubgen-test-tiny-framework-host-impl-dump",
+ defaults: ["hoststubgen-jar-dump-defaults"],
+ srcs: [
+ ":hoststubgen-test-tiny-framework-host-impl",
+ ],
+ out: [
+ "03-hoststubgen-test-tiny-framework-host-impl-dump.txt",
+ ],
+ visibility: ["//visibility:private"],
+}
+
+// Run it with `atest`. Compare the dump of the jar files to the golden output.
+python_test_host {
+ name: "tiny-framework-dump-test",
+ srcs: [
+ "tiny-framework-dump-test.py",
+ ],
+ data: [
+ "golden-output/*.txt",
+ ],
+ java_data: [
+ "hoststubgen-test-tiny-framework-host-stub-dump",
+ "hoststubgen-test-tiny-framework-host-impl-dump",
+ "hoststubgen-test-tiny-framework-orig-dump",
+ ],
+ test_suites: ["general-tests"],
+}
diff --git a/tools/hoststubgen/hoststubgen/test-tiny-framework/AndroidTest-host.xml b/tools/hoststubgen/hoststubgen/test-tiny-framework/AndroidTest-host.xml
new file mode 100644
index 000000000000..84aad69c33bc
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/test-tiny-framework/AndroidTest-host.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2023 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<!-- [Ravenwood] Copied from $ANDROID_BUILD_TOP/cts/hostsidetests/devicepolicy/AndroidTest.xml -->
+<configuration description="HostStubGen sample test">
+ <option name="test-suite-tag" value="ravenwood" />
+ <option name="config-descriptor:metadata" key="component" value="framework" />
+ <option name="config-descriptor:metadata" key="parameter" value="not_instant_app" />
+ <option name="config-descriptor:metadata" key="parameter" value="not_multi_abi" />
+ <option name="config-descriptor:metadata" key="parameter" value="not_secondary_user" />
+ <option name="config-descriptor:metadata" key="parameter" value="no_foldable_states" />
+
+ <test class="com.android.tradefed.testtype.IsolatedHostTest" >
+ <option name="jar" value="hoststubgen-test-tiny-test.jar" />
+ </test>
+</configuration>
diff --git a/tools/hoststubgen/hoststubgen/test-tiny-framework/README.md b/tools/hoststubgen/hoststubgen/test-tiny-framework/README.md
new file mode 100644
index 000000000000..f3c0450d42a3
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/test-tiny-framework/README.md
@@ -0,0 +1,27 @@
+# HostStubGen: tiny-framework test
+
+This directory contains a small classes that "simulates" framework.jar, and tests against it.
+
+This test doesn't use the actual android framework code.
+
+## How to run
+
+- With `atest`. This is the proper way to run it, but `atest` has known problems that may
+ affect the result. If you see weird problems, try the next `run-ravenwood-test` command.
+
+```
+$ atest hoststubgen-test-tiny-test
+```
+
+- With `run-ravenwood-test` should work too. This is the proper way to run it.
+
+```
+$ run-ravenwood-test hoststubgen-test-tiny-test
+```
+
+- `run-test-manually.sh` also run the test, but it builds the stub/impl jars and the test without
+ using the build system. This is useful for debugging the tool.
+
+```
+$ ./run-test-manually.sh
+``` \ No newline at end of file
diff --git a/tools/hoststubgen/hoststubgen/test-tiny-framework/diff-and-update-golden.sh b/tools/hoststubgen/hoststubgen/test-tiny-framework/diff-and-update-golden.sh
new file mode 100755
index 000000000000..4d588694b8da
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/test-tiny-framework/diff-and-update-golden.sh
@@ -0,0 +1,134 @@
+#!/bin/bash
+# Copyright (C) 2023 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+help() {
+ cat <<'EOF'
+
+ diff-and-update-golden.sh [OPTIONS]
+
+ Compare the generated jar files from tiny-framework to the "golden" files.
+
+ OPTIONS:
+ -u: Update the golden files.
+
+ -3: Run `meld` to compare original, stub and impl jar files in 3-way diff.
+ This is useful to visualize the exact differences between 3 jar files.
+
+ -2: Run `meld` to compare original <-> impl, and impl <-> stub as two different diffs.
+EOF
+}
+
+source "${0%/*}"/../../common.sh
+
+SCRIPT_NAME="${0##*/}"
+
+GOLDEN_DIR=golden-output
+mkdir -p $GOLDEN_DIR
+
+DIFF_CMD=${DIFF:-diff -u --ignore-blank-lines --ignore-space-change}
+
+update=0
+three_way=0
+two_way=0
+while getopts "u32" opt; do
+case "$opt" in
+ u)
+ update=1
+ ;;
+ 3)
+ three_way=1
+ ;;
+ 2)
+ two_way=1
+ ;;
+ '?')
+ help
+ exit 1
+ ;;
+esac
+done
+shift $(($OPTIND - 1))
+
+
+# Build the dump files, which are the input of this test.
+run m tiny-framework-dump-test
+
+
+# Get the path to the generate text files. (not the golden files.)
+# We get them from $OUT/module-info.json
+
+files=(
+$(python3 -c '
+import sys
+import os
+import json
+
+with open(sys.argv[1], "r") as f:
+ data = json.load(f)
+
+ # Equivalent to: jq -r '.["tiny-framework-dump-test"]["installed"][]'
+ for path in data["tiny-framework-dump-test"]["installed"]:
+
+ if "golden-output" in path:
+ continue
+ if path.endswith(".txt"):
+ print(os.getenv("ANDROID_BUILD_TOP") + "/" + path)
+' $OUT/module-info.json)
+)
+
+# Next, compare each file and update them in $GOLDEN_DIR
+
+any_file_changed=0
+
+for file in ${files[*]} ; do
+ name=$(basename $file)
+ echo "# Checking $name ..."
+
+ file_changed=0
+ if run $DIFF_CMD $GOLDEN_DIR/$name $file; then
+ : # No diff
+ else
+ file_changed=1
+ any_file_changed=1
+ fi
+
+ if (( $update && $file_changed )) ; then
+ echo "# Updating $name ..."
+ run cp $file $GOLDEN_DIR/$name
+ fi
+done
+
+if (( $three_way )) ; then
+ echo "# Running 3-way diff with meld..."
+ run meld ${files[*]} &
+fi
+
+if (( $two_way )) ; then
+ echo "# Running meld..."
+ run meld --diff ${files[0]} ${files[1]} --diff ${files[1]} ${files[2]}
+fi
+
+if (( $any_file_changed == 0 )) ; then
+ echo "$SCRIPT_NAME: Success: no changes detected."
+ exit 0
+else
+ if (( $update )) ; then
+ echo "$SCRIPT_NAME: Warning: golden files have been updated."
+ exit 2
+ else
+ echo "$SCRIPT_NAME: Failure: changes detected. See above diff for the details."
+ exit 3
+ fi
+fi
diff --git a/tools/hoststubgen/hoststubgen/test-tiny-framework/golden-output/01-hoststubgen-test-tiny-framework-orig-dump.txt b/tools/hoststubgen/hoststubgen/test-tiny-framework/golden-output/01-hoststubgen-test-tiny-framework-orig-dump.txt
new file mode 100644
index 000000000000..1aa485963f97
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/test-tiny-framework/golden-output/01-hoststubgen-test-tiny-framework-orig-dump.txt
@@ -0,0 +1,1671 @@
+## Class: android/hosttest/annotation/HostSideTestClassLoadHook.class
+ Compiled from "HostSideTestClassLoadHook.java"
+public interface android.hosttest.annotation.HostSideTestClassLoadHook extends java.lang.annotation.Annotation
+ minor version: 0
+ major version: 61
+ flags: (0x2601) ACC_PUBLIC, ACC_INTERFACE, ACC_ABSTRACT, ACC_ANNOTATION
+ this_class: #x // android/hosttest/annotation/HostSideTestClassLoadHook
+ super_class: #x // java/lang/Object
+ interfaces: 1, fields: 0, methods: 1, attributes: 2
+ public abstract java.lang.String value();
+ descriptor: ()Ljava/lang/String;
+ flags: (0x0401) ACC_PUBLIC, ACC_ABSTRACT
+}
+SourceFile: "HostSideTestClassLoadHook.java"
+RuntimeVisibleAnnotations:
+ 0: #x(#x=[e#x.#x])
+ java.lang.annotation.Target(
+ value=[Ljava/lang/annotation/ElementType;.TYPE]
+ )
+ 1: #x(#x=e#x.#x)
+ java.lang.annotation.Retention(
+ value=Ljava/lang/annotation/RetentionPolicy;.CLASS
+ )
+## Class: android/hosttest/annotation/HostSideTestKeep.class
+ Compiled from "HostSideTestKeep.java"
+public interface android.hosttest.annotation.HostSideTestKeep extends java.lang.annotation.Annotation
+ minor version: 0
+ major version: 61
+ flags: (0x2601) ACC_PUBLIC, ACC_INTERFACE, ACC_ABSTRACT, ACC_ANNOTATION
+ this_class: #x // android/hosttest/annotation/HostSideTestKeep
+ super_class: #x // java/lang/Object
+ interfaces: 1, fields: 0, methods: 0, attributes: 2
+}
+SourceFile: "HostSideTestKeep.java"
+RuntimeVisibleAnnotations:
+ 0: #x(#x=[e#x.#x,e#x.#x,e#x.#x,e#x.#x])
+ java.lang.annotation.Target(
+ value=[Ljava/lang/annotation/ElementType;.TYPE,Ljava/lang/annotation/ElementType;.FIELD,Ljava/lang/annotation/ElementType;.METHOD,Ljava/lang/annotation/ElementType;.CONSTRUCTOR]
+ )
+ 1: #x(#x=e#x.#x)
+ java.lang.annotation.Retention(
+ value=Ljava/lang/annotation/RetentionPolicy;.CLASS
+ )
+## Class: android/hosttest/annotation/HostSideTestNativeSubstitutionClass.class
+ Compiled from "HostSideTestNativeSubstitutionClass.java"
+public interface android.hosttest.annotation.HostSideTestNativeSubstitutionClass extends java.lang.annotation.Annotation
+ minor version: 0
+ major version: 61
+ flags: (0x2601) ACC_PUBLIC, ACC_INTERFACE, ACC_ABSTRACT, ACC_ANNOTATION
+ this_class: #x // android/hosttest/annotation/HostSideTestNativeSubstitutionClass
+ super_class: #x // java/lang/Object
+ interfaces: 1, fields: 0, methods: 1, attributes: 2
+ public abstract java.lang.String value();
+ descriptor: ()Ljava/lang/String;
+ flags: (0x0401) ACC_PUBLIC, ACC_ABSTRACT
+}
+SourceFile: "HostSideTestNativeSubstitutionClass.java"
+RuntimeVisibleAnnotations:
+ 0: #x(#x=[e#x.#x])
+ java.lang.annotation.Target(
+ value=[Ljava/lang/annotation/ElementType;.TYPE]
+ )
+ 1: #x(#x=e#x.#x)
+ java.lang.annotation.Retention(
+ value=Ljava/lang/annotation/RetentionPolicy;.CLASS
+ )
+## Class: android/hosttest/annotation/HostSideTestRemove.class
+ Compiled from "HostSideTestRemove.java"
+public interface android.hosttest.annotation.HostSideTestRemove extends java.lang.annotation.Annotation
+ minor version: 0
+ major version: 61
+ flags: (0x2601) ACC_PUBLIC, ACC_INTERFACE, ACC_ABSTRACT, ACC_ANNOTATION
+ this_class: #x // android/hosttest/annotation/HostSideTestRemove
+ super_class: #x // java/lang/Object
+ interfaces: 1, fields: 0, methods: 0, attributes: 2
+}
+SourceFile: "HostSideTestRemove.java"
+RuntimeVisibleAnnotations:
+ 0: #x(#x=[e#x.#x,e#x.#x,e#x.#x,e#x.#x])
+ java.lang.annotation.Target(
+ value=[Ljava/lang/annotation/ElementType;.TYPE,Ljava/lang/annotation/ElementType;.FIELD,Ljava/lang/annotation/ElementType;.METHOD,Ljava/lang/annotation/ElementType;.CONSTRUCTOR]
+ )
+ 1: #x(#x=e#x.#x)
+ java.lang.annotation.Retention(
+ value=Ljava/lang/annotation/RetentionPolicy;.CLASS
+ )
+## Class: android/hosttest/annotation/HostSideTestStub.class
+ Compiled from "HostSideTestStub.java"
+public interface android.hosttest.annotation.HostSideTestStub extends java.lang.annotation.Annotation
+ minor version: 0
+ major version: 61
+ flags: (0x2601) ACC_PUBLIC, ACC_INTERFACE, ACC_ABSTRACT, ACC_ANNOTATION
+ this_class: #x // android/hosttest/annotation/HostSideTestStub
+ super_class: #x // java/lang/Object
+ interfaces: 1, fields: 0, methods: 0, attributes: 2
+}
+SourceFile: "HostSideTestStub.java"
+RuntimeVisibleAnnotations:
+ 0: #x(#x=[e#x.#x,e#x.#x,e#x.#x,e#x.#x])
+ java.lang.annotation.Target(
+ value=[Ljava/lang/annotation/ElementType;.TYPE,Ljava/lang/annotation/ElementType;.FIELD,Ljava/lang/annotation/ElementType;.METHOD,Ljava/lang/annotation/ElementType;.CONSTRUCTOR]
+ )
+ 1: #x(#x=e#x.#x)
+ java.lang.annotation.Retention(
+ value=Ljava/lang/annotation/RetentionPolicy;.CLASS
+ )
+## Class: android/hosttest/annotation/HostSideTestSubstitute.class
+ Compiled from "HostSideTestSubstitute.java"
+public interface android.hosttest.annotation.HostSideTestSubstitute extends java.lang.annotation.Annotation
+ minor version: 0
+ major version: 61
+ flags: (0x2601) ACC_PUBLIC, ACC_INTERFACE, ACC_ABSTRACT, ACC_ANNOTATION
+ this_class: #x // android/hosttest/annotation/HostSideTestSubstitute
+ super_class: #x // java/lang/Object
+ interfaces: 1, fields: 0, methods: 1, attributes: 2
+ public abstract java.lang.String suffix();
+ descriptor: ()Ljava/lang/String;
+ flags: (0x0401) ACC_PUBLIC, ACC_ABSTRACT
+}
+SourceFile: "HostSideTestSubstitute.java"
+RuntimeVisibleAnnotations:
+ 0: #x(#x=[e#x.#x])
+ java.lang.annotation.Target(
+ value=[Ljava/lang/annotation/ElementType;.METHOD]
+ )
+ 1: #x(#x=e#x.#x)
+ java.lang.annotation.Retention(
+ value=Ljava/lang/annotation/RetentionPolicy;.CLASS
+ )
+## Class: android/hosttest/annotation/HostSideTestThrow.class
+ Compiled from "HostSideTestThrow.java"
+public interface android.hosttest.annotation.HostSideTestThrow extends java.lang.annotation.Annotation
+ minor version: 0
+ major version: 61
+ flags: (0x2601) ACC_PUBLIC, ACC_INTERFACE, ACC_ABSTRACT, ACC_ANNOTATION
+ this_class: #x // android/hosttest/annotation/HostSideTestThrow
+ super_class: #x // java/lang/Object
+ interfaces: 1, fields: 0, methods: 0, attributes: 2
+}
+SourceFile: "HostSideTestThrow.java"
+RuntimeVisibleAnnotations:
+ 0: #x(#x=[e#x.#x,e#x.#x])
+ java.lang.annotation.Target(
+ value=[Ljava/lang/annotation/ElementType;.METHOD,Ljava/lang/annotation/ElementType;.CONSTRUCTOR]
+ )
+ 1: #x(#x=e#x.#x)
+ java.lang.annotation.Retention(
+ value=Ljava/lang/annotation/RetentionPolicy;.CLASS
+ )
+## Class: android/hosttest/annotation/HostSideTestWholeClassKeep.class
+ Compiled from "HostSideTestWholeClassKeep.java"
+public interface android.hosttest.annotation.HostSideTestWholeClassKeep extends java.lang.annotation.Annotation
+ minor version: 0
+ major version: 61
+ flags: (0x2601) ACC_PUBLIC, ACC_INTERFACE, ACC_ABSTRACT, ACC_ANNOTATION
+ this_class: #x // android/hosttest/annotation/HostSideTestWholeClassKeep
+ super_class: #x // java/lang/Object
+ interfaces: 1, fields: 0, methods: 0, attributes: 2
+}
+SourceFile: "HostSideTestWholeClassKeep.java"
+RuntimeVisibleAnnotations:
+ 0: #x(#x=[e#x.#x])
+ java.lang.annotation.Target(
+ value=[Ljava/lang/annotation/ElementType;.TYPE]
+ )
+ 1: #x(#x=e#x.#x)
+ java.lang.annotation.Retention(
+ value=Ljava/lang/annotation/RetentionPolicy;.CLASS
+ )
+## Class: android/hosttest/annotation/HostSideTestWholeClassStub.class
+ Compiled from "HostSideTestWholeClassStub.java"
+public interface android.hosttest.annotation.HostSideTestWholeClassStub extends java.lang.annotation.Annotation
+ minor version: 0
+ major version: 61
+ flags: (0x2601) ACC_PUBLIC, ACC_INTERFACE, ACC_ABSTRACT, ACC_ANNOTATION
+ this_class: #x // android/hosttest/annotation/HostSideTestWholeClassStub
+ super_class: #x // java/lang/Object
+ interfaces: 1, fields: 0, methods: 0, attributes: 2
+}
+SourceFile: "HostSideTestWholeClassStub.java"
+RuntimeVisibleAnnotations:
+ 0: #x(#x=[e#x.#x])
+ java.lang.annotation.Target(
+ value=[Ljava/lang/annotation/ElementType;.TYPE]
+ )
+ 1: #x(#x=e#x.#x)
+ java.lang.annotation.Retention(
+ value=Ljava/lang/annotation/RetentionPolicy;.CLASS
+ )
+## Class: android/hosttest/annotation/tests/HostSideTestSuppress.class
+ Compiled from "HostSideTestSuppress.java"
+public interface android.hosttest.annotation.tests.HostSideTestSuppress extends java.lang.annotation.Annotation
+ minor version: 0
+ major version: 61
+ flags: (0x2601) ACC_PUBLIC, ACC_INTERFACE, ACC_ABSTRACT, ACC_ANNOTATION
+ this_class: #x // android/hosttest/annotation/tests/HostSideTestSuppress
+ super_class: #x // java/lang/Object
+ interfaces: 1, fields: 0, methods: 0, attributes: 2
+}
+SourceFile: "HostSideTestSuppress.java"
+RuntimeVisibleAnnotations:
+ 0: #x(#x=[e#x.#x,e#x.#x,e#x.#x])
+ java.lang.annotation.Target(
+ value=[Ljava/lang/annotation/ElementType;.TYPE,Ljava/lang/annotation/ElementType;.FIELD,Ljava/lang/annotation/ElementType;.METHOD]
+ )
+## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck$Impl.class
+ Compiled from "TinyFrameworkCallerCheck.java"
+class com.android.hoststubgen.test.tinyframework.TinyFrameworkCallerCheck$Impl
+ minor version: 0
+ major version: 61
+ flags: (0x0020) ACC_SUPER
+ this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck$Impl
+ super_class: #x // java/lang/Object
+ interfaces: 0, fields: 0, methods: 3, attributes: 3
+ private com.android.hoststubgen.test.tinyframework.TinyFrameworkCallerCheck$Impl();
+ descriptor: ()V
+ flags: (0x0002) ACC_PRIVATE
+ Code:
+ stack=1, locals=1, args_size=1
+ 0: aload_0
+ 1: invokespecial #x // Method java/lang/Object."<init>":()V
+ 4: return
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck$Impl;
+
+ public static int getOneKeep();
+ descriptor: ()I
+ flags: (0x0009) ACC_PUBLIC, ACC_STATIC
+ Code:
+ stack=1, locals=0, args_size=0
+ 0: iconst_1
+ 1: ireturn
+ LineNumberTable:
+ RuntimeInvisibleAnnotations:
+ 0: #x()
+ android.hosttest.annotation.HostSideTestKeep
+
+ public static int getOneStub();
+ descriptor: ()I
+ flags: (0x0009) ACC_PUBLIC, ACC_STATIC
+ Code:
+ stack=1, locals=0, args_size=0
+ 0: iconst_1
+ 1: ireturn
+ LineNumberTable:
+ RuntimeInvisibleAnnotations:
+ 0: #x()
+ android.hosttest.annotation.HostSideTestStub
+}
+SourceFile: "TinyFrameworkCallerCheck.java"
+NestHost: class com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck
+InnerClasses:
+ private static #x= #x of #x; // Impl=class com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck$Impl of class com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck
+## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck.class
+ Compiled from "TinyFrameworkCallerCheck.java"
+public class com.android.hoststubgen.test.tinyframework.TinyFrameworkCallerCheck
+ minor version: 0
+ major version: 61
+ flags: (0x0021) ACC_PUBLIC, ACC_SUPER
+ this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck
+ super_class: #x // java/lang/Object
+ interfaces: 0, fields: 0, methods: 3, attributes: 4
+ public com.android.hoststubgen.test.tinyframework.TinyFrameworkCallerCheck();
+ descriptor: ()V
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=1, locals=1, args_size=1
+ 0: aload_0
+ 1: invokespecial #x // Method java/lang/Object."<init>":()V
+ 4: return
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck;
+
+ public static int getOne_withCheck();
+ descriptor: ()I
+ flags: (0x0009) ACC_PUBLIC, ACC_STATIC
+ Code:
+ stack=1, locals=0, args_size=0
+ 0: invokestatic #x // Method com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck$Impl.getOneKeep:()I
+ 3: ireturn
+ LineNumberTable:
+
+ public static int getOne_noCheck();
+ descriptor: ()I
+ flags: (0x0009) ACC_PUBLIC, ACC_STATIC
+ Code:
+ stack=1, locals=0, args_size=0
+ 0: invokestatic #x // Method com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck$Impl.getOneStub:()I
+ 3: ireturn
+ LineNumberTable:
+}
+SourceFile: "TinyFrameworkCallerCheck.java"
+RuntimeInvisibleAnnotations:
+ 0: #x()
+ android.hosttest.annotation.HostSideTestWholeClassStub
+NestMembers:
+ com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck$Impl
+InnerClasses:
+ private static #x= #x of #x; // Impl=class com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck$Impl of class com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck
+## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkClassAnnotations.class
+ Compiled from "TinyFrameworkClassAnnotations.java"
+public class com.android.hoststubgen.test.tinyframework.TinyFrameworkClassAnnotations
+ minor version: 0
+ major version: 61
+ flags: (0x0021) ACC_PUBLIC, ACC_SUPER
+ this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkClassAnnotations
+ super_class: #x // java/lang/Object
+ interfaces: 0, fields: 3, methods: 10, attributes: 2
+ public int stub;
+ descriptor: I
+ flags: (0x0001) ACC_PUBLIC
+ RuntimeInvisibleAnnotations:
+ 0: #x()
+ android.hosttest.annotation.HostSideTestStub
+
+ public int keep;
+ descriptor: I
+ flags: (0x0001) ACC_PUBLIC
+ RuntimeInvisibleAnnotations:
+ 0: #x()
+ android.hosttest.annotation.HostSideTestKeep
+
+ public int remove;
+ descriptor: I
+ flags: (0x0001) ACC_PUBLIC
+
+ public com.android.hoststubgen.test.tinyframework.TinyFrameworkClassAnnotations();
+ descriptor: ()V
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=2, locals=1, args_size=1
+ 0: aload_0
+ 1: invokespecial #x // Method java/lang/Object."<init>":()V
+ 4: aload_0
+ 5: iconst_1
+ 6: putfield #x // Field stub:I
+ 9: aload_0
+ 10: iconst_2
+ 11: putfield #x // Field keep:I
+ 14: return
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 15 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkClassAnnotations;
+ RuntimeInvisibleAnnotations:
+ 0: #x()
+ android.hosttest.annotation.HostSideTestStub
+
+ public int addOne(int);
+ descriptor: (I)I
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=2, locals=2, args_size=2
+ 0: aload_0
+ 1: iload_1
+ 2: invokevirtual #x // Method addOneInner:(I)I
+ 5: ireturn
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 6 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkClassAnnotations;
+ 0 6 1 value I
+ RuntimeInvisibleAnnotations:
+ 0: #x()
+ android.hosttest.annotation.HostSideTestStub
+
+ public int addOneInner(int);
+ descriptor: (I)I
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=2, locals=2, args_size=2
+ 0: iload_1
+ 1: iconst_1
+ 2: iadd
+ 3: ireturn
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 4 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkClassAnnotations;
+ 0 4 1 value I
+ RuntimeInvisibleAnnotations:
+ 0: #x()
+ android.hosttest.annotation.HostSideTestKeep
+
+ public void toBeRemoved(java.lang.String);
+ descriptor: (Ljava/lang/String;)V
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=2, locals=2, args_size=2
+ 0: new #x // class java/lang/RuntimeException
+ 3: dup
+ 4: invokespecial #x // Method java/lang/RuntimeException."<init>":()V
+ 7: athrow
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 8 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkClassAnnotations;
+ 0 8 1 foo Ljava/lang/String;
+ RuntimeInvisibleAnnotations:
+ 0: #x()
+ android.hosttest.annotation.HostSideTestRemove
+
+ public int addTwo(int);
+ descriptor: (I)I
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=3, locals=2, args_size=2
+ 0: new #x // class java/lang/RuntimeException
+ 3: dup
+ 4: ldc #x // String not supported on host side
+ 6: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
+ 9: athrow
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 10 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkClassAnnotations;
+ 0 10 1 value I
+ RuntimeInvisibleAnnotations:
+ 0: #x()
+ android.hosttest.annotation.HostSideTestStub
+ 1: #x(#x=s#x)
+ android.hosttest.annotation.HostSideTestSubstitute(
+ suffix="_host"
+ )
+
+ public int addTwo_host(int);
+ descriptor: (I)I
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=2, locals=2, args_size=2
+ 0: iload_1
+ 1: iconst_2
+ 2: iadd
+ 3: ireturn
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 4 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkClassAnnotations;
+ 0 4 1 value I
+
+ public static native int nativeAddThree(int);
+ descriptor: (I)I
+ flags: (0x0109) ACC_PUBLIC, ACC_STATIC, ACC_NATIVE
+ RuntimeInvisibleAnnotations:
+ 0: #x()
+ android.hosttest.annotation.HostSideTestStub
+ 1: #x(#x=s#x)
+ android.hosttest.annotation.HostSideTestSubstitute(
+ suffix="_host"
+ )
+
+ public static int nativeAddThree_host(int);
+ descriptor: (I)I
+ flags: (0x0009) ACC_PUBLIC, ACC_STATIC
+ Code:
+ stack=2, locals=1, args_size=1
+ 0: iload_0
+ 1: iconst_3
+ 2: iadd
+ 3: ireturn
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 4 0 value I
+
+ public java.lang.String unsupportedMethod();
+ descriptor: ()Ljava/lang/String;
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=1, locals=1, args_size=1
+ 0: ldc #x // String This value shouldn\'t be seen on the host side.
+ 2: areturn
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 3 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkClassAnnotations;
+ RuntimeInvisibleAnnotations:
+ 0: #x()
+ android.hosttest.annotation.HostSideTestThrow
+
+ public java.lang.String visibleButUsesUnsupportedMethod();
+ descriptor: ()Ljava/lang/String;
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=1, locals=1, args_size=1
+ 0: aload_0
+ 1: invokevirtual #x // Method unsupportedMethod:()Ljava/lang/String;
+ 4: areturn
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkClassAnnotations;
+ RuntimeInvisibleAnnotations:
+ 0: #x()
+ android.hosttest.annotation.HostSideTestStub
+}
+SourceFile: "TinyFrameworkClassAnnotations.java"
+RuntimeInvisibleAnnotations:
+ 0: #x()
+ android.hosttest.annotation.HostSideTestStub
+ 1: #x(#x=s#x)
+ android.hosttest.annotation.HostSideTestClassLoadHook(
+ value="com.android.hoststubgen.test.tinyframework.TinyFrameworkClassLoadHook.onClassLoaded"
+ )
+## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkClassClassWideAnnotations.class
+ Compiled from "TinyFrameworkClassClassWideAnnotations.java"
+public class com.android.hoststubgen.test.tinyframework.TinyFrameworkClassClassWideAnnotations
+ minor version: 0
+ major version: 61
+ flags: (0x0021) ACC_PUBLIC, ACC_SUPER
+ this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkClassClassWideAnnotations
+ super_class: #x // java/lang/Object
+ interfaces: 0, fields: 3, methods: 10, attributes: 2
+ public int stub;
+ descriptor: I
+ flags: (0x0001) ACC_PUBLIC
+
+ public int keep;
+ descriptor: I
+ flags: (0x0001) ACC_PUBLIC
+
+ public int remove;
+ descriptor: I
+ flags: (0x0001) ACC_PUBLIC
+
+ public com.android.hoststubgen.test.tinyframework.TinyFrameworkClassClassWideAnnotations();
+ descriptor: ()V
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=2, locals=1, args_size=1
+ 0: aload_0
+ 1: invokespecial #x // Method java/lang/Object."<init>":()V
+ 4: aload_0
+ 5: iconst_1
+ 6: putfield #x // Field stub:I
+ 9: aload_0
+ 10: iconst_2
+ 11: putfield #x // Field keep:I
+ 14: return
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 15 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkClassClassWideAnnotations;
+
+ public int addOne(int);
+ descriptor: (I)I
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=2, locals=2, args_size=2
+ 0: aload_0
+ 1: iload_1
+ 2: invokevirtual #x // Method addOneInner:(I)I
+ 5: ireturn
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 6 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkClassClassWideAnnotations;
+ 0 6 1 value I
+
+ public int addOneInner(int);
+ descriptor: (I)I
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=2, locals=2, args_size=2
+ 0: iload_1
+ 1: iconst_1
+ 2: iadd
+ 3: ireturn
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 4 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkClassClassWideAnnotations;
+ 0 4 1 value I
+
+ public void toBeRemoved(java.lang.String);
+ descriptor: (Ljava/lang/String;)V
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=2, locals=2, args_size=2
+ 0: new #x // class java/lang/RuntimeException
+ 3: dup
+ 4: invokespecial #x // Method java/lang/RuntimeException."<init>":()V
+ 7: athrow
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 8 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkClassClassWideAnnotations;
+ 0 8 1 foo Ljava/lang/String;
+
+ public int addTwo(int);
+ descriptor: (I)I
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=3, locals=2, args_size=2
+ 0: new #x // class java/lang/RuntimeException
+ 3: dup
+ 4: ldc #x // String not supported on host side
+ 6: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
+ 9: athrow
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 10 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkClassClassWideAnnotations;
+ 0 10 1 value I
+ RuntimeInvisibleAnnotations:
+ 0: #x()
+ android.hosttest.annotation.HostSideTestStub
+ 1: #x(#x=s#x)
+ android.hosttest.annotation.HostSideTestSubstitute(
+ suffix="_host"
+ )
+
+ public int addTwo_host(int);
+ descriptor: (I)I
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=2, locals=2, args_size=2
+ 0: iload_1
+ 1: iconst_2
+ 2: iadd
+ 3: ireturn
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 4 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkClassClassWideAnnotations;
+ 0 4 1 value I
+
+ public static native int nativeAddThree(int);
+ descriptor: (I)I
+ flags: (0x0109) ACC_PUBLIC, ACC_STATIC, ACC_NATIVE
+ RuntimeInvisibleAnnotations:
+ 0: #x()
+ android.hosttest.annotation.HostSideTestStub
+ 1: #x(#x=s#x)
+ android.hosttest.annotation.HostSideTestSubstitute(
+ suffix="_host"
+ )
+
+ public static int nativeAddThree_host(int);
+ descriptor: (I)I
+ flags: (0x0009) ACC_PUBLIC, ACC_STATIC
+ Code:
+ stack=2, locals=1, args_size=1
+ 0: iload_0
+ 1: iconst_3
+ 2: iadd
+ 3: ireturn
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 4 0 value I
+
+ public java.lang.String unsupportedMethod();
+ descriptor: ()Ljava/lang/String;
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=1, locals=1, args_size=1
+ 0: ldc #x // String This value shouldn\'t be seen on the host side.
+ 2: areturn
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 3 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkClassClassWideAnnotations;
+
+ public java.lang.String visibleButUsesUnsupportedMethod();
+ descriptor: ()Ljava/lang/String;
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=1, locals=1, args_size=1
+ 0: aload_0
+ 1: invokevirtual #x // Method unsupportedMethod:()Ljava/lang/String;
+ 4: areturn
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkClassClassWideAnnotations;
+}
+SourceFile: "TinyFrameworkClassClassWideAnnotations.java"
+RuntimeInvisibleAnnotations:
+ 0: #x()
+ android.hosttest.annotation.HostSideTestWholeClassStub
+## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkClassLoadHook.class
+ Compiled from "TinyFrameworkClassLoadHook.java"
+public class com.android.hoststubgen.test.tinyframework.TinyFrameworkClassLoadHook
+ minor version: 0
+ major version: 61
+ flags: (0x0021) ACC_PUBLIC, ACC_SUPER
+ this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkClassLoadHook
+ super_class: #x // java/lang/Object
+ interfaces: 0, fields: 1, methods: 3, attributes: 2
+ public static final java.util.Set<java.lang.Class<?>> sLoadedClasses;
+ descriptor: Ljava/util/Set;
+ flags: (0x0019) ACC_PUBLIC, ACC_STATIC, ACC_FINAL
+ Signature: #x // Ljava/util/Set<Ljava/lang/Class<*>;>;
+
+ private com.android.hoststubgen.test.tinyframework.TinyFrameworkClassLoadHook();
+ descriptor: ()V
+ flags: (0x0002) ACC_PRIVATE
+ Code:
+ stack=1, locals=1, args_size=1
+ 0: aload_0
+ 1: invokespecial #x // Method java/lang/Object."<init>":()V
+ 4: return
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkClassLoadHook;
+
+ public static void onClassLoaded(java.lang.Class<?>);
+ descriptor: (Ljava/lang/Class;)V
+ flags: (0x0009) ACC_PUBLIC, ACC_STATIC
+ Code:
+ stack=2, locals=1, args_size=1
+ 0: getstatic #x // Field sLoadedClasses:Ljava/util/Set;
+ 3: aload_0
+ 4: invokeinterface #x, 2 // InterfaceMethod java/util/Set.add:(Ljava/lang/Object;)Z
+ 9: pop
+ 10: return
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 11 0 clazz Ljava/lang/Class;
+ LocalVariableTypeTable:
+ Start Length Slot Name Signature
+ 0 11 0 clazz Ljava/lang/Class<*>;
+ Signature: #x // (Ljava/lang/Class<*>;)V
+
+ static {};
+ descriptor: ()V
+ flags: (0x0008) ACC_STATIC
+ Code:
+ stack=2, locals=0, args_size=0
+ 0: new #x // class java/util/HashSet
+ 3: dup
+ 4: invokespecial #x // Method java/util/HashSet."<init>":()V
+ 7: putstatic #x // Field sLoadedClasses:Ljava/util/Set;
+ 10: return
+ LineNumberTable:
+}
+SourceFile: "TinyFrameworkClassLoadHook.java"
+RuntimeInvisibleAnnotations:
+ 0: #x()
+ android.hosttest.annotation.HostSideTestWholeClassStub
+## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkClassWithInitializer.class
+ Compiled from "TinyFrameworkClassWithInitializer.java"
+public class com.android.hoststubgen.test.tinyframework.TinyFrameworkClassWithInitializer
+ minor version: 0
+ major version: 61
+ flags: (0x0021) ACC_PUBLIC, ACC_SUPER
+ this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkClassWithInitializer
+ super_class: #x // java/lang/Object
+ interfaces: 0, fields: 1, methods: 2, attributes: 2
+ public static boolean sInitialized;
+ descriptor: Z
+ flags: (0x0009) ACC_PUBLIC, ACC_STATIC
+
+ public com.android.hoststubgen.test.tinyframework.TinyFrameworkClassWithInitializer();
+ descriptor: ()V
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=1, locals=1, args_size=1
+ 0: aload_0
+ 1: invokespecial #x // Method java/lang/Object."<init>":()V
+ 4: return
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkClassWithInitializer;
+
+ static {};
+ descriptor: ()V
+ flags: (0x0008) ACC_STATIC
+ Code:
+ stack=1, locals=0, args_size=0
+ 0: iconst_1
+ 1: putstatic #x // Field sInitialized:Z
+ 4: return
+ LineNumberTable:
+}
+SourceFile: "TinyFrameworkClassWithInitializer.java"
+RuntimeInvisibleAnnotations:
+ 0: #x(#x=s#x)
+ android.hosttest.annotation.HostSideTestClassLoadHook(
+ value="com.android.hoststubgen.test.tinyframework.TinyFrameworkClassLoadHook.onClassLoaded"
+ )
+ 1: #x()
+ android.hosttest.annotation.HostSideTestWholeClassStub
+## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkExceptionTester.class
+ Compiled from "TinyFrameworkExceptionTester.java"
+public class com.android.hoststubgen.test.tinyframework.TinyFrameworkExceptionTester
+ minor version: 0
+ major version: 61
+ flags: (0x0021) ACC_PUBLIC, ACC_SUPER
+ this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkExceptionTester
+ super_class: #x // java/lang/Object
+ interfaces: 0, fields: 0, methods: 2, attributes: 2
+ public com.android.hoststubgen.test.tinyframework.TinyFrameworkExceptionTester();
+ descriptor: ()V
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=1, locals=1, args_size=1
+ 0: aload_0
+ 1: invokespecial #x // Method java/lang/Object."<init>":()V
+ 4: return
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkExceptionTester;
+
+ public static int testException();
+ descriptor: ()I
+ flags: (0x0009) ACC_PUBLIC, ACC_STATIC
+ Code:
+ stack=4, locals=1, args_size=0
+ 0: new #x // class java/lang/IllegalStateException
+ 3: dup
+ 4: ldc #x // String Inner exception
+ 6: invokespecial #x // Method java/lang/IllegalStateException."<init>":(Ljava/lang/String;)V
+ 9: athrow
+ 10: astore_0
+ 11: new #x // class java/lang/RuntimeException
+ 14: dup
+ 15: ldc #x // String Outer exception
+ 17: aload_0
+ 18: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;Ljava/lang/Throwable;)V
+ 21: athrow
+ Exception table:
+ from to target type
+ 0 10 10 Class java/lang/Exception
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 11 11 0 e Ljava/lang/Exception;
+ StackMapTable: number_of_entries = 1
+ frame_type = 74 /* same_locals_1_stack_item */
+ stack = [ class java/lang/Exception ]
+}
+SourceFile: "TinyFrameworkExceptionTester.java"
+RuntimeInvisibleAnnotations:
+ 0: #x()
+ android.hosttest.annotation.HostSideTestWholeClassStub
+## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy.class
+ Compiled from "TinyFrameworkForTextPolicy.java"
+public class com.android.hoststubgen.test.tinyframework.TinyFrameworkForTextPolicy
+ minor version: 0
+ major version: 61
+ flags: (0x0021) ACC_PUBLIC, ACC_SUPER
+ this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy
+ super_class: #x // java/lang/Object
+ interfaces: 0, fields: 3, methods: 10, attributes: 1
+ public int stub;
+ descriptor: I
+ flags: (0x0001) ACC_PUBLIC
+
+ public int keep;
+ descriptor: I
+ flags: (0x0001) ACC_PUBLIC
+
+ public int remove;
+ descriptor: I
+ flags: (0x0001) ACC_PUBLIC
+
+ public com.android.hoststubgen.test.tinyframework.TinyFrameworkForTextPolicy();
+ descriptor: ()V
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=2, locals=1, args_size=1
+ 0: aload_0
+ 1: invokespecial #x // Method java/lang/Object."<init>":()V
+ 4: aload_0
+ 5: iconst_1
+ 6: putfield #x // Field stub:I
+ 9: aload_0
+ 10: iconst_2
+ 11: putfield #x // Field keep:I
+ 14: return
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 15 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy;
+
+ public int addOne(int);
+ descriptor: (I)I
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=2, locals=2, args_size=2
+ 0: aload_0
+ 1: iload_1
+ 2: invokevirtual #x // Method addOneInner:(I)I
+ 5: ireturn
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 6 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy;
+ 0 6 1 value I
+
+ public int addOneInner(int);
+ descriptor: (I)I
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=2, locals=2, args_size=2
+ 0: iload_1
+ 1: iconst_1
+ 2: iadd
+ 3: ireturn
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 4 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy;
+ 0 4 1 value I
+
+ public void toBeRemoved(java.lang.String);
+ descriptor: (Ljava/lang/String;)V
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=2, locals=2, args_size=2
+ 0: new #x // class java/lang/RuntimeException
+ 3: dup
+ 4: invokespecial #x // Method java/lang/RuntimeException."<init>":()V
+ 7: athrow
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 8 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy;
+ 0 8 1 foo Ljava/lang/String;
+
+ public int addTwo(int);
+ descriptor: (I)I
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=3, locals=2, args_size=2
+ 0: new #x // class java/lang/RuntimeException
+ 3: dup
+ 4: ldc #x // String not supported on host side
+ 6: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
+ 9: athrow
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 10 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy;
+ 0 10 1 value I
+
+ public int addTwo_host(int);
+ descriptor: (I)I
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=2, locals=2, args_size=2
+ 0: iload_1
+ 1: iconst_2
+ 2: iadd
+ 3: ireturn
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 4 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy;
+ 0 4 1 value I
+
+ public static native int nativeAddThree(int);
+ descriptor: (I)I
+ flags: (0x0109) ACC_PUBLIC, ACC_STATIC, ACC_NATIVE
+
+ public static int addThree_host(int);
+ descriptor: (I)I
+ flags: (0x0009) ACC_PUBLIC, ACC_STATIC
+ Code:
+ stack=2, locals=1, args_size=1
+ 0: iload_0
+ 1: iconst_3
+ 2: iadd
+ 3: ireturn
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 4 0 value I
+
+ public java.lang.String unsupportedMethod();
+ descriptor: ()Ljava/lang/String;
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=1, locals=1, args_size=1
+ 0: ldc #x // String This value shouldn\'t be seen on the host side.
+ 2: areturn
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 3 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy;
+
+ public java.lang.String visibleButUsesUnsupportedMethod();
+ descriptor: ()Ljava/lang/String;
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=1, locals=1, args_size=1
+ 0: aload_0
+ 1: invokevirtual #x // Method unsupportedMethod:()Ljava/lang/String;
+ 4: areturn
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy;
+}
+SourceFile: "TinyFrameworkForTextPolicy.java"
+## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkNative.class
+ Compiled from "TinyFrameworkNative.java"
+public class com.android.hoststubgen.test.tinyframework.TinyFrameworkNative
+ minor version: 0
+ major version: 61
+ flags: (0x0021) ACC_PUBLIC, ACC_SUPER
+ this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkNative
+ super_class: #x // java/lang/Object
+ interfaces: 0, fields: 0, methods: 5, attributes: 2
+ public com.android.hoststubgen.test.tinyframework.TinyFrameworkNative();
+ descriptor: ()V
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=1, locals=1, args_size=1
+ 0: aload_0
+ 1: invokespecial #x // Method java/lang/Object."<init>":()V
+ 4: return
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNative;
+
+ public static native int nativeAddTwo(int);
+ descriptor: (I)I
+ flags: (0x0109) ACC_PUBLIC, ACC_STATIC, ACC_NATIVE
+
+ public static int nativeAddTwo_should_be_like_this(int);
+ descriptor: (I)I
+ flags: (0x0009) ACC_PUBLIC, ACC_STATIC
+ Code:
+ stack=1, locals=1, args_size=1
+ 0: iload_0
+ 1: invokestatic #x // Method com/android/hoststubgen/test/tinyframework/TinyFrameworkNative_host.nativeAddTwo:(I)I
+ 4: ireturn
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 5 0 arg I
+
+ public static native long nativeLongPlus(long, long);
+ descriptor: (JJ)J
+ flags: (0x0109) ACC_PUBLIC, ACC_STATIC, ACC_NATIVE
+
+ public static long nativeLongPlus_should_be_like_this(long, long);
+ descriptor: (JJ)J
+ flags: (0x0009) ACC_PUBLIC, ACC_STATIC
+ Code:
+ stack=4, locals=4, args_size=2
+ 0: lload_0
+ 1: lload_2
+ 2: invokestatic #x // Method com/android/hoststubgen/test/tinyframework/TinyFrameworkNative_host.nativeLongPlus:(JJ)J
+ 5: lreturn
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 6 0 arg1 J
+ 0 6 2 arg2 J
+}
+SourceFile: "TinyFrameworkNative.java"
+RuntimeInvisibleAnnotations:
+ 0: #x()
+ android.hosttest.annotation.HostSideTestWholeClassStub
+ 1: #x(#x=s#x)
+ android.hosttest.annotation.HostSideTestNativeSubstitutionClass(
+ value="TinyFrameworkNative_host"
+ )
+## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkNative_host.class
+ Compiled from "TinyFrameworkNative_host.java"
+public class com.android.hoststubgen.test.tinyframework.TinyFrameworkNative_host
+ minor version: 0
+ major version: 61
+ flags: (0x0021) ACC_PUBLIC, ACC_SUPER
+ this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkNative_host
+ super_class: #x // java/lang/Object
+ interfaces: 0, fields: 0, methods: 3, attributes: 2
+ public com.android.hoststubgen.test.tinyframework.TinyFrameworkNative_host();
+ descriptor: ()V
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=1, locals=1, args_size=1
+ 0: aload_0
+ 1: invokespecial #x // Method java/lang/Object."<init>":()V
+ 4: return
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNative_host;
+
+ public static int nativeAddTwo(int);
+ descriptor: (I)I
+ flags: (0x0009) ACC_PUBLIC, ACC_STATIC
+ Code:
+ stack=2, locals=1, args_size=1
+ 0: iload_0
+ 1: iconst_2
+ 2: iadd
+ 3: ireturn
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 4 0 arg I
+
+ public static long nativeLongPlus(long, long);
+ descriptor: (JJ)J
+ flags: (0x0009) ACC_PUBLIC, ACC_STATIC
+ Code:
+ stack=4, locals=4, args_size=2
+ 0: lload_0
+ 1: lload_2
+ 2: ladd
+ 3: lreturn
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 4 0 arg1 J
+ 0 4 2 arg2 J
+}
+SourceFile: "TinyFrameworkNative_host.java"
+RuntimeInvisibleAnnotations:
+ 0: #x()
+ android.hosttest.annotation.HostSideTestWholeClassKeep
+## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$1.class
+ Compiled from "TinyFrameworkNestedClasses.java"
+class com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$1 extends java.lang.Object implements java.util.function.Supplier<java.lang.Integer>
+ minor version: 0
+ major version: 61
+ flags: (0x0020) ACC_SUPER
+ this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$1
+ super_class: #x // java/lang/Object
+ interfaces: 1, fields: 1, methods: 3, attributes: 5
+ final com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses this$0;
+ descriptor: Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses;
+ flags: (0x1010) ACC_FINAL, ACC_SYNTHETIC
+
+ com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$1(com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses);
+ descriptor: (Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses;)V
+ flags: (0x0000)
+ Code:
+ stack=2, locals=2, args_size=2
+ 0: aload_0
+ 1: aload_1
+ 2: putfield #x // Field this$0:Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses;
+ 5: aload_0
+ 6: invokespecial #x // Method java/lang/Object."<init>":()V
+ 9: return
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 10 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$1;
+ 0 10 1 this$0 Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses;
+
+ public java.lang.Integer get();
+ descriptor: ()Ljava/lang/Integer;
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=1, locals=1, args_size=1
+ 0: iconst_1
+ 1: invokestatic #x // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
+ 4: areturn
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$1;
+
+ public java.lang.Object get();
+ descriptor: ()Ljava/lang/Object;
+ flags: (0x1041) ACC_PUBLIC, ACC_BRIDGE, ACC_SYNTHETIC
+ Code:
+ stack=1, locals=1, args_size=1
+ 0: aload_0
+ 1: invokevirtual #x // Method get:()Ljava/lang/Integer;
+ 4: areturn
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$1;
+}
+Signature: #x // Ljava/lang/Object;Ljava/util/function/Supplier<Ljava/lang/Integer;>;
+SourceFile: "TinyFrameworkNestedClasses.java"
+EnclosingMethod: #x.#x // com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses
+NestHost: class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
+InnerClasses:
+ #x; // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$1
+## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$2.class
+ Compiled from "TinyFrameworkNestedClasses.java"
+class com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$2 extends java.lang.Object implements java.util.function.Supplier<java.lang.Integer>
+ minor version: 0
+ major version: 61
+ flags: (0x0020) ACC_SUPER
+ this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$2
+ super_class: #x // java/lang/Object
+ interfaces: 1, fields: 0, methods: 3, attributes: 5
+ com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$2();
+ descriptor: ()V
+ flags: (0x0000)
+ Code:
+ stack=1, locals=1, args_size=1
+ 0: aload_0
+ 1: invokespecial #x // Method java/lang/Object."<init>":()V
+ 4: return
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$2;
+
+ public java.lang.Integer get();
+ descriptor: ()Ljava/lang/Integer;
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=1, locals=1, args_size=1
+ 0: iconst_2
+ 1: invokestatic #x // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
+ 4: areturn
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$2;
+
+ public java.lang.Object get();
+ descriptor: ()Ljava/lang/Object;
+ flags: (0x1041) ACC_PUBLIC, ACC_BRIDGE, ACC_SYNTHETIC
+ Code:
+ stack=1, locals=1, args_size=1
+ 0: aload_0
+ 1: invokevirtual #x // Method get:()Ljava/lang/Integer;
+ 4: areturn
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$2;
+}
+Signature: #x // Ljava/lang/Object;Ljava/util/function/Supplier<Ljava/lang/Integer;>;
+SourceFile: "TinyFrameworkNestedClasses.java"
+EnclosingMethod: #x.#x // com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses
+NestHost: class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
+InnerClasses:
+ #x; // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$2
+## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$3.class
+ Compiled from "TinyFrameworkNestedClasses.java"
+class com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$3 extends java.lang.Object implements java.util.function.Supplier<java.lang.Integer>
+ minor version: 0
+ major version: 61
+ flags: (0x0020) ACC_SUPER
+ this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$3
+ super_class: #x // java/lang/Object
+ interfaces: 1, fields: 1, methods: 3, attributes: 5
+ final com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses this$0;
+ descriptor: Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses;
+ flags: (0x1010) ACC_FINAL, ACC_SYNTHETIC
+
+ com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$3(com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses);
+ descriptor: (Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses;)V
+ flags: (0x0000)
+ Code:
+ stack=2, locals=2, args_size=2
+ 0: aload_0
+ 1: aload_1
+ 2: putfield #x // Field this$0:Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses;
+ 5: aload_0
+ 6: invokespecial #x // Method java/lang/Object."<init>":()V
+ 9: return
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 10 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$3;
+ 0 10 1 this$0 Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses;
+
+ public java.lang.Integer get();
+ descriptor: ()Ljava/lang/Integer;
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=1, locals=1, args_size=1
+ 0: iconst_3
+ 1: invokestatic #x // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
+ 4: areturn
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$3;
+
+ public java.lang.Object get();
+ descriptor: ()Ljava/lang/Object;
+ flags: (0x1041) ACC_PUBLIC, ACC_BRIDGE, ACC_SYNTHETIC
+ Code:
+ stack=1, locals=1, args_size=1
+ 0: aload_0
+ 1: invokevirtual #x // Method get:()Ljava/lang/Integer;
+ 4: areturn
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$3;
+}
+Signature: #x // Ljava/lang/Object;Ljava/util/function/Supplier<Ljava/lang/Integer;>;
+SourceFile: "TinyFrameworkNestedClasses.java"
+EnclosingMethod: #x.#x // com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses.getSupplier
+NestHost: class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
+InnerClasses:
+ #x; // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$3
+## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$4.class
+ Compiled from "TinyFrameworkNestedClasses.java"
+class com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$4 extends java.lang.Object implements java.util.function.Supplier<java.lang.Integer>
+ minor version: 0
+ major version: 61
+ flags: (0x0020) ACC_SUPER
+ this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$4
+ super_class: #x // java/lang/Object
+ interfaces: 1, fields: 0, methods: 3, attributes: 5
+ com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$4();
+ descriptor: ()V
+ flags: (0x0000)
+ Code:
+ stack=1, locals=1, args_size=1
+ 0: aload_0
+ 1: invokespecial #x // Method java/lang/Object."<init>":()V
+ 4: return
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$4;
+
+ public java.lang.Integer get();
+ descriptor: ()Ljava/lang/Integer;
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=1, locals=1, args_size=1
+ 0: iconst_4
+ 1: invokestatic #x // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
+ 4: areturn
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$4;
+
+ public java.lang.Object get();
+ descriptor: ()Ljava/lang/Object;
+ flags: (0x1041) ACC_PUBLIC, ACC_BRIDGE, ACC_SYNTHETIC
+ Code:
+ stack=1, locals=1, args_size=1
+ 0: aload_0
+ 1: invokevirtual #x // Method get:()Ljava/lang/Integer;
+ 4: areturn
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$4;
+}
+Signature: #x // Ljava/lang/Object;Ljava/util/function/Supplier<Ljava/lang/Integer;>;
+SourceFile: "TinyFrameworkNestedClasses.java"
+EnclosingMethod: #x.#x // com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses.getSupplier_static
+NestHost: class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
+InnerClasses:
+ #x; // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$4
+## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$BaseClass.class
+ Compiled from "TinyFrameworkNestedClasses.java"
+public class com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$BaseClass
+ minor version: 0
+ major version: 61
+ flags: (0x0021) ACC_PUBLIC, ACC_SUPER
+ this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$BaseClass
+ super_class: #x // java/lang/Object
+ interfaces: 0, fields: 1, methods: 1, attributes: 3
+ public int value;
+ descriptor: I
+ flags: (0x0001) ACC_PUBLIC
+
+ public com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$BaseClass(int);
+ descriptor: (I)V
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=2, locals=2, args_size=2
+ 0: aload_0
+ 1: invokespecial #x // Method java/lang/Object."<init>":()V
+ 4: aload_0
+ 5: iload_1
+ 6: putfield #x // Field value:I
+ 9: return
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 10 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$BaseClass;
+ 0 10 1 x I
+}
+SourceFile: "TinyFrameworkNestedClasses.java"
+NestHost: class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
+InnerClasses:
+ public static #x= #x of #x; // BaseClass=class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$BaseClass of class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
+## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$InnerClass.class
+ Compiled from "TinyFrameworkNestedClasses.java"
+public class com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$InnerClass
+ minor version: 0
+ major version: 61
+ flags: (0x0021) ACC_PUBLIC, ACC_SUPER
+ this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$InnerClass
+ super_class: #x // java/lang/Object
+ interfaces: 0, fields: 2, methods: 1, attributes: 4
+ public int value;
+ descriptor: I
+ flags: (0x0001) ACC_PUBLIC
+
+ final com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses this$0;
+ descriptor: Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses;
+ flags: (0x1010) ACC_FINAL, ACC_SYNTHETIC
+
+ public com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$InnerClass(com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses);
+ descriptor: (Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses;)V
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=2, locals=2, args_size=2
+ 0: aload_0
+ 1: aload_1
+ 2: putfield #x // Field this$0:Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses;
+ 5: aload_0
+ 6: invokespecial #x // Method java/lang/Object."<init>":()V
+ 9: aload_0
+ 10: iconst_5
+ 11: putfield #x // Field value:I
+ 14: return
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 15 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$InnerClass;
+ 0 15 1 this$0 Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses;
+}
+SourceFile: "TinyFrameworkNestedClasses.java"
+RuntimeInvisibleAnnotations:
+ 0: #x()
+ android.hosttest.annotation.HostSideTestWholeClassStub
+NestHost: class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
+InnerClasses:
+ public #x= #x of #x; // InnerClass=class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$InnerClass of class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
+## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass$1.class
+ Compiled from "TinyFrameworkNestedClasses.java"
+class com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$StaticNestedClass$1 extends java.lang.Object implements java.util.function.Supplier<java.lang.Integer>
+ minor version: 0
+ major version: 61
+ flags: (0x0020) ACC_SUPER
+ this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass$1
+ super_class: #x // java/lang/Object
+ interfaces: 1, fields: 0, methods: 3, attributes: 5
+ com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$StaticNestedClass$1();
+ descriptor: ()V
+ flags: (0x0000)
+ Code:
+ stack=1, locals=1, args_size=1
+ 0: aload_0
+ 1: invokespecial #x // Method java/lang/Object."<init>":()V
+ 4: return
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass$1;
+
+ public java.lang.Integer get();
+ descriptor: ()Ljava/lang/Integer;
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=1, locals=1, args_size=1
+ 0: bipush 7
+ 2: invokestatic #x // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
+ 5: areturn
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 6 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass$1;
+
+ public java.lang.Object get();
+ descriptor: ()Ljava/lang/Object;
+ flags: (0x1041) ACC_PUBLIC, ACC_BRIDGE, ACC_SYNTHETIC
+ Code:
+ stack=1, locals=1, args_size=1
+ 0: aload_0
+ 1: invokevirtual #x // Method get:()Ljava/lang/Integer;
+ 4: areturn
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass$1;
+}
+Signature: #x // Ljava/lang/Object;Ljava/util/function/Supplier<Ljava/lang/Integer;>;
+SourceFile: "TinyFrameworkNestedClasses.java"
+EnclosingMethod: #x.#x // com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$StaticNestedClass.getSupplier_static
+NestHost: class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
+InnerClasses:
+ public static #x= #x of #x; // StaticNestedClass=class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass of class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
+ #x; // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass$1
+## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass.class
+ Compiled from "TinyFrameworkNestedClasses.java"
+public class com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$StaticNestedClass
+ minor version: 0
+ major version: 61
+ flags: (0x0021) ACC_PUBLIC, ACC_SUPER
+ this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass
+ super_class: #x // java/lang/Object
+ interfaces: 0, fields: 1, methods: 2, attributes: 4
+ public int value;
+ descriptor: I
+ flags: (0x0001) ACC_PUBLIC
+
+ public com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$StaticNestedClass();
+ descriptor: ()V
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=2, locals=1, args_size=1
+ 0: aload_0
+ 1: invokespecial #x // Method java/lang/Object."<init>":()V
+ 4: aload_0
+ 5: bipush 6
+ 7: putfield #x // Field value:I
+ 10: return
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 11 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass;
+
+ public static java.util.function.Supplier<java.lang.Integer> getSupplier_static();
+ descriptor: ()Ljava/util/function/Supplier;
+ flags: (0x0009) ACC_PUBLIC, ACC_STATIC
+ Code:
+ stack=2, locals=0, args_size=0
+ 0: new #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass$1
+ 3: dup
+ 4: invokespecial #x // Method com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass$1."<init>":()V
+ 7: areturn
+ LineNumberTable:
+ Signature: #x // ()Ljava/util/function/Supplier<Ljava/lang/Integer;>;
+}
+SourceFile: "TinyFrameworkNestedClasses.java"
+RuntimeInvisibleAnnotations:
+ 0: #x()
+ android.hosttest.annotation.HostSideTestWholeClassStub
+NestHost: class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
+InnerClasses:
+ public static #x= #x of #x; // StaticNestedClass=class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass of class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
+ #x; // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass$1
+## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$SubClass.class
+ Compiled from "TinyFrameworkNestedClasses.java"
+public class com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$SubClass extends com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$BaseClass
+ minor version: 0
+ major version: 61
+ flags: (0x0021) ACC_PUBLIC, ACC_SUPER
+ this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$SubClass
+ super_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$BaseClass
+ interfaces: 0, fields: 0, methods: 1, attributes: 3
+ public com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$SubClass(int);
+ descriptor: (I)V
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=2, locals=2, args_size=2
+ 0: aload_0
+ 1: iload_1
+ 2: invokespecial #x // Method com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$BaseClass."<init>":(I)V
+ 5: return
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 6 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$SubClass;
+ 0 6 1 x I
+}
+SourceFile: "TinyFrameworkNestedClasses.java"
+NestHost: class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
+InnerClasses:
+ public static #x= #x of #x; // BaseClass=class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$BaseClass of class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
+ public static #x= #x of #x; // SubClass=class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$SubClass of class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
+## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses.class
+ Compiled from "TinyFrameworkNestedClasses.java"
+public class com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses
+ minor version: 0
+ major version: 61
+ flags: (0x0021) ACC_PUBLIC, ACC_SUPER
+ this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
+ super_class: #x // java/lang/Object
+ interfaces: 0, fields: 2, methods: 4, attributes: 4
+ public final java.util.function.Supplier<java.lang.Integer> mSupplier;
+ descriptor: Ljava/util/function/Supplier;
+ flags: (0x0011) ACC_PUBLIC, ACC_FINAL
+ Signature: #x // Ljava/util/function/Supplier<Ljava/lang/Integer;>;
+
+ public static final java.util.function.Supplier<java.lang.Integer> sSupplier;
+ descriptor: Ljava/util/function/Supplier;
+ flags: (0x0019) ACC_PUBLIC, ACC_STATIC, ACC_FINAL
+ Signature: #x // Ljava/util/function/Supplier<Ljava/lang/Integer;>;
+
+ public com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses();
+ descriptor: ()V
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=4, locals=1, args_size=1
+ 0: aload_0
+ 1: invokespecial #x // Method java/lang/Object."<init>":()V
+ 4: aload_0
+ 5: new #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$1
+ 8: dup
+ 9: aload_0
+ 10: invokespecial #x // Method com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$1."<init>":(Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses;)V
+ 13: putfield #x // Field mSupplier:Ljava/util/function/Supplier;
+ 16: return
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 17 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses;
+
+ public java.util.function.Supplier<java.lang.Integer> getSupplier();
+ descriptor: ()Ljava/util/function/Supplier;
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=3, locals=1, args_size=1
+ 0: new #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$3
+ 3: dup
+ 4: aload_0
+ 5: invokespecial #x // Method com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$3."<init>":(Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses;)V
+ 8: areturn
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 9 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses;
+ Signature: #x // ()Ljava/util/function/Supplier<Ljava/lang/Integer;>;
+
+ public static java.util.function.Supplier<java.lang.Integer> getSupplier_static();
+ descriptor: ()Ljava/util/function/Supplier;
+ flags: (0x0009) ACC_PUBLIC, ACC_STATIC
+ Code:
+ stack=2, locals=0, args_size=0
+ 0: new #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$4
+ 3: dup
+ 4: invokespecial #x // Method com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$4."<init>":()V
+ 7: areturn
+ LineNumberTable:
+ Signature: #x // ()Ljava/util/function/Supplier<Ljava/lang/Integer;>;
+
+ static {};
+ descriptor: ()V
+ flags: (0x0008) ACC_STATIC
+ Code:
+ stack=2, locals=0, args_size=0
+ 0: new #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$2
+ 3: dup
+ 4: invokespecial #x // Method com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$2."<init>":()V
+ 7: putstatic #x // Field sSupplier:Ljava/util/function/Supplier;
+ 10: return
+ LineNumberTable:
+}
+SourceFile: "TinyFrameworkNestedClasses.java"
+RuntimeInvisibleAnnotations:
+ 0: #x()
+ android.hosttest.annotation.HostSideTestWholeClassStub
+NestMembers:
+ com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$SubClass
+ com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$BaseClass
+ com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass
+ com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass$1
+ com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$InnerClass
+ com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$4
+ com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$3
+ com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$2
+ com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$1
+InnerClasses:
+ #x; // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$1
+ #x; // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$3
+ #x; // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$4
+ #x; // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$2
+ public static #x= #x of #x; // SubClass=class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$SubClass of class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
+ public static #x= #x of #x; // BaseClass=class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$BaseClass of class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
+ public static #x= #x of #x; // StaticNestedClass=class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass of class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
+ public #x= #x of #x; // InnerClass=class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$InnerClass of class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
+ #x; // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass$1
diff --git a/tools/hoststubgen/hoststubgen/test-tiny-framework/golden-output/02-hoststubgen-test-tiny-framework-host-stub-dump.txt b/tools/hoststubgen/hoststubgen/test-tiny-framework/golden-output/02-hoststubgen-test-tiny-framework-host-stub-dump.txt
new file mode 100644
index 000000000000..6e1528aedc1e
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/test-tiny-framework/golden-output/02-hoststubgen-test-tiny-framework-host-stub-dump.txt
@@ -0,0 +1,837 @@
+## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck$Impl.class
+ Compiled from "TinyFrameworkCallerCheck.java"
+class com.android.hoststubgen.test.tinyframework.TinyFrameworkCallerCheck$Impl
+ minor version: 0
+ major version: 61
+ flags: (0x0020) ACC_SUPER
+ this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck$Impl
+ super_class: #x // java/lang/Object
+ interfaces: 0, fields: 0, methods: 2, attributes: 4
+ private com.android.hoststubgen.test.tinyframework.TinyFrameworkCallerCheck$Impl();
+ descriptor: ()V
+ flags: (0x0002) ACC_PRIVATE
+ Code:
+ stack=3, locals=1, args_size=1
+ 0: new #x // class java/lang/RuntimeException
+ 3: dup
+ 4: ldc #x // String Stub!
+ 6: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
+ 9: athrow
+
+ public static int getOneStub();
+ descriptor: ()I
+ flags: (0x0009) ACC_PUBLIC, ACC_STATIC
+ Code:
+ stack=3, locals=0, args_size=0
+ 0: new #x // class java/lang/RuntimeException
+ 3: dup
+ 4: ldc #x // String Stub!
+ 6: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
+ 9: athrow
+ RuntimeInvisibleAnnotations:
+ 0: #x()
+ android.hosttest.annotation.HostSideTestStub
+}
+InnerClasses:
+ private static #x= #x of #x; // Impl=class com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck$Impl of class com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck
+SourceFile: "TinyFrameworkCallerCheck.java"
+RuntimeVisibleAnnotations:
+ 0: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedStubClass
+ 1: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+NestHost: class com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck
+## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck.class
+ Compiled from "TinyFrameworkCallerCheck.java"
+public class com.android.hoststubgen.test.tinyframework.TinyFrameworkCallerCheck
+ minor version: 0
+ major version: 61
+ flags: (0x0021) ACC_PUBLIC, ACC_SUPER
+ this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck
+ super_class: #x // java/lang/Object
+ interfaces: 0, fields: 0, methods: 3, attributes: 5
+ public com.android.hoststubgen.test.tinyframework.TinyFrameworkCallerCheck();
+ descriptor: ()V
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=3, locals=1, args_size=1
+ 0: new #x // class java/lang/RuntimeException
+ 3: dup
+ 4: ldc #x // String Stub!
+ 6: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
+ 9: athrow
+
+ public static int getOne_withCheck();
+ descriptor: ()I
+ flags: (0x0009) ACC_PUBLIC, ACC_STATIC
+ Code:
+ stack=3, locals=0, args_size=0
+ 0: new #x // class java/lang/RuntimeException
+ 3: dup
+ 4: ldc #x // String Stub!
+ 6: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
+ 9: athrow
+
+ public static int getOne_noCheck();
+ descriptor: ()I
+ flags: (0x0009) ACC_PUBLIC, ACC_STATIC
+ Code:
+ stack=3, locals=0, args_size=0
+ 0: new #x // class java/lang/RuntimeException
+ 3: dup
+ 4: ldc #x // String Stub!
+ 6: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
+ 9: athrow
+}
+InnerClasses:
+ private static #x= #x of #x; // Impl=class com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck$Impl of class com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck
+SourceFile: "TinyFrameworkCallerCheck.java"
+RuntimeVisibleAnnotations:
+ 0: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedStubClass
+ 1: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+RuntimeInvisibleAnnotations:
+ 0: #x()
+ android.hosttest.annotation.HostSideTestWholeClassStub
+NestMembers:
+ com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck$Impl
+## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkClassAnnotations.class
+ Compiled from "TinyFrameworkClassAnnotations.java"
+public class com.android.hoststubgen.test.tinyframework.TinyFrameworkClassAnnotations
+ minor version: 0
+ major version: 61
+ flags: (0x0021) ACC_PUBLIC, ACC_SUPER
+ this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkClassAnnotations
+ super_class: #x // java/lang/Object
+ interfaces: 0, fields: 1, methods: 5, attributes: 3
+ public int stub;
+ descriptor: I
+ flags: (0x0001) ACC_PUBLIC
+ RuntimeInvisibleAnnotations:
+ 0: #x()
+ android.hosttest.annotation.HostSideTestStub
+
+ public com.android.hoststubgen.test.tinyframework.TinyFrameworkClassAnnotations();
+ descriptor: ()V
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=3, locals=1, args_size=1
+ 0: new #x // class java/lang/RuntimeException
+ 3: dup
+ 4: ldc #x // String Stub!
+ 6: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
+ 9: athrow
+ RuntimeInvisibleAnnotations:
+ 0: #x()
+ android.hosttest.annotation.HostSideTestStub
+
+ public int addOne(int);
+ descriptor: (I)I
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=3, locals=2, args_size=2
+ 0: new #x // class java/lang/RuntimeException
+ 3: dup
+ 4: ldc #x // String Stub!
+ 6: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
+ 9: athrow
+ RuntimeInvisibleAnnotations:
+ 0: #x()
+ android.hosttest.annotation.HostSideTestStub
+
+ public int addTwo(int);
+ descriptor: (I)I
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=3, locals=2, args_size=2
+ 0: new #x // class java/lang/RuntimeException
+ 3: dup
+ 4: ldc #x // String Stub!
+ 6: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
+ 9: athrow
+
+ public static int nativeAddThree(int);
+ descriptor: (I)I
+ flags: (0x0009) ACC_PUBLIC, ACC_STATIC
+ Code:
+ stack=3, locals=1, args_size=1
+ 0: new #x // class java/lang/RuntimeException
+ 3: dup
+ 4: ldc #x // String Stub!
+ 6: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
+ 9: athrow
+
+ public java.lang.String visibleButUsesUnsupportedMethod();
+ descriptor: ()Ljava/lang/String;
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=3, locals=1, args_size=1
+ 0: new #x // class java/lang/RuntimeException
+ 3: dup
+ 4: ldc #x // String Stub!
+ 6: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
+ 9: athrow
+ RuntimeInvisibleAnnotations:
+ 0: #x()
+ android.hosttest.annotation.HostSideTestStub
+}
+SourceFile: "TinyFrameworkClassAnnotations.java"
+RuntimeVisibleAnnotations:
+ 0: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedStubClass
+ 1: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+RuntimeInvisibleAnnotations:
+ 0: #x()
+ android.hosttest.annotation.HostSideTestStub
+ 1: #x(#x=s#x)
+ android.hosttest.annotation.HostSideTestClassLoadHook(
+ value="com.android.hoststubgen.test.tinyframework.TinyFrameworkClassLoadHook.onClassLoaded"
+ )
+## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkClassClassWideAnnotations.class
+ Compiled from "TinyFrameworkClassClassWideAnnotations.java"
+public class com.android.hoststubgen.test.tinyframework.TinyFrameworkClassClassWideAnnotations
+ minor version: 0
+ major version: 61
+ flags: (0x0021) ACC_PUBLIC, ACC_SUPER
+ this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkClassClassWideAnnotations
+ super_class: #x // java/lang/Object
+ interfaces: 0, fields: 3, methods: 8, attributes: 3
+ public int stub;
+ descriptor: I
+ flags: (0x0001) ACC_PUBLIC
+
+ public int keep;
+ descriptor: I
+ flags: (0x0001) ACC_PUBLIC
+
+ public int remove;
+ descriptor: I
+ flags: (0x0001) ACC_PUBLIC
+
+ public com.android.hoststubgen.test.tinyframework.TinyFrameworkClassClassWideAnnotations();
+ descriptor: ()V
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=3, locals=1, args_size=1
+ 0: new #x // class java/lang/RuntimeException
+ 3: dup
+ 4: ldc #x // String Stub!
+ 6: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
+ 9: athrow
+
+ public int addOne(int);
+ descriptor: (I)I
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=3, locals=2, args_size=2
+ 0: new #x // class java/lang/RuntimeException
+ 3: dup
+ 4: ldc #x // String Stub!
+ 6: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
+ 9: athrow
+
+ public int addOneInner(int);
+ descriptor: (I)I
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=3, locals=2, args_size=2
+ 0: new #x // class java/lang/RuntimeException
+ 3: dup
+ 4: ldc #x // String Stub!
+ 6: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
+ 9: athrow
+
+ public void toBeRemoved(java.lang.String);
+ descriptor: (Ljava/lang/String;)V
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=3, locals=2, args_size=2
+ 0: new #x // class java/lang/RuntimeException
+ 3: dup
+ 4: ldc #x // String Stub!
+ 6: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
+ 9: athrow
+
+ public int addTwo(int);
+ descriptor: (I)I
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=3, locals=2, args_size=2
+ 0: new #x // class java/lang/RuntimeException
+ 3: dup
+ 4: ldc #x // String Stub!
+ 6: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
+ 9: athrow
+
+ public static int nativeAddThree(int);
+ descriptor: (I)I
+ flags: (0x0009) ACC_PUBLIC, ACC_STATIC
+ Code:
+ stack=3, locals=1, args_size=1
+ 0: new #x // class java/lang/RuntimeException
+ 3: dup
+ 4: ldc #x // String Stub!
+ 6: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
+ 9: athrow
+
+ public java.lang.String unsupportedMethod();
+ descriptor: ()Ljava/lang/String;
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=3, locals=1, args_size=1
+ 0: new #x // class java/lang/RuntimeException
+ 3: dup
+ 4: ldc #x // String Stub!
+ 6: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
+ 9: athrow
+
+ public java.lang.String visibleButUsesUnsupportedMethod();
+ descriptor: ()Ljava/lang/String;
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=3, locals=1, args_size=1
+ 0: new #x // class java/lang/RuntimeException
+ 3: dup
+ 4: ldc #x // String Stub!
+ 6: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
+ 9: athrow
+}
+SourceFile: "TinyFrameworkClassClassWideAnnotations.java"
+RuntimeVisibleAnnotations:
+ 0: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedStubClass
+ 1: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+RuntimeInvisibleAnnotations:
+ 0: #x()
+ android.hosttest.annotation.HostSideTestWholeClassStub
+## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkClassLoadHook.class
+ Compiled from "TinyFrameworkClassLoadHook.java"
+public class com.android.hoststubgen.test.tinyframework.TinyFrameworkClassLoadHook
+ minor version: 0
+ major version: 61
+ flags: (0x0021) ACC_PUBLIC, ACC_SUPER
+ this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkClassLoadHook
+ super_class: #x // java/lang/Object
+ interfaces: 0, fields: 1, methods: 3, attributes: 3
+ public static final java.util.Set<java.lang.Class<?>> sLoadedClasses;
+ descriptor: Ljava/util/Set;
+ flags: (0x0019) ACC_PUBLIC, ACC_STATIC, ACC_FINAL
+ Signature: #x // Ljava/util/Set<Ljava/lang/Class<*>;>;
+
+ private com.android.hoststubgen.test.tinyframework.TinyFrameworkClassLoadHook();
+ descriptor: ()V
+ flags: (0x0002) ACC_PRIVATE
+ Code:
+ stack=3, locals=1, args_size=1
+ 0: new #x // class java/lang/RuntimeException
+ 3: dup
+ 4: ldc #x // String Stub!
+ 6: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
+ 9: athrow
+
+ public static void onClassLoaded(java.lang.Class<?>);
+ descriptor: (Ljava/lang/Class;)V
+ flags: (0x0009) ACC_PUBLIC, ACC_STATIC
+ Code:
+ stack=3, locals=1, args_size=1
+ 0: new #x // class java/lang/RuntimeException
+ 3: dup
+ 4: ldc #x // String Stub!
+ 6: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
+ 9: athrow
+ Signature: #x // (Ljava/lang/Class<*>;)V
+
+ static {};
+ descriptor: ()V
+ flags: (0x0008) ACC_STATIC
+ Code:
+ stack=3, locals=0, args_size=0
+ 0: new #x // class java/lang/RuntimeException
+ 3: dup
+ 4: ldc #x // String Stub!
+ 6: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
+ 9: athrow
+}
+SourceFile: "TinyFrameworkClassLoadHook.java"
+RuntimeVisibleAnnotations:
+ 0: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedStubClass
+ 1: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+RuntimeInvisibleAnnotations:
+ 0: #x()
+ android.hosttest.annotation.HostSideTestWholeClassStub
+## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkClassWithInitializer.class
+ Compiled from "TinyFrameworkClassWithInitializer.java"
+public class com.android.hoststubgen.test.tinyframework.TinyFrameworkClassWithInitializer
+ minor version: 0
+ major version: 61
+ flags: (0x0021) ACC_PUBLIC, ACC_SUPER
+ this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkClassWithInitializer
+ super_class: #x // java/lang/Object
+ interfaces: 0, fields: 1, methods: 2, attributes: 3
+ public static boolean sInitialized;
+ descriptor: Z
+ flags: (0x0009) ACC_PUBLIC, ACC_STATIC
+
+ public com.android.hoststubgen.test.tinyframework.TinyFrameworkClassWithInitializer();
+ descriptor: ()V
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=3, locals=1, args_size=1
+ 0: new #x // class java/lang/RuntimeException
+ 3: dup
+ 4: ldc #x // String Stub!
+ 6: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
+ 9: athrow
+
+ static {};
+ descriptor: ()V
+ flags: (0x0008) ACC_STATIC
+ Code:
+ stack=3, locals=0, args_size=0
+ 0: new #x // class java/lang/RuntimeException
+ 3: dup
+ 4: ldc #x // String Stub!
+ 6: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
+ 9: athrow
+}
+SourceFile: "TinyFrameworkClassWithInitializer.java"
+RuntimeVisibleAnnotations:
+ 0: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedStubClass
+ 1: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+RuntimeInvisibleAnnotations:
+ 0: #x(#x=s#x)
+ android.hosttest.annotation.HostSideTestClassLoadHook(
+ value="com.android.hoststubgen.test.tinyframework.TinyFrameworkClassLoadHook.onClassLoaded"
+ )
+ 1: #x()
+ android.hosttest.annotation.HostSideTestWholeClassStub
+## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkExceptionTester.class
+ Compiled from "TinyFrameworkExceptionTester.java"
+public class com.android.hoststubgen.test.tinyframework.TinyFrameworkExceptionTester
+ minor version: 0
+ major version: 61
+ flags: (0x0021) ACC_PUBLIC, ACC_SUPER
+ this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkExceptionTester
+ super_class: #x // java/lang/Object
+ interfaces: 0, fields: 0, methods: 2, attributes: 3
+ public com.android.hoststubgen.test.tinyframework.TinyFrameworkExceptionTester();
+ descriptor: ()V
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=3, locals=1, args_size=1
+ 0: new #x // class java/lang/RuntimeException
+ 3: dup
+ 4: ldc #x // String Stub!
+ 6: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
+ 9: athrow
+
+ public static int testException();
+ descriptor: ()I
+ flags: (0x0009) ACC_PUBLIC, ACC_STATIC
+ Code:
+ stack=3, locals=0, args_size=0
+ 0: new #x // class java/lang/RuntimeException
+ 3: dup
+ 4: ldc #x // String Stub!
+ 6: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
+ 9: athrow
+}
+SourceFile: "TinyFrameworkExceptionTester.java"
+RuntimeVisibleAnnotations:
+ 0: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedStubClass
+ 1: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+RuntimeInvisibleAnnotations:
+ 0: #x()
+ android.hosttest.annotation.HostSideTestWholeClassStub
+## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy.class
+ Compiled from "TinyFrameworkForTextPolicy.java"
+public class com.android.hoststubgen.test.tinyframework.TinyFrameworkForTextPolicy
+ minor version: 0
+ major version: 61
+ flags: (0x0021) ACC_PUBLIC, ACC_SUPER
+ this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy
+ super_class: #x // java/lang/Object
+ interfaces: 0, fields: 1, methods: 5, attributes: 2
+ public int stub;
+ descriptor: I
+ flags: (0x0001) ACC_PUBLIC
+
+ public com.android.hoststubgen.test.tinyframework.TinyFrameworkForTextPolicy();
+ descriptor: ()V
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=3, locals=1, args_size=1
+ 0: new #x // class java/lang/RuntimeException
+ 3: dup
+ 4: ldc #x // String Stub!
+ 6: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
+ 9: athrow
+
+ public int addOne(int);
+ descriptor: (I)I
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=3, locals=2, args_size=2
+ 0: new #x // class java/lang/RuntimeException
+ 3: dup
+ 4: ldc #x // String Stub!
+ 6: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
+ 9: athrow
+
+ public int addTwo(int);
+ descriptor: (I)I
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=3, locals=2, args_size=2
+ 0: new #x // class java/lang/RuntimeException
+ 3: dup
+ 4: ldc #x // String Stub!
+ 6: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
+ 9: athrow
+
+ public static int nativeAddThree(int);
+ descriptor: (I)I
+ flags: (0x0009) ACC_PUBLIC, ACC_STATIC
+ Code:
+ stack=3, locals=1, args_size=1
+ 0: new #x // class java/lang/RuntimeException
+ 3: dup
+ 4: ldc #x // String Stub!
+ 6: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
+ 9: athrow
+
+ public java.lang.String visibleButUsesUnsupportedMethod();
+ descriptor: ()Ljava/lang/String;
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=3, locals=1, args_size=1
+ 0: new #x // class java/lang/RuntimeException
+ 3: dup
+ 4: ldc #x // String Stub!
+ 6: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
+ 9: athrow
+}
+SourceFile: "TinyFrameworkForTextPolicy.java"
+RuntimeVisibleAnnotations:
+ 0: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedStubClass
+ 1: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkNative.class
+ Compiled from "TinyFrameworkNative.java"
+public class com.android.hoststubgen.test.tinyframework.TinyFrameworkNative
+ minor version: 0
+ major version: 61
+ flags: (0x0021) ACC_PUBLIC, ACC_SUPER
+ this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkNative
+ super_class: #x // java/lang/Object
+ interfaces: 0, fields: 0, methods: 5, attributes: 3
+ public com.android.hoststubgen.test.tinyframework.TinyFrameworkNative();
+ descriptor: ()V
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=3, locals=1, args_size=1
+ 0: new #x // class java/lang/RuntimeException
+ 3: dup
+ 4: ldc #x // String Stub!
+ 6: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
+ 9: athrow
+
+ public static native int nativeAddTwo(int);
+ descriptor: (I)I
+ flags: (0x0109) ACC_PUBLIC, ACC_STATIC, ACC_NATIVE
+
+ public static int nativeAddTwo_should_be_like_this(int);
+ descriptor: (I)I
+ flags: (0x0009) ACC_PUBLIC, ACC_STATIC
+ Code:
+ stack=3, locals=1, args_size=1
+ 0: new #x // class java/lang/RuntimeException
+ 3: dup
+ 4: ldc #x // String Stub!
+ 6: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
+ 9: athrow
+
+ public static native long nativeLongPlus(long, long);
+ descriptor: (JJ)J
+ flags: (0x0109) ACC_PUBLIC, ACC_STATIC, ACC_NATIVE
+
+ public static long nativeLongPlus_should_be_like_this(long, long);
+ descriptor: (JJ)J
+ flags: (0x0009) ACC_PUBLIC, ACC_STATIC
+ Code:
+ stack=3, locals=4, args_size=2
+ 0: new #x // class java/lang/RuntimeException
+ 3: dup
+ 4: ldc #x // String Stub!
+ 6: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
+ 9: athrow
+}
+SourceFile: "TinyFrameworkNative.java"
+RuntimeVisibleAnnotations:
+ 0: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedStubClass
+ 1: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+RuntimeInvisibleAnnotations:
+ 0: #x()
+ android.hosttest.annotation.HostSideTestWholeClassStub
+ 1: #x(#x=s#x)
+ android.hosttest.annotation.HostSideTestNativeSubstitutionClass(
+ value="TinyFrameworkNative_host"
+ )
+## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$BaseClass.class
+ Compiled from "TinyFrameworkNestedClasses.java"
+public class com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$BaseClass
+ minor version: 0
+ major version: 61
+ flags: (0x0021) ACC_PUBLIC, ACC_SUPER
+ this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$BaseClass
+ super_class: #x // java/lang/Object
+ interfaces: 0, fields: 1, methods: 1, attributes: 4
+ public int value;
+ descriptor: I
+ flags: (0x0001) ACC_PUBLIC
+
+ public com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$BaseClass(int);
+ descriptor: (I)V
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=3, locals=2, args_size=2
+ 0: new #x // class java/lang/RuntimeException
+ 3: dup
+ 4: ldc #x // String Stub!
+ 6: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
+ 9: athrow
+}
+InnerClasses:
+ public static #x= #x of #x; // BaseClass=class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$BaseClass of class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
+SourceFile: "TinyFrameworkNestedClasses.java"
+RuntimeVisibleAnnotations:
+ 0: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedStubClass
+ 1: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+NestHost: class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
+## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$InnerClass.class
+ Compiled from "TinyFrameworkNestedClasses.java"
+public class com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$InnerClass
+ minor version: 0
+ major version: 61
+ flags: (0x0021) ACC_PUBLIC, ACC_SUPER
+ this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$InnerClass
+ super_class: #x // java/lang/Object
+ interfaces: 0, fields: 2, methods: 1, attributes: 5
+ public int value;
+ descriptor: I
+ flags: (0x0001) ACC_PUBLIC
+
+ final com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses this$0;
+ descriptor: Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses;
+ flags: (0x1010) ACC_FINAL, ACC_SYNTHETIC
+
+ public com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$InnerClass(com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses);
+ descriptor: (Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses;)V
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=3, locals=2, args_size=2
+ 0: new #x // class java/lang/RuntimeException
+ 3: dup
+ 4: ldc #x // String Stub!
+ 6: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
+ 9: athrow
+}
+InnerClasses:
+ public #x= #x of #x; // InnerClass=class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$InnerClass of class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
+SourceFile: "TinyFrameworkNestedClasses.java"
+RuntimeVisibleAnnotations:
+ 0: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedStubClass
+ 1: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+RuntimeInvisibleAnnotations:
+ 0: #x()
+ android.hosttest.annotation.HostSideTestWholeClassStub
+NestHost: class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
+## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass.class
+ Compiled from "TinyFrameworkNestedClasses.java"
+public class com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$StaticNestedClass
+ minor version: 0
+ major version: 61
+ flags: (0x0021) ACC_PUBLIC, ACC_SUPER
+ this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass
+ super_class: #x // java/lang/Object
+ interfaces: 0, fields: 1, methods: 2, attributes: 5
+ public int value;
+ descriptor: I
+ flags: (0x0001) ACC_PUBLIC
+
+ public com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$StaticNestedClass();
+ descriptor: ()V
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=3, locals=1, args_size=1
+ 0: new #x // class java/lang/RuntimeException
+ 3: dup
+ 4: ldc #x // String Stub!
+ 6: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
+ 9: athrow
+
+ public static java.util.function.Supplier<java.lang.Integer> getSupplier_static();
+ descriptor: ()Ljava/util/function/Supplier;
+ flags: (0x0009) ACC_PUBLIC, ACC_STATIC
+ Code:
+ stack=3, locals=0, args_size=0
+ 0: new #x // class java/lang/RuntimeException
+ 3: dup
+ 4: ldc #x // String Stub!
+ 6: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
+ 9: athrow
+ Signature: #x // ()Ljava/util/function/Supplier<Ljava/lang/Integer;>;
+}
+InnerClasses:
+ public static #x= #x of #x; // StaticNestedClass=class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass of class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
+ #x; // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass$1
+SourceFile: "TinyFrameworkNestedClasses.java"
+RuntimeVisibleAnnotations:
+ 0: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedStubClass
+ 1: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+RuntimeInvisibleAnnotations:
+ 0: #x()
+ android.hosttest.annotation.HostSideTestWholeClassStub
+NestHost: class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
+## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$SubClass.class
+ Compiled from "TinyFrameworkNestedClasses.java"
+public class com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$SubClass extends com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$BaseClass
+ minor version: 0
+ major version: 61
+ flags: (0x0021) ACC_PUBLIC, ACC_SUPER
+ this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$SubClass
+ super_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$BaseClass
+ interfaces: 0, fields: 0, methods: 1, attributes: 4
+ public com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$SubClass(int);
+ descriptor: (I)V
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=3, locals=2, args_size=2
+ 0: new #x // class java/lang/RuntimeException
+ 3: dup
+ 4: ldc #x // String Stub!
+ 6: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
+ 9: athrow
+}
+InnerClasses:
+ public static #x= #x of #x; // BaseClass=class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$BaseClass of class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
+ public static #x= #x of #x; // SubClass=class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$SubClass of class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
+SourceFile: "TinyFrameworkNestedClasses.java"
+RuntimeVisibleAnnotations:
+ 0: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedStubClass
+ 1: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+NestHost: class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
+## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses.class
+ Compiled from "TinyFrameworkNestedClasses.java"
+public class com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses
+ minor version: 0
+ major version: 61
+ flags: (0x0021) ACC_PUBLIC, ACC_SUPER
+ this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
+ super_class: #x // java/lang/Object
+ interfaces: 0, fields: 2, methods: 4, attributes: 5
+ public final java.util.function.Supplier<java.lang.Integer> mSupplier;
+ descriptor: Ljava/util/function/Supplier;
+ flags: (0x0011) ACC_PUBLIC, ACC_FINAL
+ Signature: #x // Ljava/util/function/Supplier<Ljava/lang/Integer;>;
+
+ public static final java.util.function.Supplier<java.lang.Integer> sSupplier;
+ descriptor: Ljava/util/function/Supplier;
+ flags: (0x0019) ACC_PUBLIC, ACC_STATIC, ACC_FINAL
+ Signature: #x // Ljava/util/function/Supplier<Ljava/lang/Integer;>;
+
+ public com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses();
+ descriptor: ()V
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=3, locals=1, args_size=1
+ 0: new #x // class java/lang/RuntimeException
+ 3: dup
+ 4: ldc #x // String Stub!
+ 6: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
+ 9: athrow
+
+ public java.util.function.Supplier<java.lang.Integer> getSupplier();
+ descriptor: ()Ljava/util/function/Supplier;
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=3, locals=1, args_size=1
+ 0: new #x // class java/lang/RuntimeException
+ 3: dup
+ 4: ldc #x // String Stub!
+ 6: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
+ 9: athrow
+ Signature: #x // ()Ljava/util/function/Supplier<Ljava/lang/Integer;>;
+
+ public static java.util.function.Supplier<java.lang.Integer> getSupplier_static();
+ descriptor: ()Ljava/util/function/Supplier;
+ flags: (0x0009) ACC_PUBLIC, ACC_STATIC
+ Code:
+ stack=3, locals=0, args_size=0
+ 0: new #x // class java/lang/RuntimeException
+ 3: dup
+ 4: ldc #x // String Stub!
+ 6: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
+ 9: athrow
+ Signature: #x // ()Ljava/util/function/Supplier<Ljava/lang/Integer;>;
+
+ static {};
+ descriptor: ()V
+ flags: (0x0008) ACC_STATIC
+ Code:
+ stack=3, locals=0, args_size=0
+ 0: new #x // class java/lang/RuntimeException
+ 3: dup
+ 4: ldc #x // String Stub!
+ 6: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
+ 9: athrow
+}
+InnerClasses:
+ #x; // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$1
+ #x; // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$3
+ #x; // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$4
+ #x; // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$2
+ public static #x= #x of #x; // SubClass=class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$SubClass of class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
+ public static #x= #x of #x; // BaseClass=class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$BaseClass of class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
+ public static #x= #x of #x; // StaticNestedClass=class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass of class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
+ public #x= #x of #x; // InnerClass=class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$InnerClass of class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
+ #x; // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass$1
+SourceFile: "TinyFrameworkNestedClasses.java"
+RuntimeVisibleAnnotations:
+ 0: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedStubClass
+ 1: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+RuntimeInvisibleAnnotations:
+ 0: #x()
+ android.hosttest.annotation.HostSideTestWholeClassStub
+NestMembers:
+ com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$SubClass
+ com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$BaseClass
+ com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass
+ com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass$1
+ com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$InnerClass
+ com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$4
+ com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$3
+ com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$2
+ com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$1
diff --git a/tools/hoststubgen/hoststubgen/test-tiny-framework/golden-output/03-hoststubgen-test-tiny-framework-host-impl-dump.txt b/tools/hoststubgen/hoststubgen/test-tiny-framework/golden-output/03-hoststubgen-test-tiny-framework-host-impl-dump.txt
new file mode 100644
index 000000000000..5672e9c36706
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/test-tiny-framework/golden-output/03-hoststubgen-test-tiny-framework-host-impl-dump.txt
@@ -0,0 +1,1774 @@
+## Class: android/hosttest/annotation/HostSideTestClassLoadHook.class
+ Compiled from "HostSideTestClassLoadHook.java"
+public interface android.hosttest.annotation.HostSideTestClassLoadHook extends java.lang.annotation.Annotation
+ minor version: 0
+ major version: 61
+ flags: (0x2601) ACC_PUBLIC, ACC_INTERFACE, ACC_ABSTRACT, ACC_ANNOTATION
+ this_class: #x // android/hosttest/annotation/HostSideTestClassLoadHook
+ super_class: #x // java/lang/Object
+ interfaces: 1, fields: 0, methods: 1, attributes: 2
+ public abstract java.lang.String value();
+ descriptor: ()Ljava/lang/String;
+ flags: (0x0401) ACC_PUBLIC, ACC_ABSTRACT
+}
+SourceFile: "HostSideTestClassLoadHook.java"
+RuntimeVisibleAnnotations:
+ 0: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+ 1: #x(#x=[e#x.#x])
+ java.lang.annotation.Target(
+ value=[Ljava/lang/annotation/ElementType;.TYPE]
+ )
+ 2: #x(#x=e#x.#x)
+ java.lang.annotation.Retention(
+ value=Ljava/lang/annotation/RetentionPolicy;.CLASS
+ )
+## Class: android/hosttest/annotation/HostSideTestKeep.class
+ Compiled from "HostSideTestKeep.java"
+public interface android.hosttest.annotation.HostSideTestKeep extends java.lang.annotation.Annotation
+ minor version: 0
+ major version: 61
+ flags: (0x2601) ACC_PUBLIC, ACC_INTERFACE, ACC_ABSTRACT, ACC_ANNOTATION
+ this_class: #x // android/hosttest/annotation/HostSideTestKeep
+ super_class: #x // java/lang/Object
+ interfaces: 1, fields: 0, methods: 0, attributes: 2
+}
+SourceFile: "HostSideTestKeep.java"
+RuntimeVisibleAnnotations:
+ 0: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+ 1: #x(#x=[e#x.#x,e#x.#x,e#x.#x,e#x.#x])
+ java.lang.annotation.Target(
+ value=[Ljava/lang/annotation/ElementType;.TYPE,Ljava/lang/annotation/ElementType;.FIELD,Ljava/lang/annotation/ElementType;.METHOD,Ljava/lang/annotation/ElementType;.CONSTRUCTOR]
+ )
+ 2: #x(#x=e#x.#x)
+ java.lang.annotation.Retention(
+ value=Ljava/lang/annotation/RetentionPolicy;.CLASS
+ )
+## Class: android/hosttest/annotation/HostSideTestNativeSubstitutionClass.class
+ Compiled from "HostSideTestNativeSubstitutionClass.java"
+public interface android.hosttest.annotation.HostSideTestNativeSubstitutionClass extends java.lang.annotation.Annotation
+ minor version: 0
+ major version: 61
+ flags: (0x2601) ACC_PUBLIC, ACC_INTERFACE, ACC_ABSTRACT, ACC_ANNOTATION
+ this_class: #x // android/hosttest/annotation/HostSideTestNativeSubstitutionClass
+ super_class: #x // java/lang/Object
+ interfaces: 1, fields: 0, methods: 1, attributes: 2
+ public abstract java.lang.String value();
+ descriptor: ()Ljava/lang/String;
+ flags: (0x0401) ACC_PUBLIC, ACC_ABSTRACT
+}
+SourceFile: "HostSideTestNativeSubstitutionClass.java"
+RuntimeVisibleAnnotations:
+ 0: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+ 1: #x(#x=[e#x.#x])
+ java.lang.annotation.Target(
+ value=[Ljava/lang/annotation/ElementType;.TYPE]
+ )
+ 2: #x(#x=e#x.#x)
+ java.lang.annotation.Retention(
+ value=Ljava/lang/annotation/RetentionPolicy;.CLASS
+ )
+## Class: android/hosttest/annotation/HostSideTestRemove.class
+ Compiled from "HostSideTestRemove.java"
+public interface android.hosttest.annotation.HostSideTestRemove extends java.lang.annotation.Annotation
+ minor version: 0
+ major version: 61
+ flags: (0x2601) ACC_PUBLIC, ACC_INTERFACE, ACC_ABSTRACT, ACC_ANNOTATION
+ this_class: #x // android/hosttest/annotation/HostSideTestRemove
+ super_class: #x // java/lang/Object
+ interfaces: 1, fields: 0, methods: 0, attributes: 2
+}
+SourceFile: "HostSideTestRemove.java"
+RuntimeVisibleAnnotations:
+ 0: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+ 1: #x(#x=[e#x.#x,e#x.#x,e#x.#x,e#x.#x])
+ java.lang.annotation.Target(
+ value=[Ljava/lang/annotation/ElementType;.TYPE,Ljava/lang/annotation/ElementType;.FIELD,Ljava/lang/annotation/ElementType;.METHOD,Ljava/lang/annotation/ElementType;.CONSTRUCTOR]
+ )
+ 2: #x(#x=e#x.#x)
+ java.lang.annotation.Retention(
+ value=Ljava/lang/annotation/RetentionPolicy;.CLASS
+ )
+## Class: android/hosttest/annotation/HostSideTestStub.class
+ Compiled from "HostSideTestStub.java"
+public interface android.hosttest.annotation.HostSideTestStub extends java.lang.annotation.Annotation
+ minor version: 0
+ major version: 61
+ flags: (0x2601) ACC_PUBLIC, ACC_INTERFACE, ACC_ABSTRACT, ACC_ANNOTATION
+ this_class: #x // android/hosttest/annotation/HostSideTestStub
+ super_class: #x // java/lang/Object
+ interfaces: 1, fields: 0, methods: 0, attributes: 2
+}
+SourceFile: "HostSideTestStub.java"
+RuntimeVisibleAnnotations:
+ 0: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+ 1: #x(#x=[e#x.#x,e#x.#x,e#x.#x,e#x.#x])
+ java.lang.annotation.Target(
+ value=[Ljava/lang/annotation/ElementType;.TYPE,Ljava/lang/annotation/ElementType;.FIELD,Ljava/lang/annotation/ElementType;.METHOD,Ljava/lang/annotation/ElementType;.CONSTRUCTOR]
+ )
+ 2: #x(#x=e#x.#x)
+ java.lang.annotation.Retention(
+ value=Ljava/lang/annotation/RetentionPolicy;.CLASS
+ )
+## Class: android/hosttest/annotation/HostSideTestSubstitute.class
+ Compiled from "HostSideTestSubstitute.java"
+public interface android.hosttest.annotation.HostSideTestSubstitute extends java.lang.annotation.Annotation
+ minor version: 0
+ major version: 61
+ flags: (0x2601) ACC_PUBLIC, ACC_INTERFACE, ACC_ABSTRACT, ACC_ANNOTATION
+ this_class: #x // android/hosttest/annotation/HostSideTestSubstitute
+ super_class: #x // java/lang/Object
+ interfaces: 1, fields: 0, methods: 1, attributes: 2
+ public abstract java.lang.String suffix();
+ descriptor: ()Ljava/lang/String;
+ flags: (0x0401) ACC_PUBLIC, ACC_ABSTRACT
+}
+SourceFile: "HostSideTestSubstitute.java"
+RuntimeVisibleAnnotations:
+ 0: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+ 1: #x(#x=[e#x.#x])
+ java.lang.annotation.Target(
+ value=[Ljava/lang/annotation/ElementType;.METHOD]
+ )
+ 2: #x(#x=e#x.#x)
+ java.lang.annotation.Retention(
+ value=Ljava/lang/annotation/RetentionPolicy;.CLASS
+ )
+## Class: android/hosttest/annotation/HostSideTestThrow.class
+ Compiled from "HostSideTestThrow.java"
+public interface android.hosttest.annotation.HostSideTestThrow extends java.lang.annotation.Annotation
+ minor version: 0
+ major version: 61
+ flags: (0x2601) ACC_PUBLIC, ACC_INTERFACE, ACC_ABSTRACT, ACC_ANNOTATION
+ this_class: #x // android/hosttest/annotation/HostSideTestThrow
+ super_class: #x // java/lang/Object
+ interfaces: 1, fields: 0, methods: 0, attributes: 2
+}
+SourceFile: "HostSideTestThrow.java"
+RuntimeVisibleAnnotations:
+ 0: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+ 1: #x(#x=[e#x.#x,e#x.#x])
+ java.lang.annotation.Target(
+ value=[Ljava/lang/annotation/ElementType;.METHOD,Ljava/lang/annotation/ElementType;.CONSTRUCTOR]
+ )
+ 2: #x(#x=e#x.#x)
+ java.lang.annotation.Retention(
+ value=Ljava/lang/annotation/RetentionPolicy;.CLASS
+ )
+## Class: android/hosttest/annotation/HostSideTestWholeClassKeep.class
+ Compiled from "HostSideTestWholeClassKeep.java"
+public interface android.hosttest.annotation.HostSideTestWholeClassKeep extends java.lang.annotation.Annotation
+ minor version: 0
+ major version: 61
+ flags: (0x2601) ACC_PUBLIC, ACC_INTERFACE, ACC_ABSTRACT, ACC_ANNOTATION
+ this_class: #x // android/hosttest/annotation/HostSideTestWholeClassKeep
+ super_class: #x // java/lang/Object
+ interfaces: 1, fields: 0, methods: 0, attributes: 2
+}
+SourceFile: "HostSideTestWholeClassKeep.java"
+RuntimeVisibleAnnotations:
+ 0: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+ 1: #x(#x=[e#x.#x])
+ java.lang.annotation.Target(
+ value=[Ljava/lang/annotation/ElementType;.TYPE]
+ )
+ 2: #x(#x=e#x.#x)
+ java.lang.annotation.Retention(
+ value=Ljava/lang/annotation/RetentionPolicy;.CLASS
+ )
+## Class: android/hosttest/annotation/HostSideTestWholeClassStub.class
+ Compiled from "HostSideTestWholeClassStub.java"
+public interface android.hosttest.annotation.HostSideTestWholeClassStub extends java.lang.annotation.Annotation
+ minor version: 0
+ major version: 61
+ flags: (0x2601) ACC_PUBLIC, ACC_INTERFACE, ACC_ABSTRACT, ACC_ANNOTATION
+ this_class: #x // android/hosttest/annotation/HostSideTestWholeClassStub
+ super_class: #x // java/lang/Object
+ interfaces: 1, fields: 0, methods: 0, attributes: 2
+}
+SourceFile: "HostSideTestWholeClassStub.java"
+RuntimeVisibleAnnotations:
+ 0: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+ 1: #x(#x=[e#x.#x])
+ java.lang.annotation.Target(
+ value=[Ljava/lang/annotation/ElementType;.TYPE]
+ )
+ 2: #x(#x=e#x.#x)
+ java.lang.annotation.Retention(
+ value=Ljava/lang/annotation/RetentionPolicy;.CLASS
+ )
+## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck$Impl.class
+ Compiled from "TinyFrameworkCallerCheck.java"
+class com.android.hoststubgen.test.tinyframework.TinyFrameworkCallerCheck$Impl
+ minor version: 0
+ major version: 61
+ flags: (0x0020) ACC_SUPER
+ this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck$Impl
+ super_class: #x // java/lang/Object
+ interfaces: 0, fields: 0, methods: 3, attributes: 4
+ private com.android.hoststubgen.test.tinyframework.TinyFrameworkCallerCheck$Impl();
+ descriptor: ()V
+ flags: (0x0002) ACC_PRIVATE
+ Code:
+ stack=1, locals=1, args_size=1
+ 0: aload_0
+ 1: invokespecial #x // Method java/lang/Object."<init>":()V
+ 4: return
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck$Impl;
+
+ public static int getOneKeep();
+ descriptor: ()I
+ flags: (0x0009) ACC_PUBLIC, ACC_STATIC
+ Code:
+ stack=4, locals=0, args_size=0
+ 0: ldc #x // String com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck$Impl
+ 2: ldc #x // String getOneKeep
+ 4: ldc #x // String ()I
+ 6: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.getStackWalker:()Ljava/lang/StackWalker;
+ 9: invokevirtual #x // Method java/lang/StackWalker.getCallerClass:()Ljava/lang/Class;
+ 12: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onNonStubMethodCalled:(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Class;)V
+ 15: iconst_1
+ 16: ireturn
+ LineNumberTable:
+ RuntimeInvisibleAnnotations:
+ 0: #x()
+ android.hosttest.annotation.HostSideTestKeep
+
+ public static int getOneStub();
+ descriptor: ()I
+ flags: (0x0009) ACC_PUBLIC, ACC_STATIC
+ Code:
+ stack=1, locals=0, args_size=0
+ 0: iconst_1
+ 1: ireturn
+ LineNumberTable:
+ RuntimeInvisibleAnnotations:
+ 0: #x()
+ android.hosttest.annotation.HostSideTestStub
+}
+InnerClasses:
+ private static #x= #x of #x; // Impl=class com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck$Impl of class com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck
+SourceFile: "TinyFrameworkCallerCheck.java"
+RuntimeVisibleAnnotations:
+ 0: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedStubClass
+ 1: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+NestHost: class com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck
+## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck.class
+ Compiled from "TinyFrameworkCallerCheck.java"
+public class com.android.hoststubgen.test.tinyframework.TinyFrameworkCallerCheck
+ minor version: 0
+ major version: 61
+ flags: (0x0021) ACC_PUBLIC, ACC_SUPER
+ this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck
+ super_class: #x // java/lang/Object
+ interfaces: 0, fields: 0, methods: 3, attributes: 5
+ public com.android.hoststubgen.test.tinyframework.TinyFrameworkCallerCheck();
+ descriptor: ()V
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=1, locals=1, args_size=1
+ 0: aload_0
+ 1: invokespecial #x // Method java/lang/Object."<init>":()V
+ 4: return
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck;
+
+ public static int getOne_withCheck();
+ descriptor: ()I
+ flags: (0x0009) ACC_PUBLIC, ACC_STATIC
+ Code:
+ stack=1, locals=0, args_size=0
+ 0: invokestatic #x // Method com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck$Impl.getOneKeep:()I
+ 3: ireturn
+ LineNumberTable:
+
+ public static int getOne_noCheck();
+ descriptor: ()I
+ flags: (0x0009) ACC_PUBLIC, ACC_STATIC
+ Code:
+ stack=1, locals=0, args_size=0
+ 0: invokestatic #x // Method com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck$Impl.getOneStub:()I
+ 3: ireturn
+ LineNumberTable:
+}
+InnerClasses:
+ private static #x= #x of #x; // Impl=class com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck$Impl of class com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck
+SourceFile: "TinyFrameworkCallerCheck.java"
+RuntimeVisibleAnnotations:
+ 0: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedStubClass
+ 1: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+RuntimeInvisibleAnnotations:
+ 0: #x()
+ android.hosttest.annotation.HostSideTestWholeClassStub
+NestMembers:
+ com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck$Impl
+## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkClassAnnotations.class
+ Compiled from "TinyFrameworkClassAnnotations.java"
+public class com.android.hoststubgen.test.tinyframework.TinyFrameworkClassAnnotations
+ minor version: 0
+ major version: 61
+ flags: (0x0021) ACC_PUBLIC, ACC_SUPER
+ this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkClassAnnotations
+ super_class: #x // java/lang/Object
+ interfaces: 0, fields: 2, methods: 8, attributes: 3
+ public int stub;
+ descriptor: I
+ flags: (0x0001) ACC_PUBLIC
+ RuntimeInvisibleAnnotations:
+ 0: #x()
+ android.hosttest.annotation.HostSideTestStub
+
+ public int keep;
+ descriptor: I
+ flags: (0x0001) ACC_PUBLIC
+ RuntimeInvisibleAnnotations:
+ 0: #x()
+ android.hosttest.annotation.HostSideTestKeep
+
+ private static {};
+ descriptor: ()V
+ flags: (0x000a) ACC_PRIVATE, ACC_STATIC
+ Code:
+ stack=2, locals=0, args_size=0
+ 0: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkClassAnnotations
+ 2: ldc #x // String com.android.hoststubgen.test.tinyframework.TinyFrameworkClassLoadHook.onClassLoaded
+ 4: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onClassLoaded:(Ljava/lang/Class;Ljava/lang/String;)V
+ 7: return
+
+ public com.android.hoststubgen.test.tinyframework.TinyFrameworkClassAnnotations();
+ descriptor: ()V
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=2, locals=1, args_size=1
+ 0: aload_0
+ 1: invokespecial #x // Method java/lang/Object."<init>":()V
+ 4: aload_0
+ 5: iconst_1
+ 6: putfield #x // Field stub:I
+ 9: aload_0
+ 10: iconst_2
+ 11: putfield #x // Field keep:I
+ 14: return
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 15 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkClassAnnotations;
+ RuntimeInvisibleAnnotations:
+ 0: #x()
+ android.hosttest.annotation.HostSideTestStub
+
+ public int addOne(int);
+ descriptor: (I)I
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=2, locals=2, args_size=2
+ 0: aload_0
+ 1: iload_1
+ 2: invokevirtual #x // Method addOneInner:(I)I
+ 5: ireturn
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 6 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkClassAnnotations;
+ 0 6 1 value I
+ RuntimeInvisibleAnnotations:
+ 0: #x()
+ android.hosttest.annotation.HostSideTestStub
+
+ public int addOneInner(int);
+ descriptor: (I)I
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=4, locals=2, args_size=2
+ 0: ldc #x // String com/android/hoststubgen/test/tinyframework/TinyFrameworkClassAnnotations
+ 2: ldc #x // String addOneInner
+ 4: ldc #x // String (I)I
+ 6: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.getStackWalker:()Ljava/lang/StackWalker;
+ 9: invokevirtual #x // Method java/lang/StackWalker.getCallerClass:()Ljava/lang/Class;
+ 12: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onNonStubMethodCalled:(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Class;)V
+ 15: iload_1
+ 16: iconst_1
+ 17: iadd
+ 18: ireturn
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 15 4 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkClassAnnotations;
+ 15 4 1 value I
+ RuntimeInvisibleAnnotations:
+ 0: #x()
+ android.hosttest.annotation.HostSideTestKeep
+
+ public int addTwo(int);
+ descriptor: (I)I
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=2, locals=2, args_size=2
+ 0: iload_1
+ 1: iconst_2
+ 2: iadd
+ 3: ireturn
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 4 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkClassAnnotations;
+ 0 4 1 value I
+
+ public static int nativeAddThree(int);
+ descriptor: (I)I
+ flags: (0x0009) ACC_PUBLIC, ACC_STATIC
+ Code:
+ stack=2, locals=1, args_size=1
+ 0: iload_0
+ 1: iconst_3
+ 2: iadd
+ 3: ireturn
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 4 0 value I
+
+ public java.lang.String unsupportedMethod();
+ descriptor: ()Ljava/lang/String;
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=4, locals=1, args_size=1
+ 0: ldc #x // String com/android/hoststubgen/test/tinyframework/TinyFrameworkClassAnnotations
+ 2: ldc #x // String unsupportedMethod
+ 4: ldc #x // String ()Ljava/lang/String;
+ 6: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.getStackWalker:()Ljava/lang/StackWalker;
+ 9: invokevirtual #x // Method java/lang/StackWalker.getCallerClass:()Ljava/lang/Class;
+ 12: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onNonStubMethodCalled:(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Class;)V
+ 15: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onThrowMethodCalled:()V
+ 18: new #x // class java/lang/RuntimeException
+ 21: dup
+ 22: ldc #x // String Unreachable
+ 24: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
+ 27: athrow
+ RuntimeInvisibleAnnotations:
+ 0: #x()
+ android.hosttest.annotation.HostSideTestThrow
+
+ public java.lang.String visibleButUsesUnsupportedMethod();
+ descriptor: ()Ljava/lang/String;
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=1, locals=1, args_size=1
+ 0: aload_0
+ 1: invokevirtual #x // Method unsupportedMethod:()Ljava/lang/String;
+ 4: areturn
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkClassAnnotations;
+ RuntimeInvisibleAnnotations:
+ 0: #x()
+ android.hosttest.annotation.HostSideTestStub
+}
+SourceFile: "TinyFrameworkClassAnnotations.java"
+RuntimeVisibleAnnotations:
+ 0: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedStubClass
+ 1: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+RuntimeInvisibleAnnotations:
+ 0: #x()
+ android.hosttest.annotation.HostSideTestStub
+ 1: #x(#x=s#x)
+ android.hosttest.annotation.HostSideTestClassLoadHook(
+ value="com.android.hoststubgen.test.tinyframework.TinyFrameworkClassLoadHook.onClassLoaded"
+ )
+## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkClassClassWideAnnotations.class
+ Compiled from "TinyFrameworkClassClassWideAnnotations.java"
+public class com.android.hoststubgen.test.tinyframework.TinyFrameworkClassClassWideAnnotations
+ minor version: 0
+ major version: 61
+ flags: (0x0021) ACC_PUBLIC, ACC_SUPER
+ this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkClassClassWideAnnotations
+ super_class: #x // java/lang/Object
+ interfaces: 0, fields: 3, methods: 8, attributes: 3
+ public int stub;
+ descriptor: I
+ flags: (0x0001) ACC_PUBLIC
+
+ public int keep;
+ descriptor: I
+ flags: (0x0001) ACC_PUBLIC
+
+ public int remove;
+ descriptor: I
+ flags: (0x0001) ACC_PUBLIC
+
+ public com.android.hoststubgen.test.tinyframework.TinyFrameworkClassClassWideAnnotations();
+ descriptor: ()V
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=2, locals=1, args_size=1
+ 0: aload_0
+ 1: invokespecial #x // Method java/lang/Object."<init>":()V
+ 4: aload_0
+ 5: iconst_1
+ 6: putfield #x // Field stub:I
+ 9: aload_0
+ 10: iconst_2
+ 11: putfield #x // Field keep:I
+ 14: return
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 15 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkClassClassWideAnnotations;
+
+ public int addOne(int);
+ descriptor: (I)I
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=2, locals=2, args_size=2
+ 0: aload_0
+ 1: iload_1
+ 2: invokevirtual #x // Method addOneInner:(I)I
+ 5: ireturn
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 6 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkClassClassWideAnnotations;
+ 0 6 1 value I
+
+ public int addOneInner(int);
+ descriptor: (I)I
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=2, locals=2, args_size=2
+ 0: iload_1
+ 1: iconst_1
+ 2: iadd
+ 3: ireturn
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 4 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkClassClassWideAnnotations;
+ 0 4 1 value I
+
+ public void toBeRemoved(java.lang.String);
+ descriptor: (Ljava/lang/String;)V
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=2, locals=2, args_size=2
+ 0: new #x // class java/lang/RuntimeException
+ 3: dup
+ 4: invokespecial #x // Method java/lang/RuntimeException."<init>":()V
+ 7: athrow
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 8 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkClassClassWideAnnotations;
+ 0 8 1 foo Ljava/lang/String;
+
+ public int addTwo(int);
+ descriptor: (I)I
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=2, locals=2, args_size=2
+ 0: iload_1
+ 1: iconst_2
+ 2: iadd
+ 3: ireturn
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 4 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkClassClassWideAnnotations;
+ 0 4 1 value I
+
+ public static int nativeAddThree(int);
+ descriptor: (I)I
+ flags: (0x0009) ACC_PUBLIC, ACC_STATIC
+ Code:
+ stack=2, locals=1, args_size=1
+ 0: iload_0
+ 1: iconst_3
+ 2: iadd
+ 3: ireturn
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 4 0 value I
+
+ public java.lang.String unsupportedMethod();
+ descriptor: ()Ljava/lang/String;
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=1, locals=1, args_size=1
+ 0: ldc #x // String This value shouldn\'t be seen on the host side.
+ 2: areturn
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 3 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkClassClassWideAnnotations;
+
+ public java.lang.String visibleButUsesUnsupportedMethod();
+ descriptor: ()Ljava/lang/String;
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=1, locals=1, args_size=1
+ 0: aload_0
+ 1: invokevirtual #x // Method unsupportedMethod:()Ljava/lang/String;
+ 4: areturn
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkClassClassWideAnnotations;
+}
+SourceFile: "TinyFrameworkClassClassWideAnnotations.java"
+RuntimeVisibleAnnotations:
+ 0: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedStubClass
+ 1: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+RuntimeInvisibleAnnotations:
+ 0: #x()
+ android.hosttest.annotation.HostSideTestWholeClassStub
+## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkClassLoadHook.class
+ Compiled from "TinyFrameworkClassLoadHook.java"
+public class com.android.hoststubgen.test.tinyframework.TinyFrameworkClassLoadHook
+ minor version: 0
+ major version: 61
+ flags: (0x0021) ACC_PUBLIC, ACC_SUPER
+ this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkClassLoadHook
+ super_class: #x // java/lang/Object
+ interfaces: 0, fields: 1, methods: 3, attributes: 3
+ public static final java.util.Set<java.lang.Class<?>> sLoadedClasses;
+ descriptor: Ljava/util/Set;
+ flags: (0x0019) ACC_PUBLIC, ACC_STATIC, ACC_FINAL
+ Signature: #x // Ljava/util/Set<Ljava/lang/Class<*>;>;
+
+ private com.android.hoststubgen.test.tinyframework.TinyFrameworkClassLoadHook();
+ descriptor: ()V
+ flags: (0x0002) ACC_PRIVATE
+ Code:
+ stack=1, locals=1, args_size=1
+ 0: aload_0
+ 1: invokespecial #x // Method java/lang/Object."<init>":()V
+ 4: return
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkClassLoadHook;
+
+ public static void onClassLoaded(java.lang.Class<?>);
+ descriptor: (Ljava/lang/Class;)V
+ flags: (0x0009) ACC_PUBLIC, ACC_STATIC
+ Code:
+ stack=2, locals=1, args_size=1
+ 0: getstatic #x // Field sLoadedClasses:Ljava/util/Set;
+ 3: aload_0
+ 4: invokeinterface #x, 2 // InterfaceMethod java/util/Set.add:(Ljava/lang/Object;)Z
+ 9: pop
+ 10: return
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 11 0 clazz Ljava/lang/Class;
+ LocalVariableTypeTable:
+ Start Length Slot Name Signature
+ 0 11 0 clazz Ljava/lang/Class<*>;
+ Signature: #x // (Ljava/lang/Class<*>;)V
+
+ static {};
+ descriptor: ()V
+ flags: (0x0008) ACC_STATIC
+ Code:
+ stack=2, locals=0, args_size=0
+ 0: new #x // class java/util/HashSet
+ 3: dup
+ 4: invokespecial #x // Method java/util/HashSet."<init>":()V
+ 7: putstatic #x // Field sLoadedClasses:Ljava/util/Set;
+ 10: return
+ LineNumberTable:
+}
+SourceFile: "TinyFrameworkClassLoadHook.java"
+RuntimeVisibleAnnotations:
+ 0: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedStubClass
+ 1: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+RuntimeInvisibleAnnotations:
+ 0: #x()
+ android.hosttest.annotation.HostSideTestWholeClassStub
+## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkClassWithInitializer.class
+ Compiled from "TinyFrameworkClassWithInitializer.java"
+public class com.android.hoststubgen.test.tinyframework.TinyFrameworkClassWithInitializer
+ minor version: 0
+ major version: 61
+ flags: (0x0021) ACC_PUBLIC, ACC_SUPER
+ this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkClassWithInitializer
+ super_class: #x // java/lang/Object
+ interfaces: 0, fields: 1, methods: 2, attributes: 3
+ public static boolean sInitialized;
+ descriptor: Z
+ flags: (0x0009) ACC_PUBLIC, ACC_STATIC
+
+ public com.android.hoststubgen.test.tinyframework.TinyFrameworkClassWithInitializer();
+ descriptor: ()V
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=1, locals=1, args_size=1
+ 0: aload_0
+ 1: invokespecial #x // Method java/lang/Object."<init>":()V
+ 4: return
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkClassWithInitializer;
+
+ static {};
+ descriptor: ()V
+ flags: (0x0008) ACC_STATIC
+ Code:
+ stack=2, locals=0, args_size=0
+ 0: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkClassWithInitializer
+ 2: ldc #x // String com.android.hoststubgen.test.tinyframework.TinyFrameworkClassLoadHook.onClassLoaded
+ 4: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onClassLoaded:(Ljava/lang/Class;Ljava/lang/String;)V
+ 7: iconst_1
+ 8: putstatic #x // Field sInitialized:Z
+ 11: return
+ LineNumberTable:
+}
+SourceFile: "TinyFrameworkClassWithInitializer.java"
+RuntimeVisibleAnnotations:
+ 0: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedStubClass
+ 1: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+RuntimeInvisibleAnnotations:
+ 0: #x(#x=s#x)
+ android.hosttest.annotation.HostSideTestClassLoadHook(
+ value="com.android.hoststubgen.test.tinyframework.TinyFrameworkClassLoadHook.onClassLoaded"
+ )
+ 1: #x()
+ android.hosttest.annotation.HostSideTestWholeClassStub
+## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkExceptionTester.class
+ Compiled from "TinyFrameworkExceptionTester.java"
+public class com.android.hoststubgen.test.tinyframework.TinyFrameworkExceptionTester
+ minor version: 0
+ major version: 61
+ flags: (0x0021) ACC_PUBLIC, ACC_SUPER
+ this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkExceptionTester
+ super_class: #x // java/lang/Object
+ interfaces: 0, fields: 0, methods: 2, attributes: 3
+ public com.android.hoststubgen.test.tinyframework.TinyFrameworkExceptionTester();
+ descriptor: ()V
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=1, locals=1, args_size=1
+ 0: aload_0
+ 1: invokespecial #x // Method java/lang/Object."<init>":()V
+ 4: return
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkExceptionTester;
+
+ public static int testException();
+ descriptor: ()I
+ flags: (0x0009) ACC_PUBLIC, ACC_STATIC
+ Code:
+ stack=4, locals=1, args_size=0
+ 0: new #x // class java/lang/IllegalStateException
+ 3: dup
+ 4: ldc #x // String Inner exception
+ 6: invokespecial #x // Method java/lang/IllegalStateException."<init>":(Ljava/lang/String;)V
+ 9: athrow
+ 10: astore_0
+ 11: new #x // class java/lang/RuntimeException
+ 14: dup
+ 15: ldc #x // String Outer exception
+ 17: aload_0
+ 18: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;Ljava/lang/Throwable;)V
+ 21: athrow
+ Exception table:
+ from to target type
+ 0 10 10 Class java/lang/Exception
+ StackMapTable: number_of_entries = 1
+ frame_type = 74 /* same_locals_1_stack_item */
+ stack = [ class java/lang/Exception ]
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 11 11 0 e Ljava/lang/Exception;
+}
+SourceFile: "TinyFrameworkExceptionTester.java"
+RuntimeVisibleAnnotations:
+ 0: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedStubClass
+ 1: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+RuntimeInvisibleAnnotations:
+ 0: #x()
+ android.hosttest.annotation.HostSideTestWholeClassStub
+## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy.class
+ Compiled from "TinyFrameworkForTextPolicy.java"
+public class com.android.hoststubgen.test.tinyframework.TinyFrameworkForTextPolicy
+ minor version: 0
+ major version: 61
+ flags: (0x0021) ACC_PUBLIC, ACC_SUPER
+ this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy
+ super_class: #x // java/lang/Object
+ interfaces: 0, fields: 2, methods: 8, attributes: 2
+ public int stub;
+ descriptor: I
+ flags: (0x0001) ACC_PUBLIC
+
+ public int keep;
+ descriptor: I
+ flags: (0x0001) ACC_PUBLIC
+
+ private static {};
+ descriptor: ()V
+ flags: (0x000a) ACC_PRIVATE, ACC_STATIC
+ Code:
+ stack=2, locals=0, args_size=0
+ 0: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy
+ 2: ldc #x // String com.android.hoststubgen.test.tinyframework.TinyFrameworkClassLoadHook.onClassLoaded
+ 4: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onClassLoaded:(Ljava/lang/Class;Ljava/lang/String;)V
+ 7: return
+
+ public com.android.hoststubgen.test.tinyframework.TinyFrameworkForTextPolicy();
+ descriptor: ()V
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=2, locals=1, args_size=1
+ 0: aload_0
+ 1: invokespecial #x // Method java/lang/Object."<init>":()V
+ 4: aload_0
+ 5: iconst_1
+ 6: putfield #x // Field stub:I
+ 9: aload_0
+ 10: iconst_2
+ 11: putfield #x // Field keep:I
+ 14: return
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 15 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy;
+
+ public int addOne(int);
+ descriptor: (I)I
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=2, locals=2, args_size=2
+ 0: aload_0
+ 1: iload_1
+ 2: invokevirtual #x // Method addOneInner:(I)I
+ 5: ireturn
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 6 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy;
+ 0 6 1 value I
+
+ public int addOneInner(int);
+ descriptor: (I)I
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=4, locals=2, args_size=2
+ 0: ldc #x // String com/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy
+ 2: ldc #x // String addOneInner
+ 4: ldc #x // String (I)I
+ 6: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.getStackWalker:()Ljava/lang/StackWalker;
+ 9: invokevirtual #x // Method java/lang/StackWalker.getCallerClass:()Ljava/lang/Class;
+ 12: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onNonStubMethodCalled:(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Class;)V
+ 15: iload_1
+ 16: iconst_1
+ 17: iadd
+ 18: ireturn
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 15 4 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy;
+ 15 4 1 value I
+
+ public int addTwo(int);
+ descriptor: (I)I
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=2, locals=2, args_size=2
+ 0: iload_1
+ 1: iconst_2
+ 2: iadd
+ 3: ireturn
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 4 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy;
+ 0 4 1 value I
+
+ public static int nativeAddThree(int);
+ descriptor: (I)I
+ flags: (0x0009) ACC_PUBLIC, ACC_STATIC
+ Code:
+ stack=2, locals=1, args_size=1
+ 0: iload_0
+ 1: iconst_3
+ 2: iadd
+ 3: ireturn
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 4 0 value I
+
+ public java.lang.String unsupportedMethod();
+ descriptor: ()Ljava/lang/String;
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=4, locals=1, args_size=1
+ 0: ldc #x // String com/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy
+ 2: ldc #x // String unsupportedMethod
+ 4: ldc #x // String ()Ljava/lang/String;
+ 6: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.getStackWalker:()Ljava/lang/StackWalker;
+ 9: invokevirtual #x // Method java/lang/StackWalker.getCallerClass:()Ljava/lang/Class;
+ 12: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onNonStubMethodCalled:(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Class;)V
+ 15: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onThrowMethodCalled:()V
+ 18: new #x // class java/lang/RuntimeException
+ 21: dup
+ 22: ldc #x // String Unreachable
+ 24: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
+ 27: athrow
+
+ public java.lang.String visibleButUsesUnsupportedMethod();
+ descriptor: ()Ljava/lang/String;
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=1, locals=1, args_size=1
+ 0: aload_0
+ 1: invokevirtual #x // Method unsupportedMethod:()Ljava/lang/String;
+ 4: areturn
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy;
+}
+SourceFile: "TinyFrameworkForTextPolicy.java"
+RuntimeVisibleAnnotations:
+ 0: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedStubClass
+ 1: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkNative.class
+ Compiled from "TinyFrameworkNative.java"
+public class com.android.hoststubgen.test.tinyframework.TinyFrameworkNative
+ minor version: 0
+ major version: 61
+ flags: (0x0021) ACC_PUBLIC, ACC_SUPER
+ this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkNative
+ super_class: #x // java/lang/Object
+ interfaces: 0, fields: 0, methods: 5, attributes: 3
+ public com.android.hoststubgen.test.tinyframework.TinyFrameworkNative();
+ descriptor: ()V
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=1, locals=1, args_size=1
+ 0: aload_0
+ 1: invokespecial #x // Method java/lang/Object."<init>":()V
+ 4: return
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNative;
+
+ public static int nativeAddTwo(int);
+ descriptor: (I)I
+ flags: (0x0009) ACC_PUBLIC, ACC_STATIC
+ Code:
+ stack=1, locals=1, args_size=1
+ 0: iload_0
+ 1: invokestatic #x // Method com/android/hoststubgen/test/tinyframework/TinyFrameworkNative_host.nativeAddTwo:(I)I
+ 4: ireturn
+
+ public static int nativeAddTwo_should_be_like_this(int);
+ descriptor: (I)I
+ flags: (0x0009) ACC_PUBLIC, ACC_STATIC
+ Code:
+ stack=1, locals=1, args_size=1
+ 0: iload_0
+ 1: invokestatic #x // Method com/android/hoststubgen/test/tinyframework/TinyFrameworkNative_host.nativeAddTwo:(I)I
+ 4: ireturn
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 5 0 arg I
+
+ public static long nativeLongPlus(long, long);
+ descriptor: (JJ)J
+ flags: (0x0009) ACC_PUBLIC, ACC_STATIC
+ Code:
+ stack=4, locals=4, args_size=2
+ 0: lload_0
+ 1: lload_2
+ 2: invokestatic #x // Method com/android/hoststubgen/test/tinyframework/TinyFrameworkNative_host.nativeLongPlus:(JJ)J
+ 5: lreturn
+
+ public static long nativeLongPlus_should_be_like_this(long, long);
+ descriptor: (JJ)J
+ flags: (0x0009) ACC_PUBLIC, ACC_STATIC
+ Code:
+ stack=4, locals=4, args_size=2
+ 0: lload_0
+ 1: lload_2
+ 2: invokestatic #x // Method com/android/hoststubgen/test/tinyframework/TinyFrameworkNative_host.nativeLongPlus:(JJ)J
+ 5: lreturn
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 6 0 arg1 J
+ 0 6 2 arg2 J
+}
+SourceFile: "TinyFrameworkNative.java"
+RuntimeVisibleAnnotations:
+ 0: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedStubClass
+ 1: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+RuntimeInvisibleAnnotations:
+ 0: #x()
+ android.hosttest.annotation.HostSideTestWholeClassStub
+ 1: #x(#x=s#x)
+ android.hosttest.annotation.HostSideTestNativeSubstitutionClass(
+ value="TinyFrameworkNative_host"
+ )
+## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkNative_host.class
+ Compiled from "TinyFrameworkNative_host.java"
+public class com.android.hoststubgen.test.tinyframework.TinyFrameworkNative_host
+ minor version: 0
+ major version: 61
+ flags: (0x0021) ACC_PUBLIC, ACC_SUPER
+ this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkNative_host
+ super_class: #x // java/lang/Object
+ interfaces: 0, fields: 0, methods: 3, attributes: 3
+ public com.android.hoststubgen.test.tinyframework.TinyFrameworkNative_host();
+ descriptor: ()V
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=4, locals=1, args_size=1
+ 0: ldc #x // String com/android/hoststubgen/test/tinyframework/TinyFrameworkNative_host
+ 2: ldc #x // String <init>
+ 4: ldc #x // String ()V
+ 6: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.getStackWalker:()Ljava/lang/StackWalker;
+ 9: invokevirtual #x // Method java/lang/StackWalker.getCallerClass:()Ljava/lang/Class;
+ 12: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onNonStubMethodCalled:(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Class;)V
+ 15: aload_0
+ 16: invokespecial #x // Method java/lang/Object."<init>":()V
+ 19: return
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 15 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNative_host;
+
+ public static int nativeAddTwo(int);
+ descriptor: (I)I
+ flags: (0x0009) ACC_PUBLIC, ACC_STATIC
+ Code:
+ stack=4, locals=1, args_size=1
+ 0: ldc #x // String com/android/hoststubgen/test/tinyframework/TinyFrameworkNative_host
+ 2: ldc #x // String nativeAddTwo
+ 4: ldc #x // String (I)I
+ 6: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.getStackWalker:()Ljava/lang/StackWalker;
+ 9: invokevirtual #x // Method java/lang/StackWalker.getCallerClass:()Ljava/lang/Class;
+ 12: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onNonStubMethodCalled:(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Class;)V
+ 15: iload_0
+ 16: iconst_2
+ 17: iadd
+ 18: ireturn
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 15 4 0 arg I
+
+ public static long nativeLongPlus(long, long);
+ descriptor: (JJ)J
+ flags: (0x0009) ACC_PUBLIC, ACC_STATIC
+ Code:
+ stack=4, locals=4, args_size=2
+ 0: ldc #x // String com/android/hoststubgen/test/tinyframework/TinyFrameworkNative_host
+ 2: ldc #x // String nativeLongPlus
+ 4: ldc #x // String (JJ)J
+ 6: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.getStackWalker:()Ljava/lang/StackWalker;
+ 9: invokevirtual #x // Method java/lang/StackWalker.getCallerClass:()Ljava/lang/Class;
+ 12: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onNonStubMethodCalled:(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Class;)V
+ 15: lload_0
+ 16: lload_2
+ 17: ladd
+ 18: lreturn
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 15 4 0 arg1 J
+ 15 4 2 arg2 J
+}
+SourceFile: "TinyFrameworkNative_host.java"
+RuntimeVisibleAnnotations:
+ 0: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+RuntimeInvisibleAnnotations:
+ 0: #x()
+ android.hosttest.annotation.HostSideTestWholeClassKeep
+## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$1.class
+ Compiled from "TinyFrameworkNestedClasses.java"
+class com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$1 extends java.lang.Object implements java.util.function.Supplier<java.lang.Integer>
+ minor version: 0
+ major version: 61
+ flags: (0x0020) ACC_SUPER
+ this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$1
+ super_class: #x // java/lang/Object
+ interfaces: 1, fields: 1, methods: 3, attributes: 6
+ final com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses this$0;
+ descriptor: Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses;
+ flags: (0x1010) ACC_FINAL, ACC_SYNTHETIC
+
+ com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$1(com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses);
+ descriptor: (Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses;)V
+ flags: (0x0000)
+ Code:
+ stack=2, locals=2, args_size=2
+ 0: aload_0
+ 1: aload_1
+ 2: putfield #x // Field this$0:Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses;
+ 5: aload_0
+ 6: invokespecial #x // Method java/lang/Object."<init>":()V
+ 9: return
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 10 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$1;
+ 0 10 1 this$0 Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses;
+
+ public java.lang.Integer get();
+ descriptor: ()Ljava/lang/Integer;
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=4, locals=1, args_size=1
+ 0: ldc #x // String com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$1
+ 2: ldc #x // String get
+ 4: ldc #x // String ()Ljava/lang/Integer;
+ 6: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.getStackWalker:()Ljava/lang/StackWalker;
+ 9: invokevirtual #x // Method java/lang/StackWalker.getCallerClass:()Ljava/lang/Class;
+ 12: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onNonStubMethodCalled:(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Class;)V
+ 15: iconst_1
+ 16: invokestatic #x // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
+ 19: areturn
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 15 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$1;
+
+ public java.lang.Object get();
+ descriptor: ()Ljava/lang/Object;
+ flags: (0x1041) ACC_PUBLIC, ACC_BRIDGE, ACC_SYNTHETIC
+ Code:
+ stack=4, locals=1, args_size=1
+ 0: ldc #x // String com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$1
+ 2: ldc #x // String get
+ 4: ldc #x // String ()Ljava/lang/Object;
+ 6: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.getStackWalker:()Ljava/lang/StackWalker;
+ 9: invokevirtual #x // Method java/lang/StackWalker.getCallerClass:()Ljava/lang/Class;
+ 12: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onNonStubMethodCalled:(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Class;)V
+ 15: aload_0
+ 16: invokevirtual #x // Method get:()Ljava/lang/Integer;
+ 19: areturn
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 15 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$1;
+}
+InnerClasses:
+ #x; // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$1
+EnclosingMethod: #x.#x // com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses
+Signature: #x // Ljava/lang/Object;Ljava/util/function/Supplier<Ljava/lang/Integer;>;
+SourceFile: "TinyFrameworkNestedClasses.java"
+RuntimeVisibleAnnotations:
+ 0: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+NestHost: class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
+## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$2.class
+ Compiled from "TinyFrameworkNestedClasses.java"
+class com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$2 extends java.lang.Object implements java.util.function.Supplier<java.lang.Integer>
+ minor version: 0
+ major version: 61
+ flags: (0x0020) ACC_SUPER
+ this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$2
+ super_class: #x // java/lang/Object
+ interfaces: 1, fields: 0, methods: 3, attributes: 6
+ com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$2();
+ descriptor: ()V
+ flags: (0x0000)
+ Code:
+ stack=1, locals=1, args_size=1
+ 0: aload_0
+ 1: invokespecial #x // Method java/lang/Object."<init>":()V
+ 4: return
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$2;
+
+ public java.lang.Integer get();
+ descriptor: ()Ljava/lang/Integer;
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=4, locals=1, args_size=1
+ 0: ldc #x // String com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$2
+ 2: ldc #x // String get
+ 4: ldc #x // String ()Ljava/lang/Integer;
+ 6: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.getStackWalker:()Ljava/lang/StackWalker;
+ 9: invokevirtual #x // Method java/lang/StackWalker.getCallerClass:()Ljava/lang/Class;
+ 12: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onNonStubMethodCalled:(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Class;)V
+ 15: iconst_2
+ 16: invokestatic #x // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
+ 19: areturn
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 15 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$2;
+
+ public java.lang.Object get();
+ descriptor: ()Ljava/lang/Object;
+ flags: (0x1041) ACC_PUBLIC, ACC_BRIDGE, ACC_SYNTHETIC
+ Code:
+ stack=4, locals=1, args_size=1
+ 0: ldc #x // String com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$2
+ 2: ldc #x // String get
+ 4: ldc #x // String ()Ljava/lang/Object;
+ 6: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.getStackWalker:()Ljava/lang/StackWalker;
+ 9: invokevirtual #x // Method java/lang/StackWalker.getCallerClass:()Ljava/lang/Class;
+ 12: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onNonStubMethodCalled:(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Class;)V
+ 15: aload_0
+ 16: invokevirtual #x // Method get:()Ljava/lang/Integer;
+ 19: areturn
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 15 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$2;
+}
+InnerClasses:
+ #x; // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$2
+EnclosingMethod: #x.#x // com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses
+Signature: #x // Ljava/lang/Object;Ljava/util/function/Supplier<Ljava/lang/Integer;>;
+SourceFile: "TinyFrameworkNestedClasses.java"
+RuntimeVisibleAnnotations:
+ 0: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+NestHost: class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
+## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$3.class
+ Compiled from "TinyFrameworkNestedClasses.java"
+class com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$3 extends java.lang.Object implements java.util.function.Supplier<java.lang.Integer>
+ minor version: 0
+ major version: 61
+ flags: (0x0020) ACC_SUPER
+ this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$3
+ super_class: #x // java/lang/Object
+ interfaces: 1, fields: 1, methods: 3, attributes: 6
+ final com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses this$0;
+ descriptor: Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses;
+ flags: (0x1010) ACC_FINAL, ACC_SYNTHETIC
+
+ com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$3(com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses);
+ descriptor: (Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses;)V
+ flags: (0x0000)
+ Code:
+ stack=2, locals=2, args_size=2
+ 0: aload_0
+ 1: aload_1
+ 2: putfield #x // Field this$0:Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses;
+ 5: aload_0
+ 6: invokespecial #x // Method java/lang/Object."<init>":()V
+ 9: return
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 10 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$3;
+ 0 10 1 this$0 Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses;
+
+ public java.lang.Integer get();
+ descriptor: ()Ljava/lang/Integer;
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=4, locals=1, args_size=1
+ 0: ldc #x // String com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$3
+ 2: ldc #x // String get
+ 4: ldc #x // String ()Ljava/lang/Integer;
+ 6: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.getStackWalker:()Ljava/lang/StackWalker;
+ 9: invokevirtual #x // Method java/lang/StackWalker.getCallerClass:()Ljava/lang/Class;
+ 12: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onNonStubMethodCalled:(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Class;)V
+ 15: iconst_3
+ 16: invokestatic #x // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
+ 19: areturn
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 15 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$3;
+
+ public java.lang.Object get();
+ descriptor: ()Ljava/lang/Object;
+ flags: (0x1041) ACC_PUBLIC, ACC_BRIDGE, ACC_SYNTHETIC
+ Code:
+ stack=4, locals=1, args_size=1
+ 0: ldc #x // String com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$3
+ 2: ldc #x // String get
+ 4: ldc #x // String ()Ljava/lang/Object;
+ 6: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.getStackWalker:()Ljava/lang/StackWalker;
+ 9: invokevirtual #x // Method java/lang/StackWalker.getCallerClass:()Ljava/lang/Class;
+ 12: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onNonStubMethodCalled:(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Class;)V
+ 15: aload_0
+ 16: invokevirtual #x // Method get:()Ljava/lang/Integer;
+ 19: areturn
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 15 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$3;
+}
+InnerClasses:
+ #x; // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$3
+EnclosingMethod: #x.#x // com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses.getSupplier
+Signature: #x // Ljava/lang/Object;Ljava/util/function/Supplier<Ljava/lang/Integer;>;
+SourceFile: "TinyFrameworkNestedClasses.java"
+RuntimeVisibleAnnotations:
+ 0: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+NestHost: class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
+## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$4.class
+ Compiled from "TinyFrameworkNestedClasses.java"
+class com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$4 extends java.lang.Object implements java.util.function.Supplier<java.lang.Integer>
+ minor version: 0
+ major version: 61
+ flags: (0x0020) ACC_SUPER
+ this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$4
+ super_class: #x // java/lang/Object
+ interfaces: 1, fields: 0, methods: 3, attributes: 6
+ com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$4();
+ descriptor: ()V
+ flags: (0x0000)
+ Code:
+ stack=1, locals=1, args_size=1
+ 0: aload_0
+ 1: invokespecial #x // Method java/lang/Object."<init>":()V
+ 4: return
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$4;
+
+ public java.lang.Integer get();
+ descriptor: ()Ljava/lang/Integer;
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=4, locals=1, args_size=1
+ 0: ldc #x // String com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$4
+ 2: ldc #x // String get
+ 4: ldc #x // String ()Ljava/lang/Integer;
+ 6: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.getStackWalker:()Ljava/lang/StackWalker;
+ 9: invokevirtual #x // Method java/lang/StackWalker.getCallerClass:()Ljava/lang/Class;
+ 12: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onNonStubMethodCalled:(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Class;)V
+ 15: iconst_4
+ 16: invokestatic #x // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
+ 19: areturn
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 15 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$4;
+
+ public java.lang.Object get();
+ descriptor: ()Ljava/lang/Object;
+ flags: (0x1041) ACC_PUBLIC, ACC_BRIDGE, ACC_SYNTHETIC
+ Code:
+ stack=4, locals=1, args_size=1
+ 0: ldc #x // String com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$4
+ 2: ldc #x // String get
+ 4: ldc #x // String ()Ljava/lang/Object;
+ 6: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.getStackWalker:()Ljava/lang/StackWalker;
+ 9: invokevirtual #x // Method java/lang/StackWalker.getCallerClass:()Ljava/lang/Class;
+ 12: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onNonStubMethodCalled:(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Class;)V
+ 15: aload_0
+ 16: invokevirtual #x // Method get:()Ljava/lang/Integer;
+ 19: areturn
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 15 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$4;
+}
+InnerClasses:
+ #x; // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$4
+EnclosingMethod: #x.#x // com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses.getSupplier_static
+Signature: #x // Ljava/lang/Object;Ljava/util/function/Supplier<Ljava/lang/Integer;>;
+SourceFile: "TinyFrameworkNestedClasses.java"
+RuntimeVisibleAnnotations:
+ 0: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+NestHost: class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
+## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$BaseClass.class
+ Compiled from "TinyFrameworkNestedClasses.java"
+public class com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$BaseClass
+ minor version: 0
+ major version: 61
+ flags: (0x0021) ACC_PUBLIC, ACC_SUPER
+ this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$BaseClass
+ super_class: #x // java/lang/Object
+ interfaces: 0, fields: 1, methods: 1, attributes: 4
+ public int value;
+ descriptor: I
+ flags: (0x0001) ACC_PUBLIC
+
+ public com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$BaseClass(int);
+ descriptor: (I)V
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=2, locals=2, args_size=2
+ 0: aload_0
+ 1: invokespecial #x // Method java/lang/Object."<init>":()V
+ 4: aload_0
+ 5: iload_1
+ 6: putfield #x // Field value:I
+ 9: return
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 10 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$BaseClass;
+ 0 10 1 x I
+}
+InnerClasses:
+ public static #x= #x of #x; // BaseClass=class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$BaseClass of class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
+SourceFile: "TinyFrameworkNestedClasses.java"
+RuntimeVisibleAnnotations:
+ 0: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedStubClass
+ 1: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+NestHost: class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
+## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$InnerClass.class
+ Compiled from "TinyFrameworkNestedClasses.java"
+public class com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$InnerClass
+ minor version: 0
+ major version: 61
+ flags: (0x0021) ACC_PUBLIC, ACC_SUPER
+ this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$InnerClass
+ super_class: #x // java/lang/Object
+ interfaces: 0, fields: 2, methods: 1, attributes: 5
+ public int value;
+ descriptor: I
+ flags: (0x0001) ACC_PUBLIC
+
+ final com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses this$0;
+ descriptor: Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses;
+ flags: (0x1010) ACC_FINAL, ACC_SYNTHETIC
+
+ public com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$InnerClass(com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses);
+ descriptor: (Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses;)V
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=2, locals=2, args_size=2
+ 0: aload_0
+ 1: aload_1
+ 2: putfield #x // Field this$0:Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses;
+ 5: aload_0
+ 6: invokespecial #x // Method java/lang/Object."<init>":()V
+ 9: aload_0
+ 10: iconst_5
+ 11: putfield #x // Field value:I
+ 14: return
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 15 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$InnerClass;
+ 0 15 1 this$0 Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses;
+}
+InnerClasses:
+ public #x= #x of #x; // InnerClass=class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$InnerClass of class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
+SourceFile: "TinyFrameworkNestedClasses.java"
+RuntimeVisibleAnnotations:
+ 0: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedStubClass
+ 1: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+RuntimeInvisibleAnnotations:
+ 0: #x()
+ android.hosttest.annotation.HostSideTestWholeClassStub
+NestHost: class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
+## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass$1.class
+ Compiled from "TinyFrameworkNestedClasses.java"
+class com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$StaticNestedClass$1 extends java.lang.Object implements java.util.function.Supplier<java.lang.Integer>
+ minor version: 0
+ major version: 61
+ flags: (0x0020) ACC_SUPER
+ this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass$1
+ super_class: #x // java/lang/Object
+ interfaces: 1, fields: 0, methods: 3, attributes: 6
+ com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$StaticNestedClass$1();
+ descriptor: ()V
+ flags: (0x0000)
+ Code:
+ stack=1, locals=1, args_size=1
+ 0: aload_0
+ 1: invokespecial #x // Method java/lang/Object."<init>":()V
+ 4: return
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass$1;
+
+ public java.lang.Integer get();
+ descriptor: ()Ljava/lang/Integer;
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=4, locals=1, args_size=1
+ 0: ldc #x // String com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass$1
+ 2: ldc #x // String get
+ 4: ldc #x // String ()Ljava/lang/Integer;
+ 6: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.getStackWalker:()Ljava/lang/StackWalker;
+ 9: invokevirtual #x // Method java/lang/StackWalker.getCallerClass:()Ljava/lang/Class;
+ 12: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onNonStubMethodCalled:(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Class;)V
+ 15: bipush 7
+ 17: invokestatic #x // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
+ 20: areturn
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 15 6 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass$1;
+
+ public java.lang.Object get();
+ descriptor: ()Ljava/lang/Object;
+ flags: (0x1041) ACC_PUBLIC, ACC_BRIDGE, ACC_SYNTHETIC
+ Code:
+ stack=4, locals=1, args_size=1
+ 0: ldc #x // String com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass$1
+ 2: ldc #x // String get
+ 4: ldc #x // String ()Ljava/lang/Object;
+ 6: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.getStackWalker:()Ljava/lang/StackWalker;
+ 9: invokevirtual #x // Method java/lang/StackWalker.getCallerClass:()Ljava/lang/Class;
+ 12: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onNonStubMethodCalled:(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Class;)V
+ 15: aload_0
+ 16: invokevirtual #x // Method get:()Ljava/lang/Integer;
+ 19: areturn
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 15 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass$1;
+}
+InnerClasses:
+ public static #x= #x of #x; // StaticNestedClass=class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass of class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
+ #x; // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass$1
+EnclosingMethod: #x.#x // com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$StaticNestedClass.getSupplier_static
+Signature: #x // Ljava/lang/Object;Ljava/util/function/Supplier<Ljava/lang/Integer;>;
+SourceFile: "TinyFrameworkNestedClasses.java"
+RuntimeVisibleAnnotations:
+ 0: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+NestHost: class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
+## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass.class
+ Compiled from "TinyFrameworkNestedClasses.java"
+public class com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$StaticNestedClass
+ minor version: 0
+ major version: 61
+ flags: (0x0021) ACC_PUBLIC, ACC_SUPER
+ this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass
+ super_class: #x // java/lang/Object
+ interfaces: 0, fields: 1, methods: 2, attributes: 5
+ public int value;
+ descriptor: I
+ flags: (0x0001) ACC_PUBLIC
+
+ public com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$StaticNestedClass();
+ descriptor: ()V
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=2, locals=1, args_size=1
+ 0: aload_0
+ 1: invokespecial #x // Method java/lang/Object."<init>":()V
+ 4: aload_0
+ 5: bipush 6
+ 7: putfield #x // Field value:I
+ 10: return
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 11 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass;
+
+ public static java.util.function.Supplier<java.lang.Integer> getSupplier_static();
+ descriptor: ()Ljava/util/function/Supplier;
+ flags: (0x0009) ACC_PUBLIC, ACC_STATIC
+ Code:
+ stack=2, locals=0, args_size=0
+ 0: new #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass$1
+ 3: dup
+ 4: invokespecial #x // Method com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass$1."<init>":()V
+ 7: areturn
+ LineNumberTable:
+ Signature: #x // ()Ljava/util/function/Supplier<Ljava/lang/Integer;>;
+}
+InnerClasses:
+ public static #x= #x of #x; // StaticNestedClass=class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass of class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
+ #x; // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass$1
+SourceFile: "TinyFrameworkNestedClasses.java"
+RuntimeVisibleAnnotations:
+ 0: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedStubClass
+ 1: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+RuntimeInvisibleAnnotations:
+ 0: #x()
+ android.hosttest.annotation.HostSideTestWholeClassStub
+NestHost: class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
+## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$SubClass.class
+ Compiled from "TinyFrameworkNestedClasses.java"
+public class com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$SubClass extends com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$BaseClass
+ minor version: 0
+ major version: 61
+ flags: (0x0021) ACC_PUBLIC, ACC_SUPER
+ this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$SubClass
+ super_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$BaseClass
+ interfaces: 0, fields: 0, methods: 1, attributes: 4
+ public com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$SubClass(int);
+ descriptor: (I)V
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=2, locals=2, args_size=2
+ 0: aload_0
+ 1: iload_1
+ 2: invokespecial #x // Method com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$BaseClass."<init>":(I)V
+ 5: return
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 6 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$SubClass;
+ 0 6 1 x I
+}
+InnerClasses:
+ public static #x= #x of #x; // BaseClass=class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$BaseClass of class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
+ public static #x= #x of #x; // SubClass=class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$SubClass of class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
+SourceFile: "TinyFrameworkNestedClasses.java"
+RuntimeVisibleAnnotations:
+ 0: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedStubClass
+ 1: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+NestHost: class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
+## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses.class
+ Compiled from "TinyFrameworkNestedClasses.java"
+public class com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses
+ minor version: 0
+ major version: 61
+ flags: (0x0021) ACC_PUBLIC, ACC_SUPER
+ this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
+ super_class: #x // java/lang/Object
+ interfaces: 0, fields: 2, methods: 4, attributes: 5
+ public final java.util.function.Supplier<java.lang.Integer> mSupplier;
+ descriptor: Ljava/util/function/Supplier;
+ flags: (0x0011) ACC_PUBLIC, ACC_FINAL
+ Signature: #x // Ljava/util/function/Supplier<Ljava/lang/Integer;>;
+
+ public static final java.util.function.Supplier<java.lang.Integer> sSupplier;
+ descriptor: Ljava/util/function/Supplier;
+ flags: (0x0019) ACC_PUBLIC, ACC_STATIC, ACC_FINAL
+ Signature: #x // Ljava/util/function/Supplier<Ljava/lang/Integer;>;
+
+ public com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses();
+ descriptor: ()V
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=4, locals=1, args_size=1
+ 0: aload_0
+ 1: invokespecial #x // Method java/lang/Object."<init>":()V
+ 4: aload_0
+ 5: new #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$1
+ 8: dup
+ 9: aload_0
+ 10: invokespecial #x // Method com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$1."<init>":(Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses;)V
+ 13: putfield #x // Field mSupplier:Ljava/util/function/Supplier;
+ 16: return
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 17 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses;
+
+ public java.util.function.Supplier<java.lang.Integer> getSupplier();
+ descriptor: ()Ljava/util/function/Supplier;
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=3, locals=1, args_size=1
+ 0: new #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$3
+ 3: dup
+ 4: aload_0
+ 5: invokespecial #x // Method com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$3."<init>":(Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses;)V
+ 8: areturn
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 9 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses;
+ Signature: #x // ()Ljava/util/function/Supplier<Ljava/lang/Integer;>;
+
+ public static java.util.function.Supplier<java.lang.Integer> getSupplier_static();
+ descriptor: ()Ljava/util/function/Supplier;
+ flags: (0x0009) ACC_PUBLIC, ACC_STATIC
+ Code:
+ stack=2, locals=0, args_size=0
+ 0: new #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$4
+ 3: dup
+ 4: invokespecial #x // Method com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$4."<init>":()V
+ 7: areturn
+ LineNumberTable:
+ Signature: #x // ()Ljava/util/function/Supplier<Ljava/lang/Integer;>;
+
+ static {};
+ descriptor: ()V
+ flags: (0x0008) ACC_STATIC
+ Code:
+ stack=2, locals=0, args_size=0
+ 0: new #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$2
+ 3: dup
+ 4: invokespecial #x // Method com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$2."<init>":()V
+ 7: putstatic #x // Field sSupplier:Ljava/util/function/Supplier;
+ 10: return
+ LineNumberTable:
+}
+InnerClasses:
+ #x; // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$1
+ #x; // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$3
+ #x; // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$4
+ #x; // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$2
+ public static #x= #x of #x; // SubClass=class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$SubClass of class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
+ public static #x= #x of #x; // BaseClass=class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$BaseClass of class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
+ public static #x= #x of #x; // StaticNestedClass=class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass of class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
+ public #x= #x of #x; // InnerClass=class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$InnerClass of class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
+ #x; // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass$1
+SourceFile: "TinyFrameworkNestedClasses.java"
+RuntimeVisibleAnnotations:
+ 0: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedStubClass
+ 1: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+RuntimeInvisibleAnnotations:
+ 0: #x()
+ android.hosttest.annotation.HostSideTestWholeClassStub
+NestMembers:
+ com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$SubClass
+ com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$BaseClass
+ com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass
+ com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass$1
+ com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$InnerClass
+ com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$4
+ com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$3
+ com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$2
+ com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$1
diff --git a/tools/hoststubgen/hoststubgen/test-tiny-framework/policy-override-tiny-framework.txt b/tools/hoststubgen/hoststubgen/test-tiny-framework/policy-override-tiny-framework.txt
new file mode 100644
index 000000000000..079d2a84e498
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/test-tiny-framework/policy-override-tiny-framework.txt
@@ -0,0 +1,17 @@
+class com/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy stub
+ field stub stub
+ field keep keep
+ # field remove remove # Implicitly remove
+ method <init> ()V stub
+ method addOne (I)I stub
+ method addOneInner (I)I keep
+ method toBeRemoved (Ljava/lang/String;)V remove
+ method addTwo (I)I @addTwo_host
+ # method addTwo_host (I)I # used as a substitute
+ method nativeAddThree (I)I @addThree_host
+ # method addThree_host (I)I # used as a substitute
+ method unsupportedMethod ()Ljava/lang/String; throw
+ method visibleButUsesUnsupportedMethod ()Ljava/lang/String; stub
+
+# Class load hook
+class com/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy ~com.android.hoststubgen.test.tinyframework.TinyFrameworkClassLoadHook.onClassLoaded
diff --git a/tools/hoststubgen/hoststubgen/test-tiny-framework/run-test-manually.sh b/tools/hoststubgen/hoststubgen/test-tiny-framework/run-test-manually.sh
new file mode 100755
index 000000000000..fd486468a1a7
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/test-tiny-framework/run-test-manually.sh
@@ -0,0 +1,132 @@
+#!/bin/bash
+# Copyright (C) 2023 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+
+source "${0%/*}"/../../common.sh
+
+# This scripts run the "tiny-framework" test, but does most stuff from the command line, using
+# the native java and javac commands.
+# This is useful to
+
+
+debug=0
+while getopts "d" opt; do
+case "$opt" in
+ d) debug=1 ;;
+esac
+done
+shift $(($OPTIND - 1))
+
+
+out=out
+
+rm -fr $out
+mkdir -p $out
+
+HOSTSTUBGEN=hoststubgen
+
+# Rebuild the tool and the dependencies. These are the only things we build with the build system.
+run m $HOSTSTUBGEN hoststubgen-annotations hoststubgen-helper-runtime truth-prebuilt junit
+
+
+# Build tiny-framework
+
+tiny_framework_classes=$out/tiny-framework/classes/
+tiny_framework_jar=$out/tiny-framework.jar
+tiny_framework_host_stub_jar=$out/tiny-framework_host_stub.jar
+tiny_framework_host_impl_jar=$out/tiny-framework_host_impl.jar
+
+tiny_test_classes=$out/tiny-test/classes/
+tiny_test_jar=$out/tiny-test.jar
+
+framework_compile_classpaths=(
+ $SOONG_INT/frameworks/base/tools/hoststubgen/hoststubgen/hoststubgen-annotations/android_common/javac/hoststubgen-annotations.jar
+)
+
+test_compile_classpaths=(
+ $SOONG_INT/external/junit/junit/android_common/combined/junit.jar
+ $SOONG_INT/prebuilts/tools/common/m2/truth-prebuilt/android_common/combined/truth-prebuilt.jar
+)
+
+test_runtime_classpaths=(
+ $SOONG_INT/frameworks/base/tools/hoststubgen/hoststubgen/hoststubgen-helper-runtime/linux_glibc_common/javac/hoststubgen-helper-runtime.jar
+)
+
+# This suite runs all tests in the JAR.
+test_classes=(com.android.hoststubgen.hosthelper.HostTestSuite)
+
+# Uncomment this to run a specific test.
+# tests=(com.android.hoststubgen.test.tinyframework.TinyFrameworkBenchmark)
+
+
+# Build tiny-framework.jar
+echo "# Building tiny-framework..."
+run $JAVAC \
+ -cp $( \
+ join : \
+ ${framework_compile_classpaths[@]} \
+ ) \
+ -d $tiny_framework_classes \
+ tiny-framework/src/**/*.java
+
+run $JAR cvf $tiny_framework_jar \
+ -C $tiny_framework_classes .
+
+# Build stub/impl jars
+echo "# Generating the stub and impl jars..."
+run $HOSTSTUBGEN \
+ @../hoststubgen-standard-options.txt \
+ --in-jar $tiny_framework_jar \
+ --out-stub-jar $tiny_framework_host_stub_jar \
+ --out-impl-jar $tiny_framework_host_impl_jar \
+ --policy-override-file policy-override-tiny-framework.txt \
+ --gen-keep-all-file out/tiny-framework_keep_all.txt \
+ --gen-input-dump-file out/tiny-framework_dump.txt \
+ $HOSTSTUBGEN_OPTS
+
+# Extract the jar files, so we can look into them.
+extract $tiny_framework_host_stub_jar $tiny_framework_host_impl_jar
+
+# Build the test
+echo "# Building tiny-test..."
+run $JAVAC \
+ -cp $( \
+ join : \
+ $tiny_framework_host_stub_jar \
+ "${test_compile_classpaths[@]}" \
+ ) \
+ -d $tiny_test_classes \
+ tiny-test/src/**/*.java
+
+run $JAR cvf $tiny_test_jar \
+ -C $tiny_test_classes .
+
+if (( $debug )) ; then
+ JAVA_OPTS="$JAVA_OPTS -agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=8700"
+fi
+
+# Run the test
+echo "# Running tiny-test..."
+run $JAVA \
+ $JAVA_OPTS \
+ -cp $( \
+ join : \
+ $tiny_test_jar \
+ $tiny_framework_host_impl_jar \
+ "${test_compile_classpaths[@]}" \
+ "${test_runtime_classpaths[@]}" \
+ ) \
+ org.junit.runner.JUnitCore \
+ ${test_classes[@]}
diff --git a/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework-dump-test.py b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework-dump-test.py
new file mode 100755
index 000000000000..cee29dcd1d59
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework-dump-test.py
@@ -0,0 +1,64 @@
+#!/usr/bin/python3
+# Copyright (C) 2023 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# Compare the tiny-framework JAR dumps to the golden files.
+
+import sys
+import os
+import unittest
+import subprocess
+
+GOLDEN_DIR = 'golden-output'
+
+# Run diff.
+def run_diff(file1, file2):
+ command = ['diff', '-u', '--ignore-blank-lines', '--ignore-space-change', file1, file2]
+ print(' '.join(command))
+ result = subprocess.run(command, stderr = sys.stdout)
+
+ success = result.returncode == 0
+
+ if success:
+ print(f'No diff found.')
+ else:
+ print(f'Fail: {file1} and {file2} are different.')
+
+ return success
+
+
+# Check one golden file.
+def check_one_file(filename):
+ print(f'= Checking file: {filename}')
+ return run_diff(os.path.join(GOLDEN_DIR, filename), filename)
+
+class TestWithGoldenOutput(unittest.TestCase):
+
+ # Test to check the generated jar files to the golden output.
+ def test_compare_to_golden(self):
+ files = os.listdir(GOLDEN_DIR)
+ files.sort()
+
+ print(f"Golden files: {files}")
+ success = True
+
+ for file in files:
+ if not check_one_file(file):
+ success = False
+
+ if not success:
+ self.fail('Some files are different. See stdout log for more details.')
+
+if __name__ == "__main__":
+ unittest.main(verbosity=2)
diff --git a/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck.java b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck.java
new file mode 100644
index 000000000000..f53020771cc3
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.hoststubgen.test.tinyframework;
+
+import android.hosttest.annotation.HostSideTestKeep;
+import android.hosttest.annotation.HostSideTestStub;
+import android.hosttest.annotation.HostSideTestWholeClassStub;
+
+/**
+ * Used by the benchmark.
+ */
+@HostSideTestWholeClassStub
+public class TinyFrameworkCallerCheck {
+
+ /**
+ * This method uses an inner method (which has the caller check).
+ *
+ * Benchmark result: 768ns
+ */
+ public static int getOne_withCheck() {
+ return Impl.getOneKeep();
+ }
+
+ /**
+ * This method doesn't have any caller check.
+ *
+ * Benchmark result: 2ns
+ */
+ public static int getOne_noCheck() {
+ return Impl.getOneStub();
+ }
+
+ private static class Impl {
+ @HostSideTestKeep
+ public static int getOneKeep() {
+ return 1;
+ }
+
+ @HostSideTestStub
+ public static int getOneStub() {
+ return 1;
+ }
+ }
+}
diff --git a/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkClassAnnotations.java b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkClassAnnotations.java
new file mode 100644
index 000000000000..ab387e0938c3
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkClassAnnotations.java
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.hoststubgen.test.tinyframework;
+
+import android.hosttest.annotation.HostSideTestClassLoadHook;
+import android.hosttest.annotation.HostSideTestKeep;
+import android.hosttest.annotation.HostSideTestRemove;
+import android.hosttest.annotation.HostSideTestStub;
+import android.hosttest.annotation.HostSideTestSubstitute;
+import android.hosttest.annotation.HostSideTestThrow;
+
+/**
+ * Test without class-wide annotations.
+ */
+@HostSideTestStub
+@HostSideTestClassLoadHook(
+ "com.android.hoststubgen.test.tinyframework.TinyFrameworkClassLoadHook.onClassLoaded")
+public class TinyFrameworkClassAnnotations {
+ @HostSideTestStub
+ public TinyFrameworkClassAnnotations() {
+ }
+
+ @HostSideTestStub
+ public int stub = 1;
+
+ @HostSideTestKeep
+ public int keep = 2;
+
+ // Members will be deleted by default.
+ // Deleted fields cannot have an initial value, because otherwise .ctor will fail to set it at
+ // runtime.
+ public int remove;
+
+ @HostSideTestStub
+ public int addOne(int value) {
+ return addOneInner(value);
+ }
+
+ @HostSideTestKeep
+ public int addOneInner(int value) {
+ return value + 1;
+ }
+
+ @HostSideTestRemove // Explicitly remove
+ public void toBeRemoved(String foo) {
+ throw new RuntimeException();
+ }
+
+ @HostSideTestStub
+ @HostSideTestSubstitute(suffix = "_host")
+ public int addTwo(int value) {
+ throw new RuntimeException("not supported on host side");
+ }
+
+ public int addTwo_host(int value) {
+ return value + 2;
+ }
+
+ @HostSideTestStub
+ @HostSideTestSubstitute(suffix = "_host")
+ public static native int nativeAddThree(int value);
+
+ public static int nativeAddThree_host(int value) {
+ return value + 3;
+ }
+
+ @HostSideTestThrow
+ public String unsupportedMethod() {
+ return "This value shouldn't be seen on the host side.";
+ }
+
+ @HostSideTestStub
+ public String visibleButUsesUnsupportedMethod() {
+ return unsupportedMethod();
+ }
+}
diff --git a/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkClassClassWideAnnotations.java b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkClassClassWideAnnotations.java
new file mode 100644
index 000000000000..145b65a98d7b
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkClassClassWideAnnotations.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.hoststubgen.test.tinyframework;
+
+import android.hosttest.annotation.HostSideTestStub;
+import android.hosttest.annotation.HostSideTestSubstitute;
+import android.hosttest.annotation.HostSideTestWholeClassStub;
+
+@HostSideTestWholeClassStub
+public class TinyFrameworkClassClassWideAnnotations {
+ public TinyFrameworkClassClassWideAnnotations() {
+ }
+
+ public int stub = 1;
+
+ public int keep = 2;
+
+ // Cannot have an initial value, because otherwise .ctor will fail to set it at runtime.
+ public int remove;
+
+ // @Stub
+ public int addOne(int value) {
+ return addOneInner(value);
+ }
+
+ // @Keep
+ public int addOneInner(int value) {
+ return value + 1;
+ }
+
+ // @Remove
+ public void toBeRemoved(String foo) {
+ throw new RuntimeException();
+ }
+
+ @HostSideTestStub
+ @HostSideTestSubstitute(suffix = "_host")
+ public int addTwo(int value) {
+ throw new RuntimeException("not supported on host side");
+ }
+
+ public int addTwo_host(int value) {
+ return value + 2;
+ }
+
+ @HostSideTestStub
+ @HostSideTestSubstitute(suffix = "_host")
+ public static native int nativeAddThree(int value);
+
+ public static int nativeAddThree_host(int value) {
+ return value + 3;
+ }
+
+ public String unsupportedMethod() {
+ return "This value shouldn't be seen on the host side.";
+ }
+
+ public String visibleButUsesUnsupportedMethod() {
+ return unsupportedMethod();
+ }
+}
diff --git a/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkClassLoadHook.java b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkClassLoadHook.java
new file mode 100644
index 000000000000..98fc6349cdc9
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkClassLoadHook.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.hoststubgen.test.tinyframework;
+
+import android.hosttest.annotation.HostSideTestWholeClassStub;
+
+import java.util.HashSet;
+import java.util.Set;
+
+@HostSideTestWholeClassStub
+public class TinyFrameworkClassLoadHook {
+ private TinyFrameworkClassLoadHook() {
+ }
+
+ public static final Set<Class<?>> sLoadedClasses = new HashSet<>();
+
+ public static void onClassLoaded(Class<?> clazz) {
+ sLoadedClasses.add(clazz);
+ }
+}
diff --git a/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkClassWithInitializer.java b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkClassWithInitializer.java
new file mode 100644
index 000000000000..53cfdf6cd412
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkClassWithInitializer.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.hoststubgen.test.tinyframework;
+
+import android.hosttest.annotation.HostSideTestClassLoadHook;
+import android.hosttest.annotation.HostSideTestWholeClassStub;
+
+@HostSideTestClassLoadHook(
+ "com.android.hoststubgen.test.tinyframework.TinyFrameworkClassLoadHook.onClassLoaded")
+@HostSideTestWholeClassStub
+public class TinyFrameworkClassWithInitializer {
+ static {
+ sInitialized = true;
+ }
+
+ public static boolean sInitialized;
+}
diff --git a/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkExceptionTester.java b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkExceptionTester.java
new file mode 100644
index 000000000000..909d3b440f50
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkExceptionTester.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.hoststubgen.test.tinyframework;
+
+import android.hosttest.annotation.HostSideTestWholeClassStub;
+
+@HostSideTestWholeClassStub
+public class TinyFrameworkExceptionTester {
+ public static int testException() {
+ try {
+ throw new IllegalStateException("Inner exception");
+ } catch (Exception e) {
+ throw new RuntimeException("Outer exception", e);
+ }
+ }
+}
diff --git a/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy.java b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy.java
new file mode 100644
index 000000000000..bde7c35dc294
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.hoststubgen.test.tinyframework;
+
+/**
+ * Class for testing the "text policy" file.
+ */
+public class TinyFrameworkForTextPolicy {
+ public TinyFrameworkForTextPolicy() {
+ }
+
+ public int stub = 1;
+
+ public int keep = 2;
+
+ // Removed fields cannot have an initial value, because otherwise .ctor will fail to set it at
+ // runtime.
+ public int remove;
+
+ public int addOne(int value) {
+ return addOneInner(value);
+ }
+
+ public int addOneInner(int value) {
+ return value + 1;
+ }
+
+ public void toBeRemoved(String foo) {
+ throw new RuntimeException();
+ }
+
+ public int addTwo(int value) {
+ throw new RuntimeException("not supported on host side");
+ }
+
+ public int addTwo_host(int value) {
+ return value + 2;
+ }
+
+ public static native int nativeAddThree(int value);
+
+ public static int addThree_host(int value) {
+ return value + 3;
+ }
+
+ public String unsupportedMethod() {
+ return "This value shouldn't be seen on the host side.";
+ }
+
+ public String visibleButUsesUnsupportedMethod() {
+ return unsupportedMethod();
+ }
+}
diff --git a/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkNative.java b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkNative.java
new file mode 100644
index 000000000000..c151dcc9c90e
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkNative.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.hoststubgen.test.tinyframework;
+
+import android.hosttest.annotation.HostSideTestNativeSubstitutionClass;
+import android.hosttest.annotation.HostSideTestWholeClassStub;
+
+@HostSideTestWholeClassStub
+@HostSideTestNativeSubstitutionClass("TinyFrameworkNative_host")
+public class TinyFrameworkNative {
+ public static native int nativeAddTwo(int arg);
+
+ public static int nativeAddTwo_should_be_like_this(int arg) {
+ return TinyFrameworkNative_host.nativeAddTwo(arg);
+ }
+
+ public static native long nativeLongPlus(long arg1, long arg2);
+
+ public static long nativeLongPlus_should_be_like_this(long arg1, long arg2) {
+ return TinyFrameworkNative_host.nativeLongPlus(arg1, arg2);
+ }
+}
diff --git a/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkNative_host.java b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkNative_host.java
new file mode 100644
index 000000000000..48f7dea8c66c
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkNative_host.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.hoststubgen.test.tinyframework;
+
+import android.hosttest.annotation.HostSideTestWholeClassKeep;
+
+// TODO: This annotation shouldn't be needed.
+// We should infer it from HostSideTestNativeSubstitutionClass.
+@HostSideTestWholeClassKeep
+public class TinyFrameworkNative_host {
+ public static int nativeAddTwo(int arg) {
+ return arg + 2;
+ }
+
+ public static long nativeLongPlus(long arg1, long arg2) {
+ return arg1 + arg2;
+ }
+}
diff --git a/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses.java b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses.java
new file mode 100644
index 000000000000..e1c48bb85563
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses.java
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.hoststubgen.test.tinyframework;
+
+import android.hosttest.annotation.HostSideTestWholeClassStub;
+
+import java.util.function.Supplier;
+
+@HostSideTestWholeClassStub
+public class TinyFrameworkNestedClasses {
+ public final Supplier<Integer> mSupplier = new Supplier<Integer>() {
+ @Override
+ public Integer get() {
+ return 1;
+ }
+ };
+
+ public static final Supplier<Integer> sSupplier = new Supplier<Integer>() {
+ @Override
+ public Integer get() {
+ return 2;
+ }
+ };
+ public Supplier<Integer> getSupplier() {
+ return new Supplier<Integer>() {
+ @Override
+ public Integer get() {
+ return 3;
+ }
+ };
+ }
+
+ public static Supplier<Integer> getSupplier_static() {
+ return new Supplier<Integer>() {
+ @Override
+ public Integer get() {
+ return 4;
+ }
+ };
+ }
+
+ @HostSideTestWholeClassStub
+ public class InnerClass {
+ public int value = 5;
+ }
+
+ @HostSideTestWholeClassStub
+ public static class StaticNestedClass {
+ public int value = 6;
+
+ // Double-nest
+ public static Supplier<Integer> getSupplier_static() {
+ return new Supplier<Integer>() {
+ @Override
+ public Integer get() {
+ return 7;
+ }
+ };
+ }
+ }
+
+ public static class BaseClass {
+ public int value;
+ public BaseClass(int x) {
+ value = x;
+ }
+ }
+
+ public static class SubClass extends BaseClass {
+ public SubClass(int x) {
+ super(x);
+ }
+ }
+}
diff --git a/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-test/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkBenchmark.java b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-test/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkBenchmark.java
new file mode 100644
index 000000000000..6b5110ef2cef
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-test/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkBenchmark.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.hoststubgen.test.tinyframework;
+
+import org.junit.Test;
+
+import java.text.DecimalFormat;
+
+/**
+ * Contains simple micro-benchmarks.
+ */
+public class TinyFrameworkBenchmark {
+ private static final int MINIMAL_ITERATION = 1000;
+ private static final int MEASURE_SECONDS = 3;
+
+ private static final DecimalFormat sFormatter = new DecimalFormat("#,###");
+
+ private void doBenchmark(String name, Runnable r) {
+ // Worm up
+ for (int i = 0; i < MINIMAL_ITERATION; i++) {
+ r.run();
+ }
+
+ // Start measuring.
+ final long start = System.nanoTime();
+ final long end = start + MEASURE_SECONDS * 1_000_000_000L;
+
+ double iteration = 0;
+ while (System.nanoTime() <= end) {
+ for (int i = 0; i < MINIMAL_ITERATION; i++) {
+ r.run();
+ }
+ iteration += MINIMAL_ITERATION;
+ }
+
+ final long realEnd = System.nanoTime();
+
+ System.out.println(String.format("%s\t%s", name,
+ sFormatter.format((((double) realEnd - start)) / iteration)));
+ }
+
+ /**
+ * Micro-benchmark for a method without a non-stub caller check.
+ */
+ @Test
+ public void benchNoCallerCheck() {
+ doBenchmark("No caller check", TinyFrameworkCallerCheck::getOne_noCheck);
+ }
+
+ /**
+ * Micro-benchmark for a method with a non-stub caller check.
+ */
+ @Test
+ public void benchWithCallerCheck() {
+ doBenchmark("With caller check", TinyFrameworkCallerCheck::getOne_withCheck);
+ }
+}
diff --git a/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-test/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkClassTest.java b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-test/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkClassTest.java
new file mode 100644
index 000000000000..246d06526f5b
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-test/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkClassTest.java
@@ -0,0 +1,143 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.hoststubgen.test.tinyframework;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses.SubClass;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+
+public class TinyFrameworkClassTest {
+ @Rule
+ public ExpectedException thrown = ExpectedException.none();
+
+ @Test
+ public void testSimple() {
+ TinyFrameworkForTextPolicy tfc = new TinyFrameworkForTextPolicy();
+ assertThat(tfc.addOne(1)).isEqualTo(2);
+ assertThat(tfc.stub).isEqualTo(1);
+ }
+
+// @Test
+// public void testDoesntCompile() {
+// TinyFrameworkClass tfc = new TinyFrameworkClass();
+//
+// tfc.addOneInner(1); // Shouldn't compile.
+// tfc.toBeRemoved("abc"); // Shouldn't compile.
+// tfc.unsupportedMethod(); // Shouldn't compile.
+// int a = tfc.keep; // Shouldn't compile
+// int b = tfc.remove; // Shouldn't compile
+// }
+
+ @Test
+ public void testSubstitute() {
+ TinyFrameworkForTextPolicy tfc = new TinyFrameworkForTextPolicy();
+ assertThat(tfc.addTwo(1)).isEqualTo(3);
+ }
+
+ @Test
+ public void testSubstituteNative() {
+ TinyFrameworkForTextPolicy tfc = new TinyFrameworkForTextPolicy();
+ assertThat(tfc.nativeAddThree(1)).isEqualTo(4);
+ }
+
+ @Test
+ public void testVisibleButUsesUnsupportedMethod() {
+ TinyFrameworkForTextPolicy tfc = new TinyFrameworkForTextPolicy();
+
+ thrown.expect(RuntimeException.class);
+ thrown.expectMessage("This method is not supported on the host side");
+ tfc.visibleButUsesUnsupportedMethod();
+ }
+
+ @Test
+ public void testNestedClass1() {
+ assertThat(new TinyFrameworkNestedClasses().mSupplier.get()).isEqualTo(1);
+ }
+
+ @Test
+ public void testNestedClass2() {
+ assertThat(TinyFrameworkNestedClasses.sSupplier.get()).isEqualTo(2);
+ }
+
+ @Test
+ public void testNestedClass3() {
+ assertThat(new TinyFrameworkNestedClasses().getSupplier().get()).isEqualTo(3);
+ }
+
+ @Test
+ public void testNestedClass4() {
+ assertThat(TinyFrameworkNestedClasses.getSupplier_static().get()).isEqualTo(4);
+ }
+
+ @Test
+ public void testNestedClass5() {
+ assertThat((new TinyFrameworkNestedClasses()).new InnerClass().value).isEqualTo(5);
+ }
+
+ @Test
+ public void testNestedClass6() {
+ assertThat(new TinyFrameworkNestedClasses.StaticNestedClass().value).isEqualTo(6);
+ }
+
+ @Test
+ public void testNestedClass7() {
+ assertThat(TinyFrameworkNestedClasses.StaticNestedClass.getSupplier_static().get())
+ .isEqualTo(7);
+ }
+
+ @Test
+ public void testNativeSubstitutionClass() {
+ assertThat(TinyFrameworkNative.nativeAddTwo(3)).isEqualTo(5);
+ }
+
+ @Test
+ public void testExitLog() {
+ thrown.expect(RuntimeException.class);
+ thrown.expectMessage("Outer exception");
+
+ TinyFrameworkExceptionTester.testException();
+
+ }
+
+ @Test
+ public void testMethodCallBeforeSuperCall() {
+ assertThat(new SubClass(3).value).isEqualTo(3);
+ }
+
+ @Test
+ public void testClassLoadHook() {
+ assertThat(TinyFrameworkClassWithInitializer.sInitialized).isTrue();
+
+ // Having this line before assertThat() will ensure these class are already loaded.
+ var classes = new Class[] {
+ TinyFrameworkClassWithInitializer.class,
+ TinyFrameworkClassAnnotations.class,
+ TinyFrameworkForTextPolicy.class,
+ };
+
+ // The following classes have a class load hook, so they should be registered.
+ assertThat(TinyFrameworkClassLoadHook.sLoadedClasses)
+ .containsAnyIn(classes);
+
+ // This class doesn't have a class load hook, so shouldn't be included.
+ assertThat(TinyFrameworkClassLoadHook.sLoadedClasses)
+ .doesNotContain(TinyFrameworkNestedClasses.class);
+ }
+}
diff --git a/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-test/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkClassWithAnnotTest.java b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-test/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkClassWithAnnotTest.java
new file mode 100644
index 000000000000..20cc2ec9d50d
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-test/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkClassWithAnnotTest.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.hoststubgen.test.tinyframework;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+
+public class TinyFrameworkClassWithAnnotTest {
+ @Rule
+ public ExpectedException thrown = ExpectedException.none();
+
+ @Test
+ public void testSimple() {
+ TinyFrameworkClassAnnotations tfc = new TinyFrameworkClassAnnotations();
+ assertThat(tfc.addOne(1)).isEqualTo(2);
+ assertThat(tfc.stub).isEqualTo(1);
+ }
+
+// @Test
+// public void testDoesntCompile() {
+// TinyFrameworkClassWithAnnot tfc = new TinyFrameworkClassWithAnnot();
+//
+// tfc.addOneInner(1); // Shouldn't compile.
+// tfc.toBeRemoved("abc"); // Shouldn't compile.
+// tfc.unsupportedMethod(); // Shouldn't compile.
+// int a = tfc.keep; // Shouldn't compile
+// int b = tfc.remove; // Shouldn't compile
+// }
+
+ @Test
+ public void testSubstitute() {
+ TinyFrameworkClassAnnotations tfc = new TinyFrameworkClassAnnotations();
+ assertThat(tfc.addTwo(1)).isEqualTo(3);
+ }
+
+ @Test
+ public void testSubstituteNative() {
+ TinyFrameworkClassAnnotations tfc = new TinyFrameworkClassAnnotations();
+ assertThat(tfc.nativeAddThree(1)).isEqualTo(4);
+ }
+
+ @Test
+ public void testVisibleButUsesUnsupportedMethod() {
+ TinyFrameworkClassAnnotations tfc = new TinyFrameworkClassAnnotations();
+
+ thrown.expect(RuntimeException.class);
+ thrown.expectMessage("This method is not supported on the host side");
+ tfc.visibleButUsesUnsupportedMethod();
+ }
+}
diff --git a/tools/hoststubgen/scripts/Android.bp b/tools/hoststubgen/scripts/Android.bp
new file mode 100644
index 000000000000..5da805e5640e
--- /dev/null
+++ b/tools/hoststubgen/scripts/Android.bp
@@ -0,0 +1,26 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_base_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_base_license"],
+}
+
+sh_binary_host {
+ name: "dump-jar",
+ src: "dump-jar",
+ visibility: ["//visibility:public"],
+}
+
+genrule_defaults {
+ name: "hoststubgen-jar-dump-defaults",
+ tools: ["dump-jar"],
+ cmd: "$(location dump-jar) -s -o $(out) $(in)",
+}
+
+sh_binary_host {
+ name: "run-ravenwood-test",
+ src: "run-ravenwood-test",
+ visibility: ["//visibility:public"],
+}
diff --git a/tools/hoststubgen/scripts/build-framework-hostside-jars-and-extract.sh b/tools/hoststubgen/scripts/build-framework-hostside-jars-and-extract.sh
new file mode 100755
index 000000000000..72681234dad8
--- /dev/null
+++ b/tools/hoststubgen/scripts/build-framework-hostside-jars-and-extract.sh
@@ -0,0 +1,35 @@
+#!/bin/bash
+# Copyright (C) 2023 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+
+# Script to build `framework-host-stub` and `framework-host-impl`, and copy the
+# generated jars to $out, and unzip them. Useful for looking into the generated files.
+
+source "${0%/*}"/../common.sh
+
+out=framework-all-stub-out
+
+rm -fr $out
+mkdir -p $out
+
+# Build the jars with `m`.
+run m framework-all-hidden-api-host
+
+# Copy the jar to out/ and extract them.
+run cp \
+ $SOONG_INT/frameworks/base/tools/hoststubgen/hoststubgen/framework-all-hidden-api-host/linux_glibc_common/gen/* \
+ $out
+
+extract $out/*.jar
diff --git a/tools/hoststubgen/scripts/build-framework-hostside-jars-without-genrules.sh b/tools/hoststubgen/scripts/build-framework-hostside-jars-without-genrules.sh
new file mode 100755
index 000000000000..c3605a9ffaa5
--- /dev/null
+++ b/tools/hoststubgen/scripts/build-framework-hostside-jars-without-genrules.sh
@@ -0,0 +1,76 @@
+#!/bin/bash
+# Copyright (C) 2023 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+
+# Script to build hoststubgen and run it directly (without using the build rules)
+# on framework-all.jar.
+
+
+echo "THIS SCRIPT IS BROKEN DUE TO CHANGES TO FILE PATHS TO DEPENDENT FILES. FIX IT WHEN YOU NEED TO USE IT." 1>&2
+
+exit 99
+
+
+source "${0%/*}"/../common.sh
+
+out=out
+
+mkdir -p $out
+
+# Build the tool and target jar.
+run m hoststubgen framework-all
+
+base_args=(
+ @../hoststubgen/hoststubgen-standard-options.txt
+
+ --in-jar $ANDROID_BUILD_TOP/out/soong/.intermediates/frameworks/base/framework-all/android_common/combined/framework-all.jar
+ --policy-override-file ../hoststubgen/framework-policy-override.txt "${@}"
+
+ # This file will contain all classes as an annotation file, with "keep all" policy.
+ --gen-keep-all-file $out/framework-all-keep-all-policy.txt
+
+ # This file will contains dump of all classes in the input jar.
+ --gen-input-dump-file $out/framework-all-dump.txt
+)
+
+do_it() {
+ local out_file_stem="$1"
+ shift
+ local extra_args=("${@}")
+
+ run hoststubgen \
+ "${base_args[@]}" \
+ "${extra_args[@]}" \
+ --out-stub-jar ${out_file_stem}_stub.jar \
+ --out-impl-jar ${out_file_stem}_impl.jar \
+ $HOSTSTUBGEN_OPTS
+
+ # Extract the jar files, so we can look into them.
+ run extract ${out_file_stem}_*.jar
+}
+
+#-----------------------------------------------------------------------------
+# framework-all, with all hidden APIs.
+#-----------------------------------------------------------------------------
+
+# No extra args.
+do_it $out/framework-all_host
+
+#-----------------------------------------------------------------------------
+# framework-test-api, only public/system/test-APIs in the stub.
+#-----------------------------------------------------------------------------
+
+do_it $out/framework-test-api_host \
+ --intersect-stub-jar $SOONG_INT/frameworks/base/api/android_test_stubs_current/android_common/combined/*.jar
diff --git a/tools/hoststubgen/scripts/dump-jar b/tools/hoststubgen/scripts/dump-jar
new file mode 100755
index 000000000000..93729fb22caa
--- /dev/null
+++ b/tools/hoststubgen/scripts/dump-jar
@@ -0,0 +1,163 @@
+#!/bin/bash
+# Copyright (C) 2023 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+set -e
+
+
+help() {
+ cat <<'EOF'
+
+ dump-jar: Dump java classes in jar files
+
+ Usage:
+ dump-jar [-v] CLASS-FILE [...]
+
+ Dump a *.class file
+
+ dump-jar [-v] [-s] [-o OUTPUT-FILENAME] JAR-FILE[: filename regex] [...]
+
+ Dump a jar file.
+
+ If a filename contains a ':', then the following part
+ will be used to filter files in the jar file.
+
+ For example, "file.jar:/MyClass$" will only dump "MyClass" in file.jar.
+
+ Options:
+ -v: Enable verbose output.
+
+ -s: Simple output mode, used to check HostStubGen output jars.
+
+ -o: Write the output to a specified file.
+EOF
+}
+
+# Parse the options.
+
+verbose=0
+simple=0
+output=""
+while getopts "hvso:" opt; do
+case "$opt" in
+ h)
+ help
+ exit 0
+ ;;
+ v)
+ verbose=1
+ ;;
+ s)
+ simple=1
+ ;;
+ o)
+ output="$OPTARG"
+ ;;
+ '?')
+ help
+ exit 1
+ ;;
+esac
+done
+shift $(($OPTIND - 1))
+
+JAVAP_OPTS="${JAVAP_OPTS:--v -p -s -sysinfo -constants}"
+
+if (( $simple )) ; then
+ JAVAP_OPTS="-p -c -v"
+fi
+
+
+# Normalize a java class name.
+# Convert '.' to '/'
+# Remove the *.class suffix.
+normalize() {
+ local name="$1"
+ name="${name%.class}" # Remove the .class suffix.
+ echo "$name" | tr '.' '/'
+}
+
+# Convert the output for `-s` as needed.
+filter_output() {
+ if (( $simple )) ; then
+ # For "simple output" mode,
+ # - Normalize the constant numbers (replace with "#x")
+ # - Remove the constant pool
+ # - Remove the line number table
+ # - Some other transient lines
+ #
+ # `/PATTERN-1/,/PATTERN-1/{//!d}` is a trick to delete lines between two patterns, without
+ # the start and the end lines.
+ sed -e 's/#[0-9][0-9]*/#x/g' \
+ -e '/^Constant pool:/,/^[^ ]/{//!d}' \
+ -e '/^ *line *[0-9][0-9]*: *[0-9][0-9]*$/d' \
+ -e '/SHA-256 checksum/d' \
+ -e '/Last modified/d' \
+ -e '/^Classfile jar/d'
+ else
+ cat # Print as-is.
+ fi
+}
+
+# Write to the output file (specified with -o) as needed.
+write_to_out() {
+ if [[ -n "$output" ]] ; then
+ cat >"$output"
+ echo "Wrote output to $output" 1>&2
+ else
+ cat # print to stdout
+ fi
+}
+
+for file in "${@}"; do
+
+ # *.class?
+ if echo "$file" | grep -qE '\.class$' ; then
+ echo "# Class: $file" 1>&2
+ javap $dump_code_opt $JAVAP_OPTS $file
+
+ # *.jar?
+ elif echo "$file" | grep -qE '\.jar(:.*)?$' ; then
+ # Take the regex. Remove everything up to : in $file
+ regex=""
+ if [[ "$file" =~ : ]] ; then
+ regex="$(normalize "${file##*:}")"
+ fi
+
+ # Remove everything after ':', inclusively, in $file.
+ file="${file%:*}"
+
+ # Print the filename and the regex.
+ if ! (( $simple )) ; then
+ echo -n "# Jar: $file"
+ if [[ "$regex" != "" ]] ;then
+ echo -n " (regex: $regex)"
+ fi
+ echo
+ fi
+
+ jar tf "$file" | grep '\.class$' | sort | while read -r class ; do
+ if normalize "$class" | grep -q -- "$regex" ; then
+ echo "## Class: $class"
+ javap $dump_code_opt $JAVAP_OPTS -cp $file ${class%.class}
+ else
+ (( $verbose )) && echo "## Skipping class: $class"
+ fi
+ done
+
+ else
+ echo "Unknown file type: $file" 1>&2
+ exit 1
+ fi
+done | filter_output | write_to_out
diff --git a/tools/hoststubgen/scripts/run-all-tests.sh b/tools/hoststubgen/scripts/run-all-tests.sh
new file mode 100755
index 000000000000..6bc0ddb1a8dc
--- /dev/null
+++ b/tools/hoststubgen/scripts/run-all-tests.sh
@@ -0,0 +1,45 @@
+#!/bin/bash
+# Copyright (C) 2023 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+source "${0%/*}"/../common.sh
+
+# Move to the top directory of hoststubgen
+cd ..
+
+# These tests are known to pass.
+READY_TEST_MODULES=(
+ HostStubGenTest-framework-all-test-host-test
+ hoststubgen-test-tiny-test
+)
+
+# First, build all the test modules. This shouldn't fail.
+run m run-ravenwood-test ${READY_TEST_MODULES[*]} ${NOT_READY_TEST_MODULES[*]}
+
+# Next, run the golden check. This should always pass too.
+# The following scripts _should_ pass too, but they depend on the internal paths to soong generated
+# files, and they may fail when something changes in the build system.
+run ./hoststubgen/test-tiny-framework/diff-and-update-golden.sh
+
+run ./hoststubgen/test-framework/run-test-without-atest.sh
+run ./hoststubgen/test-tiny-framework/run-test-manually.sh
+run ./scripts/build-framework-hostside-jars-and-extract.sh
+
+# This script is already broken on goog/master
+# run ./scripts/build-framework-hostside-jars-without-genrules.sh
+
+# These tests should all pass.
+run-ravenwood-test ${READY_TEST_MODULES[*]}
+
+echo ""${0##*/}" finished, with no unexpected failures. Ready to submit!" \ No newline at end of file
diff --git a/tools/hoststubgen/scripts/run-ravenwood-test b/tools/hoststubgen/scripts/run-ravenwood-test
new file mode 100755
index 000000000000..9bbb859f5c3d
--- /dev/null
+++ b/tools/hoststubgen/scripts/run-ravenwood-test
@@ -0,0 +1,129 @@
+#!/bin/bash
+# Copyright (C) 2023 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+set -e
+
+# Script to run a "Ravenwood" host side test.
+#
+# A proper way to run these tests is to use `atest`, but `atest` has a known issue of loading
+# unrelated jar files as the class path, so for now we use this script to run host side tests.
+
+# Copy (with some changes) some functions from ../common.sh, so this script can be used without it.
+
+m() {
+ if (( $SKIP_BUILD )) ; then
+ echo "Skipping build: $*" 1>&2
+ return 0
+ fi
+ run ${ANDROID_BUILD_TOP}/build/soong/soong_ui.bash --make-mode "$@"
+}
+
+run() {
+ echo "Running: $*" 1>&2
+ "$@"
+}
+
+run_junit_test_jar() {
+ local jar="$1"
+ echo "Starting test: $jar ..."
+ run cd "${jar%/*}"
+
+ run ${JAVA:-java} $JAVA_OPTS \
+ -cp $jar \
+ org.junit.runner.JUnitCore \
+ com.android.hoststubgen.hosthelper.HostTestSuite || return 1
+ return 0
+}
+
+help() {
+ cat <<'EOF'
+
+ run-ravenwood-test -- Run Ravenwood host tests
+
+ Usage:
+ run-ravenwood-test [options] MODULE-NAME ...
+
+ Options:
+ -h: Help
+ -t: Run test only, without building
+ -b: Build only, without running
+
+ Example:
+ run-ravenwood-test HostStubGenTest-framework-test-host-test
+
+EOF
+}
+
+#-------------------------------------------------------------------------
+# Parse options
+#-------------------------------------------------------------------------
+build=0
+test=0
+
+while getopts "htb" opt; do
+ case "$opt" in
+ h) help; exit 0 ;;
+ t)
+ test=1
+ ;;
+ b)
+ build=1
+ ;;
+ esac
+done
+shift $(($OPTIND - 1))
+
+# If neither -t nor -b is provided, then build and run./
+if (( ( $build + $test ) == 0 )) ; then
+ build=1
+ test=1
+fi
+
+
+modules=("${@}")
+
+if (( "${#modules[@]}" == 0 )); then
+ help
+ exit 1
+fi
+
+#-------------------------------------------------------------------------
+# Build
+#-------------------------------------------------------------------------
+if (( $build )) ; then
+ run m "${modules[@]}"
+fi
+
+#-------------------------------------------------------------------------
+# Run
+#-------------------------------------------------------------------------
+
+failures=0
+if (( test )) ; then
+ for module in "${modules[@]}"; do
+ if run_junit_test_jar "$ANDROID_BUILD_TOP/out/host/linux-x86/testcases/${module}/${module}.jar"; then
+ : # passed.
+ else
+ failures=$(( failures + 1 ))
+ fi
+ done
+
+ if (( $failures > 0 )) ; then
+ echo "$failures test jar(s) failed." 1>&2
+ exit 2
+ fi
+fi
+
+exit 0 \ No newline at end of file