summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--apex/appsearch/framework/java/android/app/appsearch/AppSearchSession.java22
-rw-r--r--apex/appsearch/framework/java/android/app/appsearch/aidl/IAppSearchManager.aidl4
-rw-r--r--apex/appsearch/service/java/com/android/server/appsearch/AppSearchManagerService.java6
-rw-r--r--apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/AppSearchImpl.java40
-rw-r--r--apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/stats/SchemaMigrationStats.java189
-rw-r--r--apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/stats/SetSchemaStats.java27
-rw-r--r--apex/appsearch/service/java/com/android/server/appsearch/visibilitystore/NotDisplayedBySystemMap.java (renamed from apex/appsearch/service/java/com/android/server/appsearch/visibilitystore/NotPlatformSurfaceableMap.java)6
-rw-r--r--apex/appsearch/service/java/com/android/server/appsearch/visibilitystore/VisibilityDocument.java28
-rw-r--r--apex/appsearch/service/java/com/android/server/appsearch/visibilitystore/VisibilityStore.java105
-rw-r--r--apex/appsearch/service/java/com/android/server/appsearch/visibilitystore/VisibleToPackagesDocument.java (renamed from apex/appsearch/service/java/com/android/server/appsearch/visibilitystore/PackageAccessibleDocument.java)14
-rw-r--r--apex/appsearch/service/java/com/android/server/appsearch/visibilitystore/VisibleToPackagesMap.java (renamed from apex/appsearch/service/java/com/android/server/appsearch/visibilitystore/PackageAccessibleMap.java)4
-rw-r--r--apex/appsearch/synced_jetpack_changeid.txt2
-rw-r--r--apex/appsearch/testing/java/com/android/server/appsearch/testing/external/AppSearchSessionShim.java2
-rw-r--r--apex/jobscheduler/service/java/com/android/server/DeviceIdleController.java207
-rw-r--r--api/Android.bp73
-rwxr-xr-xapi/api_versions_trimmer.py136
-rw-r--r--api/api_versions_trimmer_unittests.py307
-rw-r--r--core/java/android/app/Notification.java14
-rw-r--r--core/java/android/content/pm/IPackageInstaller.aidl2
-rw-r--r--core/java/android/content/pm/PackageManager.java7
-rw-r--r--core/java/android/content/pm/parsing/ParsingPackageImpl.java6
-rw-r--r--core/java/android/content/pm/parsing/ParsingPackageUtils.java63
-rw-r--r--core/java/android/content/pm/parsing/component/ParsedComponent.java2
-rw-r--r--core/java/android/hardware/biometrics/BiometricFingerprintConstants.java11
-rw-r--r--core/java/android/hardware/fingerprint/FingerprintManager.java3
-rw-r--r--core/java/android/hardware/input/InputDeviceVibrator.java8
-rw-r--r--core/java/android/net/VpnManager.java4
-rw-r--r--core/java/android/os/Vibrator.java31
-rw-r--r--core/java/android/os/VibratorInfo.java275
-rw-r--r--core/java/android/security/keymaster/KeymasterDefs.java1
-rw-r--r--core/java/android/service/voice/AlwaysOnHotwordDetector.java10
-rw-r--r--core/java/android/service/voice/HotwordDetectionService.java4
-rw-r--r--core/java/android/service/voice/SoftwareHotwordDetector.java34
-rw-r--r--core/java/android/view/contentcapture/ContentCaptureEvent.java9
-rw-r--r--core/java/android/view/contentcapture/MainContentCaptureSession.java5
-rw-r--r--core/java/android/view/inputmethod/BaseInputConnection.java13
-rw-r--r--core/java/android/widget/TextView.java12
-rw-r--r--core/java/com/android/internal/app/IHotwordRecognitionStatusCallback.aidl3
-rw-r--r--core/java/com/android/internal/infra/ServiceConnector.java2
-rw-r--r--core/java/com/android/internal/os/BatteryStatsImpl.java18
-rw-r--r--core/java/com/android/internal/view/ScrollCaptureViewSupport.java15
-rw-r--r--core/java/com/android/internal/widget/EditableInputConnection.java6
-rw-r--r--core/java/com/android/server/AppWidgetBackupBridge.java8
-rw-r--r--core/java/com/android/server/SystemConfig.java29
-rw-r--r--core/java/com/android/server/WidgetBackupProvider.java4
-rw-r--r--core/res/res/values-television/config.xml4
-rw-r--r--core/res/res/values/config.xml4
-rw-r--r--core/res/res/values/strings.xml2
-rw-r--r--core/res/res/values/symbols.xml2
-rw-r--r--core/tests/coretests/src/android/app/appsearch/external/app/AppSearchResultTest.java4
-rw-r--r--core/tests/coretests/src/android/os/VibratorInfoTest.java63
-rw-r--r--location/java/android/location/GnssMeasurement.java22
-rwxr-xr-xmedia/java/android/mtp/MtpDatabase.java37
-rw-r--r--media/java/android/mtp/MtpDevice.java13
-rw-r--r--media/java/android/mtp/MtpDeviceInfo.java27
-rw-r--r--media/jni/android_mtp_MtpDatabase.cpp2
-rw-r--r--media/jni/android_mtp_MtpDevice.cpp61
-rw-r--r--obex/javax/obex/ObexHelper.java14
-rw-r--r--obex/javax/obex/ObexTransport.java2
-rw-r--r--packages/SettingsLib/BannerMessagePreference/res/values-bn/strings.xml21
-rw-r--r--packages/SettingsLib/BannerMessagePreference/res/values-de/strings.xml21
-rw-r--r--packages/SettingsLib/BannerMessagePreference/res/values-mr/strings.xml21
-rw-r--r--packages/SettingsLib/BannerMessagePreference/res/values-ne/strings.xml21
-rw-r--r--packages/SettingsLib/BannerMessagePreference/res/values-or/strings.xml21
-rw-r--r--packages/SettingsLib/FooterPreference/res/values-bn/strings.xml21
-rw-r--r--packages/SettingsLib/FooterPreference/res/values-de/strings.xml21
-rw-r--r--packages/SettingsLib/FooterPreference/res/values-mr/strings.xml21
-rw-r--r--packages/SettingsLib/FooterPreference/res/values-ne/strings.xml21
-rw-r--r--packages/SettingsLib/FooterPreference/res/values-or/strings.xml21
-rw-r--r--packages/SettingsLib/SettingsTheme/res/values-v31/styles.xml1
-rw-r--r--packages/SettingsLib/res/values-af/strings.xml3
-rw-r--r--packages/SettingsLib/res/values-am/strings.xml3
-rw-r--r--packages/SettingsLib/res/values-as/strings.xml3
-rw-r--r--packages/SettingsLib/res/values-az/strings.xml5
-rw-r--r--packages/SettingsLib/res/values-b+sr+Latn/strings.xml3
-rw-r--r--packages/SettingsLib/res/values-bg/strings.xml3
-rw-r--r--packages/SettingsLib/res/values-bs/strings.xml3
-rw-r--r--packages/SettingsLib/res/values-ca/strings.xml3
-rw-r--r--packages/SettingsLib/res/values-cs/strings.xml3
-rw-r--r--packages/SettingsLib/res/values-el/strings.xml3
-rw-r--r--packages/SettingsLib/res/values-es/strings.xml3
-rw-r--r--packages/SettingsLib/res/values-et/strings.xml3
-rw-r--r--packages/SettingsLib/res/values-eu/strings.xml5
-rw-r--r--packages/SettingsLib/res/values-fi/strings.xml3
-rw-r--r--packages/SettingsLib/res/values-gl/strings.xml3
-rw-r--r--packages/SettingsLib/res/values-hi/strings.xml3
-rw-r--r--packages/SettingsLib/res/values-hr/strings.xml3
-rw-r--r--packages/SettingsLib/res/values-hu/strings.xml3
-rw-r--r--packages/SettingsLib/res/values-is/strings.xml3
-rw-r--r--packages/SettingsLib/res/values-it/strings.xml3
-rw-r--r--packages/SettingsLib/res/values-kk/strings.xml3
-rw-r--r--packages/SettingsLib/res/values-km/strings.xml3
-rw-r--r--packages/SettingsLib/res/values-kn/strings.xml3
-rw-r--r--packages/SettingsLib/res/values-lt/strings.xml3
-rw-r--r--packages/SettingsLib/res/values-lv/strings.xml3
-rw-r--r--packages/SettingsLib/res/values-mk/strings.xml3
-rw-r--r--packages/SettingsLib/res/values-ml/strings.xml3
-rw-r--r--packages/SettingsLib/res/values-mn/strings.xml3
-rw-r--r--packages/SettingsLib/res/values-mr/strings.xml3
-rw-r--r--packages/SettingsLib/res/values-my/strings.xml3
-rw-r--r--packages/SettingsLib/res/values-nb/strings.xml3
-rw-r--r--packages/SettingsLib/res/values-nl/strings.xml3
-rw-r--r--packages/SettingsLib/res/values-pl/strings.xml3
-rw-r--r--packages/SettingsLib/res/values-pt-rBR/strings.xml3
-rw-r--r--packages/SettingsLib/res/values-pt-rPT/strings.xml3
-rw-r--r--packages/SettingsLib/res/values-pt/strings.xml3
-rw-r--r--packages/SettingsLib/res/values-ro/strings.xml3
-rw-r--r--packages/SettingsLib/res/values-ru/strings.xml3
-rw-r--r--packages/SettingsLib/res/values-sk/strings.xml3
-rw-r--r--packages/SettingsLib/res/values-sl/strings.xml3
-rw-r--r--packages/SettingsLib/res/values-sr/strings.xml3
-rw-r--r--packages/SettingsLib/res/values-sv/strings.xml3
-rw-r--r--packages/SettingsLib/res/values-th/strings.xml5
-rw-r--r--packages/SettingsLib/res/values-tl/strings.xml3
-rw-r--r--packages/SettingsLib/res/values-uk/strings.xml3
-rw-r--r--packages/SettingsLib/res/values-uz/strings.xml3
-rw-r--r--packages/SettingsLib/res/values-zu/strings.xml3
-rw-r--r--packages/SystemUI/AndroidManifest.xml8
-rw-r--r--packages/SystemUI/res/anim/tv_bottom_sheet_button_state_list_animator.xml52
-rw-r--r--packages/SystemUI/res/anim/tv_bottom_sheet_enter.xml23
-rw-r--r--packages/SystemUI/res/anim/tv_bottom_sheet_exit.xml23
-rw-r--r--packages/SystemUI/res/color/bottom_sheet_button_background_color.xml21
-rw-r--r--packages/SystemUI/res/color/bottom_sheet_button_text_color.xml21
-rw-r--r--packages/SystemUI/res/drawable/bottom_sheet_background.xml20
-rw-r--r--packages/SystemUI/res/drawable/bottom_sheet_background_with_blur.xml20
-rw-r--r--packages/SystemUI/res/drawable/bottom_sheet_button_background.xml20
-rw-r--r--packages/SystemUI/res/layout/tv_bottom_sheet.xml87
-rw-r--r--packages/SystemUI/res/values-az/strings.xml2
-rw-r--r--packages/SystemUI/res/values-be/strings.xml6
-rw-r--r--packages/SystemUI/res/values-bn/strings.xml3
-rw-r--r--packages/SystemUI/res/values-bs/strings.xml6
-rw-r--r--packages/SystemUI/res/values-de/strings.xml3
-rw-r--r--packages/SystemUI/res/values-et/strings.xml6
-rw-r--r--packages/SystemUI/res/values-hr/strings.xml6
-rw-r--r--packages/SystemUI/res/values-hu/strings.xml6
-rw-r--r--packages/SystemUI/res/values-hy/strings.xml6
-rw-r--r--packages/SystemUI/res/values-in/strings.xml6
-rw-r--r--packages/SystemUI/res/values-it/strings.xml6
-rw-r--r--packages/SystemUI/res/values-iw/strings.xml2
-rw-r--r--packages/SystemUI/res/values-ja/strings.xml6
-rw-r--r--packages/SystemUI/res/values-kk/strings.xml8
-rw-r--r--packages/SystemUI/res/values-km/strings.xml6
-rw-r--r--packages/SystemUI/res/values-ko/strings.xml6
-rw-r--r--packages/SystemUI/res/values-ky/strings.xml6
-rw-r--r--packages/SystemUI/res/values-lo/strings.xml6
-rw-r--r--packages/SystemUI/res/values-mk/strings.xml6
-rw-r--r--packages/SystemUI/res/values-mn/strings.xml6
-rw-r--r--packages/SystemUI/res/values-mr/strings.xml3
-rw-r--r--packages/SystemUI/res/values-my/strings.xml6
-rw-r--r--packages/SystemUI/res/values-ne/strings.xml3
-rw-r--r--packages/SystemUI/res/values-nl/strings.xml6
-rw-r--r--packages/SystemUI/res/values-or/strings.xml6
-rw-r--r--packages/SystemUI/res/values-pt-rBR/strings.xml6
-rw-r--r--packages/SystemUI/res/values-pt-rPT/strings.xml6
-rw-r--r--packages/SystemUI/res/values-pt/strings.xml6
-rw-r--r--packages/SystemUI/res/values-si/strings.xml6
-rw-r--r--packages/SystemUI/res/values-sv/strings.xml6
-rw-r--r--packages/SystemUI/res/values-sw/strings.xml6
-rw-r--r--packages/SystemUI/res/values-sw600dp/dimens.xml4
-rw-r--r--packages/SystemUI/res/values-television/colors.xml15
-rw-r--r--packages/SystemUI/res/values-television/dimens.xml23
-rw-r--r--packages/SystemUI/res/values-television/styles.xml30
-rw-r--r--packages/SystemUI/res/values-th/strings.xml6
-rw-r--r--packages/SystemUI/res/values-tl/strings.xml6
-rw-r--r--packages/SystemUI/res/values-tr/strings.xml6
-rw-r--r--packages/SystemUI/res/values-zh-rCN/strings.xml6
-rw-r--r--packages/SystemUI/res/values-zh-rHK/strings.xml6
-rw-r--r--packages/SystemUI/res/values/config.xml3
-rw-r--r--packages/SystemUI/res/values/dimens.xml4
-rw-r--r--packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitchController.java4
-rw-r--r--packages/SystemUI/src/com/android/keyguard/KeyguardStatusViewController.java7
-rw-r--r--packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java5
-rw-r--r--packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardViewController.java19
-rw-r--r--packages/SystemUI/src/com/android/systemui/dagger/DefaultActivityBinder.java7
-rw-r--r--packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java51
-rw-r--r--packages/SystemUI/src/com/android/systemui/media/MediaCarouselController.kt7
-rw-r--r--packages/SystemUI/src/com/android/systemui/media/MediaDataManager.kt24
-rw-r--r--packages/SystemUI/src/com/android/systemui/media/MediaHierarchyManager.kt14
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/QSContainerImpl.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/QSPanel.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeaderController.java5
-rw-r--r--packages/SystemUI/src/com/android/systemui/sensorprivacy/television/TvUnblockSensorActivity.java145
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/LockscreenShadeTransitionController.kt7
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/ExpandAnimationParameters.kt16
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationLaunchAnimatorController.kt28
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java58
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationBackgroundView.java8
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/AmbientState.java18
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationListContainer.java7
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java171
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java5
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithm.java41
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconAreaController.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java29
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java13
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimState.java17
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java7
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/UnlockedScreenOffAnimationController.kt3
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java11
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/WifiSignalController.java20
-rw-r--r--packages/SystemUI/src/com/android/systemui/tv/TvBottomSheetActivity.java98
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerTest.java4
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsKeyguardViewControllerTest.java4
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/doze/DozeTriggersTest.java23
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ScrimControllerTest.java46
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerWifiTest.java4
-rw-r--r--services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java22
-rw-r--r--services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java145
-rw-r--r--services/backup/java/com/android/server/backup/restore/PerformUnifiedRestoreTask.java8
-rw-r--r--services/core/java/com/android/server/VpnManagerService.java9
-rw-r--r--services/core/java/com/android/server/appop/DiscreteRegistry.java112
-rw-r--r--services/core/java/com/android/server/appop/HistoricalRegistry.java1
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/AidlConversionUtils.java3
-rwxr-xr-xservices/core/java/com/android/server/notification/NotificationManagerService.java35
-rw-r--r--services/core/java/com/android/server/pm/PackageDexOptimizer.java4
-rw-r--r--services/core/java/com/android/server/pm/PackageInstallerService.java18
-rw-r--r--services/core/java/com/android/server/pm/PackageInstallerSession.java26
-rw-r--r--services/core/java/com/android/server/pm/PackageManagerService.java40
-rw-r--r--services/core/java/com/android/server/pm/PackageManagerShellCommand.java16
-rw-r--r--services/core/java/com/android/server/pm/pkg/PackageStateUnserialized.java5
-rw-r--r--services/core/java/com/android/server/vibrator/VibrationSettings.java7
-rw-r--r--services/core/java/com/android/server/vibrator/VibrationThread.java14
-rw-r--r--services/core/java/com/android/server/vibrator/VibratorController.java38
-rw-r--r--services/core/java/com/android/server/wm/ActivityRecord.java124
-rw-r--r--services/core/java/com/android/server/wm/Task.java5
-rw-r--r--services/core/java/com/android/server/wm/WindowStateAnimator.java5
-rw-r--r--services/core/jni/com_android_server_vibrator_VibratorController.cpp139
-rw-r--r--services/tests/mockingservicestests/src/com/android/server/DeviceIdleControllerTest.java35
-rw-r--r--services/tests/servicestests/src/com/android/server/appsearch/AppSearchImplPlatformTest.java40
-rw-r--r--services/tests/servicestests/src/com/android/server/appsearch/VisibilityStoreTest.java32
-rw-r--r--services/tests/servicestests/src/com/android/server/appsearch/external/localstorage/AppSearchImplTest.java218
-rw-r--r--services/tests/servicestests/src/com/android/server/appsearch/external/localstorage/AppSearchLoggerTest.java354
-rw-r--r--services/tests/servicestests/src/com/android/server/appsearch/external/localstorage/converter/SnippetTest.java2
-rw-r--r--services/tests/servicestests/src/com/android/server/appsearch/external/localstorage/stats/AppSearchStatsTest.java43
-rw-r--r--services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java14
-rw-r--r--services/tests/servicestests/src/com/android/server/systemconfig/SystemConfigTest.java58
-rw-r--r--services/tests/servicestests/src/com/android/server/vibrator/FakeVibratorControllerProvider.java34
-rw-r--r--services/tests/servicestests/src/com/android/server/vibrator/VibrationThreadTest.java69
-rw-r--r--services/tests/servicestests/src/com/android/server/vibrator/VibratorControllerTest.java12
-rw-r--r--services/tests/uiservicestests/src/com/android/server/notification/BuzzBeepBlinkTest.java93
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java5
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/TaskTests.java11
-rw-r--r--services/voiceinteraction/java/com/android/server/voiceinteraction/HotwordDetectionConnection.java625
-rw-r--r--services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java4
-rw-r--r--services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java8
-rw-r--r--services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceShellCommand.java14
-rw-r--r--telecomm/java/android/telecom/TelecomManager.java15
-rw-r--r--telecomm/java/com/android/internal/telecom/ITelecomService.aidl2
248 files changed, 4820 insertions, 1536 deletions
diff --git a/apex/appsearch/framework/java/android/app/appsearch/AppSearchSession.java b/apex/appsearch/framework/java/android/app/appsearch/AppSearchSession.java
index 4ef91b5e3bc1..0b24c0d9f5c5 100644
--- a/apex/appsearch/framework/java/android/app/appsearch/AppSearchSession.java
+++ b/apex/appsearch/framework/java/android/app/appsearch/AppSearchSession.java
@@ -136,8 +136,6 @@ public final class AppSearchSession implements Closeable {
* @param callback Callback to receive errors resulting from setting the schema. If the
* operation succeeds, the callback will be invoked with {@code null}.
*/
- // TODO(b/169883602): Change @code references to @link when setPlatformSurfaceable APIs are
- // exposed.
public void setSchema(
@NonNull SetSchemaRequest request,
@NonNull Executor workExecutor,
@@ -152,7 +150,7 @@ public final class AppSearchSession implements Closeable {
for (AppSearchSchema schema : request.getSchemas()) {
schemaBundles.add(schema.getBundle());
}
- Map<String, List<Bundle>> schemasPackageAccessibleBundles =
+ Map<String, List<Bundle>> schemasVisibleToPackagesBundles =
new ArrayMap<>(request.getSchemasVisibleToPackagesInternal().size());
for (Map.Entry<String, Set<PackageIdentifier>> entry :
request.getSchemasVisibleToPackagesInternal().entrySet()) {
@@ -160,7 +158,7 @@ public final class AppSearchSession implements Closeable {
for (PackageIdentifier packageIdentifier : entry.getValue()) {
packageIdentifierBundles.add(packageIdentifier.getBundle());
}
- schemasPackageAccessibleBundles.put(entry.getKey(), packageIdentifierBundles);
+ schemasVisibleToPackagesBundles.put(entry.getKey(), packageIdentifierBundles);
}
// No need to trigger migration if user never set migrator
@@ -168,14 +166,14 @@ public final class AppSearchSession implements Closeable {
setSchemaNoMigrations(
request,
schemaBundles,
- schemasPackageAccessibleBundles,
+ schemasVisibleToPackagesBundles,
callbackExecutor,
callback);
} else {
setSchemaWithMigrations(
request,
schemaBundles,
- schemasPackageAccessibleBundles,
+ schemasVisibleToPackagesBundles,
workExecutor,
callbackExecutor,
callback);
@@ -704,7 +702,7 @@ public final class AppSearchSession implements Closeable {
private void setSchemaNoMigrations(
@NonNull SetSchemaRequest request,
@NonNull List<Bundle> schemaBundles,
- @NonNull Map<String, List<Bundle>> schemasPackageAccessibleBundles,
+ @NonNull Map<String, List<Bundle>> schemasVisibleToPackagesBundles,
@NonNull @CallbackExecutor Executor executor,
@NonNull Consumer<AppSearchResult<SetSchemaResponse>> callback) {
try {
@@ -713,7 +711,7 @@ public final class AppSearchSession implements Closeable {
mDatabaseName,
schemaBundles,
new ArrayList<>(request.getSchemasNotDisplayedBySystem()),
- schemasPackageAccessibleBundles,
+ schemasVisibleToPackagesBundles,
request.isForceOverride(),
request.getVersion(),
mUserHandle,
@@ -761,7 +759,7 @@ public final class AppSearchSession implements Closeable {
private void setSchemaWithMigrations(
@NonNull SetSchemaRequest request,
@NonNull List<Bundle> schemaBundles,
- @NonNull Map<String, List<Bundle>> schemasPackageAccessibleBundles,
+ @NonNull Map<String, List<Bundle>> schemasVisibleToPackagesBundles,
@NonNull Executor workExecutor,
@NonNull @CallbackExecutor Executor callbackExecutor,
@NonNull Consumer<AppSearchResult<SetSchemaResponse>> callback) {
@@ -787,7 +785,7 @@ public final class AppSearchSession implements Closeable {
// No need to trigger migration if no migrator is active.
if (activeMigrators.isEmpty()) {
- setSchemaNoMigrations(request, schemaBundles, schemasPackageAccessibleBundles,
+ setSchemaNoMigrations(request, schemaBundles, schemasVisibleToPackagesBundles,
callbackExecutor, callback);
return;
}
@@ -801,7 +799,7 @@ public final class AppSearchSession implements Closeable {
mDatabaseName,
schemaBundles,
new ArrayList<>(request.getSchemasNotDisplayedBySystem()),
- schemasPackageAccessibleBundles,
+ schemasVisibleToPackagesBundles,
/*forceOverride=*/ false,
request.getVersion(),
mUserHandle,
@@ -853,7 +851,7 @@ public final class AppSearchSession implements Closeable {
mDatabaseName,
schemaBundles,
new ArrayList<>(request.getSchemasNotDisplayedBySystem()),
- schemasPackageAccessibleBundles,
+ schemasVisibleToPackagesBundles,
/*forceOverride=*/ true,
request.getVersion(),
mUserHandle,
diff --git a/apex/appsearch/framework/java/android/app/appsearch/aidl/IAppSearchManager.aidl b/apex/appsearch/framework/java/android/app/appsearch/aidl/IAppSearchManager.aidl
index 0b26e146a7a4..c639ef604de8 100644
--- a/apex/appsearch/framework/java/android/app/appsearch/aidl/IAppSearchManager.aidl
+++ b/apex/appsearch/framework/java/android/app/appsearch/aidl/IAppSearchManager.aidl
@@ -32,7 +32,7 @@ interface IAppSearchManager {
* @param schemaBundles List of {@link AppSearchSchema} bundles.
* @param schemasNotDisplayedBySystem Schema types that should not be surfaced on platform
* surfaces.
- * @param schemasPackageAccessibleBundles Schema types that are visible to the specified
+ * @param schemasVisibleToPackagesBundles Schema types that are visible to the specified
* packages. The value List contains PackageIdentifier Bundles.
* @param forceOverride Whether to apply the new schema even if it is incompatible. All
* incompatible documents will be deleted.
@@ -48,7 +48,7 @@ interface IAppSearchManager {
in String databaseName,
in List<Bundle> schemaBundles,
in List<String> schemasNotDisplayedBySystem,
- in Map<String, List<Bundle>> schemasPackageAccessibleBundles,
+ in Map<String, List<Bundle>> schemasVisibleToPackagesBundles,
boolean forceOverride,
in int schemaVersion,
in UserHandle userHandle,
diff --git a/apex/appsearch/service/java/com/android/server/appsearch/AppSearchManagerService.java b/apex/appsearch/service/java/com/android/server/appsearch/AppSearchManagerService.java
index 400c24138060..ac584fe4b91b 100644
--- a/apex/appsearch/service/java/com/android/server/appsearch/AppSearchManagerService.java
+++ b/apex/appsearch/service/java/com/android/server/appsearch/AppSearchManagerService.java
@@ -333,7 +333,7 @@ public class AppSearchManagerService extends SystemService {
for (int i = 0; i < schemaBundles.size(); i++) {
schemas.add(new AppSearchSchema(schemaBundles.get(i)));
}
- Map<String, List<PackageIdentifier>> schemasPackageAccessible =
+ Map<String, List<PackageIdentifier>> schemasVisibleToPackages =
new ArrayMap<>(schemasVisibleToPackagesBundles.size());
for (Map.Entry<String, List<Bundle>> entry :
schemasVisibleToPackagesBundles.entrySet()) {
@@ -343,7 +343,7 @@ public class AppSearchManagerService extends SystemService {
packageIdentifiers.add(
new PackageIdentifier(entry.getValue().get(i)));
}
- schemasPackageAccessible.put(entry.getKey(), packageIdentifiers);
+ schemasVisibleToPackages.put(entry.getKey(), packageIdentifiers);
}
instance = mAppSearchUserInstanceManager.getUserInstance(callingUser);
SetSchemaResponse setSchemaResponse = instance.getAppSearchImpl().setSchema(
@@ -352,7 +352,7 @@ public class AppSearchManagerService extends SystemService {
schemas,
instance.getVisibilityStore(),
schemasNotDisplayedBySystem,
- schemasPackageAccessible,
+ schemasVisibleToPackages,
forceOverride,
schemaVersion);
++operationSuccessCount;
diff --git a/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/AppSearchImpl.java b/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/AppSearchImpl.java
index 77a1bb402bd3..4ad1c8c56979 100644
--- a/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/AppSearchImpl.java
+++ b/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/AppSearchImpl.java
@@ -346,11 +346,11 @@ public final class AppSearchImpl implements Closeable {
* @param packageName The package name that owns the schemas.
* @param databaseName The name of the database where this schema lives.
* @param schemas Schemas to set for this app.
- * @param visibilityStore If set, {@code schemasNotPlatformSurfaceable} and {@code
- * schemasPackageAccessible} will be saved here if the schema is successfully applied.
- * @param schemasNotPlatformSurfaceable Schema types that should not be surfaced on platform
+ * @param visibilityStore If set, {@code schemasNotDisplayedBySystem} and {@code
+ * schemasVisibleToPackages} will be saved here if the schema is successfully applied.
+ * @param schemasNotDisplayedBySystem Schema types that should not be surfaced on platform
* surfaces.
- * @param schemasPackageAccessible Schema types that are visible to the specified packages.
+ * @param schemasVisibleToPackages Schema types that are visible to the specified packages.
* @param forceOverride Whether to force-apply the schema even if it is incompatible. Documents
* which do not comply with the new schema will be deleted.
* @param version The overall version number of the request.
@@ -366,8 +366,8 @@ public final class AppSearchImpl implements Closeable {
@NonNull String databaseName,
@NonNull List<AppSearchSchema> schemas,
@Nullable VisibilityStore visibilityStore,
- @NonNull List<String> schemasNotPlatformSurfaceable,
- @NonNull Map<String, List<PackageIdentifier>> schemasPackageAccessible,
+ @NonNull List<String> schemasNotDisplayedBySystem,
+ @NonNull Map<String, List<PackageIdentifier>> schemasVisibleToPackages,
boolean forceOverride,
int version)
throws AppSearchException {
@@ -430,25 +430,25 @@ public final class AppSearchImpl implements Closeable {
}
if (visibilityStore != null) {
- Set<String> prefixedSchemasNotPlatformSurfaceable =
- new ArraySet<>(schemasNotPlatformSurfaceable.size());
- for (int i = 0; i < schemasNotPlatformSurfaceable.size(); i++) {
- prefixedSchemasNotPlatformSurfaceable.add(
- prefix + schemasNotPlatformSurfaceable.get(i));
+ Set<String> prefixedSchemasNotDisplayedBySystem =
+ new ArraySet<>(schemasNotDisplayedBySystem.size());
+ for (int i = 0; i < schemasNotDisplayedBySystem.size(); i++) {
+ prefixedSchemasNotDisplayedBySystem.add(
+ prefix + schemasNotDisplayedBySystem.get(i));
}
- Map<String, List<PackageIdentifier>> prefixedSchemasPackageAccessible =
- new ArrayMap<>(schemasPackageAccessible.size());
+ Map<String, List<PackageIdentifier>> prefixedSchemasVisibleToPackages =
+ new ArrayMap<>(schemasVisibleToPackages.size());
for (Map.Entry<String, List<PackageIdentifier>> entry :
- schemasPackageAccessible.entrySet()) {
- prefixedSchemasPackageAccessible.put(prefix + entry.getKey(), entry.getValue());
+ schemasVisibleToPackages.entrySet()) {
+ prefixedSchemasVisibleToPackages.put(prefix + entry.getKey(), entry.getValue());
}
visibilityStore.setVisibility(
packageName,
databaseName,
- prefixedSchemasNotPlatformSurfaceable,
- prefixedSchemasPackageAccessible);
+ prefixedSchemasNotDisplayedBySystem,
+ prefixedSchemasVisibleToPackages);
}
return SetSchemaResponseToProtoConverter.toSetSchemaResponse(
@@ -737,6 +737,9 @@ public final class AppSearchImpl implements Closeable {
if (!filterPackageNames.isEmpty() && !filterPackageNames.contains(packageName)) {
// Client wanted to query over some packages that weren't its own. This isn't
// allowed through local query so we can return early with no results.
+ if (logger != null) {
+ sStatsBuilder.setStatusCode(AppSearchResult.RESULT_SECURITY_ERROR);
+ }
return new SearchResultPage(Bundle.EMPTY);
}
@@ -768,7 +771,7 @@ public final class AppSearchImpl implements Closeable {
* @param queryExpression Query String to search.
* @param searchSpec Spec for setting filters, raw query etc.
* @param callerPackageName Package name of the caller, should belong to the {@code
- * userContext}.
+ * callerUserHandle}.
* @param visibilityStore Optional visibility store to obtain system and package visibility
* settings from
* @param callerUid UID of the client making the globalQuery call.
@@ -1465,7 +1468,6 @@ public final class AppSearchImpl implements Closeable {
mOptimizeIntervalCountLocked = 0;
mSchemaMapLocked.clear();
mNamespaceMapLocked.clear();
-
if (initStatsBuilder != null) {
initStatsBuilder
.setHasReset(true)
diff --git a/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/stats/SchemaMigrationStats.java b/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/stats/SchemaMigrationStats.java
new file mode 100644
index 000000000000..6e1e2d5f774b
--- /dev/null
+++ b/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/stats/SchemaMigrationStats.java
@@ -0,0 +1,189 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.appsearch.external.localstorage.stats;
+
+import android.annotation.NonNull;
+import android.app.appsearch.SetSchemaRequest;
+
+import java.util.Objects;
+
+/**
+ * Class holds detailed stats for Schema migration.
+ *
+ * @hide
+ */
+// TODO(b/173532925): Hides getter and setter functions for accessing {@code
+// mFirstSetSchemaLatencyMillis} and {@code mSecondSetSchemaLatencyMillis} field.
+
+public final class SchemaMigrationStats {
+ /** GetSchema latency in milliseconds. */
+ private final int mGetSchemaLatencyMillis;
+
+ /**
+ * Latency of querying all documents that need to be migrated to new version and transforming
+ * documents to new version in milliseconds.
+ */
+ private final int mQueryAndTransformLatencyMillis;
+
+ private final int mFirstSetSchemaLatencyMillis;
+
+ private final int mSecondSetSchemaLatencyMillis;
+
+ /** Latency of putting migrated document to Icing lib in milliseconds. */
+ private final int mSaveDocumentLatencyMillis;
+
+ private final int mMigratedDocumentCount;
+
+ private final int mSavedDocumentCount;
+
+ SchemaMigrationStats(@NonNull Builder builder) {
+ Objects.requireNonNull(builder);
+ mGetSchemaLatencyMillis = builder.mGetSchemaLatencyMillis;
+ mQueryAndTransformLatencyMillis = builder.mQueryAndTransformLatencyMillis;
+ mFirstSetSchemaLatencyMillis = builder.mFirstSetSchemaLatencyMillis;
+ mSecondSetSchemaLatencyMillis = builder.mSecondSetSchemaLatencyMillis;
+ mSaveDocumentLatencyMillis = builder.mSaveDocumentLatencyMillis;
+ mMigratedDocumentCount = builder.mMigratedDocumentCount;
+ mSavedDocumentCount = builder.mSavedDocumentCount;
+ }
+
+ /** Returns GetSchema latency in milliseconds. */
+ public int getGetSchemaLatencyMillis() {
+ return mGetSchemaLatencyMillis;
+ }
+
+ /**
+ * Returns latency of querying all documents that need to be migrated to new version and
+ * transforming documents to new version in milliseconds.
+ */
+ public int getQueryAndTransformLatencyMillis() {
+ return mQueryAndTransformLatencyMillis;
+ }
+
+ /**
+ * Returns latency of first SetSchema action in milliseconds.
+ *
+ * <p>If all schema fields are backward compatible, the schema will be successful set to Icing.
+ * Otherwise, we will retrieve incompatible types here.
+ *
+ * <p>Please see {@link SetSchemaRequest} for what is "incompatible".
+ */
+ public int getFirstSetSchemaLatencyMillis() {
+ return mFirstSetSchemaLatencyMillis;
+ }
+
+ /**
+ * Returns latency of second SetSchema action in milliseconds.
+ *
+ * <p>If all schema fields are backward compatible, the schema will be successful set to Icing
+ * in the first setSchema action and this value will be 0. Otherwise, schema types will be set
+ * to Icing by this action.
+ */
+ public int getSecondSetSchemaLatencyMillis() {
+ return mSecondSetSchemaLatencyMillis;
+ }
+
+ /** Returns latency of putting migrated document to Icing lib in milliseconds. */
+ public int getSaveDocumentLatencyMillis() {
+ return mSaveDocumentLatencyMillis;
+ }
+
+ /** Returns number of migrated documents. */
+ public int getMigratedDocumentCount() {
+ return mMigratedDocumentCount;
+ }
+
+ /** Returns number of updated documents which are saved in Icing lib. */
+ public int getSavedDocumentCount() {
+ return mSavedDocumentCount;
+ }
+
+ /** Builder for {@link SchemaMigrationStats}. */
+ public static class Builder {
+ int mGetSchemaLatencyMillis;
+ int mQueryAndTransformLatencyMillis;
+ int mFirstSetSchemaLatencyMillis;
+ int mSecondSetSchemaLatencyMillis;
+ int mSaveDocumentLatencyMillis;
+ int mMigratedDocumentCount;
+ int mSavedDocumentCount;
+
+ /** Sets latency for the GetSchema action in milliseconds. */
+ @NonNull
+ public SchemaMigrationStats.Builder setGetSchemaLatencyMillis(int getSchemaLatencyMillis) {
+ mGetSchemaLatencyMillis = getSchemaLatencyMillis;
+ return this;
+ }
+
+ /**
+ * Sets latency for querying all documents that need to be migrated to new version and
+ * transforming documents to new version in milliseconds.
+ */
+ @NonNull
+ public SchemaMigrationStats.Builder setQueryAndTransformLatencyMillis(
+ int queryAndTransformLatencyMillis) {
+ mQueryAndTransformLatencyMillis = queryAndTransformLatencyMillis;
+ return this;
+ }
+
+ /** Sets latency of first SetSchema action in milliseconds. */
+ @NonNull
+ public SchemaMigrationStats.Builder setFirstSetSchemaLatencyMillis(
+ int firstSetSchemaLatencyMillis) {
+ mFirstSetSchemaLatencyMillis = firstSetSchemaLatencyMillis;
+ return this;
+ }
+
+ /** Sets latency of second SetSchema action in milliseconds. */
+ @NonNull
+ public SchemaMigrationStats.Builder setSecondSetSchemaLatencyMillis(
+ int secondSetSchemaLatencyMillis) {
+ mSecondSetSchemaLatencyMillis = secondSetSchemaLatencyMillis;
+ return this;
+ }
+
+ /** Sets latency for putting migrated document to Icing lib in milliseconds. */
+ @NonNull
+ public SchemaMigrationStats.Builder setSaveDocumentLatencyMillis(
+ int saveDocumentLatencyMillis) {
+ mSaveDocumentLatencyMillis = saveDocumentLatencyMillis;
+ return this;
+ }
+
+ /** Sets number of migrated documents. */
+ @NonNull
+ public SchemaMigrationStats.Builder setMigratedDocumentCount(int migratedDocumentCount) {
+ mMigratedDocumentCount = migratedDocumentCount;
+ return this;
+ }
+
+ /** Sets number of updated documents which are saved in Icing lib. */
+ @NonNull
+ public SchemaMigrationStats.Builder setSavedDocumentCount(int savedDocumentCount) {
+ mSavedDocumentCount = savedDocumentCount;
+ return this;
+ }
+
+ /**
+ * Builds a new {@link SchemaMigrationStats} from the {@link SchemaMigrationStats.Builder}.
+ */
+ @NonNull
+ public SchemaMigrationStats build() {
+ return new SchemaMigrationStats(/* builder= */ this);
+ }
+ }
+}
diff --git a/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/stats/SetSchemaStats.java b/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/stats/SetSchemaStats.java
index 56a546a2e8e1..9d789a894855 100644
--- a/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/stats/SetSchemaStats.java
+++ b/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/stats/SetSchemaStats.java
@@ -17,6 +17,7 @@
package com.android.server.appsearch.external.localstorage.stats;
import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.app.appsearch.AppSearchResult;
import java.util.Objects;
@@ -38,6 +39,12 @@ public final class SetSchemaStats {
*/
@AppSearchResult.ResultCode private final int mStatusCode;
+ /**
+ * Stores stats of SchemaMigration in SetSchema process. Is {@code null} if no schema migration
+ * is needed.
+ */
+ @Nullable private final SchemaMigrationStats mSchemaMigrationStats;
+
private final int mTotalLatencyMillis;
/** Overall time used for the native function call. */
@@ -63,6 +70,7 @@ public final class SetSchemaStats {
mPackageName = builder.mPackageName;
mDatabase = builder.mDatabase;
mStatusCode = builder.mStatusCode;
+ mSchemaMigrationStats = builder.mSchemaMigrationStats;
mTotalLatencyMillis = builder.mTotalLatencyMillis;
mNativeLatencyMillis = builder.mNativeLatencyMillis;
mNewTypeCount = builder.mNewTypeCount;
@@ -90,6 +98,15 @@ public final class SetSchemaStats {
return mStatusCode;
}
+ /**
+ * Returns the status of schema migration, if migration is executed during the SetSchema
+ * process. Otherwise, returns {@code null}.
+ */
+ @Nullable
+ public SchemaMigrationStats getSchemaMigrationStats() {
+ return mSchemaMigrationStats;
+ }
+
/** Returns the total latency of the SetSchema action. */
public int getTotalLatencyMillis() {
return mTotalLatencyMillis;
@@ -140,6 +157,7 @@ public final class SetSchemaStats {
@NonNull final String mPackageName;
@NonNull final String mDatabase;
@AppSearchResult.ResultCode int mStatusCode;
+ @Nullable SchemaMigrationStats mSchemaMigrationStats;
int mTotalLatencyMillis;
int mNativeLatencyMillis;
int mNewTypeCount;
@@ -161,7 +179,14 @@ public final class SetSchemaStats {
return this;
}
- /** Sets total latency for the SetSchema action. */
+ /** Sets the status of schema migration. */
+ @NonNull
+ public Builder setSchemaMigrationStats(@NonNull SchemaMigrationStats schemaMigrationStats) {
+ mSchemaMigrationStats = Objects.requireNonNull(schemaMigrationStats);
+ return this;
+ }
+
+ /** Sets total latency for the SetSchema action in milliseconds. */
@NonNull
public Builder setTotalLatencyMillis(int totalLatencyMillis) {
mTotalLatencyMillis = totalLatencyMillis;
diff --git a/apex/appsearch/service/java/com/android/server/appsearch/visibilitystore/NotPlatformSurfaceableMap.java b/apex/appsearch/service/java/com/android/server/appsearch/visibilitystore/NotDisplayedBySystemMap.java
index 9e36fd02569f..95905af76123 100644
--- a/apex/appsearch/service/java/com/android/server/appsearch/visibilitystore/NotPlatformSurfaceableMap.java
+++ b/apex/appsearch/service/java/com/android/server/appsearch/visibilitystore/NotDisplayedBySystemMap.java
@@ -27,7 +27,7 @@ import java.util.Set;
*
* This object is not thread safe.
*/
-class NotPlatformSurfaceableMap {
+class NotDisplayedBySystemMap {
/**
* Maps packages to databases to the set of prefixed schemas that are platform-hidden within
* that database.
@@ -39,7 +39,7 @@ class NotPlatformSurfaceableMap {
*
* <p>Any existing mappings for this prefix are overwritten.
*/
- public void setNotPlatformSurfaceable(
+ public void setNotDisplayedBySystem(
@NonNull String packageName,
@NonNull String databaseName,
@NonNull Set<String> prefixedSchemas) {
@@ -55,7 +55,7 @@ class NotPlatformSurfaceableMap {
* Returns whether the given prefixed schema is platform surfaceable (has not opted out) in the
* given database.
*/
- public boolean isSchemaPlatformSurfaceable(
+ public boolean isSchemaDisplayedBySystem(
@NonNull String packageName,
@NonNull String databaseName,
@NonNull String prefixedSchema) {
diff --git a/apex/appsearch/service/java/com/android/server/appsearch/visibilitystore/VisibilityDocument.java b/apex/appsearch/service/java/com/android/server/appsearch/visibilitystore/VisibilityDocument.java
index 1771b1ddc6b6..b0108704be34 100644
--- a/apex/appsearch/service/java/com/android/server/appsearch/visibilitystore/VisibilityDocument.java
+++ b/apex/appsearch/service/java/com/android/server/appsearch/visibilitystore/VisibilityDocument.java
@@ -28,10 +28,10 @@ class VisibilityDocument extends GenericDocument {
/**
* Property that holds the list of platform-hidden schemas, as part of the visibility settings.
*/
- private static final String NOT_PLATFORM_SURFACEABLE_PROPERTY = "notPlatformSurfaceable";
+ private static final String NOT_DISPLAYED_BY_SYSTEM_PROPERTY = "notPlatformSurfaceable";
/** Property that holds nested documents of package accessible schemas. */
- private static final String PACKAGE_ACCESSIBLE_PROPERTY = "packageAccessible";
+ private static final String VISIBLE_TO_PACKAGES_PROPERTY = "packageAccessible";
/**
* Schema for the VisibilityStore's documents.
@@ -41,11 +41,11 @@ class VisibilityDocument extends GenericDocument {
*/
public static final AppSearchSchema SCHEMA = new AppSearchSchema.Builder(SCHEMA_TYPE)
.addProperty(new AppSearchSchema.StringPropertyConfig.Builder(
- NOT_PLATFORM_SURFACEABLE_PROPERTY)
+ NOT_DISPLAYED_BY_SYSTEM_PROPERTY)
.setCardinality(AppSearchSchema.PropertyConfig.CARDINALITY_REPEATED)
.build())
.addProperty(new AppSearchSchema.DocumentPropertyConfig.Builder(
- PACKAGE_ACCESSIBLE_PROPERTY, PackageAccessibleDocument.SCHEMA_TYPE)
+ VISIBLE_TO_PACKAGES_PROPERTY, VisibleToPackagesDocument.SCHEMA_TYPE)
.setCardinality(AppSearchSchema.PropertyConfig.CARDINALITY_REPEATED)
.build())
.build();
@@ -55,13 +55,13 @@ class VisibilityDocument extends GenericDocument {
}
@Nullable
- public String[] getNotPlatformSurfaceableSchemas() {
- return getPropertyStringArray(NOT_PLATFORM_SURFACEABLE_PROPERTY);
+ public String[] getNotDisplayedBySystem() {
+ return getPropertyStringArray(NOT_DISPLAYED_BY_SYSTEM_PROPERTY);
}
@Nullable
- public GenericDocument[] getPackageAccessibleSchemas() {
- return getPropertyDocumentArray(PACKAGE_ACCESSIBLE_PROPERTY);
+ public GenericDocument[] getVisibleToPackages() {
+ return getPropertyDocumentArray(VISIBLE_TO_PACKAGES_PROPERTY);
}
/** Builder for {@link VisibilityDocument}. */
@@ -72,17 +72,15 @@ class VisibilityDocument extends GenericDocument {
/** Sets which prefixed schemas have opted out of platform surfacing. */
@NonNull
- public Builder setSchemasNotPlatformSurfaceable(
- @NonNull String[] notPlatformSurfaceableSchemas) {
- return setPropertyString(
- NOT_PLATFORM_SURFACEABLE_PROPERTY, notPlatformSurfaceableSchemas);
+ public Builder setNotDisplayedBySystem(@NonNull String[] notDisplayedBySystemSchemas) {
+ return setPropertyString(NOT_DISPLAYED_BY_SYSTEM_PROPERTY, notDisplayedBySystemSchemas);
}
/** Sets which prefixed schemas have configured package access. */
@NonNull
- public Builder setPackageAccessibleSchemas(
- @NonNull PackageAccessibleDocument[] packageAccessibleSchemas) {
- return setPropertyDocument(PACKAGE_ACCESSIBLE_PROPERTY, packageAccessibleSchemas);
+ public Builder setVisibleToPackages(
+ @NonNull VisibleToPackagesDocument[] visibleToPackagesDocuments) {
+ return setPropertyDocument(VISIBLE_TO_PACKAGES_PROPERTY, visibleToPackagesDocuments);
}
}
}
diff --git a/apex/appsearch/service/java/com/android/server/appsearch/visibilitystore/VisibilityStore.java b/apex/appsearch/service/java/com/android/server/appsearch/visibilitystore/VisibilityStore.java
index ae1ec56b4ee6..a096aef34c71 100644
--- a/apex/appsearch/service/java/com/android/server/appsearch/visibilitystore/VisibilityStore.java
+++ b/apex/appsearch/service/java/com/android/server/appsearch/visibilitystore/VisibilityStore.java
@@ -66,9 +66,6 @@ import java.util.Set;
* @hide
*/
public class VisibilityStore {
- /** No-op uid that won't have any visibility settings. */
- public static final int NO_OP_UID = -1;
-
/** Version for the visibility schema */
private static final int SCHEMA_VERSION = 0;
@@ -92,11 +89,10 @@ public class VisibilityStore {
private final Context mUserContext;
/** Stores the schemas that are platform-hidden. All values are prefixed. */
- private final NotPlatformSurfaceableMap mNotPlatformSurfaceableMap =
- new NotPlatformSurfaceableMap();
+ private final NotDisplayedBySystemMap mNotDisplayedBySystemMap = new NotDisplayedBySystemMap();
- /** Stores the schemas that are package accessible. All values are prefixed. */
- private final PackageAccessibleMap mPackageAccessibleMap = new PackageAccessibleMap();
+ /** Stores the schemas that are visible to 3p packages. All values are prefixed. */
+ private final VisibleToPackagesMap mVisibleToPackagesMap = new VisibleToPackagesMap();
/**
* Creates and initializes VisibilityStore.
@@ -118,28 +114,28 @@ public class VisibilityStore {
GetSchemaResponse getSchemaResponse = mAppSearchImpl.getSchema(PACKAGE_NAME, DATABASE_NAME);
boolean hasVisibilityType = false;
- boolean hasPackageAccessibleType = false;
+ boolean hasVisibleToPackagesType = false;
for (AppSearchSchema schema : getSchemaResponse.getSchemas()) {
if (schema.getSchemaType().equals(VisibilityDocument.SCHEMA_TYPE)) {
hasVisibilityType = true;
- } else if (schema.getSchemaType().equals(PackageAccessibleDocument.SCHEMA_TYPE)) {
- hasPackageAccessibleType = true;
+ } else if (schema.getSchemaType().equals(VisibleToPackagesDocument.SCHEMA_TYPE)) {
+ hasVisibleToPackagesType = true;
}
- if (hasVisibilityType && hasPackageAccessibleType) {
+ if (hasVisibilityType && hasVisibleToPackagesType) {
// Found both our types, can exit early.
break;
}
}
- if (!hasVisibilityType || !hasPackageAccessibleType) {
+ if (!hasVisibilityType || !hasVisibleToPackagesType) {
// Schema type doesn't exist yet. Add it.
mAppSearchImpl.setSchema(
PACKAGE_NAME,
DATABASE_NAME,
- Arrays.asList(VisibilityDocument.SCHEMA, PackageAccessibleDocument.SCHEMA),
+ Arrays.asList(VisibilityDocument.SCHEMA, VisibleToPackagesDocument.SCHEMA),
/*visibilityStore=*/ null, // Avoid recursive calls
- /*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
- /*schemasPackageAccessible=*/ Collections.emptyMap(),
+ /*schemasNotDisplayedBySystem=*/ Collections.emptyList(),
+ /*schemasVisibleToPackages=*/ Collections.emptyMap(),
/*forceOverride=*/ false,
/*version=*/ SCHEMA_VERSION);
}
@@ -177,26 +173,25 @@ public class VisibilityStore {
}
// Update platform visibility settings
- String[] notPlatformSurfaceableSchemas =
- visibilityDocument.getNotPlatformSurfaceableSchemas();
- if (notPlatformSurfaceableSchemas != null) {
- mNotPlatformSurfaceableMap.setNotPlatformSurfaceable(
+ String[] notDisplayedBySystemSchemas = visibilityDocument.getNotDisplayedBySystem();
+ if (notDisplayedBySystemSchemas != null) {
+ mNotDisplayedBySystemMap.setNotDisplayedBySystem(
packageName,
databaseName,
- new ArraySet<>(notPlatformSurfaceableSchemas));
+ new ArraySet<>(notDisplayedBySystemSchemas));
}
// Update 3p package visibility settings
Map<String, Set<PackageIdentifier>> schemaToPackageIdentifierMap = new ArrayMap<>();
- GenericDocument[] packageAccessibleDocuments =
- visibilityDocument.getPackageAccessibleSchemas();
- if (packageAccessibleDocuments != null) {
- for (int i = 0; i < packageAccessibleDocuments.length; i++) {
- PackageAccessibleDocument packageAccessibleDocument =
- new PackageAccessibleDocument(packageAccessibleDocuments[i]);
+ GenericDocument[] visibleToPackagesDocuments =
+ visibilityDocument.getVisibleToPackages();
+ if (visibleToPackagesDocuments != null) {
+ for (int i = 0; i < visibleToPackagesDocuments.length; i++) {
+ VisibleToPackagesDocument visibleToPackagesDocument =
+ new VisibleToPackagesDocument(visibleToPackagesDocuments[i]);
PackageIdentifier packageIdentifier =
- packageAccessibleDocument.getPackageIdentifier();
- String prefixedSchema = packageAccessibleDocument.getAccessibleSchemaType();
+ visibleToPackagesDocument.getPackageIdentifier();
+ String prefixedSchema = visibleToPackagesDocument.getAccessibleSchemaType();
Set<PackageIdentifier> packageIdentifiers =
schemaToPackageIdentifierMap.get(prefixedSchema);
if (packageIdentifiers == null) {
@@ -206,7 +201,7 @@ public class VisibilityStore {
schemaToPackageIdentifierMap.put(prefixedSchema, packageIdentifiers);
}
}
- mPackageAccessibleMap.setPackageAccessible(
+ mVisibleToPackagesMap.setVisibleToPackages(
packageName, databaseName, schemaToPackageIdentifierMap);
}
}
@@ -216,51 +211,51 @@ public class VisibilityStore {
* Sets visibility settings for the given database. Any previous visibility settings will be
* overwritten.
*
- * @param packageName Package of app that owns the {@code schemasNotPlatformSurfaceable}.
- * @param databaseName Database that owns the {@code schemasNotPlatformSurfaceable}.
- * @param schemasNotPlatformSurfaceable Set of prefixed schemas that should be hidden from the
+ * @param packageName Package of app that owns the schemas.
+ * @param databaseName Database that owns the schemas.
+ * @param schemasNotDisplayedBySystem Set of prefixed schemas that should be hidden from the
* platform.
- * @param schemasPackageAccessible Map of prefixed schemas to a list of package identifiers that
+ * @param schemasVisibleToPackages Map of prefixed schemas to a list of package identifiers that
* have access to the schema.
* @throws AppSearchException on AppSearchImpl error.
*/
public void setVisibility(
@NonNull String packageName,
@NonNull String databaseName,
- @NonNull Set<String> schemasNotPlatformSurfaceable,
- @NonNull Map<String, List<PackageIdentifier>> schemasPackageAccessible)
+ @NonNull Set<String> schemasNotDisplayedBySystem,
+ @NonNull Map<String, List<PackageIdentifier>> schemasVisibleToPackages)
throws AppSearchException {
Objects.requireNonNull(packageName);
Objects.requireNonNull(databaseName);
- Objects.requireNonNull(schemasNotPlatformSurfaceable);
- Objects.requireNonNull(schemasPackageAccessible);
+ Objects.requireNonNull(schemasNotDisplayedBySystem);
+ Objects.requireNonNull(schemasVisibleToPackages);
// Persist the document
VisibilityDocument.Builder visibilityDocument =
new VisibilityDocument.Builder(
NAMESPACE, /*id=*/ getVisibilityDocumentId(packageName, databaseName));
- if (!schemasNotPlatformSurfaceable.isEmpty()) {
- visibilityDocument.setSchemasNotPlatformSurfaceable(
- schemasNotPlatformSurfaceable.toArray(new String[0]));
+ if (!schemasNotDisplayedBySystem.isEmpty()) {
+ visibilityDocument.setNotDisplayedBySystem(
+ schemasNotDisplayedBySystem.toArray(new String[0]));
}
Map<String, Set<PackageIdentifier>> schemaToPackageIdentifierMap = new ArrayMap<>();
- List<PackageAccessibleDocument> packageAccessibleDocuments = new ArrayList<>();
+ List<VisibleToPackagesDocument> visibleToPackagesDocuments = new ArrayList<>();
for (Map.Entry<String, List<PackageIdentifier>> entry :
- schemasPackageAccessible.entrySet()) {
+ schemasVisibleToPackages.entrySet()) {
for (int i = 0; i < entry.getValue().size(); i++) {
- PackageAccessibleDocument packageAccessibleDocument =
- new PackageAccessibleDocument.Builder(NAMESPACE, /*id=*/ "")
+ VisibleToPackagesDocument visibleToPackagesDocument =
+ new VisibleToPackagesDocument.Builder(NAMESPACE, /*id=*/ "")
.setAccessibleSchemaType(entry.getKey())
.setPackageIdentifier(entry.getValue().get(i))
.build();
- packageAccessibleDocuments.add(packageAccessibleDocument);
+ visibleToPackagesDocuments.add(visibleToPackagesDocument);
}
schemaToPackageIdentifierMap.put(entry.getKey(), new ArraySet<>(entry.getValue()));
}
- if (!packageAccessibleDocuments.isEmpty()) {
- visibilityDocument.setPackageAccessibleSchemas(
- packageAccessibleDocuments.toArray(new PackageAccessibleDocument[0]));
+ if (!visibleToPackagesDocuments.isEmpty()) {
+ visibilityDocument.setVisibleToPackages(
+ visibleToPackagesDocuments.toArray(new VisibleToPackagesDocument[0]));
}
mAppSearchImpl.putDocument(
@@ -269,9 +264,9 @@ public class VisibilityStore {
mAppSearchImpl.persistToDisk(PersistType.Code.LITE);
// Update derived data structures.
- mNotPlatformSurfaceableMap.setNotPlatformSurfaceable(
- packageName, databaseName, schemasNotPlatformSurfaceable);
- mPackageAccessibleMap.setPackageAccessible(
+ mNotDisplayedBySystemMap.setNotDisplayedBySystem(
+ packageName, databaseName, schemasNotDisplayedBySystem);
+ mVisibleToPackagesMap.setVisibleToPackages(
packageName, databaseName, schemaToPackageIdentifierMap);
}
@@ -313,13 +308,13 @@ public class VisibilityStore {
}
if (callerHasSystemAccess
- && mNotPlatformSurfaceableMap.isSchemaPlatformSurfaceable(
+ && mNotDisplayedBySystemMap.isSchemaDisplayedBySystem(
packageName, databaseName, prefixedSchema)) {
return true;
}
// May not be platform surfaceable, but might still be accessible through 3p access.
- return isSchemaPackageAccessible(packageName, databaseName, prefixedSchema, callerUid);
+ return isSchemaVisibleToPackages(packageName, databaseName, prefixedSchema, callerUid);
}
/**
@@ -331,13 +326,13 @@ public class VisibilityStore {
* certificate was once used to sign the package, the package will still be granted access. This
* does not handle packages that have been signed by multiple certificates.
*/
- private boolean isSchemaPackageAccessible(
+ private boolean isSchemaVisibleToPackages(
@NonNull String packageName,
@NonNull String databaseName,
@NonNull String prefixedSchema,
int callerUid) {
Set<PackageIdentifier> packageIdentifiers =
- mPackageAccessibleMap.getAccessiblePackages(
+ mVisibleToPackagesMap.getAccessiblePackages(
packageName, databaseName, prefixedSchema);
if (packageIdentifiers.isEmpty()) {
return false;
diff --git a/apex/appsearch/service/java/com/android/server/appsearch/visibilitystore/PackageAccessibleDocument.java b/apex/appsearch/service/java/com/android/server/appsearch/visibilitystore/VisibleToPackagesDocument.java
index 0b4e196fd0c4..8d503390eaaa 100644
--- a/apex/appsearch/service/java/com/android/server/appsearch/visibilitystore/PackageAccessibleDocument.java
+++ b/apex/appsearch/service/java/com/android/server/appsearch/visibilitystore/VisibleToPackagesDocument.java
@@ -26,7 +26,7 @@ import android.app.appsearch.PackageIdentifier;
*
* @see android.app.appsearch.SetSchemaRequest.Builder#setSchemaTypeVisibilityForPackage
*/
-class PackageAccessibleDocument extends GenericDocument {
+class VisibleToPackagesDocument extends GenericDocument {
/** Schema type for nested documents that hold package accessible information. */
public static final String SCHEMA_TYPE = "PackageAccessibleType";
@@ -59,7 +59,7 @@ class PackageAccessibleDocument extends GenericDocument {
.build())
.build();
- public PackageAccessibleDocument(@NonNull GenericDocument genericDocument) {
+ VisibleToPackagesDocument(@NonNull GenericDocument genericDocument) {
super(genericDocument);
}
@@ -76,9 +76,9 @@ class PackageAccessibleDocument extends GenericDocument {
return new PackageIdentifier(packageName, sha256Cert);
}
- /** Builder for {@link PackageAccessibleDocument} instances. */
- public static class Builder extends GenericDocument.Builder<PackageAccessibleDocument.Builder> {
- public Builder(@NonNull String namespace, @NonNull String id) {
+ /** Builder for {@link VisibleToPackagesDocument} instances. */
+ public static class Builder extends GenericDocument.Builder<VisibleToPackagesDocument.Builder> {
+ Builder(@NonNull String namespace, @NonNull String id) {
super(namespace, id, SCHEMA_TYPE);
}
@@ -98,8 +98,8 @@ class PackageAccessibleDocument extends GenericDocument {
@Override
@NonNull
- public PackageAccessibleDocument build() {
- return new PackageAccessibleDocument(super.build());
+ public VisibleToPackagesDocument build() {
+ return new VisibleToPackagesDocument(super.build());
}
}
}
diff --git a/apex/appsearch/service/java/com/android/server/appsearch/visibilitystore/PackageAccessibleMap.java b/apex/appsearch/service/java/com/android/server/appsearch/visibilitystore/VisibleToPackagesMap.java
index cff729aa4e8a..e2b51a75025c 100644
--- a/apex/appsearch/service/java/com/android/server/appsearch/visibilitystore/PackageAccessibleMap.java
+++ b/apex/appsearch/service/java/com/android/server/appsearch/visibilitystore/VisibleToPackagesMap.java
@@ -29,7 +29,7 @@ import java.util.Set;
*
* This object is not thread safe.
*/
-class PackageAccessibleMap {
+class VisibleToPackagesMap {
/**
* Maps packages to databases to prefixed schemas to PackageIdentifiers that have access to that
* schema.
@@ -42,7 +42,7 @@ class PackageAccessibleMap {
*
* <p>Any existing mappings for this prefix are overwritten.
*/
- public void setPackageAccessible(
+ public void setVisibleToPackages(
@NonNull String packageName,
@NonNull String databaseName,
@NonNull Map<String, Set<PackageIdentifier>> schemaToPackageIdentifier) {
diff --git a/apex/appsearch/synced_jetpack_changeid.txt b/apex/appsearch/synced_jetpack_changeid.txt
index 78d39cc6deac..9859f20643b5 100644
--- a/apex/appsearch/synced_jetpack_changeid.txt
+++ b/apex/appsearch/synced_jetpack_changeid.txt
@@ -1 +1 @@
-31a54dba5bda4d0109ea91eb1ac047c937cbaae3
+04351b43fbbf9d59ffeae41903322023931c84f2
diff --git a/apex/appsearch/testing/java/com/android/server/appsearch/testing/external/AppSearchSessionShim.java b/apex/appsearch/testing/java/com/android/server/appsearch/testing/external/AppSearchSessionShim.java
index d6ce3ebc267f..7b74578adfc7 100644
--- a/apex/appsearch/testing/java/com/android/server/appsearch/testing/external/AppSearchSessionShim.java
+++ b/apex/appsearch/testing/java/com/android/server/appsearch/testing/external/AppSearchSessionShim.java
@@ -51,8 +51,6 @@ public interface AppSearchSessionShim extends Closeable {
* @param request the schema to set or update the AppSearch database to.
* @return a {@link ListenableFuture} which resolves to a {@link SetSchemaResponse} object.
*/
- // TODO(b/169883602): Change @code references to @link when setPlatformSurfaceable APIs are
- // exposed.
@NonNull
ListenableFuture<SetSchemaResponse> setSchema(@NonNull SetSchemaRequest request);
diff --git a/apex/jobscheduler/service/java/com/android/server/DeviceIdleController.java b/apex/jobscheduler/service/java/com/android/server/DeviceIdleController.java
index 0e9efbcc98b8..ac2018707c75 100644
--- a/apex/jobscheduler/service/java/com/android/server/DeviceIdleController.java
+++ b/apex/jobscheduler/service/java/com/android/server/DeviceIdleController.java
@@ -442,6 +442,7 @@ public class DeviceIdleController extends SystemService
private long mNextIdlePendingDelay;
private long mNextIdleDelay;
private long mNextLightIdleDelay;
+ private long mNextLightIdleDelayFlex;
private long mNextLightAlarmTime;
private long mNextSensingTimeoutAlarmTime;
@@ -886,16 +887,20 @@ public class DeviceIdleController extends SystemService
*/
public final class Constants implements DeviceConfig.OnPropertiesChangedListener {
// Key names stored in the settings value.
- private static final String KEY_LIGHT_IDLE_AFTER_INACTIVE_TIMEOUT
- = "light_after_inactive_to";
+ private static final String KEY_FLEX_TIME_SHORT = "flex_time_short";
+ private static final String KEY_LIGHT_IDLE_AFTER_INACTIVE_TIMEOUT =
+ "light_after_inactive_to";
private static final String KEY_LIGHT_PRE_IDLE_TIMEOUT = "light_pre_idle_to";
private static final String KEY_LIGHT_IDLE_TIMEOUT = "light_idle_to";
+ private static final String KEY_LIGHT_IDLE_TIMEOUT_INITIAL_FLEX =
+ "light_idle_to_initial_flex";
+ private static final String KEY_LIGHT_MAX_IDLE_TIMEOUT_FLEX = "light_max_idle_to_flex";
private static final String KEY_LIGHT_IDLE_FACTOR = "light_idle_factor";
private static final String KEY_LIGHT_MAX_IDLE_TIMEOUT = "light_max_idle_to";
- private static final String KEY_LIGHT_IDLE_MAINTENANCE_MIN_BUDGET
- = "light_idle_maintenance_min_budget";
- private static final String KEY_LIGHT_IDLE_MAINTENANCE_MAX_BUDGET
- = "light_idle_maintenance_max_budget";
+ private static final String KEY_LIGHT_IDLE_MAINTENANCE_MIN_BUDGET =
+ "light_idle_maintenance_min_budget";
+ private static final String KEY_LIGHT_IDLE_MAINTENANCE_MAX_BUDGET =
+ "light_idle_maintenance_max_budget";
private static final String KEY_MIN_LIGHT_MAINTENANCE_TIME = "min_light_maintenance_time";
private static final String KEY_MIN_DEEP_MAINTENANCE_TIME = "min_deep_maintenance_time";
private static final String KEY_INACTIVE_TIMEOUT = "inactive_to";
@@ -903,6 +908,7 @@ public class DeviceIdleController extends SystemService
private static final String KEY_LOCATING_TIMEOUT = "locating_to";
private static final String KEY_LOCATION_ACCURACY = "location_accuracy";
private static final String KEY_MOTION_INACTIVE_TIMEOUT = "motion_inactive_to";
+ private static final String KEY_MOTION_INACTIVE_TIMEOUT_FLEX = "motion_inactive_to_flex";
private static final String KEY_IDLE_AFTER_INACTIVE_TIMEOUT = "idle_after_inactive_to";
private static final String KEY_IDLE_PENDING_TIMEOUT = "idle_pending_to";
private static final String KEY_MAX_IDLE_PENDING_TIMEOUT = "max_idle_pending_to";
@@ -929,13 +935,20 @@ public class DeviceIdleController extends SystemService
"pre_idle_factor_long";
private static final String KEY_PRE_IDLE_FACTOR_SHORT =
"pre_idle_factor_short";
+ private static final String KEY_USE_WINDOW_ALARMS = "use_window_alarms";
+ private static final long DEFAULT_FLEX_TIME_SHORT =
+ !COMPRESS_TIME ? 60 * 1000L : 5 * 1000L;
private static final long DEFAULT_LIGHT_IDLE_AFTER_INACTIVE_TIMEOUT =
- !COMPRESS_TIME ? 3 * 60 * 1000L : 15 * 1000L;
+ !COMPRESS_TIME ? 60 * 1000L : 15 * 1000L;
private static final long DEFAULT_LIGHT_PRE_IDLE_TIMEOUT =
!COMPRESS_TIME ? 3 * 60 * 1000L : 30 * 1000L;
private static final long DEFAULT_LIGHT_IDLE_TIMEOUT =
!COMPRESS_TIME ? 5 * 60 * 1000L : 15 * 1000L;
+ private static final long DEFAULT_LIGHT_IDLE_TIMEOUT_INITIAL_FLEX =
+ !COMPRESS_TIME ? 60 * 1000L : 5 * 1000L;
+ private static final long DEFAULT_LIGHT_MAX_IDLE_TIMEOUT_FLEX =
+ !COMPRESS_TIME ? 15 * 60 * 1000L : 60 * 1000L;
private static final float DEFAULT_LIGHT_IDLE_FACTOR = 2f;
private static final long DEFAULT_LIGHT_MAX_IDLE_TIMEOUT =
!COMPRESS_TIME ? 15 * 60 * 1000L : 60 * 1000L;
@@ -958,6 +971,8 @@ public class DeviceIdleController extends SystemService
private static final float DEFAULT_LOCATION_ACCURACY = 20f;
private static final long DEFAULT_MOTION_INACTIVE_TIMEOUT =
!COMPRESS_TIME ? 10 * 60 * 1000L : 60 * 1000L;
+ private static final long DEFAULT_MOTION_INACTIVE_TIMEOUT_FLEX =
+ !COMPRESS_TIME ? 60 * 1000L : 5 * 1000L;
private static final long DEFAULT_IDLE_AFTER_INACTIVE_TIMEOUT =
(30 * 60 * 1000L) / (!COMPRESS_TIME ? 1 : 10);
private static final long DEFAULT_IDLE_AFTER_INACTIVE_TIMEOUT_SMALL_BATTERY =
@@ -983,6 +998,14 @@ public class DeviceIdleController extends SystemService
private static final boolean DEFAULT_WAIT_FOR_UNLOCK = true;
private static final float DEFAULT_PRE_IDLE_FACTOR_LONG = 1.67f;
private static final float DEFAULT_PRE_IDLE_FACTOR_SHORT = .33f;
+ private static final boolean DEFAULT_USE_WINDOW_ALARMS = true;
+
+ /**
+ * A somewhat short alarm window size that we will tolerate for various alarm timings.
+ *
+ * @see #KEY_FLEX_TIME_SHORT
+ */
+ public long FLEX_TIME_SHORT = DEFAULT_FLEX_TIME_SHORT;
/**
* This is the time, after becoming inactive, that we go in to the first
@@ -1002,13 +1025,28 @@ public class DeviceIdleController extends SystemService
public long LIGHT_PRE_IDLE_TIMEOUT = DEFAULT_LIGHT_PRE_IDLE_TIMEOUT;
/**
- * This is the initial time that we will run in idle maintenance mode.
+ * This is the initial time that we will run in light idle maintenance mode.
*
* @see #KEY_LIGHT_IDLE_TIMEOUT
*/
public long LIGHT_IDLE_TIMEOUT = DEFAULT_LIGHT_IDLE_TIMEOUT;
/**
+ * This is the initial alarm window size that we will tolerate for light idle maintenance
+ * timing.
+ *
+ * @see #KEY_LIGHT_IDLE_TIMEOUT_INITIAL_FLEX
+ */
+ public long LIGHT_IDLE_TIMEOUT_INITIAL_FLEX = DEFAULT_LIGHT_IDLE_TIMEOUT_INITIAL_FLEX;
+
+ /**
+ * This is the maximum value that {@link #LIGHT_IDLE_TIMEOUT_INITIAL_FLEX} should take.
+ *
+ * @see #KEY_LIGHT_MAX_IDLE_TIMEOUT_FLEX
+ */
+ public long LIGHT_MAX_IDLE_TIMEOUT_FLEX = DEFAULT_LIGHT_MAX_IDLE_TIMEOUT_FLEX;
+
+ /**
* Scaling factor to apply to the light idle mode time each time we complete a cycle.
*
* @see #KEY_LIGHT_IDLE_FACTOR
@@ -1016,7 +1054,7 @@ public class DeviceIdleController extends SystemService
public float LIGHT_IDLE_FACTOR = DEFAULT_LIGHT_IDLE_FACTOR;
/**
- * This is the maximum time we will run in idle maintenance mode.
+ * This is the maximum time we will stay in light idle mode.
*
* @see #KEY_LIGHT_MAX_IDLE_TIMEOUT
*/
@@ -1099,13 +1137,22 @@ public class DeviceIdleController extends SystemService
/**
* This is the time, after seeing motion, that we wait after becoming inactive from
* that until we start looking for motion again.
+ *
* @see #KEY_MOTION_INACTIVE_TIMEOUT
*/
public long MOTION_INACTIVE_TIMEOUT = DEFAULT_MOTION_INACTIVE_TIMEOUT;
/**
+ * This is the alarm window size we will tolerate for motion detection timings.
+ *
+ * @see #KEY_MOTION_INACTIVE_TIMEOUT_FLEX
+ */
+ public long MOTION_INACTIVE_TIMEOUT_FLEX = DEFAULT_MOTION_INACTIVE_TIMEOUT_FLEX;
+
+ /**
* This is the time, after the inactive timeout elapses, that we will wait looking
* for motion until we truly consider the device to be idle.
+ *
* @see #KEY_IDLE_AFTER_INACTIVE_TIMEOUT
*/
public long IDLE_AFTER_INACTIVE_TIMEOUT = DEFAULT_IDLE_AFTER_INACTIVE_TIMEOUT;
@@ -1204,6 +1251,12 @@ public class DeviceIdleController extends SystemService
public boolean WAIT_FOR_UNLOCK = DEFAULT_WAIT_FOR_UNLOCK;
+ /**
+ * Whether to use window alarms. True to use window alarms (call AlarmManager.setWindow()).
+ * False to use the legacy inexact alarms (call AlarmManager.set()).
+ */
+ public boolean USE_WINDOW_ALARMS = DEFAULT_USE_WINDOW_ALARMS;
+
private final boolean mSmallBatteryDevice;
public Constants() {
@@ -1227,6 +1280,10 @@ public class DeviceIdleController extends SystemService
continue;
}
switch (name) {
+ case KEY_FLEX_TIME_SHORT:
+ FLEX_TIME_SHORT = properties.getLong(
+ KEY_FLEX_TIME_SHORT, DEFAULT_FLEX_TIME_SHORT);
+ break;
case KEY_LIGHT_IDLE_AFTER_INACTIVE_TIMEOUT:
LIGHT_IDLE_AFTER_INACTIVE_TIMEOUT = properties.getLong(
KEY_LIGHT_IDLE_AFTER_INACTIVE_TIMEOUT,
@@ -1240,9 +1297,19 @@ public class DeviceIdleController extends SystemService
LIGHT_IDLE_TIMEOUT = properties.getLong(
KEY_LIGHT_IDLE_TIMEOUT, DEFAULT_LIGHT_IDLE_TIMEOUT);
break;
+ case KEY_LIGHT_IDLE_TIMEOUT_INITIAL_FLEX:
+ LIGHT_IDLE_TIMEOUT_INITIAL_FLEX = properties.getLong(
+ KEY_LIGHT_IDLE_TIMEOUT_INITIAL_FLEX,
+ DEFAULT_LIGHT_IDLE_TIMEOUT_INITIAL_FLEX);
+ break;
+ case KEY_LIGHT_MAX_IDLE_TIMEOUT_FLEX:
+ LIGHT_MAX_IDLE_TIMEOUT_FLEX = properties.getLong(
+ KEY_LIGHT_MAX_IDLE_TIMEOUT_FLEX,
+ DEFAULT_LIGHT_MAX_IDLE_TIMEOUT_FLEX);
+ break;
case KEY_LIGHT_IDLE_FACTOR:
- LIGHT_IDLE_FACTOR = properties.getFloat(
- KEY_LIGHT_IDLE_FACTOR, DEFAULT_LIGHT_IDLE_FACTOR);
+ LIGHT_IDLE_FACTOR = Math.max(1, properties.getFloat(
+ KEY_LIGHT_IDLE_FACTOR, DEFAULT_LIGHT_IDLE_FACTOR));
break;
case KEY_LIGHT_MAX_IDLE_TIMEOUT:
LIGHT_MAX_IDLE_TIMEOUT = properties.getLong(
@@ -1291,6 +1358,11 @@ public class DeviceIdleController extends SystemService
MOTION_INACTIVE_TIMEOUT = properties.getLong(
KEY_MOTION_INACTIVE_TIMEOUT, DEFAULT_MOTION_INACTIVE_TIMEOUT);
break;
+ case KEY_MOTION_INACTIVE_TIMEOUT_FLEX:
+ MOTION_INACTIVE_TIMEOUT_FLEX = properties.getLong(
+ KEY_MOTION_INACTIVE_TIMEOUT_FLEX,
+ DEFAULT_MOTION_INACTIVE_TIMEOUT_FLEX);
+ break;
case KEY_IDLE_AFTER_INACTIVE_TIMEOUT:
final long defaultIdleAfterInactiveTimeout = mSmallBatteryDevice
? DEFAULT_IDLE_AFTER_INACTIVE_TIMEOUT_SMALL_BATTERY
@@ -1362,6 +1434,10 @@ public class DeviceIdleController extends SystemService
PRE_IDLE_FACTOR_SHORT = properties.getFloat(
KEY_PRE_IDLE_FACTOR_SHORT, DEFAULT_PRE_IDLE_FACTOR_SHORT);
break;
+ case KEY_USE_WINDOW_ALARMS:
+ USE_WINDOW_ALARMS = properties.getBoolean(
+ KEY_USE_WINDOW_ALARMS, DEFAULT_USE_WINDOW_ALARMS);
+ break;
default:
Slog.e(TAG, "Unknown configuration key: " + name);
break;
@@ -1373,6 +1449,10 @@ public class DeviceIdleController extends SystemService
void dump(PrintWriter pw) {
pw.println(" Settings:");
+ pw.print(" "); pw.print(KEY_FLEX_TIME_SHORT); pw.print("=");
+ TimeUtils.formatDuration(FLEX_TIME_SHORT, pw);
+ pw.println();
+
pw.print(" ");
pw.print(KEY_LIGHT_IDLE_AFTER_INACTIVE_TIMEOUT);
pw.print("=");
@@ -1387,6 +1467,14 @@ public class DeviceIdleController extends SystemService
TimeUtils.formatDuration(LIGHT_IDLE_TIMEOUT, pw);
pw.println();
+ pw.print(" "); pw.print(KEY_LIGHT_IDLE_TIMEOUT_INITIAL_FLEX); pw.print("=");
+ TimeUtils.formatDuration(LIGHT_IDLE_TIMEOUT_INITIAL_FLEX, pw);
+ pw.println();
+
+ pw.print(" "); pw.print(KEY_LIGHT_MAX_IDLE_TIMEOUT_FLEX); pw.print("=");
+ TimeUtils.formatDuration(LIGHT_MAX_IDLE_TIMEOUT_FLEX, pw);
+ pw.println();
+
pw.print(" "); pw.print(KEY_LIGHT_IDLE_FACTOR); pw.print("=");
pw.print(LIGHT_IDLE_FACTOR);
pw.println();
@@ -1431,6 +1519,10 @@ public class DeviceIdleController extends SystemService
TimeUtils.formatDuration(MOTION_INACTIVE_TIMEOUT, pw);
pw.println();
+ pw.print(" "); pw.print(KEY_MOTION_INACTIVE_TIMEOUT_FLEX); pw.print("=");
+ TimeUtils.formatDuration(MOTION_INACTIVE_TIMEOUT_FLEX, pw);
+ pw.println();
+
pw.print(" "); pw.print(KEY_IDLE_AFTER_INACTIVE_TIMEOUT); pw.print("=");
TimeUtils.formatDuration(IDLE_AFTER_INACTIVE_TIMEOUT, pw);
pw.println();
@@ -1489,6 +1581,9 @@ public class DeviceIdleController extends SystemService
pw.print(" "); pw.print(KEY_PRE_IDLE_FACTOR_SHORT); pw.print("=");
pw.println(PRE_IDLE_FACTOR_SHORT);
+
+ pw.print(" "); pw.print(KEY_USE_WINDOW_ALARMS); pw.print("=");
+ pw.println(USE_WINDOW_ALARMS);
}
}
@@ -3199,7 +3294,8 @@ public class DeviceIdleController extends SystemService
mLightState = LIGHT_STATE_INACTIVE;
if (DEBUG) Slog.d(TAG, "Moved from LIGHT_STATE_ACTIVE to LIGHT_STATE_INACTIVE");
resetLightIdleManagementLocked();
- scheduleLightAlarmLocked(mConstants.LIGHT_IDLE_AFTER_INACTIVE_TIMEOUT);
+ scheduleLightAlarmLocked(mConstants.LIGHT_IDLE_AFTER_INACTIVE_TIMEOUT,
+ mConstants.FLEX_TIME_SHORT);
EventLogTags.writeDeviceIdleLight(mLightState, "no activity");
}
}
@@ -3219,6 +3315,7 @@ public class DeviceIdleController extends SystemService
private void resetLightIdleManagementLocked() {
mNextLightIdleDelay = 0;
+ mNextLightIdleDelayFlex = 0;
mCurLightIdleBudget = 0;
cancelLightAlarmLocked();
}
@@ -3265,13 +3362,15 @@ public class DeviceIdleController extends SystemService
mCurLightIdleBudget = mConstants.LIGHT_IDLE_MAINTENANCE_MIN_BUDGET;
// Reset the upcoming idle delays.
mNextLightIdleDelay = mConstants.LIGHT_IDLE_TIMEOUT;
+ mNextLightIdleDelayFlex = mConstants.LIGHT_IDLE_TIMEOUT_INITIAL_FLEX;
mMaintenanceStartTime = 0;
if (!isOpsInactiveLocked()) {
// We have some active ops going on... give them a chance to finish
// before going in to our first idle.
mLightState = LIGHT_STATE_PRE_IDLE;
EventLogTags.writeDeviceIdleLight(mLightState, reason);
- scheduleLightAlarmLocked(mConstants.LIGHT_PRE_IDLE_TIMEOUT);
+ scheduleLightAlarmLocked(mConstants.LIGHT_PRE_IDLE_TIMEOUT,
+ mConstants.FLEX_TIME_SHORT);
break;
}
// Nothing active, fall through to immediately idle.
@@ -3290,12 +3389,11 @@ public class DeviceIdleController extends SystemService
}
}
mMaintenanceStartTime = 0;
- scheduleLightAlarmLocked(mNextLightIdleDelay);
+ scheduleLightAlarmLocked(mNextLightIdleDelay, mNextLightIdleDelayFlex);
mNextLightIdleDelay = Math.min(mConstants.LIGHT_MAX_IDLE_TIMEOUT,
- (long)(mNextLightIdleDelay * mConstants.LIGHT_IDLE_FACTOR));
- if (mNextLightIdleDelay < mConstants.LIGHT_IDLE_TIMEOUT) {
- mNextLightIdleDelay = mConstants.LIGHT_IDLE_TIMEOUT;
- }
+ (long) (mNextLightIdleDelay * mConstants.LIGHT_IDLE_FACTOR));
+ mNextLightIdleDelayFlex = Math.min(mConstants.LIGHT_MAX_IDLE_TIMEOUT_FLEX,
+ (long) (mNextLightIdleDelayFlex * mConstants.LIGHT_IDLE_FACTOR));
if (DEBUG) Slog.d(TAG, "Moved to LIGHT_STATE_IDLE.");
mLightState = LIGHT_STATE_IDLE;
EventLogTags.writeDeviceIdleLight(mLightState, reason);
@@ -3315,7 +3413,7 @@ public class DeviceIdleController extends SystemService
} else if (mCurLightIdleBudget > mConstants.LIGHT_IDLE_MAINTENANCE_MAX_BUDGET) {
mCurLightIdleBudget = mConstants.LIGHT_IDLE_MAINTENANCE_MAX_BUDGET;
}
- scheduleLightAlarmLocked(mCurLightIdleBudget);
+ scheduleLightAlarmLocked(mCurLightIdleBudget, mConstants.FLEX_TIME_SHORT);
if (DEBUG) Slog.d(TAG,
"Moved from LIGHT_STATE_IDLE to LIGHT_STATE_IDLE_MAINTENANCE.");
mLightState = LIGHT_STATE_IDLE_MAINTENANCE;
@@ -3326,7 +3424,7 @@ public class DeviceIdleController extends SystemService
// We'd like to do maintenance, but currently don't have network
// connectivity... let's try to wait until the network comes back.
// We'll only wait for another full idle period, however, and then give up.
- scheduleLightAlarmLocked(mNextLightIdleDelay);
+ scheduleLightAlarmLocked(mNextLightIdleDelay, mNextLightIdleDelayFlex / 2);
if (DEBUG) Slog.d(TAG, "Moved to LIGHT_WAITING_FOR_NETWORK.");
mLightState = LIGHT_STATE_WAITING_FOR_NETWORK;
EventLogTags.writeDeviceIdleLight(mLightState, reason);
@@ -3844,40 +3942,75 @@ public class DeviceIdleController extends SystemService
mAlarmManager.setIdleUntil(AlarmManager.ELAPSED_REALTIME_WAKEUP,
mNextAlarmTime, "DeviceIdleController.deep", mDeepAlarmListener, mHandler);
} else {
- mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP,
- mNextAlarmTime, "DeviceIdleController.deep", mDeepAlarmListener, mHandler);
+ if (mConstants.USE_WINDOW_ALARMS) {
+ mAlarmManager.setWindow(AlarmManager.ELAPSED_REALTIME_WAKEUP,
+ mConstants.FLEX_TIME_SHORT,
+ mNextAlarmTime, "DeviceIdleController.deep", mDeepAlarmListener, mHandler);
+ } else {
+ mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP,
+ mNextAlarmTime, "DeviceIdleController.deep", mDeepAlarmListener, mHandler);
+ }
}
}
- void scheduleLightAlarmLocked(long delay) {
- if (DEBUG) Slog.d(TAG, "scheduleLightAlarmLocked(" + delay + ")");
+ void scheduleLightAlarmLocked(long delay, long flex) {
+ if (DEBUG) {
+ Slog.d(TAG, "scheduleLightAlarmLocked(" + delay
+ + (mConstants.USE_WINDOW_ALARMS ? "/" + flex : "") + ")");
+ }
mNextLightAlarmTime = SystemClock.elapsedRealtime() + delay;
- mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP,
- mNextLightAlarmTime, "DeviceIdleController.light", mLightAlarmListener, mHandler);
+ if (mConstants.USE_WINDOW_ALARMS) {
+ mAlarmManager.setWindow(AlarmManager.ELAPSED_REALTIME_WAKEUP, mNextLightAlarmTime, flex,
+ "DeviceIdleController.light", mLightAlarmListener, mHandler);
+ } else {
+ mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, mNextLightAlarmTime,
+ "DeviceIdleController.light", mLightAlarmListener, mHandler);
+ }
}
private void scheduleMotionRegistrationAlarmLocked() {
if (DEBUG) Slog.d(TAG, "scheduleMotionRegistrationAlarmLocked");
long nextMotionRegistrationAlarmTime =
mInjector.getElapsedRealtime() + mConstants.MOTION_INACTIVE_TIMEOUT / 2;
- mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, nextMotionRegistrationAlarmTime,
- "DeviceIdleController.motion_registration", mMotionRegistrationAlarmListener,
- mHandler);
+ if (mConstants.USE_WINDOW_ALARMS) {
+ mAlarmManager.setWindow(AlarmManager.ELAPSED_REALTIME_WAKEUP,
+ nextMotionRegistrationAlarmTime, mConstants.MOTION_INACTIVE_TIMEOUT_FLEX,
+ "DeviceIdleController.motion_registration", mMotionRegistrationAlarmListener,
+ mHandler);
+ } else {
+ mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, nextMotionRegistrationAlarmTime,
+ "DeviceIdleController.motion_registration", mMotionRegistrationAlarmListener,
+ mHandler);
+ }
}
private void scheduleMotionTimeoutAlarmLocked() {
if (DEBUG) Slog.d(TAG, "scheduleMotionAlarmLocked");
long nextMotionTimeoutAlarmTime =
mInjector.getElapsedRealtime() + mConstants.MOTION_INACTIVE_TIMEOUT;
- mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, nextMotionTimeoutAlarmTime,
- "DeviceIdleController.motion", mMotionTimeoutAlarmListener, mHandler);
+ if (mConstants.USE_WINDOW_ALARMS) {
+ mAlarmManager.setWindow(AlarmManager.ELAPSED_REALTIME_WAKEUP,
+ nextMotionTimeoutAlarmTime,
+ mConstants.MOTION_INACTIVE_TIMEOUT_FLEX,
+ "DeviceIdleController.motion", mMotionTimeoutAlarmListener, mHandler);
+ } else {
+ mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, nextMotionTimeoutAlarmTime,
+ "DeviceIdleController.motion", mMotionTimeoutAlarmListener, mHandler);
+ }
}
void scheduleSensingTimeoutAlarmLocked(long delay) {
if (DEBUG) Slog.d(TAG, "scheduleSensingAlarmLocked(" + delay + ")");
mNextSensingTimeoutAlarmTime = SystemClock.elapsedRealtime() + delay;
- mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, mNextSensingTimeoutAlarmTime,
- "DeviceIdleController.sensing", mSensingTimeoutAlarmListener, mHandler);
+ if (mConstants.USE_WINDOW_ALARMS) {
+ mAlarmManager.setWindow(AlarmManager.ELAPSED_REALTIME_WAKEUP,
+ mNextSensingTimeoutAlarmTime,
+ mConstants.FLEX_TIME_SHORT,
+ "DeviceIdleController.sensing", mSensingTimeoutAlarmListener, mHandler);
+ } else {
+ mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, mNextSensingTimeoutAlarmTime,
+ "DeviceIdleController.sensing", mSensingTimeoutAlarmListener, mHandler);
+ }
}
private static int[] buildAppIdArray(ArrayMap<String, Integer> systemApps,
@@ -4852,7 +4985,13 @@ public class DeviceIdleController extends SystemService
if (mNextLightIdleDelay != 0) {
pw.print(" mNextIdleDelay=");
TimeUtils.formatDuration(mNextLightIdleDelay, pw);
- pw.println();
+ if (mConstants.USE_WINDOW_ALARMS) {
+ pw.print(" (flex=");
+ TimeUtils.formatDuration(mNextLightIdleDelayFlex, pw);
+ pw.println(")");
+ } else {
+ pw.println();
+ }
}
if (mNextLightAlarmTime != 0) {
pw.print(" mNextLightAlarmTime=");
diff --git a/api/Android.bp b/api/Android.bp
index a84e6a6cb031..2ea180ebf598 100644
--- a/api/Android.bp
+++ b/api/Android.bp
@@ -24,6 +24,41 @@ package {
default_applicable_licenses: ["frameworks_base_license"],
}
+python_binary_host {
+ name: "api_versions_trimmer",
+ srcs: ["api_versions_trimmer.py"],
+ version: {
+ py2: {
+ enabled: false,
+ },
+ py3: {
+ enabled: true,
+ embedded_launcher: false,
+ },
+ },
+}
+
+python_test_host {
+ name: "api_versions_trimmer_unittests",
+ main: "api_versions_trimmer_unittests.py",
+ srcs: [
+ "api_versions_trimmer_unittests.py",
+ "api_versions_trimmer.py",
+ ],
+ test_options: {
+ unit_test: true,
+ },
+ version: {
+ py2: {
+ enabled: false,
+ },
+ py3: {
+ enabled: true,
+ embedded_launcher: false,
+ },
+ },
+}
+
metalava_cmd = "$(location metalava)"
// Silence reflection warnings. See b/168689341
metalava_cmd += " -J--add-opens=java.base/java.util=ALL-UNNAMED "
@@ -431,3 +466,41 @@ genrule {
},
],
}
+
+// This rule will filter classes present in the jar files of mainline modules
+// from the lint database in api-versions.xml.
+// This is done to reduce the number of false positive NewApi findings in
+// java libraries that compile against the module SDK
+genrule {
+ name: "api-versions-xml-public-filtered",
+ srcs: [
+ // Note: order matters: first parameter is the full api-versions.xml
+ // after that the stubs files in any order
+ // stubs files are all modules that export API surfaces EXCEPT ART
+ ":framework-doc-stubs{.api_versions.xml}",
+ ":android.net.ipsec.ike.stubs{.jar}",
+ ":conscrypt.module.public.api.stubs{.jar}",
+ ":framework-appsearch.stubs{.jar}",
+ ":framework-connectivity.stubs{.jar}",
+ ":framework-graphics.stubs{.jar}",
+ ":framework-media.stubs{.jar}",
+ ":framework-mediaprovider.stubs{.jar}",
+ ":framework-permission.stubs{.jar}",
+ ":framework-permission-s.stubs{.jar}",
+ ":framework-scheduling.stubs{.jar}",
+ ":framework-sdkextensions.stubs{.jar}",
+ ":framework-statsd.stubs{.jar}",
+ ":framework-tethering.stubs{.jar}",
+ ":framework-wifi.stubs{.jar}",
+ ":i18n.module.public.api.stubs{.jar}",
+ ],
+ out: ["api-versions-public-filtered.xml"],
+ tools: ["api_versions_trimmer"],
+ cmd: "$(location api_versions_trimmer) $(out) $(in)",
+ dist: {
+ targets: [
+ "sdk",
+ "win_sdk",
+ ],
+ },
+}
diff --git a/api/api_versions_trimmer.py b/api/api_versions_trimmer.py
new file mode 100755
index 000000000000..9afd95a3003a
--- /dev/null
+++ b/api/api_versions_trimmer.py
@@ -0,0 +1,136 @@
+#!/usr/bin/env python3
+#
+# Copyright (C) 2021 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+"""Script to remove mainline APIs from the api-versions.xml."""
+
+import argparse
+import re
+import xml.etree.ElementTree as ET
+import zipfile
+
+
+def read_classes(stubs):
+ """Read classes from the stubs file.
+
+ Args:
+ stubs: argument can be a path to a file (a string), a file-like object or a
+ path-like object
+
+ Returns:
+ a set of the classes found in the file (set of strings)
+ """
+ classes = set()
+ with zipfile.ZipFile(stubs) as z:
+ for info in z.infolist():
+ if (not info.is_dir()
+ and info.filename.endswith(".class")
+ and not info.filename.startswith("META-INF")):
+ # drop ".class" extension
+ classes.add(info.filename[:-6])
+ return classes
+
+
+def filter_method_tag(method, classes_to_remove):
+ """Updates the signature of this method by calling filter_method_signature.
+
+ Updates the method passed into this function.
+
+ Args:
+ method: xml element that represents a method
+ classes_to_remove: set of classes you to remove
+ """
+ filtered = filter_method_signature(method.get("name"), classes_to_remove)
+ method.set("name", filtered)
+
+
+def filter_method_signature(signature, classes_to_remove):
+ """Removes mentions of certain classes from this method signature.
+
+ Replaces any existing classes that need to be removed, with java/lang/Object
+
+ Args:
+ signature: string that is a java representation of a method signature
+ classes_to_remove: set of classes you to remove
+ """
+ regex = re.compile("L.*?;")
+ start = signature.find("(")
+ matches = set(regex.findall(signature[start:]))
+ for m in matches:
+ # m[1:-1] to drop the leading `L` and `;` ending
+ if m[1:-1] in classes_to_remove:
+ signature = signature.replace(m, "Ljava/lang/Object;")
+ return signature
+
+
+def filter_lint_database(database, classes_to_remove, output):
+ """Reads a lint database and writes a filtered version without some classes.
+
+ Reads database from api-versions.xml and removes any references to classes
+ in the second argument. Writes the result (another xml with the same format
+ of the database) to output.
+
+ Args:
+ database: path to xml with lint database to read
+ classes_to_remove: iterable (ideally a set or similar for quick
+ lookups) that enumerates the classes that should be removed
+ output: path to write the filtered database
+ """
+ xml = ET.parse(database)
+ root = xml.getroot()
+ for c in xml.findall("class"):
+ cname = c.get("name")
+ if cname in classes_to_remove:
+ root.remove(c)
+ else:
+ # find the <extends /> tag inside this class to see if the parent
+ # has been removed from the known classes (attribute called name)
+ super_classes = c.findall("extends")
+ for super_class in super_classes:
+ super_class_name = super_class.get("name")
+ if super_class_name in classes_to_remove:
+ super_class.set("name", "java/lang/Object")
+ interfaces = c.findall("implements")
+ for interface in interfaces:
+ interface_name = interface.get("name")
+ if interface_name in classes_to_remove:
+ c.remove(interface)
+ for method in c.findall("method"):
+ filter_method_tag(method, classes_to_remove)
+ xml.write(output)
+
+
+def main():
+ """Run the program."""
+ parser = argparse.ArgumentParser(
+ description=
+ ("Read a lint database (api-versions.xml) and many stubs jar files. "
+ "Produce another database file that doesn't include the classes present "
+ "in the stubs file(s)."))
+ parser.add_argument("output", help="Destination of the result (xml file).")
+ parser.add_argument(
+ "api_versions",
+ help="The lint database (api-versions.xml file) to read data from"
+ )
+ parser.add_argument("stubs", nargs="+", help="The stubs jar file(s)")
+ parsed = parser.parse_args()
+ classes = set()
+ for stub in parsed.stubs:
+ classes.update(read_classes(stub))
+ filter_lint_database(parsed.api_versions, classes, parsed.output)
+
+
+if __name__ == "__main__":
+ main()
diff --git a/api/api_versions_trimmer_unittests.py b/api/api_versions_trimmer_unittests.py
new file mode 100644
index 000000000000..4eb929ea1b5d
--- /dev/null
+++ b/api/api_versions_trimmer_unittests.py
@@ -0,0 +1,307 @@
+#!/usr/bin/env python3
+#
+# Copyright (C) 2021 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import io
+import re
+import unittest
+import xml.etree.ElementTree as ET
+import zipfile
+
+import api_versions_trimmer
+
+
+def create_in_memory_zip_file(files):
+ f = io.BytesIO()
+ with zipfile.ZipFile(f, "w") as z:
+ for fname in files:
+ with z.open(fname, mode="w") as class_file:
+ class_file.write(b"")
+ return f
+
+
+def indent(elem, level=0):
+ i = "\n" + level * " "
+ j = "\n" + (level - 1) * " "
+ if len(elem):
+ if not elem.text or not elem.text.strip():
+ elem.text = i + " "
+ if not elem.tail or not elem.tail.strip():
+ elem.tail = i
+ for subelem in elem:
+ indent(subelem, level + 1)
+ if not elem.tail or not elem.tail.strip():
+ elem.tail = j
+ else:
+ if level and (not elem.tail or not elem.tail.strip()):
+ elem.tail = j
+ return elem
+
+
+def pretty_print(s):
+ tree = ET.parse(io.StringIO(s))
+ el = indent(tree.getroot())
+ res = ET.tostring(el).decode("utf-8")
+ # remove empty lines inside the result because this still breaks some
+ # comparisons
+ return re.sub(r"\n\s*\n", "\n", res, re.MULTILINE)
+
+
+class ApiVersionsTrimmerUnittests(unittest.TestCase):
+
+ def setUp(self):
+ # so it prints diffs in long strings (xml files)
+ self.maxDiff = None
+
+ def test_read_classes(self):
+ f = create_in_memory_zip_file(
+ ["a/b/C.class",
+ "a/b/D.class",
+ ]
+ )
+ res = api_versions_trimmer.read_classes(f)
+ self.assertEqual({"a/b/C", "a/b/D"}, res)
+
+ def test_read_classes_ignore_dex(self):
+ f = create_in_memory_zip_file(
+ ["a/b/C.class",
+ "a/b/D.class",
+ "a/b/E.dex",
+ "f.dex",
+ ]
+ )
+ res = api_versions_trimmer.read_classes(f)
+ self.assertEqual({"a/b/C", "a/b/D"}, res)
+
+ def test_read_classes_ignore_manifest(self):
+ f = create_in_memory_zip_file(
+ ["a/b/C.class",
+ "a/b/D.class",
+ "META-INFO/G.class"
+ ]
+ )
+ res = api_versions_trimmer.read_classes(f)
+ self.assertEqual({"a/b/C", "a/b/D"}, res)
+
+ def test_filter_method_signature(self):
+ xml = """
+ <method name="dispatchGesture(Landroid/accessibilityservice/GestureDescription;Landroid/accessibilityservice/AccessibilityService$GestureResultCallback;Landroid/os/Handler;)Z" since="24"/>
+ """
+ method = ET.fromstring(xml)
+ classes_to_remove = {"android/accessibilityservice/GestureDescription"}
+ expected = "dispatchGesture(Ljava/lang/Object;Landroid/accessibilityservice/AccessibilityService$GestureResultCallback;Landroid/os/Handler;)Z"
+ api_versions_trimmer.filter_method_tag(method, classes_to_remove)
+ self.assertEqual(expected, method.get("name"))
+
+ def test_filter_method_signature_with_L_in_method(self):
+ xml = """
+ <method name="dispatchLeftGesture(Landroid/accessibilityservice/GestureDescription;Landroid/accessibilityservice/AccessibilityService$GestureResultCallback;Landroid/os/Handler;)Z" since="24"/>
+ """
+ method = ET.fromstring(xml)
+ classes_to_remove = {"android/accessibilityservice/GestureDescription"}
+ expected = "dispatchLeftGesture(Ljava/lang/Object;Landroid/accessibilityservice/AccessibilityService$GestureResultCallback;Landroid/os/Handler;)Z"
+ api_versions_trimmer.filter_method_tag(method, classes_to_remove)
+ self.assertEqual(expected, method.get("name"))
+
+ def test_filter_method_signature_with_L_in_class(self):
+ xml = """
+ <method name="dispatchGesture(Landroid/accessibilityservice/LeftGestureDescription;Landroid/accessibilityservice/AccessibilityService$GestureResultCallback;Landroid/os/Handler;)Z" since="24"/>
+ """
+ method = ET.fromstring(xml)
+ classes_to_remove = {"android/accessibilityservice/LeftGestureDescription"}
+ expected = "dispatchGesture(Ljava/lang/Object;Landroid/accessibilityservice/AccessibilityService$GestureResultCallback;Landroid/os/Handler;)Z"
+ api_versions_trimmer.filter_method_tag(method, classes_to_remove)
+ self.assertEqual(expected, method.get("name"))
+
+ def test_filter_method_signature_with_inner_class(self):
+ xml = """
+ <method name="dispatchGesture(Landroid/accessibilityservice/GestureDescription$Inner;Landroid/accessibilityservice/AccessibilityService$GestureResultCallback;Landroid/os/Handler;)Z" since="24"/>
+ """
+ method = ET.fromstring(xml)
+ classes_to_remove = {"android/accessibilityservice/GestureDescription$Inner"}
+ expected = "dispatchGesture(Ljava/lang/Object;Landroid/accessibilityservice/AccessibilityService$GestureResultCallback;Landroid/os/Handler;)Z"
+ api_versions_trimmer.filter_method_tag(method, classes_to_remove)
+ self.assertEqual(expected, method.get("name"))
+
+ def _run_filter_db_test(self, database_str, expected):
+ """Performs the pattern of testing the filter_lint_database method.
+
+ Filters instances of the class "a/b/C" (hard-coded) from the database string
+ and compares the result with the expected result (performs formatting of
+ the xml of both inputs)
+
+ Args:
+ database_str: string, the contents of the lint database (api-versions.xml)
+ expected: string, the expected result after filtering the original
+ database
+ """
+ database = io.StringIO(database_str)
+ classes_to_remove = {"a/b/C"}
+ output = io.BytesIO()
+ api_versions_trimmer.filter_lint_database(
+ database,
+ classes_to_remove,
+ output
+ )
+ expected = pretty_print(expected)
+ res = pretty_print(output.getvalue().decode("utf-8"))
+ self.assertEqual(expected, res)
+
+ def test_filter_lint_database_updates_method_signature_params(self):
+ self._run_filter_db_test(
+ database_str="""
+ <api version="2">
+ <!-- will be removed -->
+ <class name="a/b/C" since="1">
+ <extends name="java/lang/Object"/>
+ </class>
+
+ <class name="a/b/E" since="1">
+ <!-- extends will be modified -->
+ <extends name="a/b/C"/>
+ <!-- first parameter will be modified -->
+ <method name="dispatchGesture(La/b/C;Landroid/os/Handler;)Z" since="24"/>
+ <!-- second should remain untouched -->
+ <method name="dispatchGesture(Landroid/accessibilityservice/GestureDescription;Landroid/accessibilityservice/AccessibilityService$GestureRe
+sultCallback;Landroid/os/Handler;)Z" since="24"/>
+ </class>
+ </api>
+ """,
+ expected="""
+ <api version="2">
+ <class name="a/b/E" since="1">
+ <extends name="java/lang/Object"/>
+ <method name="dispatchGesture(Ljava/lang/Object;Landroid/os/Handler;)Z" since="24"/>
+ <method name="dispatchGesture(Landroid/accessibilityservice/GestureDescription;Landroid/accessibilityservice/AccessibilityService$GestureRe
+sultCallback;Landroid/os/Handler;)Z" since="24"/>
+ </class>
+ </api>
+ """)
+
+ def test_filter_lint_database_updates_method_signature_return(self):
+ self._run_filter_db_test(
+ database_str="""
+ <api version="2">
+ <!-- will be removed -->
+ <class name="a/b/C" since="1">
+ <extends name="java/lang/Object"/>
+ </class>
+
+ <class name="a/b/E" since="1">
+ <!-- extends will be modified -->
+ <extends name="a/b/C"/>
+ <!-- return type should be changed -->
+ <method name="gestureIdToString(I)La/b/C;" since="24"/>
+ </class>
+ </api>
+ """,
+ expected="""
+ <api version="2">
+ <class name="a/b/E" since="1">
+
+ <extends name="java/lang/Object"/>
+
+ <method name="gestureIdToString(I)Ljava/lang/Object;" since="24"/>
+ </class>
+ </api>
+ """)
+
+ def test_filter_lint_database_removes_implements(self):
+ self._run_filter_db_test(
+ database_str="""
+ <api version="2">
+ <!-- will be removed -->
+ <class name="a/b/C" since="1">
+ <extends name="java/lang/Object"/>
+ </class>
+
+ <class name="a/b/D" since="1">
+ <extends name="java/lang/Object"/>
+ <implements name="a/b/C"/>
+ <method name="dispatchGesture(Landroid/accessibilityservice/GestureDescription;Landroid/accessibilityservice/AccessibilityService$GestureRe
+sultCallback;Landroid/os/Handler;)Z" since="24"/>
+ </class>
+ </api>
+ """,
+ expected="""
+ <api version="2">
+
+ <class name="a/b/D" since="1">
+ <extends name="java/lang/Object"/>
+ <method name="dispatchGesture(Landroid/accessibilityservice/GestureDescription;Landroid/accessibilityservice/AccessibilityService$GestureRe
+sultCallback;Landroid/os/Handler;)Z" since="24"/>
+ </class>
+ </api>
+ """)
+
+ def test_filter_lint_database_updates_extends(self):
+ self._run_filter_db_test(
+ database_str="""
+ <api version="2">
+ <!-- will be removed -->
+ <class name="a/b/C" since="1">
+ <extends name="java/lang/Object"/>
+ </class>
+
+ <class name="a/b/E" since="1">
+ <!-- extends will be modified -->
+ <extends name="a/b/C"/>
+ <method name="dispatchGesture(Ljava/lang/Object;Landroid/os/Handler;)Z" since="24"/>
+ <method name="dispatchGesture(Landroid/accessibilityservice/GestureDescription;Landroid/accessibilityservice/AccessibilityService$GestureRe
+sultCallback;Landroid/os/Handler;)Z" since="24"/>
+ </class>
+ </api>
+ """,
+ expected="""
+ <api version="2">
+ <class name="a/b/E" since="1">
+ <extends name="java/lang/Object"/>
+ <method name="dispatchGesture(Ljava/lang/Object;Landroid/os/Handler;)Z" since="24"/>
+ <method name="dispatchGesture(Landroid/accessibilityservice/GestureDescription;Landroid/accessibilityservice/AccessibilityService$GestureRe
+sultCallback;Landroid/os/Handler;)Z" since="24"/>
+ </class>
+ </api>
+ """)
+
+ def test_filter_lint_database_removes_class(self):
+ self._run_filter_db_test(
+ database_str="""
+ <api version="2">
+ <!-- will be removed -->
+ <class name="a/b/C" since="1">
+ <extends name="java/lang/Object"/>
+ </class>
+
+ <class name="a/b/D" since="1">
+ <extends name="java/lang/Object"/>
+ <method name="dispatchGesture(Landroid/accessibilityservice/GestureDescription;Landroid/accessibilityservice/AccessibilityService$GestureRe
+sultCallback;Landroid/os/Handler;)Z" since="24"/>
+ </class>
+ </api>
+ """,
+ expected="""
+ <api version="2">
+
+ <class name="a/b/D" since="1">
+ <extends name="java/lang/Object"/>
+ <method name="dispatchGesture(Landroid/accessibilityservice/GestureDescription;Landroid/accessibilityservice/AccessibilityService$GestureRe
+sultCallback;Landroid/os/Handler;)Z" since="24"/>
+ </class>
+ </api>
+ """)
+
+
+if __name__ == "__main__":
+ unittest.main()
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index ba0bc555eb57..506dfe09f3fa 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -5606,14 +5606,24 @@ public class Notification implements Parcelable
final boolean snoozeEnabled = !hideSnoozeButton
&& mContext.getContentResolver() != null
- && (Settings.Secure.getInt(mContext.getContentResolver(),
- Settings.Secure.SHOW_NOTIFICATION_SNOOZE, 0) == 1);
+ && isSnoozeSettingEnabled();
if (snoozeEnabled) {
big.setViewLayoutMarginDimen(R.id.notification_action_list_margin_target,
RemoteViews.MARGIN_BOTTOM, 0);
}
}
+ private boolean isSnoozeSettingEnabled() {
+ try {
+ return Settings.Secure.getInt(mContext.getContentResolver(),
+ Settings.Secure.SHOW_NOTIFICATION_SNOOZE, 0) == 1;
+ } catch (SecurityException ex) {
+ // Most 3p apps can't access this snooze setting, so their NotificationListeners
+ // would be unable to create notification views if we propagated this exception.
+ return false;
+ }
+ }
+
/**
* Returns the actions that are not contextual.
*/
diff --git a/core/java/android/content/pm/IPackageInstaller.aidl b/core/java/android/content/pm/IPackageInstaller.aidl
index b0ce6a55e9ba..12911d6e1232 100644
--- a/core/java/android/content/pm/IPackageInstaller.aidl
+++ b/core/java/android/content/pm/IPackageInstaller.aidl
@@ -62,6 +62,8 @@ interface IPackageInstaller {
void bypassNextStagedInstallerCheck(boolean value);
+ void bypassNextAllowedApexUpdateCheck(boolean value);
+
void setAllowUnlimitedSilentUpdates(String installerPackageName);
void setSilentUpdatesThrottleTime(long throttleTimeInSeconds);
}
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index 33a34be1b968..2ed00b5d2982 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -1278,6 +1278,13 @@ public abstract class PackageManager {
*/
public static final int INSTALL_STAGED = 0x00200000;
+ /**
+ * Flag parameter for {@link #installPackage} to indicate that check whether given APEX can be
+ * updated should be disabled for this install.
+ * @hide
+ */
+ public static final int INSTALL_DISABLE_ALLOWED_APEX_UPDATE_CHECK = 0x00400000;
+
/** @hide */
@IntDef(flag = true, value = {
DONT_KILL_APP,
diff --git a/core/java/android/content/pm/parsing/ParsingPackageImpl.java b/core/java/android/content/pm/parsing/ParsingPackageImpl.java
index 4c44ba1fc9ef..5a7f21040d0a 100644
--- a/core/java/android/content/pm/parsing/ParsingPackageImpl.java
+++ b/core/java/android/content/pm/parsing/ParsingPackageImpl.java
@@ -1164,7 +1164,7 @@ public class ParsingPackageImpl implements ParsingPackage, Parcelable {
dest.writeTypedList(this.usesPermissions);
sForInternedStringList.parcel(this.implicitPermissions, dest, flags);
sForStringSet.parcel(this.upgradeKeySets, dest, flags);
- dest.writeMap(this.keySetMapping);
+ ParsingPackageUtils.writeKeySetMapping(dest, this.keySetMapping);
sForInternedStringList.parcel(this.protectedBroadcasts, dest, flags);
dest.writeTypedList(this.activities);
dest.writeTypedList(this.receivers);
@@ -1180,7 +1180,7 @@ public class ParsingPackageImpl implements ParsingPackage, Parcelable {
sForInternedString.parcel(this.volumeUuid, dest, flags);
dest.writeParcelable(this.signingDetails, flags);
dest.writeString(this.mPath);
- dest.writeParcelableList(this.queriesIntents, flags);
+ dest.writeTypedList(this.queriesIntents, flags);
sForInternedStringList.parcel(this.queriesPackages, dest, flags);
sForInternedStringSet.parcel(this.queriesProviders, dest, flags);
dest.writeString(this.appComponentFactory);
@@ -1287,7 +1287,7 @@ public class ParsingPackageImpl implements ParsingPackage, Parcelable {
this.usesPermissions = in.createTypedArrayList(ParsedUsesPermission.CREATOR);
this.implicitPermissions = sForInternedStringList.unparcel(in);
this.upgradeKeySets = sForStringSet.unparcel(in);
- this.keySetMapping = in.readHashMap(boot);
+ this.keySetMapping = ParsingPackageUtils.readKeySetMapping(in);
this.protectedBroadcasts = sForInternedStringList.unparcel(in);
this.activities = in.createTypedArrayList(ParsedActivity.CREATOR);
diff --git a/core/java/android/content/pm/parsing/ParsingPackageUtils.java b/core/java/android/content/pm/parsing/ParsingPackageUtils.java
index 6fd533355aad..dce242c9d87c 100644
--- a/core/java/android/content/pm/parsing/ParsingPackageUtils.java
+++ b/core/java/android/content/pm/parsing/ParsingPackageUtils.java
@@ -87,6 +87,7 @@ import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.FileUtils;
+import android.os.Parcel;
import android.os.RemoteException;
import android.os.Trace;
import android.os.UserHandle;
@@ -3160,6 +3161,68 @@ public class ParsingPackageUtils {
}
/**
+ * Writes the keyset mapping to the provided package. {@code null} mappings are permitted.
+ */
+ public static void writeKeySetMapping(@NonNull Parcel dest,
+ @NonNull Map<String, ArraySet<PublicKey>> keySetMapping) {
+ if (keySetMapping == null) {
+ dest.writeInt(-1);
+ return;
+ }
+
+ final int N = keySetMapping.size();
+ dest.writeInt(N);
+
+ for (String key : keySetMapping.keySet()) {
+ dest.writeString(key);
+ ArraySet<PublicKey> keys = keySetMapping.get(key);
+ if (keys == null) {
+ dest.writeInt(-1);
+ continue;
+ }
+
+ final int M = keys.size();
+ dest.writeInt(M);
+ for (int j = 0; j < M; j++) {
+ dest.writeSerializable(keys.valueAt(j));
+ }
+ }
+ }
+
+ /**
+ * Reads a keyset mapping from the given parcel at the given data position. May return
+ * {@code null} if the serialized mapping was {@code null}.
+ */
+ @NonNull
+ public static ArrayMap<String, ArraySet<PublicKey>> readKeySetMapping(@NonNull Parcel in) {
+ final int N = in.readInt();
+ if (N == -1) {
+ return null;
+ }
+
+ ArrayMap<String, ArraySet<PublicKey>> keySetMapping = new ArrayMap<>();
+ for (int i = 0; i < N; ++i) {
+ String key = in.readString();
+ final int M = in.readInt();
+ if (M == -1) {
+ keySetMapping.put(key, null);
+ continue;
+ }
+
+ ArraySet<PublicKey> keys = new ArraySet<>(M);
+ for (int j = 0; j < M; ++j) {
+ PublicKey pk = (PublicKey) in.readSerializable();
+ keys.add(pk);
+ }
+
+ keySetMapping.put(key, keys);
+ }
+
+ return keySetMapping;
+ }
+
+
+ /**
* Callback interface for retrieving information that may be needed while parsing
* a package.
*/
diff --git a/core/java/android/content/pm/parsing/component/ParsedComponent.java b/core/java/android/content/pm/parsing/component/ParsedComponent.java
index 4aed77ae641b..9d830ec7a227 100644
--- a/core/java/android/content/pm/parsing/component/ParsedComponent.java
+++ b/core/java/android/content/pm/parsing/component/ParsedComponent.java
@@ -172,7 +172,7 @@ public abstract class ParsedComponent implements Parcelable {
this.packageName = sForInternedString.unparcel(in);
this.intents = sForIntentInfos.unparcel(in);
this.metaData = in.readBundle(boot);
- this.mProperties = in.createTypedArrayMap(Property.CREATOR);
+ this.mProperties = in.readHashMap(boot);
}
@NonNull
diff --git a/core/java/android/hardware/biometrics/BiometricFingerprintConstants.java b/core/java/android/hardware/biometrics/BiometricFingerprintConstants.java
index 2d46a4073809..e665d0fcc836 100644
--- a/core/java/android/hardware/biometrics/BiometricFingerprintConstants.java
+++ b/core/java/android/hardware/biometrics/BiometricFingerprintConstants.java
@@ -208,7 +208,8 @@ public interface BiometricFingerprintConstants {
FINGERPRINT_ACQUIRED_TOO_FAST,
FINGERPRINT_ACQUIRED_VENDOR,
FINGERPRINT_ACQUIRED_START,
- FINGERPRINT_ACQUIRED_UNKNOWN})
+ FINGERPRINT_ACQUIRED_UNKNOWN,
+ FINGERPRINT_ACQUIRED_IMMOBILE})
@Retention(RetentionPolicy.SOURCE)
@interface FingerprintAcquired {}
@@ -278,6 +279,14 @@ public interface BiometricFingerprintConstants {
int FINGERPRINT_ACQUIRED_UNKNOWN = 8;
/**
+ * This message may be sent during enrollment if the same area of the finger has already
+ * been captured during this enrollment session. In general, enrolling multiple areas of the
+ * same finger can help against false rejections.
+ * @hide
+ */
+ int FINGERPRINT_ACQUIRED_IMMOBILE = 9;
+
+ /**
* @hide
*/
int FINGERPRINT_ACQUIRED_VENDOR_BASE = 1000;
diff --git a/core/java/android/hardware/fingerprint/FingerprintManager.java b/core/java/android/hardware/fingerprint/FingerprintManager.java
index 688f9f1174dd..0819835f5fb5 100644
--- a/core/java/android/hardware/fingerprint/FingerprintManager.java
+++ b/core/java/android/hardware/fingerprint/FingerprintManager.java
@@ -1417,6 +1417,9 @@ public class FingerprintManager implements BiometricAuthenticator, BiometricFing
case FINGERPRINT_ACQUIRED_TOO_FAST:
return context.getString(
com.android.internal.R.string.fingerprint_acquired_too_fast);
+ case FINGERPRINT_ACQUIRED_IMMOBILE:
+ return context.getString(
+ com.android.internal.R.string.fingerprint_acquired_immobile);
case FINGERPRINT_ACQUIRED_VENDOR: {
String[] msgArray = context.getResources().getStringArray(
com.android.internal.R.array.fingerprint_acquired_vendor);
diff --git a/core/java/android/hardware/input/InputDeviceVibrator.java b/core/java/android/hardware/input/InputDeviceVibrator.java
index d8150e483fd6..653c622386d6 100644
--- a/core/java/android/hardware/input/InputDeviceVibrator.java
+++ b/core/java/android/hardware/input/InputDeviceVibrator.java
@@ -56,10 +56,10 @@ final class InputDeviceVibrator extends Vibrator {
mDeviceId = deviceId;
mVibratorInfo = new VibratorInfo.Builder(vibratorId)
.setCapabilities(IVibrator.CAP_AMPLITUDE_CONTROL)
- // Set predefined support to empty as we know input devices do not support them.
- .setSupportedEffects()
- .setSupportedPrimitives()
- .setSupportedBraking()
+ // The supported effect and braking lists are known to be empty for input devices,
+ // which is different from not being set (that means the device support is unknown).
+ .setSupportedEffects(new int[0])
+ .setSupportedBraking(new int[0])
.build();
mToken = new Binder();
}
diff --git a/core/java/android/net/VpnManager.java b/core/java/android/net/VpnManager.java
index 662ebb356f4c..5c2855307509 100644
--- a/core/java/android/net/VpnManager.java
+++ b/core/java/android/net/VpnManager.java
@@ -389,6 +389,10 @@ public class VpnManager {
/**
* Starts a legacy VPN.
+ *
+ * Legacy VPN is deprecated starting from Android S. So this API shouldn't be called if the
+ * initial SDK version of device is Android S+. Otherwise, UnsupportedOperationException will be
+ * thrown.
* @hide
*/
public void startLegacyVpn(VpnProfile profile) {
diff --git a/core/java/android/os/Vibrator.java b/core/java/android/os/Vibrator.java
index 12538e6cd46b..d7893e4bbefd 100644
--- a/core/java/android/os/Vibrator.java
+++ b/core/java/android/os/Vibrator.java
@@ -126,6 +126,7 @@ public abstract class Vibrator {
// The default vibration intensity level for ringtones.
@VibrationIntensity
private int mDefaultRingVibrationIntensity;
+ private float mHapticChannelMaxVibrationAmplitude;
/**
* @hide to prevent subclassing from outside of the framework
@@ -134,7 +135,7 @@ public abstract class Vibrator {
public Vibrator() {
mPackageName = ActivityThread.currentPackageName();
final Context ctx = ActivityThread.currentActivityThread().getSystemContext();
- loadVibrationIntensities(ctx);
+ loadVibrationConfig(ctx);
}
/**
@@ -142,22 +143,28 @@ public abstract class Vibrator {
*/
protected Vibrator(Context context) {
mPackageName = context.getOpPackageName();
- loadVibrationIntensities(context);
+ loadVibrationConfig(context);
}
- private void loadVibrationIntensities(Context context) {
+ private void loadVibrationConfig(Context context) {
mDefaultHapticFeedbackIntensity = loadDefaultIntensity(context,
com.android.internal.R.integer.config_defaultHapticFeedbackIntensity);
mDefaultNotificationVibrationIntensity = loadDefaultIntensity(context,
com.android.internal.R.integer.config_defaultNotificationVibrationIntensity);
mDefaultRingVibrationIntensity = loadDefaultIntensity(context,
com.android.internal.R.integer.config_defaultRingVibrationIntensity);
+ mHapticChannelMaxVibrationAmplitude = loadFloat(context,
+ com.android.internal.R.dimen.config_hapticChannelMaxVibrationAmplitude, 0);
}
private int loadDefaultIntensity(Context ctx, int resId) {
return ctx != null ? ctx.getResources().getInteger(resId) : VIBRATION_INTENSITY_MEDIUM;
}
+ private float loadFloat(Context ctx, int resId, float defaultValue) {
+ return ctx != null ? ctx.getResources().getFloat(resId) : defaultValue;
+ }
+
/** @hide */
protected VibratorInfo getInfo() {
return VibratorInfo.EMPTY_VIBRATOR_INFO;
@@ -297,6 +304,24 @@ public abstract class Vibrator {
}
/**
+ * Return the maximum amplitude the vibrator can play using the audio haptic channels.
+ *
+ * <p>This is a positive value, or {@link Float#NaN NaN} if it's unknown. If this returns a
+ * positive value <code>maxAmplitude</code>, then the signals from the haptic channels of audio
+ * tracks should be in the range <code>[-maxAmplitude, maxAmplitude]</code>.
+ *
+ * @return a positive value representing the maximum absolute value the device can play signals
+ * from audio haptic channels, or {@link Float#NaN NaN} if it's unknown.
+ * @hide
+ */
+ public float getHapticChannelMaximumAmplitude() {
+ if (mHapticChannelMaxVibrationAmplitude <= 0) {
+ return Float.NaN;
+ }
+ return mHapticChannelMaxVibrationAmplitude;
+ }
+
+ /**
* Configure an always-on haptics effect.
*
* @param alwaysOnId The board-specific always-on ID to configure.
diff --git a/core/java/android/os/VibratorInfo.java b/core/java/android/os/VibratorInfo.java
index 597df0811e20..486f9f139e0a 100644
--- a/core/java/android/os/VibratorInfo.java
+++ b/core/java/android/os/VibratorInfo.java
@@ -51,8 +51,11 @@ public class VibratorInfo implements Parcelable {
private final SparseBooleanArray mSupportedEffects;
@Nullable
private final SparseBooleanArray mSupportedBraking;
- @Nullable
private final SparseIntArray mSupportedPrimitives;
+ private final int mPrimitiveDelayMax;
+ private final int mCompositionSizeMax;
+ private final int mPwlePrimitiveDurationMax;
+ private final int mPwleSizeMax;
private final float mQFactor;
private final FrequencyMapping mFrequencyMapping;
@@ -62,6 +65,10 @@ public class VibratorInfo implements Parcelable {
mSupportedEffects = in.readSparseBooleanArray();
mSupportedBraking = in.readSparseBooleanArray();
mSupportedPrimitives = in.readSparseIntArray();
+ mPrimitiveDelayMax = in.readInt();
+ mCompositionSizeMax = in.readInt();
+ mPwlePrimitiveDurationMax = in.readInt();
+ mPwleSizeMax = in.readInt();
mQFactor = in.readFloat();
mFrequencyMapping = in.readParcelable(VibratorInfo.class.getClassLoader());
}
@@ -69,48 +76,50 @@ public class VibratorInfo implements Parcelable {
/**
* Default constructor.
*
- * @param id The vibrator id.
- * @param capabilities All capability flags of the vibrator, defined in IVibrator.CAP_*.
- * @param supportedEffects All supported predefined effects, enum values from {@link
- * android.hardware.vibrator.Effect}.
- * @param supportedBraking All supported braking types, enum values from {@link Braking}.
- * @param supportedPrimitives All supported primitive effects, enum values from {@link
- * android.hardware.vibrator.CompositePrimitive}.
- * @param primitiveDurations A mapping of primitive durations, where indexes are enum values
- * from {@link android.hardware.vibrator.CompositePrimitive} and the
- * values are estimated durations in milliseconds.
- * @param qFactor The vibrator quality factor.
- * @param frequencyMapping The description of the vibrator supported frequencies and max
- * amplitude mappings.
+ * @param id The vibrator id.
+ * @param capabilities All capability flags of the vibrator, defined in
+ * IVibrator.CAP_*.
+ * @param supportedEffects All supported predefined effects, enum values from
+ * {@link android.hardware.vibrator.Effect}.
+ * @param supportedBraking All supported braking types, enum values from {@link
+ * Braking}.
+ * @param supportedPrimitives All supported primitive effects, key are enum values from
+ * {@link android.hardware.vibrator.CompositePrimitive} and
+ * values are estimated durations in milliseconds.
+ * @param primitiveDelayMax The maximum delay that can be set to a composition primitive
+ * in milliseconds.
+ * @param compositionSizeMax The maximum number of primitives supported by a composition.
+ * @param pwlePrimitiveDurationMax The maximum duration of a PWLE primitive in milliseconds.
+ * @param pwleSizeMax The maximum number of primitives supported by a PWLE
+ * composition.
+ * @param qFactor The vibrator quality factor.
+ * @param frequencyMapping The description of the vibrator supported frequencies and max
+ * amplitude mappings.
* @hide
*/
- public VibratorInfo(int id, long capabilities, int[] supportedEffects, int[] supportedBraking,
- int[] supportedPrimitives, int[] primitiveDurations, float qFactor,
- @NonNull FrequencyMapping frequencyMapping) {
+ public VibratorInfo(int id, long capabilities, @Nullable SparseBooleanArray supportedEffects,
+ @Nullable SparseBooleanArray supportedBraking,
+ @NonNull SparseIntArray supportedPrimitives, int primitiveDelayMax,
+ int compositionSizeMax, int pwlePrimitiveDurationMax, int pwleSizeMax,
+ float qFactor, @NonNull FrequencyMapping frequencyMapping) {
mId = id;
mCapabilities = capabilities;
- mSupportedEffects = toSparseBooleanArray(supportedEffects);
- mSupportedBraking = toSparseBooleanArray(supportedBraking);
- mSupportedPrimitives = toSparseIntArray(supportedPrimitives, primitiveDurations);
+ mSupportedEffects = supportedEffects == null ? null : supportedEffects.clone();
+ mSupportedBraking = supportedBraking == null ? null : supportedBraking.clone();
+ mSupportedPrimitives = supportedPrimitives.clone();
+ mPrimitiveDelayMax = primitiveDelayMax;
+ mCompositionSizeMax = compositionSizeMax;
+ mPwlePrimitiveDurationMax = pwlePrimitiveDurationMax;
+ mPwleSizeMax = pwleSizeMax;
mQFactor = qFactor;
mFrequencyMapping = frequencyMapping;
}
protected VibratorInfo(int id, int capabilities, VibratorInfo baseVibrator) {
- mId = id;
- mCapabilities = capabilities;
- mSupportedEffects = baseVibrator.mSupportedEffects == null ? null :
- baseVibrator.mSupportedEffects.clone();
- mSupportedBraking = baseVibrator.mSupportedBraking == null ? null :
- baseVibrator.mSupportedBraking.clone();
- mSupportedPrimitives = baseVibrator.mSupportedPrimitives == null ? null :
- baseVibrator.mSupportedPrimitives.clone();
- mQFactor = baseVibrator.mQFactor;
- mFrequencyMapping = new FrequencyMapping(baseVibrator.mFrequencyMapping.mMinFrequencyHz,
- baseVibrator.mFrequencyMapping.mResonantFrequencyHz,
- baseVibrator.mFrequencyMapping.mFrequencyResolutionHz,
- baseVibrator.mFrequencyMapping.mSuggestedSafeRangeHz,
- baseVibrator.mFrequencyMapping.mMaxAmplitudes);
+ this(id, capabilities, baseVibrator.mSupportedEffects, baseVibrator.mSupportedBraking,
+ baseVibrator.mSupportedPrimitives, baseVibrator.mPrimitiveDelayMax,
+ baseVibrator.mCompositionSizeMax, baseVibrator.mPwlePrimitiveDurationMax,
+ baseVibrator.mPwleSizeMax, baseVibrator.mQFactor, baseVibrator.mFrequencyMapping);
}
@Override
@@ -120,6 +129,10 @@ public class VibratorInfo implements Parcelable {
dest.writeSparseBooleanArray(mSupportedEffects);
dest.writeSparseBooleanArray(mSupportedBraking);
dest.writeSparseIntArray(mSupportedPrimitives);
+ dest.writeInt(mPrimitiveDelayMax);
+ dest.writeInt(mCompositionSizeMax);
+ dest.writeInt(mPwlePrimitiveDurationMax);
+ dest.writeInt(mPwleSizeMax);
dest.writeFloat(mQFactor);
dest.writeParcelable(mFrequencyMapping, flags);
}
@@ -138,24 +151,23 @@ public class VibratorInfo implements Parcelable {
return false;
}
VibratorInfo that = (VibratorInfo) o;
- if (mSupportedPrimitives == null || that.mSupportedPrimitives == null) {
- if (mSupportedPrimitives != that.mSupportedPrimitives) {
+ int supportedPrimitivesCount = mSupportedPrimitives.size();
+ if (supportedPrimitivesCount != that.mSupportedPrimitives.size()) {
+ return false;
+ }
+ for (int i = 0; i < supportedPrimitivesCount; i++) {
+ if (mSupportedPrimitives.keyAt(i) != that.mSupportedPrimitives.keyAt(i)) {
return false;
}
- } else {
- if (mSupportedPrimitives.size() != that.mSupportedPrimitives.size()) {
+ if (mSupportedPrimitives.valueAt(i) != that.mSupportedPrimitives.valueAt(i)) {
return false;
}
- for (int i = 0; i < mSupportedPrimitives.size(); i++) {
- if (mSupportedPrimitives.keyAt(i) != that.mSupportedPrimitives.keyAt(i)) {
- return false;
- }
- if (mSupportedPrimitives.valueAt(i) != that.mSupportedPrimitives.valueAt(i)) {
- return false;
- }
- }
}
return mId == that.mId && mCapabilities == that.mCapabilities
+ && mPrimitiveDelayMax == that.mPrimitiveDelayMax
+ && mCompositionSizeMax == that.mCompositionSizeMax
+ && mPwlePrimitiveDurationMax == that.mPwlePrimitiveDurationMax
+ && mPwleSizeMax == that.mPwleSizeMax
&& Objects.equals(mSupportedEffects, that.mSupportedEffects)
&& Objects.equals(mSupportedBraking, that.mSupportedBraking)
&& Objects.equals(mQFactor, that.mQFactor)
@@ -166,11 +178,9 @@ public class VibratorInfo implements Parcelable {
public int hashCode() {
int hashCode = Objects.hash(mId, mCapabilities, mSupportedEffects, mSupportedBraking,
mQFactor, mFrequencyMapping);
- if (mSupportedPrimitives != null) {
- for (int i = 0; i < mSupportedPrimitives.size(); i++) {
- hashCode = 31 * hashCode + mSupportedPrimitives.keyAt(i);
- hashCode = 31 * hashCode + mSupportedPrimitives.valueAt(i);
- }
+ for (int i = 0; i < mSupportedPrimitives.size(); i++) {
+ hashCode = 31 * hashCode + mSupportedPrimitives.keyAt(i);
+ hashCode = 31 * hashCode + mSupportedPrimitives.valueAt(i);
}
return hashCode;
}
@@ -184,6 +194,10 @@ public class VibratorInfo implements Parcelable {
+ ", mSupportedEffects=" + Arrays.toString(getSupportedEffectsNames())
+ ", mSupportedBraking=" + Arrays.toString(getSupportedBrakingNames())
+ ", mSupportedPrimitives=" + Arrays.toString(getSupportedPrimitivesNames())
+ + ", mPrimitiveDelayMax=" + mPrimitiveDelayMax
+ + ", mCompositionSizeMax=" + mCompositionSizeMax
+ + ", mPwlePrimitiveDurationMax=" + mPwlePrimitiveDurationMax
+ + ", mPwleSizeMax=" + mPwleSizeMax
+ ", mQFactor=" + mQFactor
+ ", mFrequencyMapping=" + mFrequencyMapping
+ '}';
@@ -247,7 +261,7 @@ public class VibratorInfo implements Parcelable {
*/
public boolean isPrimitiveSupported(
@VibrationEffect.Composition.PrimitiveType int primitiveId) {
- return hasCapability(IVibrator.CAP_COMPOSE_EFFECTS) && mSupportedPrimitives != null
+ return hasCapability(IVibrator.CAP_COMPOSE_EFFECTS)
&& (mSupportedPrimitives.indexOfKey(primitiveId) >= 0);
}
@@ -260,7 +274,43 @@ public class VibratorInfo implements Parcelable {
*/
public int getPrimitiveDuration(
@VibrationEffect.Composition.PrimitiveType int primitiveId) {
- return mSupportedPrimitives != null ? mSupportedPrimitives.get(primitiveId) : 0;
+ return mSupportedPrimitives.get(primitiveId);
+ }
+
+ /**
+ * Query the maximum delay supported for a primitive in a composed effect.
+ *
+ * @return The max delay in milliseconds, or zero if unlimited.
+ */
+ public int getPrimitiveDelayMax() {
+ return mPrimitiveDelayMax;
+ }
+
+ /**
+ * Query the maximum number of primitives supported in a composed effect.
+ *
+ * @return The max number of primitives supported, or zero if unlimited.
+ */
+ public int getCompositionSizeMax() {
+ return mCompositionSizeMax;
+ }
+
+ /**
+ * Query the maximum duration supported for a primitive in a PWLE composition.
+ *
+ * @return The max duration in milliseconds, or zero if unlimited.
+ */
+ public int getPwlePrimitiveDurationMax() {
+ return mPwlePrimitiveDurationMax;
+ }
+
+ /**
+ * Query the maximum number of primitives supported in a PWLE composition.
+ *
+ * @return The max number of primitives supported, or zero if unlimited.
+ */
+ public int getPwleSizeMax() {
+ return mPwleSizeMax;
}
/**
@@ -408,52 +458,15 @@ public class VibratorInfo implements Parcelable {
}
private String[] getSupportedPrimitivesNames() {
- if (mSupportedPrimitives == null) {
- return new String[0];
- }
- String[] names = new String[mSupportedPrimitives.size()];
- for (int i = 0; i < mSupportedPrimitives.size(); i++) {
+ int supportedPrimitivesCount = mSupportedPrimitives.size();
+ String[] names = new String[supportedPrimitivesCount];
+ for (int i = 0; i < supportedPrimitivesCount; i++) {
names[i] = VibrationEffect.Composition.primitiveToString(mSupportedPrimitives.keyAt(i));
}
return names;
}
/**
- * Create a {@link SparseBooleanArray} from given {@code supportedKeys} where each key is mapped
- * to {@code true}.
- */
- @Nullable
- private static SparseBooleanArray toSparseBooleanArray(int[] supportedKeys) {
- if (supportedKeys == null) {
- return null;
- }
- SparseBooleanArray array = new SparseBooleanArray();
- for (int key : supportedKeys) {
- array.put(key, true);
- }
- return array;
- }
-
- /**
- * Create a {@link SparseIntArray} from given {@code supportedKeys} where each key is mapped
- * to the value indexed by it.
- *
- * <p>If {@code values} is null or does not contain a given key as a index, then zero is stored
- * to the sparse array so it can still be used to query the supported keys.
- */
- @Nullable
- private static SparseIntArray toSparseIntArray(int[] supportedKeys, int[] values) {
- if (supportedKeys == null) {
- return null;
- }
- SparseIntArray array = new SparseIntArray();
- for (int key : supportedKeys) {
- array.put(key, (values == null || key >= values.length) ? 0 : values[key]);
- }
- return array;
- }
-
- /**
* Describes how frequency should be mapped to absolute values for a specific {@link Vibrator}.
*
* <p>This mapping is defined by the following parameters:
@@ -675,11 +688,14 @@ public class VibratorInfo implements Parcelable {
/** @hide */
public static final class Builder {
private final int mId;
- private int mCapabilities = 0;
- private int[] mSupportedEffects = null;
- private int[] mSupportedBraking = null;
- private int[] mSupportedPrimitives = null;
- private int[] mPrimitiveDurations = new int[0];
+ private long mCapabilities;
+ private SparseBooleanArray mSupportedEffects;
+ private SparseBooleanArray mSupportedBraking;
+ private SparseIntArray mSupportedPrimitives = new SparseIntArray();
+ private int mPrimitiveDelayMax;
+ private int mCompositionSizeMax;
+ private int mPwlePrimitiveDurationMax;
+ private int mPwleSizeMax;
private float mQFactor = Float.NaN;
private FrequencyMapping mFrequencyMapping =
new FrequencyMapping(Float.NaN, Float.NaN, Float.NaN, Float.NaN, null);
@@ -691,7 +707,7 @@ public class VibratorInfo implements Parcelable {
/** Configure the vibrator capabilities with a combination of IVibrator.CAP_* values. */
@NonNull
- public Builder setCapabilities(int capabilities) {
+ public Builder setCapabilities(long capabilities) {
mCapabilities = capabilities;
return this;
}
@@ -699,34 +715,49 @@ public class VibratorInfo implements Parcelable {
/** Configure the effects supported with {@link android.hardware.vibrator.Effect} values. */
@NonNull
public Builder setSupportedEffects(int... supportedEffects) {
- mSupportedEffects = supportedEffects;
+ mSupportedEffects = toSparseBooleanArray(supportedEffects);
return this;
}
/** Configure braking supported with {@link android.hardware.vibrator.Braking} values. */
@NonNull
public Builder setSupportedBraking(int... supportedBraking) {
- mSupportedBraking = supportedBraking;
+ mSupportedBraking = toSparseBooleanArray(supportedBraking);
return this;
}
- /**
- * Configure the primitives supported with
- * {@link android.hardware.vibrator.CompositePrimitive} values.
- */
+ /** Configure maximum duration, in milliseconds, of a PWLE primitive. */
+ @NonNull
+ public Builder setPwlePrimitiveDurationMax(int pwlePrimitiveDurationMax) {
+ mPwlePrimitiveDurationMax = pwlePrimitiveDurationMax;
+ return this;
+ }
+
+ /** Configure maximum number of primitives supported in a single PWLE composed effect. */
@NonNull
- public Builder setSupportedPrimitives(int... supportedPrimitives) {
- mSupportedPrimitives = supportedPrimitives;
+ public Builder setPwleSizeMax(int pwleSizeMax) {
+ mPwleSizeMax = pwleSizeMax;
return this;
}
/** Configure the duration of a {@link android.hardware.vibrator.CompositePrimitive}. */
@NonNull
- public Builder setPrimitiveDuration(int primitiveId, int duration) {
- if (mPrimitiveDurations.length <= primitiveId) {
- mPrimitiveDurations = Arrays.copyOf(mPrimitiveDurations, primitiveId + 1);
- }
- mPrimitiveDurations[primitiveId] = duration;
+ public Builder setSupportedPrimitive(int primitiveId, int duration) {
+ mSupportedPrimitives.put(primitiveId, duration);
+ return this;
+ }
+
+ /** Configure maximum delay, in milliseconds, supported in a composed effect primitive. */
+ @NonNull
+ public Builder setPrimitiveDelayMax(int primitiveDelayMax) {
+ mPrimitiveDelayMax = primitiveDelayMax;
+ return this;
+ }
+
+ /** Configure maximum number of primitives supported in a single composed effect. */
+ @NonNull
+ public Builder setCompositionSizeMax(int compositionSizeMax) {
+ mCompositionSizeMax = compositionSizeMax;
return this;
}
@@ -748,7 +779,25 @@ public class VibratorInfo implements Parcelable {
@NonNull
public VibratorInfo build() {
return new VibratorInfo(mId, mCapabilities, mSupportedEffects, mSupportedBraking,
- mSupportedPrimitives, mPrimitiveDurations, mQFactor, mFrequencyMapping);
+ mSupportedPrimitives, mPrimitiveDelayMax, mCompositionSizeMax,
+ mPwlePrimitiveDurationMax, mPwleSizeMax, mQFactor, mFrequencyMapping);
+ }
+
+ /**
+ * Create a {@link SparseBooleanArray} from given {@code supportedKeys} where each key is
+ * mapped
+ * to {@code true}.
+ */
+ @Nullable
+ private static SparseBooleanArray toSparseBooleanArray(int[] supportedKeys) {
+ if (supportedKeys == null) {
+ return null;
+ }
+ SparseBooleanArray array = new SparseBooleanArray();
+ for (int key : supportedKeys) {
+ array.put(key, true);
+ }
+ return array;
}
}
diff --git a/core/java/android/security/keymaster/KeymasterDefs.java b/core/java/android/security/keymaster/KeymasterDefs.java
index 0b11aeb1ed65..3b4f7e241852 100644
--- a/core/java/android/security/keymaster/KeymasterDefs.java
+++ b/core/java/android/security/keymaster/KeymasterDefs.java
@@ -124,7 +124,6 @@ public final class KeymasterDefs {
public static final int KM_TAG_DEVICE_UNIQUE_ATTESTATION =
Tag.DEVICE_UNIQUE_ATTESTATION; // KM_BOOL | 720;
- public static final int KM_TAG_ASSOCIATED_DATA = Tag.ASSOCIATED_DATA; // KM_BYTES | 1000;
public static final int KM_TAG_NONCE = Tag.NONCE; // KM_BYTES | 1001;
public static final int KM_TAG_MAC_LENGTH = Tag.MAC_LENGTH; // KM_UINT | 1003;
public static final int KM_TAG_RESET_SINCE_ID_ROTATION =
diff --git a/core/java/android/service/voice/AlwaysOnHotwordDetector.java b/core/java/android/service/voice/AlwaysOnHotwordDetector.java
index 67b97cee1b51..41374167cc56 100644
--- a/core/java/android/service/voice/AlwaysOnHotwordDetector.java
+++ b/core/java/android/service/voice/AlwaysOnHotwordDetector.java
@@ -263,6 +263,7 @@ public class AlwaysOnHotwordDetector extends AbstractHotwordDetector {
private static final int MSG_DETECTION_RESUME = 5;
private static final int MSG_HOTWORD_REJECTED = 6;
private static final int MSG_HOTWORD_STATUS_REPORTED = 7;
+ private static final int MSG_PROCESS_RESTARTED = 8;
private final String mText;
private final Locale mLocale;
@@ -1212,6 +1213,12 @@ public class AlwaysOnHotwordDetector extends AbstractHotwordDetector {
message.arg1 = status;
message.sendToTarget();
}
+
+ @Override
+ public void onProcessRestarted() {
+ Slog.i(TAG, "onProcessRestarted");
+ mHandler.sendEmptyMessage(MSG_PROCESS_RESTARTED);
+ }
}
class MyHandler extends Handler {
@@ -1246,6 +1253,9 @@ public class AlwaysOnHotwordDetector extends AbstractHotwordDetector {
case MSG_HOTWORD_STATUS_REPORTED:
mExternalCallback.onHotwordDetectionServiceInitialized(msg.arg1);
break;
+ case MSG_PROCESS_RESTARTED:
+ mExternalCallback.onHotwordDetectionServiceRestarted();
+ break;
default:
super.handleMessage(msg);
}
diff --git a/core/java/android/service/voice/HotwordDetectionService.java b/core/java/android/service/voice/HotwordDetectionService.java
index b66d93d6316e..93a7ec793536 100644
--- a/core/java/android/service/voice/HotwordDetectionService.java
+++ b/core/java/android/service/voice/HotwordDetectionService.java
@@ -291,9 +291,7 @@ public abstract class HotwordDetectionService extends Service {
@Nullable PersistableBundle options,
@Nullable SharedMemory sharedMemory,
@DurationMillisLong long callbackTimeoutMillis,
- @Nullable IntConsumer statusCallback) {
- // TODO: Handle the unimplemented case by throwing?
- }
+ @Nullable IntConsumer statusCallback) {}
/**
* Called when the {@link VoiceInteractionService} requests that this service
diff --git a/core/java/android/service/voice/SoftwareHotwordDetector.java b/core/java/android/service/voice/SoftwareHotwordDetector.java
index 204e7df89706..fb540b1622e6 100644
--- a/core/java/android/service/voice/SoftwareHotwordDetector.java
+++ b/core/java/android/service/voice/SoftwareHotwordDetector.java
@@ -122,7 +122,7 @@ class SoftwareHotwordDetector extends AbstractHotwordDetector {
this.mCallback = callback;
}
- /** TODO: onDetected */
+ /** Called when the detected result is valid. */
@Override
public void onDetected(
@Nullable HotwordDetectedResult hotwordDetectedResult,
@@ -150,33 +150,45 @@ class SoftwareHotwordDetector extends AbstractHotwordDetector {
public void onKeyphraseDetected(
SoundTrigger.KeyphraseRecognitionEvent recognitionEvent,
HotwordDetectedResult result) {
-
+ if (DEBUG) {
+ Slog.i(TAG, "Ignored #onKeyphraseDetected event");
+ }
}
@Override
public void onGenericSoundTriggerDetected(
SoundTrigger.GenericRecognitionEvent recognitionEvent) throws RemoteException {
-
+ if (DEBUG) {
+ Slog.i(TAG, "Ignored #onGenericSoundTriggerDetected event");
+ }
}
@Override
public void onRejected(HotwordRejectedResult result) throws RemoteException {
-
+ if (DEBUG) {
+ Slog.i(TAG, "Ignored #onRejected event");
+ }
}
@Override
public void onError(int status) throws RemoteException {
-
+ if (DEBUG) {
+ Slog.i(TAG, "Ignored #onError (" + status + ") event");
+ }
}
@Override
public void onRecognitionPaused() throws RemoteException {
-
+ if (DEBUG) {
+ Slog.i(TAG, "Ignored #onRecognitionPaused event");
+ }
}
@Override
public void onRecognitionResumed() throws RemoteException {
-
+ if (DEBUG) {
+ Slog.i(TAG, "Ignored #onRecognitionResumed event");
+ }
}
@Override
@@ -187,6 +199,14 @@ class SoftwareHotwordDetector extends AbstractHotwordDetector {
mCallback,
status));
}
+
+ @Override
+ public void onProcessRestarted() throws RemoteException {
+ Slog.v(TAG, "onProcessRestarted()");
+ mHandler.sendMessage(obtainMessage(
+ HotwordDetector.Callback::onHotwordDetectionServiceRestarted,
+ mCallback));
+ }
}
/** @hide */
diff --git a/core/java/android/view/contentcapture/ContentCaptureEvent.java b/core/java/android/view/contentcapture/ContentCaptureEvent.java
index 10ae69118f54..ce6d034c585e 100644
--- a/core/java/android/view/contentcapture/ContentCaptureEvent.java
+++ b/core/java/android/view/contentcapture/ContentCaptureEvent.java
@@ -286,6 +286,15 @@ public final class ContentCaptureEvent implements Parcelable {
return this;
}
+ boolean hasSameComposingSpan(@NonNull ContentCaptureEvent other) {
+ return mComposingStart == other.mComposingStart && mComposingEnd == other.mComposingEnd;
+ }
+
+ boolean hasSameSelectionSpan(@NonNull ContentCaptureEvent other) {
+ return mSelectionStartIndex == other.mSelectionStartIndex
+ && mSelectionEndIndex == other.mSelectionEndIndex;
+ }
+
private int getComposingStart() {
return mComposingStart;
}
diff --git a/core/java/android/view/contentcapture/MainContentCaptureSession.java b/core/java/android/view/contentcapture/MainContentCaptureSession.java
index bcb914208958..7ec9d34bd364 100644
--- a/core/java/android/view/contentcapture/MainContentCaptureSession.java
+++ b/core/java/android/view/contentcapture/MainContentCaptureSession.java
@@ -368,7 +368,10 @@ public final class MainContentCaptureSession extends ContentCaptureSession {
final CharSequence lastText = lastEvent.getText();
final boolean bothNonEmpty = !TextUtils.isEmpty(lastText)
&& !TextUtils.isEmpty(text);
- boolean equalContent = TextUtils.equals(lastText, text);
+ boolean equalContent =
+ TextUtils.equals(lastText, text)
+ && lastEvent.hasSameComposingSpan(event)
+ && lastEvent.hasSameSelectionSpan(event);
if (equalContent) {
addEvent = false;
} else if (bothNonEmpty) {
diff --git a/core/java/android/view/inputmethod/BaseInputConnection.java b/core/java/android/view/inputmethod/BaseInputConnection.java
index bdd12063e6cf..c4540b0d8726 100644
--- a/core/java/android/view/inputmethod/BaseInputConnection.java
+++ b/core/java/android/view/inputmethod/BaseInputConnection.java
@@ -163,6 +163,17 @@ public class BaseInputConnection implements InputConnection {
}
/**
+ * Called after only the composing region is modified (so it isn't called if the text also
+ * changes).
+ * <p>
+ * Default implementation does nothing.
+ *
+ * @hide
+ */
+ public void endComposingRegionEditInternal() {
+ }
+
+ /**
* Default implementation calls {@link #finishComposingText()} and
* {@code setImeConsumesInput(false)}.
*/
@@ -468,6 +479,7 @@ public class BaseInputConnection implements InputConnection {
// Note: sendCurrentText does nothing unless mFallbackMode is set
sendCurrentText();
endBatchEdit();
+ endComposingRegionEditInternal();
}
return true;
}
@@ -734,6 +746,7 @@ public class BaseInputConnection implements InputConnection {
// Note: sendCurrentText does nothing unless mFallbackMode is set
sendCurrentText();
endBatchEdit();
+ endComposingRegionEditInternal();
}
return true;
}
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 3c4fd5e93580..cd560d75d913 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -10832,11 +10832,19 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
}
}
+ notifyContentCaptureTextChanged();
+ }
+
+ /**
+ * Notifies the ContentCapture service that the text of the view has changed (only if
+ * ContentCapture has been notified of this view's existence already).
+ *
+ * @hide
+ */
+ public void notifyContentCaptureTextChanged() {
// TODO(b/121045053): should use a flag / boolean to keep status of SHOWN / HIDDEN instead
// of using isLaidout(), so it's not called in cases where it's laid out but a
// notifyAppeared was not sent.
-
- // ContentCapture
if (isLaidOut() && isImportantForContentCapture() && getNotifiedContentCaptureAppeared()) {
final ContentCaptureManager cm = mContext.getSystemService(ContentCaptureManager.class);
if (cm != null && cm.isContentCaptureEnabled()) {
diff --git a/core/java/com/android/internal/app/IHotwordRecognitionStatusCallback.aidl b/core/java/com/android/internal/app/IHotwordRecognitionStatusCallback.aidl
index ec99c95a737c..d0214e6e0082 100644
--- a/core/java/com/android/internal/app/IHotwordRecognitionStatusCallback.aidl
+++ b/core/java/com/android/internal/app/IHotwordRecognitionStatusCallback.aidl
@@ -78,4 +78,7 @@ oneway interface IHotwordRecognitionStatusCallback {
* @param status The status about the result of requesting update state action.
*/
void onStatusReported(int status);
+
+ /** Called when the hotword detection process is restarted */
+ void onProcessRestarted();
}
diff --git a/core/java/com/android/internal/infra/ServiceConnector.java b/core/java/com/android/internal/infra/ServiceConnector.java
index af21f8183d3a..9ced6097804d 100644
--- a/core/java/com/android/internal/infra/ServiceConnector.java
+++ b/core/java/com/android/internal/infra/ServiceConnector.java
@@ -228,7 +228,7 @@ public interface ServiceConnector<I extends IInterface> {
private final int mBindingFlags;
private final @Nullable Function<IBinder, I> mBinderAsInterface;
private final @NonNull Handler mHandler;
- private final @NonNull Executor mExecutor;
+ protected final @NonNull Executor mExecutor;
private volatile I mService = null;
private boolean mBinding = false;
diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
index 945a6ab11856..dab3e9fa15fa 100644
--- a/core/java/com/android/internal/os/BatteryStatsImpl.java
+++ b/core/java/com/android/internal/os/BatteryStatsImpl.java
@@ -12141,6 +12141,15 @@ public class BatteryStatsImpl extends BatteryStats {
}
}
}
+
+ void reset() {
+ idleTimeMs = 0;
+ rxTimeMs = 0;
+ txTimeMs = 0;
+ energy = 0;
+ uidRxBytes.clear();
+ uidTxBytes.clear();
+ }
}
private final BluetoothActivityInfoCache mLastBluetoothActivityInfo
@@ -12167,6 +12176,15 @@ public class BatteryStatsImpl extends BatteryStats {
mHasBluetoothReporting = true;
+ if (info.getControllerRxTimeMillis() < mLastBluetoothActivityInfo.rxTimeMs
+ || info.getControllerTxTimeMillis() < mLastBluetoothActivityInfo.txTimeMs
+ || info.getControllerIdleTimeMillis() < mLastBluetoothActivityInfo.idleTimeMs
+ || info.getControllerEnergyUsed() < mLastBluetoothActivityInfo.energy) {
+ // A drop in accumulated Bluetooth stats is a sign of a Bluetooth crash.
+ // Reset the preserved previous snapshot in order to restart accumulating deltas.
+ mLastBluetoothActivityInfo.reset();
+ }
+
final long rxTimeMs =
info.getControllerRxTimeMillis() - mLastBluetoothActivityInfo.rxTimeMs;
final long txTimeMs =
diff --git a/core/java/com/android/internal/view/ScrollCaptureViewSupport.java b/core/java/com/android/internal/view/ScrollCaptureViewSupport.java
index 8aa2d57e8ea6..9e09006f608d 100644
--- a/core/java/com/android/internal/view/ScrollCaptureViewSupport.java
+++ b/core/java/com/android/internal/view/ScrollCaptureViewSupport.java
@@ -198,12 +198,9 @@ public class ScrollCaptureViewSupport<V extends View> implements ScrollCaptureCa
private static final float LIGHT_RADIUS_DP = 800;
private static final String TAG = "ViewRenderer";
- private HardwareRenderer mRenderer;
- private RenderNode mCaptureRenderNode;
- private final RectF mTempRectF = new RectF();
- private final Rect mSourceRect = new Rect();
+ private final HardwareRenderer mRenderer;
+ private final RenderNode mCaptureRenderNode;
private final Rect mTempRect = new Rect();
- private final Matrix mTempMatrix = new Matrix();
private final int[] mTempLocation = new int[2];
private long mLastRenderedSourceDrawingId = -1;
private Surface mSurface;
@@ -313,11 +310,9 @@ public class ScrollCaptureViewSupport<V extends View> implements ScrollCaptureCa
}
private void transformToRoot(View local, Rect localRect, Rect outRect) {
- mTempMatrix.reset();
- local.transformMatrixToGlobal(mTempMatrix);
- mTempRectF.set(localRect);
- mTempMatrix.mapRect(mTempRectF);
- mTempRectF.round(outRect);
+ local.getLocationInWindow(mTempLocation);
+ outRect.set(localRect);
+ outRect.offset(mTempLocation[0], mTempLocation[1]);
}
public void setColorMode(@ColorMode int colorMode) {
diff --git a/core/java/com/android/internal/widget/EditableInputConnection.java b/core/java/com/android/internal/widget/EditableInputConnection.java
index 3d054a5e773c..02ffe8c5268e 100644
--- a/core/java/com/android/internal/widget/EditableInputConnection.java
+++ b/core/java/com/android/internal/widget/EditableInputConnection.java
@@ -99,6 +99,12 @@ public class EditableInputConnection extends BaseInputConnection
}
@Override
+ public void endComposingRegionEditInternal() {
+ // The ContentCapture service is interested in Composing-state changes.
+ mTextView.notifyContentCaptureTextChanged();
+ }
+
+ @Override
public void closeConnection() {
super.closeConnection();
synchronized(this) {
diff --git a/core/java/com/android/server/AppWidgetBackupBridge.java b/core/java/com/android/server/AppWidgetBackupBridge.java
index 7d82d355e3eb..8e834a87784d 100644
--- a/core/java/com/android/server/AppWidgetBackupBridge.java
+++ b/core/java/com/android/server/AppWidgetBackupBridge.java
@@ -47,9 +47,9 @@ public class AppWidgetBackupBridge {
: null;
}
- public static void restoreStarting(int userId) {
+ public static void systemRestoreStarting(int userId) {
if (sAppWidgetService != null) {
- sAppWidgetService.restoreStarting(userId);
+ sAppWidgetService.systemRestoreStarting(userId);
}
}
@@ -59,9 +59,9 @@ public class AppWidgetBackupBridge {
}
}
- public static void restoreFinished(int userId) {
+ public static void systemRestoreFinished(int userId) {
if (sAppWidgetService != null) {
- sAppWidgetService.restoreFinished(userId);
+ sAppWidgetService.systemRestoreFinished(userId);
}
}
}
diff --git a/core/java/com/android/server/SystemConfig.java b/core/java/com/android/server/SystemConfig.java
index bd0de2984b7f..a8dcbaffeeb5 100644
--- a/core/java/com/android/server/SystemConfig.java
+++ b/core/java/com/android/server/SystemConfig.java
@@ -86,6 +86,7 @@ public class SystemConfig {
// and "allow-ignore-location-settings".
private static final int ALLOW_OVERRIDE_APP_RESTRICTIONS = 0x100;
private static final int ALLOW_IMPLICIT_BROADCASTS = 0x200;
+ private static final int ALLOW_VENDOR_APEX = 0x400;
private static final int ALLOW_ALL = ~0;
// property for runtime configuration differentiation
@@ -240,6 +241,7 @@ public class SystemConfig {
private final ArraySet<String> mRollbackWhitelistedPackages = new ArraySet<>();
private final ArraySet<String> mWhitelistedStagedInstallers = new ArraySet<>();
+ private final ArraySet<String> mAllowedVendorApexes = new ArraySet<>();
/**
* Map of system pre-defined, uniquely named actors; keys are namespace,
@@ -410,6 +412,10 @@ public class SystemConfig {
return mWhitelistedStagedInstallers;
}
+ public Set<String> getAllowedVendorApexes() {
+ return mAllowedVendorApexes;
+ }
+
public ArraySet<String> getAppDataIsolationWhitelistedApps() {
return mAppDataIsolationWhitelistedApps;
}
@@ -484,7 +490,7 @@ public class SystemConfig {
// Vendors are only allowed to customize these
int vendorPermissionFlag = ALLOW_LIBS | ALLOW_FEATURES | ALLOW_PRIVAPP_PERMISSIONS
- | ALLOW_ASSOCIATIONS;
+ | ALLOW_ASSOCIATIONS | ALLOW_VENDOR_APEX;
if (Build.VERSION.DEVICE_INITIAL_SDK_INT <= Build.VERSION_CODES.O_MR1) {
// For backward compatibility
vendorPermissionFlag |= (ALLOW_PERMISSIONS | ALLOW_APP_CONFIGS);
@@ -525,7 +531,8 @@ public class SystemConfig {
}
// Allow OEM to customize these
- int oemPermissionFlag = ALLOW_FEATURES | ALLOW_OEM_PERMISSIONS | ALLOW_ASSOCIATIONS;
+ int oemPermissionFlag = ALLOW_FEATURES | ALLOW_OEM_PERMISSIONS | ALLOW_ASSOCIATIONS
+ | ALLOW_VENDOR_APEX;
readPermissions(Environment.buildPath(
Environment.getOemDirectory(), "etc", "sysconfig"), oemPermissionFlag);
readPermissions(Environment.buildPath(
@@ -536,7 +543,8 @@ public class SystemConfig {
// the use of hidden APIs from the product partition.
int productPermissionFlag = ALLOW_FEATURES | ALLOW_LIBS | ALLOW_PERMISSIONS
| ALLOW_APP_CONFIGS | ALLOW_PRIVAPP_PERMISSIONS | ALLOW_HIDDENAPI_WHITELISTING
- | ALLOW_ASSOCIATIONS | ALLOW_OVERRIDE_APP_RESTRICTIONS | ALLOW_IMPLICIT_BROADCASTS;
+ | ALLOW_ASSOCIATIONS | ALLOW_OVERRIDE_APP_RESTRICTIONS | ALLOW_IMPLICIT_BROADCASTS
+ | ALLOW_VENDOR_APEX;
if (Build.VERSION.DEVICE_INITIAL_SDK_INT <= Build.VERSION_CODES.R) {
// TODO(b/157393157): This must check product interface enforcement instead of
// DEVICE_INITIAL_SDK_INT for the devices without product interface enforcement.
@@ -663,6 +671,7 @@ public class SystemConfig {
(permissionFlag & ALLOW_OVERRIDE_APP_RESTRICTIONS) != 0;
final boolean allowImplicitBroadcasts = (permissionFlag & ALLOW_IMPLICIT_BROADCASTS)
!= 0;
+ final boolean allowVendorApex = (permissionFlag & ALLOW_VENDOR_APEX) != 0;
while (true) {
XmlUtils.nextElement(parser);
if (parser.getEventType() == XmlPullParser.END_DOCUMENT) {
@@ -1212,6 +1221,20 @@ public class SystemConfig {
}
XmlUtils.skipCurrentTag(parser);
} break;
+ case "allowed-vendor-apex": {
+ if (allowVendorApex) {
+ String pkgName = parser.getAttributeValue(null, "package");
+ if (pkgName == null) {
+ Slog.w(TAG, "<" + name + "> without package in " + permFile
+ + " at " + parser.getPositionDescription());
+ } else {
+ mAllowedVendorApexes.add(pkgName);
+ }
+ } else {
+ logNotAllowedInPartition(name, permFile, parser);
+ }
+ XmlUtils.skipCurrentTag(parser);
+ } break;
default: {
Slog.w(TAG, "Tag " + name + " is unknown in "
+ permFile + " at " + parser.getPositionDescription());
diff --git a/core/java/com/android/server/WidgetBackupProvider.java b/core/java/com/android/server/WidgetBackupProvider.java
index a2efbdd6f2f8..5453c4de6986 100644
--- a/core/java/com/android/server/WidgetBackupProvider.java
+++ b/core/java/com/android/server/WidgetBackupProvider.java
@@ -28,7 +28,7 @@ import java.util.List;
public interface WidgetBackupProvider {
public List<String> getWidgetParticipants(int userId);
public byte[] getWidgetState(String packageName, int userId);
- public void restoreStarting(int userId);
+ public void systemRestoreStarting(int userId);
public void restoreWidgetState(String packageName, byte[] restoredState, int userId);
- public void restoreFinished(int userId);
+ public void systemRestoreFinished(int userId);
}
diff --git a/core/res/res/values-television/config.xml b/core/res/res/values-television/config.xml
index 3ecb1dddd916..55e5685b95e5 100644
--- a/core/res/res/values-television/config.xml
+++ b/core/res/res/values-television/config.xml
@@ -42,4 +42,8 @@
<!-- Allow SystemUI to show the shutdown dialog -->
<bool name="config_showSysuiShutdown">true</bool>
+
+ <!-- Component name of the activity used to inform a user about a sensory being blocked because
+ of privacy settings. -->
+ <string name="config_sensorUseStartedActivity">com.android.systemui/com.android.systemui.sensorprivacy.television.TvUnblockSensorActivity</string>
</resources>
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 3c47366a59db..f4aff9467cee 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -3350,6 +3350,10 @@
<!-- The default vibration strength, must be between 1 and 255 inclusive. -->
<integer name="config_defaultVibrationAmplitude">255</integer>
+ <!-- The max vibration strength allowed in audio haptic channels, must be positive or zero if
+ limit is unknown. -->
+ <item name="config_hapticChannelMaxVibrationAmplitude" format="float" type="dimen">0</item>
+
<!-- If the device should still vibrate even in low power mode, for certain priority vibrations
(e.g. accessibility, alarms). This is mainly for Wear devices that don't have speakers. -->
<bool name="config_allowPriorityVibrationsInLowPowerMode">false</bool>
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index d4ddab1ec502..302bd94c1973 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -1603,6 +1603,8 @@
<string name="fingerprint_acquired_too_bright">Too bright</string>
<!-- Message shown during fingerprint acquisition when a fingerprint must be adjusted.[CHAR LIMIT=50] -->
<string name="fingerprint_acquired_try_adjusting">Try adjusting</string>
+ <!-- Message shown during fingerprint acquisition when a fingeprint area has already been captured during enrollment [CHAR LIMIT=100] -->
+ <string name="fingerprint_acquired_immobile">Change the position of your finger slightly each time</string>
<!-- Array containing custom messages shown during fingerprint acquisision from vendor. Vendor is expected to add and translate these strings -->
<string-array name="fingerprint_acquired_vendor">
</string-array>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 960bd639960e..5f849b4e1eb0 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -2013,6 +2013,7 @@
<java-symbol type="integer" name="config_notificationServiceArchiveSize" />
<java-symbol type="integer" name="config_previousVibrationsDumpLimit" />
<java-symbol type="integer" name="config_defaultVibrationAmplitude" />
+ <java-symbol type="dimen" name="config_hapticChannelMaxVibrationAmplitude" />
<java-symbol type="integer" name="config_vibrationWaveformRampStepDuration" />
<java-symbol type="integer" name="config_vibrationWaveformRampDownDuration" />
<java-symbol type="integer" name="config_radioScanningTimeout" />
@@ -2538,6 +2539,7 @@
<java-symbol type="string" name="fingerprint_error_hw_not_present" />
<java-symbol type="string" name="fingerprint_error_security_update_required" />
<java-symbol type="string" name="fingerprint_error_bad_calibration" />
+ <java-symbol type="string" name="fingerprint_acquired_immobile" />
<!-- Fingerprint config -->
<java-symbol type="integer" name="config_fingerprintMaxTemplatesPerUser"/>
diff --git a/core/tests/coretests/src/android/app/appsearch/external/app/AppSearchResultTest.java b/core/tests/coretests/src/android/app/appsearch/external/app/AppSearchResultTest.java
index de0670b08ffd..228a061ae3c8 100644
--- a/core/tests/coretests/src/android/app/appsearch/external/app/AppSearchResultTest.java
+++ b/core/tests/coretests/src/android/app/appsearch/external/app/AppSearchResultTest.java
@@ -18,7 +18,7 @@ package android.app.appsearch;
import static com.google.common.truth.Truth.assertThat;
-import static org.testng.Assert.expectThrows;
+import static org.junit.Assert.assertThrows;
import org.junit.Test;
@@ -26,7 +26,7 @@ public class AppSearchResultTest {
@Test
public void testMapNullPointerException() {
NullPointerException e =
- expectThrows(
+ assertThrows(
NullPointerException.class,
() -> {
Object o = null;
diff --git a/core/tests/coretests/src/android/os/VibratorInfoTest.java b/core/tests/coretests/src/android/os/VibratorInfoTest.java
index 8c7d10c7a5ef..6e07fa264c1c 100644
--- a/core/tests/coretests/src/android/os/VibratorInfoTest.java
+++ b/core/tests/coretests/src/android/os/VibratorInfoTest.java
@@ -87,14 +87,14 @@ public class VibratorInfoTest {
public void testIsPrimitiveSupported() {
VibratorInfo info = new VibratorInfo.Builder(TEST_VIBRATOR_ID)
.setCapabilities(IVibrator.CAP_COMPOSE_EFFECTS)
- .setSupportedPrimitives(VibrationEffect.Composition.PRIMITIVE_CLICK)
+ .setSupportedPrimitive(VibrationEffect.Composition.PRIMITIVE_CLICK, 10)
.build();
assertTrue(info.isPrimitiveSupported(VibrationEffect.Composition.PRIMITIVE_CLICK));
assertFalse(info.isPrimitiveSupported(VibrationEffect.Composition.PRIMITIVE_TICK));
// Returns false when there is no compose capability.
info = new VibratorInfo.Builder(TEST_VIBRATOR_ID)
- .setSupportedPrimitives(VibrationEffect.Composition.PRIMITIVE_CLICK)
+ .setSupportedPrimitive(VibrationEffect.Composition.PRIMITIVE_CLICK, 10)
.build();
assertFalse(info.isPrimitiveSupported(VibrationEffect.Composition.PRIMITIVE_CLICK));
}
@@ -103,8 +103,7 @@ public class VibratorInfoTest {
public void testGetPrimitiveDuration() {
VibratorInfo info = new VibratorInfo.Builder(TEST_VIBRATOR_ID)
.setCapabilities(IVibrator.CAP_COMPOSE_EFFECTS)
- .setSupportedPrimitives(VibrationEffect.Composition.PRIMITIVE_CLICK)
- .setPrimitiveDuration(VibrationEffect.Composition.PRIMITIVE_CLICK, 20)
+ .setSupportedPrimitive(VibrationEffect.Composition.PRIMITIVE_CLICK, 20)
.build();
assertEquals(20, info.getPrimitiveDuration(VibrationEffect.Composition.PRIMITIVE_CLICK));
assertEquals(0, info.getPrimitiveDuration(VibrationEffect.Composition.PRIMITIVE_TICK));
@@ -113,6 +112,26 @@ public class VibratorInfoTest {
}
@Test
+ public void testCompositionLimits() {
+ VibratorInfo info = new VibratorInfo.Builder(TEST_VIBRATOR_ID)
+ .setPrimitiveDelayMax(100)
+ .setCompositionSizeMax(10)
+ .setPwlePrimitiveDurationMax(50)
+ .setPwleSizeMax(20)
+ .build();
+ assertEquals(100, info.getPrimitiveDelayMax());
+ assertEquals(10, info.getCompositionSizeMax());
+ assertEquals(50, info.getPwlePrimitiveDurationMax());
+ assertEquals(20, info.getPwleSizeMax());
+
+ VibratorInfo emptyInfo = new VibratorInfo.Builder(TEST_VIBRATOR_ID).build();
+ assertEquals(0, emptyInfo.getPrimitiveDelayMax());
+ assertEquals(0, emptyInfo.getCompositionSizeMax());
+ assertEquals(0, emptyInfo.getPwlePrimitiveDurationMax());
+ assertEquals(0, emptyInfo.getPwleSizeMax());
+ }
+
+ @Test
public void testGetDefaultBraking_returnsFirstSupportedBraking() {
assertEquals(Braking.NONE, new VibratorInfo.Builder(
TEST_VIBRATOR_ID).build().getDefaultBraking());
@@ -263,8 +282,12 @@ public class VibratorInfoTest {
VibratorInfo.Builder completeBuilder = new VibratorInfo.Builder(TEST_VIBRATOR_ID)
.setCapabilities(IVibrator.CAP_AMPLITUDE_CONTROL)
.setSupportedEffects(VibrationEffect.EFFECT_CLICK)
- .setSupportedPrimitives(VibrationEffect.Composition.PRIMITIVE_CLICK)
- .setPrimitiveDuration(VibrationEffect.Composition.PRIMITIVE_CLICK, 20)
+ .setSupportedPrimitive(VibrationEffect.Composition.PRIMITIVE_CLICK, 20)
+ .setPrimitiveDelayMax(100)
+ .setCompositionSizeMax(10)
+ .setSupportedBraking(Braking.CLAB)
+ .setPwlePrimitiveDurationMax(50)
+ .setPwleSizeMax(20)
.setQFactor(2f)
.setFrequencyMapping(TEST_FREQUENCY_MAPPING);
VibratorInfo complete = completeBuilder.build();
@@ -279,8 +302,7 @@ public class VibratorInfoTest {
assertNotEquals(complete, completeWithComposeControl);
VibratorInfo completeWithNoEffects = completeBuilder
- .setSupportedEffects()
- .setSupportedPrimitives()
+ .setSupportedEffects(new int[0])
.build();
assertNotEquals(complete, completeWithNoEffects);
@@ -289,13 +311,8 @@ public class VibratorInfoTest {
.build();
assertNotEquals(complete, completeWithUnknownEffects);
- VibratorInfo completeWithUnknownPrimitives = completeBuilder
- .setSupportedPrimitives(null)
- .build();
- assertNotEquals(complete, completeWithUnknownPrimitives);
-
VibratorInfo completeWithDifferentPrimitiveDuration = completeBuilder
- .setPrimitiveDuration(VibrationEffect.Composition.PRIMITIVE_CLICK, 10)
+ .setSupportedPrimitive(VibrationEffect.Composition.PRIMITIVE_CLICK, 10)
.build();
assertNotEquals(complete, completeWithDifferentPrimitiveDuration);
@@ -321,12 +338,17 @@ public class VibratorInfoTest {
.build();
assertNotEquals(complete, completeWithDifferentQFactor);
- VibratorInfo empty = new VibratorInfo.Builder(TEST_VIBRATOR_ID).build();
- VibratorInfo emptyWithKnownSupport = new VibratorInfo.Builder(TEST_VIBRATOR_ID)
- .setSupportedEffects()
- .setSupportedPrimitives()
+ VibratorInfo unknownEffectSupport = new VibratorInfo.Builder(TEST_VIBRATOR_ID).build();
+ VibratorInfo knownEmptyEffectSupport = new VibratorInfo.Builder(TEST_VIBRATOR_ID)
+ .setSupportedEffects(new int[0])
+ .build();
+ assertNotEquals(unknownEffectSupport, knownEmptyEffectSupport);
+
+ VibratorInfo unknownBrakingSupport = new VibratorInfo.Builder(TEST_VIBRATOR_ID).build();
+ VibratorInfo knownEmptyBrakingSupport = new VibratorInfo.Builder(TEST_VIBRATOR_ID)
+ .setSupportedBraking(new int[0])
.build();
- assertNotEquals(empty, emptyWithKnownSupport);
+ assertNotEquals(unknownBrakingSupport, knownEmptyBrakingSupport);
}
@Test
@@ -334,8 +356,7 @@ public class VibratorInfoTest {
VibratorInfo original = new VibratorInfo.Builder(TEST_VIBRATOR_ID)
.setCapabilities(IVibrator.CAP_COMPOSE_EFFECTS)
.setSupportedEffects(VibrationEffect.EFFECT_CLICK)
- .setSupportedPrimitives(VibrationEffect.Composition.PRIMITIVE_CLICK)
- .setPrimitiveDuration(VibrationEffect.Composition.PRIMITIVE_CLICK, 20)
+ .setSupportedPrimitive(VibrationEffect.Composition.PRIMITIVE_CLICK, 20)
.setQFactor(Float.NaN)
.setFrequencyMapping(TEST_FREQUENCY_MAPPING)
.build();
diff --git a/location/java/android/location/GnssMeasurement.java b/location/java/android/location/GnssMeasurement.java
index 4cd3616566c2..ecdd4b616e0f 100644
--- a/location/java/android/location/GnssMeasurement.java
+++ b/location/java/android/location/GnssMeasurement.java
@@ -214,6 +214,25 @@ public final class GnssMeasurement implements Parcelable {
*
* <p> When this bit is unset, the {@link #getAccumulatedDeltaRangeMeters()} corresponds to the
* carrier phase measurement plus an accumulated integer number of carrier half cycles.
+ *
+ * <p> For signals that have databits, the carrier phase tracking loops typically use a costas
+ * loop discriminator. This type of tracking loop introduces a half-cycle ambiguity that is
+ * resolved by searching through the received data for known patterns of databits (e.g. GPS uses
+ * the TLM word) which then determines the polarity of the incoming data and resolves the
+ * half-cycle ambiguity.
+ *
+ * <p>Before the half-cycle ambiguity has been resolved it is possible that the ADR_STATE_VALID
+ * flag is set:
+ *
+ * <ul>
+ * <li> In cases where ADR_STATE_HALF_CYCLE_REPORTED is not set, the
+ * ADR_STATE_HALF_CYCLE_RESOLVED flag will not be available. Here, a half wave length will be
+ * added to the returned accumulated delta range uncertainty to indicate the half cycle
+ * ambiguity.
+ * <li> In cases where ADR_STATE_HALF_CYCLE_REPORTED is set, half cycle ambiguity will be
+ * indicated via both the ADR_STATE_HALF_CYCLE_RESOLVED flag and as well a half wave length
+ * added to the returned accumulated delta range uncertainty.
+ * </ul>
*/
public static final int ADR_STATE_HALF_CYCLE_RESOLVED = (1<<3);
@@ -1039,9 +1058,6 @@ public final class GnssMeasurement implements Parcelable {
* with integer ambiguity resolution, to determine highly precise relative location between
* receivers.
*
- * <p>This includes ensuring that all half-cycle ambiguities are resolved before this value is
- * reported as {@link #ADR_STATE_VALID}.
- *
* <p>The alignment of the phase measurement will not be adjusted by the receiver so the
* in-phase and quadrature phase components will have a quarter cycle offset as they do when
* transmitted from the satellites. If the measurement is from a combination of the in-phase
diff --git a/media/java/android/mtp/MtpDatabase.java b/media/java/android/mtp/MtpDatabase.java
index 860d88afe4a2..d8f48c2cf0c6 100755
--- a/media/java/android/mtp/MtpDatabase.java
+++ b/media/java/android/mtp/MtpDatabase.java
@@ -101,6 +101,8 @@ public class MtpDatabase implements AutoCloseable {
private int mBatteryLevel;
private int mBatteryScale;
private int mDeviceType;
+ private String mHostType;
+ private boolean mSkipThumbForHost = false;
private MtpServer mServer;
private MtpStorageManager mManager;
@@ -192,6 +194,7 @@ public class MtpDatabase implements AutoCloseable {
MtpConstants.DEVICE_PROPERTY_IMAGE_SIZE,
MtpConstants.DEVICE_PROPERTY_BATTERY_LEVEL,
MtpConstants.DEVICE_PROPERTY_PERCEIVED_DEVICE_TYPE,
+ MtpConstants.DEVICE_PROPERTY_SESSION_INITIATOR_VERSION_INFO,
};
@VisibleForNative
@@ -408,6 +411,8 @@ public class MtpDatabase implements AutoCloseable {
}
context.deleteDatabase(devicePropertiesName);
}
+ mHostType = "";
+ mSkipThumbForHost = false;
}
@VisibleForNative
@@ -672,12 +677,24 @@ public class MtpDatabase implements AutoCloseable {
@VisibleForNative
private int getDeviceProperty(int property, long[] outIntValue, char[] outStringValue) {
+ int length;
+ String value;
+
switch (property) {
case MtpConstants.DEVICE_PROPERTY_SYNCHRONIZATION_PARTNER:
case MtpConstants.DEVICE_PROPERTY_DEVICE_FRIENDLY_NAME:
// writable string properties kept in shared preferences
- String value = mDeviceProperties.getString(Integer.toString(property), "");
- int length = value.length();
+ value = mDeviceProperties.getString(Integer.toString(property), "");
+ length = value.length();
+ if (length > 255) {
+ length = 255;
+ }
+ value.getChars(0, length, outStringValue, 0);
+ outStringValue[length] = 0;
+ return MtpConstants.RESPONSE_OK;
+ case MtpConstants.DEVICE_PROPERTY_SESSION_INITIATOR_VERSION_INFO:
+ value = mHostType;
+ length = value.length();
if (length > 255) {
length = 255;
}
@@ -717,6 +734,14 @@ public class MtpDatabase implements AutoCloseable {
e.putString(Integer.toString(property), stringValue);
return (e.commit() ? MtpConstants.RESPONSE_OK
: MtpConstants.RESPONSE_GENERAL_ERROR);
+ case MtpConstants.DEVICE_PROPERTY_SESSION_INITIATOR_VERSION_INFO:
+ mHostType = stringValue;
+ if (stringValue.startsWith("Android/")) {
+ Log.d(TAG, "setDeviceProperty." + Integer.toHexString(property)
+ + "=" + stringValue);
+ mSkipThumbForHost = true;
+ }
+ return MtpConstants.RESPONSE_OK;
}
return MtpConstants.RESPONSE_DEVICE_PROP_NOT_SUPPORTED;
@@ -838,6 +863,10 @@ public class MtpDatabase implements AutoCloseable {
outLongs[0] = thumbOffsetAndSize != null ? thumbOffsetAndSize[1] : 0;
outLongs[1] = exif.getAttributeInt(ExifInterface.TAG_PIXEL_X_DIMENSION, 0);
outLongs[2] = exif.getAttributeInt(ExifInterface.TAG_PIXEL_Y_DIMENSION, 0);
+ if (mSkipThumbForHost) {
+ Log.d(TAG, "getThumbnailInfo: Skip runtime thumbnail.");
+ return true;
+ }
if (exif.getThumbnailRange() != null) {
if ((outLongs[0] == 0) || (outLongs[1] == 0) || (outLongs[2] == 0)) {
Log.d(TAG, "getThumbnailInfo: check thumb info:"
@@ -880,6 +909,10 @@ public class MtpDatabase implements AutoCloseable {
try {
ExifInterface exif = new ExifInterface(path);
+ if (mSkipThumbForHost) {
+ Log.d(TAG, "getThumbnailData: Skip runtime thumbnail.");
+ return exif.getThumbnail();
+ }
if (exif.getThumbnailRange() != null)
return exif.getThumbnail();
} catch (IOException e) {
diff --git a/media/java/android/mtp/MtpDevice.java b/media/java/android/mtp/MtpDevice.java
index e8b04edb2e1b..ec925918d4e6 100644
--- a/media/java/android/mtp/MtpDevice.java
+++ b/media/java/android/mtp/MtpDevice.java
@@ -170,6 +170,18 @@ public final class MtpDevice {
}
/**
+ * Set device property SESSION_INITIATOR_VERSION_INFO
+ *
+ * @param propertyStr string value for device property SESSION_INITIATOR_VERSION_INFO
+ * @return -1 for error, 0 for success
+ *
+ * {@hide}
+ */
+ public int setDevicePropertyInitVersion(@NonNull String propertyStr) {
+ return native_set_device_property_init_version(propertyStr);
+ }
+
+ /**
* Returns the list of IDs for all storage units on this device
* Information about each storage unit can be accessed via {@link #getStorageInfo}.
*
@@ -421,6 +433,7 @@ public final class MtpDevice {
private native boolean native_open(String deviceName, int fd);
private native void native_close();
private native MtpDeviceInfo native_get_device_info();
+ private native int native_set_device_property_init_version(String propertyStr);
private native int[] native_get_storage_ids();
private native MtpStorageInfo native_get_storage_info(int storageId);
private native int[] native_get_object_handles(int storageId, int format, int objectHandle);
diff --git a/media/java/android/mtp/MtpDeviceInfo.java b/media/java/android/mtp/MtpDeviceInfo.java
index 0304ee386ace..88514515eabf 100644
--- a/media/java/android/mtp/MtpDeviceInfo.java
+++ b/media/java/android/mtp/MtpDeviceInfo.java
@@ -31,6 +31,7 @@ public class MtpDeviceInfo {
private String mSerialNumber;
private int[] mOperationsSupported;
private int[] mEventsSupported;
+ private int[] mDevicePropertySupported;
// only instantiated via JNI
private MtpDeviceInfo() {
@@ -144,6 +145,21 @@ public class MtpDeviceInfo {
}
/**
+ * Returns Device property code supported by the device.
+ *
+ * @return supported Device property code. Can be null if device does not provide the property.
+ *
+ * @see MtpConstants#DEVICE_PROPERTY_SYNCHRONIZATION_PARTNER
+ * @see MtpConstants#DEVICE_PROPERTY_DEVICE_FRIENDLY_NAME
+ * @see MtpConstants#DEVICE_PROPERTY_SESSION_INITIATOR_VERSION_INFO
+ *
+ * {@hide}
+ */
+ public final @NonNull int[] getDevicePropertySupported() {
+ return mDevicePropertySupported;
+ }
+
+ /**
* Returns if the given operation is supported by the device or not.
* @param code Operation code.
* @return If the given operation is supported by the device or not.
@@ -162,6 +178,17 @@ public class MtpDeviceInfo {
}
/**
+ * Returns if the given Device property is supported by the device or not.
+ * @param code Device property code.
+ * @return If the given Device property is supported by the device or not.
+ *
+ * {@hide}
+ */
+ public boolean isDevicePropertySupported(int code) {
+ return isSupported(mDevicePropertySupported, code);
+ }
+
+ /**
* Returns if the code set contains code.
* @hide
*/
diff --git a/media/jni/android_mtp_MtpDatabase.cpp b/media/jni/android_mtp_MtpDatabase.cpp
index ffed4747d3ea..a77bc9fe0570 100644
--- a/media/jni/android_mtp_MtpDatabase.cpp
+++ b/media/jni/android_mtp_MtpDatabase.cpp
@@ -1131,6 +1131,7 @@ static const PropertyTableEntry kDevicePropertyTable[] = {
{ MTP_DEVICE_PROPERTY_IMAGE_SIZE, MTP_TYPE_STR },
{ MTP_DEVICE_PROPERTY_BATTERY_LEVEL, MTP_TYPE_UINT8 },
{ MTP_DEVICE_PROPERTY_PERCEIVED_DEVICE_TYPE, MTP_TYPE_UINT32 },
+ { MTP_DEVICE_PROPERTY_SESSION_INITIATOR_VERSION_INFO, MTP_TYPE_STR },
};
bool MtpDatabase::getObjectPropertyInfo(MtpObjectProperty property, int& type) {
@@ -1289,6 +1290,7 @@ MtpProperty* MtpDatabase::getDevicePropertyDesc(MtpDeviceProperty property) {
switch (property) {
case MTP_DEVICE_PROPERTY_SYNCHRONIZATION_PARTNER:
case MTP_DEVICE_PROPERTY_DEVICE_FRIENDLY_NAME:
+ case MTP_DEVICE_PROPERTY_SESSION_INITIATOR_VERSION_INFO:
writable = true;
// fall through
FALLTHROUGH_INTENDED;
diff --git a/media/jni/android_mtp_MtpDevice.cpp b/media/jni/android_mtp_MtpDevice.cpp
index 3d2b00fec26c..ac89fecd9150 100644
--- a/media/jni/android_mtp_MtpDevice.cpp
+++ b/media/jni/android_mtp_MtpDevice.cpp
@@ -72,6 +72,7 @@ static jfieldID field_deviceInfo_version;
static jfieldID field_deviceInfo_serialNumber;
static jfieldID field_deviceInfo_operationsSupported;
static jfieldID field_deviceInfo_eventsSupported;
+static jfieldID field_deviceInfo_devicePropertySupported;
// MtpStorageInfo fields
static jfieldID field_storageInfo_storageId;
@@ -129,6 +130,8 @@ static void initializeJavaIDs(JNIEnv* env) {
GetFieldIDOrDie(env, clazz_deviceInfo, "mOperationsSupported", "[I");
field_deviceInfo_eventsSupported =
GetFieldIDOrDie(env, clazz_deviceInfo, "mEventsSupported", "[I");
+ field_deviceInfo_devicePropertySupported =
+ GetFieldIDOrDie(env, clazz_deviceInfo, "mDevicePropertySupported", "[I");
clazz_storageInfo =
(jclass)env->NewGlobalRef(FindClassOrDie(env, "android/mtp/MtpStorageInfo"));
@@ -377,9 +380,65 @@ android_mtp_MtpDevice_get_device_info(JNIEnv *env, jobject thiz)
}
}
+ assert(deviceInfo->mDeviceProperties);
+ {
+ const size_t size = deviceInfo->mDeviceProperties->size();
+ ScopedLocalRef<jintArray> events(env, static_cast<jintArray>(env->NewIntArray(size)));
+ {
+ ScopedIntArrayRW elements(env, events.get());
+ if (elements.get() == NULL) {
+ ALOGE("Could not create devicePropertySupported element.");
+ return NULL;
+ }
+ for (size_t i = 0; i < size; ++i) {
+ elements[i] = static_cast<int>(deviceInfo->mDeviceProperties->at(i));
+ }
+ env->SetObjectField(info, field_deviceInfo_devicePropertySupported, events.get());
+ }
+ }
+
return info;
}
+static jint
+android_mtp_MtpDevice_set_device_property_init_version(JNIEnv *env, jobject thiz,
+ jstring property_str) {
+ MtpDevice* const device = get_device_from_object(env, thiz);
+
+ if (!device) {
+ ALOGD("%s device is null\n", __func__);
+ env->ThrowNew(clazz_io_exception, "Failed to obtain MtpDevice.");
+ return -1;
+ }
+
+ const char *propertyStr = env->GetStringUTFChars(property_str, NULL);
+ if (propertyStr == NULL) {
+ return -1;
+ }
+
+ MtpProperty* property = new MtpProperty(MTP_DEVICE_PROPERTY_SESSION_INITIATOR_VERSION_INFO,
+ MTP_TYPE_STR, true);
+ if (!property) {
+ env->ThrowNew(clazz_io_exception, "Failed to obtain property.");
+ return -1;
+ }
+
+ if (property->getDataType() != MTP_TYPE_STR) {
+ env->ThrowNew(clazz_io_exception, "Unexpected property data type.");
+ return -1;
+ }
+
+ property->setCurrentValue(propertyStr);
+ if (!device->setDevicePropValueStr(property)) {
+ env->ThrowNew(clazz_io_exception, "Failed to obtain property value.");
+ return -1;
+ }
+
+ env->ReleaseStringUTFChars(property_str, propertyStr);
+
+ return 0;
+}
+
static jintArray
android_mtp_MtpDevice_get_storage_ids(JNIEnv *env, jobject thiz)
{
@@ -847,6 +906,8 @@ static const JNINativeMethod gMethods[] = {
{"native_close", "()V", (void *)android_mtp_MtpDevice_close},
{"native_get_device_info", "()Landroid/mtp/MtpDeviceInfo;",
(void *)android_mtp_MtpDevice_get_device_info},
+ {"native_set_device_property_init_version", "(Ljava/lang/String;)I",
+ (void *)android_mtp_MtpDevice_set_device_property_init_version},
{"native_get_storage_ids", "()[I", (void *)android_mtp_MtpDevice_get_storage_ids},
{"native_get_storage_info", "(I)Landroid/mtp/MtpStorageInfo;",
(void *)android_mtp_MtpDevice_get_storage_info},
diff --git a/obex/javax/obex/ObexHelper.java b/obex/javax/obex/ObexHelper.java
index 478297f2a3c9..843793ad98f8 100644
--- a/obex/javax/obex/ObexHelper.java
+++ b/obex/javax/obex/ObexHelper.java
@@ -34,6 +34,8 @@
package javax.obex;
+import android.util.Log;
+
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
@@ -43,7 +45,6 @@ import java.util.Calendar;
import java.util.Date;
import java.util.TimeZone;
-import android.util.Log;
/**
* This class defines a set of helper methods for the implementation of Obex.
@@ -1083,11 +1084,12 @@ public final class ObexHelper {
}
private static int validateMaxPacketSize(int size) {
- if(VDBG && (size > MAX_PACKET_SIZE_INT)) Log.w(TAG,
- "The packet size supported for the connection (" + size + ") is larger"
- + " than the configured OBEX packet size: " + MAX_PACKET_SIZE_INT);
- if(size != -1) {
- if(size < LOWER_LIMIT_MAX_PACKET_SIZE) {
+ if (VDBG && (size > MAX_PACKET_SIZE_INT)) {
+ Log.w(TAG, "The packet size supported for the connection (" + size + ") is larger"
+ + " than the configured OBEX packet size: " + MAX_PACKET_SIZE_INT);
+ }
+ if (size != -1 && size < MAX_PACKET_SIZE_INT) {
+ if (size < LOWER_LIMIT_MAX_PACKET_SIZE) {
throw new IllegalArgumentException(size + " is less that the lower limit: "
+ LOWER_LIMIT_MAX_PACKET_SIZE);
}
diff --git a/obex/javax/obex/ObexTransport.java b/obex/javax/obex/ObexTransport.java
index a5a75f55f553..4cef0b33df4f 100644
--- a/obex/javax/obex/ObexTransport.java
+++ b/obex/javax/obex/ObexTransport.java
@@ -81,6 +81,8 @@ public interface ObexTransport {
* size. Therefore this value shall not change.
* For RFCOMM or other transport types where the OBEX packets size
* is unrelated to the transport packet size, return -1;
+ * Exception can be made (like PBAP transport) with a smaller value
+ * to avoid bad effect on other profiles using the RFCOMM;
* @return the maximum allowed OBEX packet that can be send over
* the transport. Or -1 in case of don't care.
*/
diff --git a/packages/SettingsLib/BannerMessagePreference/res/values-bn/strings.xml b/packages/SettingsLib/BannerMessagePreference/res/values-bn/strings.xml
new file mode 100644
index 000000000000..e0dfcf24700c
--- /dev/null
+++ b/packages/SettingsLib/BannerMessagePreference/res/values-bn/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (C) 2021 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="accessibility_banner_message_dismiss" msgid="5272928723898304168">"বাতিল করুন"</string>
+</resources>
diff --git a/packages/SettingsLib/BannerMessagePreference/res/values-de/strings.xml b/packages/SettingsLib/BannerMessagePreference/res/values-de/strings.xml
new file mode 100644
index 000000000000..006301b2e94e
--- /dev/null
+++ b/packages/SettingsLib/BannerMessagePreference/res/values-de/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (C) 2021 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="accessibility_banner_message_dismiss" msgid="5272928723898304168">"Schließen"</string>
+</resources>
diff --git a/packages/SettingsLib/BannerMessagePreference/res/values-mr/strings.xml b/packages/SettingsLib/BannerMessagePreference/res/values-mr/strings.xml
new file mode 100644
index 000000000000..4bd44859ec8f
--- /dev/null
+++ b/packages/SettingsLib/BannerMessagePreference/res/values-mr/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (C) 2021 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="accessibility_banner_message_dismiss" msgid="5272928723898304168">"डिसमिस करा"</string>
+</resources>
diff --git a/packages/SettingsLib/BannerMessagePreference/res/values-ne/strings.xml b/packages/SettingsLib/BannerMessagePreference/res/values-ne/strings.xml
new file mode 100644
index 000000000000..15102541bb87
--- /dev/null
+++ b/packages/SettingsLib/BannerMessagePreference/res/values-ne/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (C) 2021 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="accessibility_banner_message_dismiss" msgid="5272928723898304168">"हटाउनुहोस्"</string>
+</resources>
diff --git a/packages/SettingsLib/BannerMessagePreference/res/values-or/strings.xml b/packages/SettingsLib/BannerMessagePreference/res/values-or/strings.xml
new file mode 100644
index 000000000000..36e7d3bdb216
--- /dev/null
+++ b/packages/SettingsLib/BannerMessagePreference/res/values-or/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (C) 2021 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="accessibility_banner_message_dismiss" msgid="5272928723898304168">"ଖାରଜ କରନ୍ତୁ"</string>
+</resources>
diff --git a/packages/SettingsLib/FooterPreference/res/values-bn/strings.xml b/packages/SettingsLib/FooterPreference/res/values-bn/strings.xml
new file mode 100644
index 000000000000..c58142d72618
--- /dev/null
+++ b/packages/SettingsLib/FooterPreference/res/values-bn/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (C) 2021 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="settingslib_learn_more_text" msgid="7385478101223578464">"আরও জানুন"</string>
+</resources>
diff --git a/packages/SettingsLib/FooterPreference/res/values-de/strings.xml b/packages/SettingsLib/FooterPreference/res/values-de/strings.xml
new file mode 100644
index 000000000000..fe885aa6f091
--- /dev/null
+++ b/packages/SettingsLib/FooterPreference/res/values-de/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (C) 2021 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="settingslib_learn_more_text" msgid="7385478101223578464">"Weitere Informationen"</string>
+</resources>
diff --git a/packages/SettingsLib/FooterPreference/res/values-mr/strings.xml b/packages/SettingsLib/FooterPreference/res/values-mr/strings.xml
new file mode 100644
index 000000000000..45387200bdc8
--- /dev/null
+++ b/packages/SettingsLib/FooterPreference/res/values-mr/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (C) 2021 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="settingslib_learn_more_text" msgid="7385478101223578464">"अधिक जाणून घ्या"</string>
+</resources>
diff --git a/packages/SettingsLib/FooterPreference/res/values-ne/strings.xml b/packages/SettingsLib/FooterPreference/res/values-ne/strings.xml
new file mode 100644
index 000000000000..ecfec36337ee
--- /dev/null
+++ b/packages/SettingsLib/FooterPreference/res/values-ne/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (C) 2021 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="settingslib_learn_more_text" msgid="7385478101223578464">"थप जान्नुहोस्"</string>
+</resources>
diff --git a/packages/SettingsLib/FooterPreference/res/values-or/strings.xml b/packages/SettingsLib/FooterPreference/res/values-or/strings.xml
new file mode 100644
index 000000000000..e7924d646861
--- /dev/null
+++ b/packages/SettingsLib/FooterPreference/res/values-or/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (C) 2021 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="settingslib_learn_more_text" msgid="7385478101223578464">"ଅଧିକ ଜାଣନ୍ତୁ"</string>
+</resources>
diff --git a/packages/SettingsLib/SettingsTheme/res/values-v31/styles.xml b/packages/SettingsLib/SettingsTheme/res/values-v31/styles.xml
index 9610c9443184..46f1e030af23 100644
--- a/packages/SettingsLib/SettingsTheme/res/values-v31/styles.xml
+++ b/packages/SettingsLib/SettingsTheme/res/values-v31/styles.xml
@@ -25,6 +25,7 @@
<style name="Switch.SettingsLib" parent="@android:style/Widget.Material.CompoundButton.Switch">
<item name="android:switchMinWidth">52dp</item>
+ <item name="android:minHeight">@dimen/settingslib_preferred_minimum_touch_target</item>
<item name="android:track">@drawable/settingslib_switch_track</item>
<item name="android:thumb">@drawable/settingslib_switch_thumb</item>
</style>
diff --git a/packages/SettingsLib/res/values-af/strings.xml b/packages/SettingsLib/res/values-af/strings.xml
index 89bb9e8bfe01..fa3f34c96ad2 100644
--- a/packages/SettingsLib/res/values-af/strings.xml
+++ b/packages/SettingsLib/res/values-af/strings.xml
@@ -566,8 +566,7 @@
<string name="user_nickname" msgid="262624187455825083">"Bynaam"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"Voeg gas by"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"Verwyder gas"</string>
- <!-- no translation found for guest_reset_guest (6110013010356013758) -->
- <skip />
+ <string name="guest_reset_guest" msgid="6110013010356013758">"Stel gassessie terug"</string>
<string name="guest_nickname" msgid="6332276931583337261">"Gas"</string>
<string name="user_image_take_photo" msgid="467512954561638530">"Neem \'n foto"</string>
<string name="user_image_choose_photo" msgid="1363820919146782908">"Kies \'n prent"</string>
diff --git a/packages/SettingsLib/res/values-am/strings.xml b/packages/SettingsLib/res/values-am/strings.xml
index bc1bd1633e4c..7b4c832fd1d0 100644
--- a/packages/SettingsLib/res/values-am/strings.xml
+++ b/packages/SettingsLib/res/values-am/strings.xml
@@ -566,8 +566,7 @@
<string name="user_nickname" msgid="262624187455825083">"ቅጽል ስም"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"እንግዳን አክል"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"እንግዳን አስወግድ"</string>
- <!-- no translation found for guest_reset_guest (6110013010356013758) -->
- <skip />
+ <string name="guest_reset_guest" msgid="6110013010356013758">"እንግዳን ዳግም አስጀምር"</string>
<string name="guest_nickname" msgid="6332276931583337261">"እንግዳ"</string>
<string name="user_image_take_photo" msgid="467512954561638530">"ፎቶ አንሳ"</string>
<string name="user_image_choose_photo" msgid="1363820919146782908">"ምስል ይምረጡ"</string>
diff --git a/packages/SettingsLib/res/values-as/strings.xml b/packages/SettingsLib/res/values-as/strings.xml
index f04aaac87b6d..611f2c44f565 100644
--- a/packages/SettingsLib/res/values-as/strings.xml
+++ b/packages/SettingsLib/res/values-as/strings.xml
@@ -566,8 +566,7 @@
<string name="user_nickname" msgid="262624187455825083">"উপনাম"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"অতিথি যোগ কৰক"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"অতিথি আঁতৰাওক"</string>
- <!-- no translation found for guest_reset_guest (6110013010356013758) -->
- <skip />
+ <string name="guest_reset_guest" msgid="6110013010356013758">"অতিথিৰ ছেশ্বন ৰিছেট কৰক"</string>
<string name="guest_nickname" msgid="6332276931583337261">"অতিথি"</string>
<string name="user_image_take_photo" msgid="467512954561638530">"এখন ফট’ তোলক"</string>
<string name="user_image_choose_photo" msgid="1363820919146782908">"এখন প্ৰতিচ্ছবি বাছনি কৰক"</string>
diff --git a/packages/SettingsLib/res/values-az/strings.xml b/packages/SettingsLib/res/values-az/strings.xml
index b7cf11ae3754..c50a22d18605 100644
--- a/packages/SettingsLib/res/values-az/strings.xml
+++ b/packages/SettingsLib/res/values-az/strings.xml
@@ -566,8 +566,7 @@
<string name="user_nickname" msgid="262624187455825083">"Ləqəb"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"Qonaq əlavə edin"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"Qonağı silin"</string>
- <!-- no translation found for guest_reset_guest (6110013010356013758) -->
- <skip />
+ <string name="guest_reset_guest" msgid="6110013010356013758">"Qonaq sessiyasını sıfırlayın"</string>
<string name="guest_nickname" msgid="6332276931583337261">"Qonaq"</string>
<string name="user_image_take_photo" msgid="467512954561638530">"Foto çəkin"</string>
<string name="user_image_choose_photo" msgid="1363820919146782908">"Şəkil seçin"</string>
@@ -576,7 +575,7 @@
<string name="cached_apps_freezer_disabled" msgid="4816382260660472042">"Deaktiv"</string>
<string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"Aktiv"</string>
<string name="cached_apps_freezer_reboot_dialog_text" msgid="695330563489230096">"Bu dəyişikliyin tətbiq edilməsi üçün cihaz yenidən başladılmalıdır. İndi yenidən başladın və ya ləğv edin."</string>
- <string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"Simli qulaqlıq"</string>
+ <string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"Naqilli qulaqlıq"</string>
<string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"Aktiv"</string>
<string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"Deaktiv"</string>
<string name="carrier_network_change_mode" msgid="4257621815706644026">"Operator şəbəkəsinin dəyişilməsi"</string>
diff --git a/packages/SettingsLib/res/values-b+sr+Latn/strings.xml b/packages/SettingsLib/res/values-b+sr+Latn/strings.xml
index 97c281ad2d67..e26d0650c8cc 100644
--- a/packages/SettingsLib/res/values-b+sr+Latn/strings.xml
+++ b/packages/SettingsLib/res/values-b+sr+Latn/strings.xml
@@ -567,8 +567,7 @@
<string name="user_nickname" msgid="262624187455825083">"Nadimak"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"Dodaj gosta"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"Ukloni gosta"</string>
- <!-- no translation found for guest_reset_guest (6110013010356013758) -->
- <skip />
+ <string name="guest_reset_guest" msgid="6110013010356013758">"Resetuj sesiju gosta"</string>
<string name="guest_nickname" msgid="6332276931583337261">"Gost"</string>
<string name="user_image_take_photo" msgid="467512954561638530">"Slikaj"</string>
<string name="user_image_choose_photo" msgid="1363820919146782908">"Odaberi sliku"</string>
diff --git a/packages/SettingsLib/res/values-bg/strings.xml b/packages/SettingsLib/res/values-bg/strings.xml
index 09e584318173..7899fa687ddc 100644
--- a/packages/SettingsLib/res/values-bg/strings.xml
+++ b/packages/SettingsLib/res/values-bg/strings.xml
@@ -566,8 +566,7 @@
<string name="user_nickname" msgid="262624187455825083">"Псевдоним"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"Добавяне на гост"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"Премахване на госта"</string>
- <!-- no translation found for guest_reset_guest (6110013010356013758) -->
- <skip />
+ <string name="guest_reset_guest" msgid="6110013010356013758">"Нулиране на сесията като гост"</string>
<string name="guest_nickname" msgid="6332276931583337261">"Гост"</string>
<string name="user_image_take_photo" msgid="467512954561638530">"Правене на снимка"</string>
<string name="user_image_choose_photo" msgid="1363820919146782908">"Избиране на изображение"</string>
diff --git a/packages/SettingsLib/res/values-bs/strings.xml b/packages/SettingsLib/res/values-bs/strings.xml
index 88abe33d1f18..9eb20f90735f 100644
--- a/packages/SettingsLib/res/values-bs/strings.xml
+++ b/packages/SettingsLib/res/values-bs/strings.xml
@@ -567,8 +567,7 @@
<string name="user_nickname" msgid="262624187455825083">"Nadimak"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"Dodaj gosta"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"Ukloni gosta"</string>
- <!-- no translation found for guest_reset_guest (6110013010356013758) -->
- <skip />
+ <string name="guest_reset_guest" msgid="6110013010356013758">"Poništi sesiju gosta"</string>
<string name="guest_nickname" msgid="6332276931583337261">"Gost"</string>
<string name="user_image_take_photo" msgid="467512954561638530">"Snimite fotografiju"</string>
<string name="user_image_choose_photo" msgid="1363820919146782908">"Odaberite sliku"</string>
diff --git a/packages/SettingsLib/res/values-ca/strings.xml b/packages/SettingsLib/res/values-ca/strings.xml
index f499ab6cc7c0..d3590bf9e8d2 100644
--- a/packages/SettingsLib/res/values-ca/strings.xml
+++ b/packages/SettingsLib/res/values-ca/strings.xml
@@ -566,8 +566,7 @@
<string name="user_nickname" msgid="262624187455825083">"Àlies"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"Afegeix un convidat"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"Suprimeix el convidat"</string>
- <!-- no translation found for guest_reset_guest (6110013010356013758) -->
- <skip />
+ <string name="guest_reset_guest" msgid="6110013010356013758">"Restableix el convidat"</string>
<string name="guest_nickname" msgid="6332276931583337261">"Convidat"</string>
<string name="user_image_take_photo" msgid="467512954561638530">"Fes una foto"</string>
<string name="user_image_choose_photo" msgid="1363820919146782908">"Tria una imatge"</string>
diff --git a/packages/SettingsLib/res/values-cs/strings.xml b/packages/SettingsLib/res/values-cs/strings.xml
index 4d07eff0e858..5c664b987101 100644
--- a/packages/SettingsLib/res/values-cs/strings.xml
+++ b/packages/SettingsLib/res/values-cs/strings.xml
@@ -568,8 +568,7 @@
<string name="user_nickname" msgid="262624187455825083">"Přezdívka"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"Přidat hosta"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"Odstranit hosta"</string>
- <!-- no translation found for guest_reset_guest (6110013010356013758) -->
- <skip />
+ <string name="guest_reset_guest" msgid="6110013010356013758">"Resetovat hosta"</string>
<string name="guest_nickname" msgid="6332276931583337261">"Host"</string>
<string name="user_image_take_photo" msgid="467512954561638530">"Pořídit fotku"</string>
<string name="user_image_choose_photo" msgid="1363820919146782908">"Vybrat obrázek"</string>
diff --git a/packages/SettingsLib/res/values-el/strings.xml b/packages/SettingsLib/res/values-el/strings.xml
index 98f53011d2ca..59bfab8ddea8 100644
--- a/packages/SettingsLib/res/values-el/strings.xml
+++ b/packages/SettingsLib/res/values-el/strings.xml
@@ -566,8 +566,7 @@
<string name="user_nickname" msgid="262624187455825083">"Ψευδώνυμο"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"Προσθήκη επισκέπτη"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"Κατάργηση επισκέπτη"</string>
- <!-- no translation found for guest_reset_guest (6110013010356013758) -->
- <skip />
+ <string name="guest_reset_guest" msgid="6110013010356013758">"Επαναφορά περιόδου επισκέπτη"</string>
<string name="guest_nickname" msgid="6332276931583337261">"Επισκέπτης"</string>
<string name="user_image_take_photo" msgid="467512954561638530">"Λήψη φωτογραφίας"</string>
<string name="user_image_choose_photo" msgid="1363820919146782908">"Επιλογή εικόνας"</string>
diff --git a/packages/SettingsLib/res/values-es/strings.xml b/packages/SettingsLib/res/values-es/strings.xml
index 6ff48541e4e8..26c7b2c7a760 100644
--- a/packages/SettingsLib/res/values-es/strings.xml
+++ b/packages/SettingsLib/res/values-es/strings.xml
@@ -566,8 +566,7 @@
<string name="user_nickname" msgid="262624187455825083">"Apodo"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"Añadir invitado"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"Quitar invitado"</string>
- <!-- no translation found for guest_reset_guest (6110013010356013758) -->
- <skip />
+ <string name="guest_reset_guest" msgid="6110013010356013758">"Restablecer invitado"</string>
<string name="guest_nickname" msgid="6332276931583337261">"Invitado"</string>
<string name="user_image_take_photo" msgid="467512954561638530">"Hacer foto"</string>
<string name="user_image_choose_photo" msgid="1363820919146782908">"Seleccionar una imagen"</string>
diff --git a/packages/SettingsLib/res/values-et/strings.xml b/packages/SettingsLib/res/values-et/strings.xml
index ef7b7db2bb9b..194aeaff4b15 100644
--- a/packages/SettingsLib/res/values-et/strings.xml
+++ b/packages/SettingsLib/res/values-et/strings.xml
@@ -566,8 +566,7 @@
<string name="user_nickname" msgid="262624187455825083">"Hüüdnimi"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"Lisa külaline"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"Eemalda külaline"</string>
- <!-- no translation found for guest_reset_guest (6110013010356013758) -->
- <skip />
+ <string name="guest_reset_guest" msgid="6110013010356013758">"Lähtesta külastajaseanss"</string>
<string name="guest_nickname" msgid="6332276931583337261">"Külaline"</string>
<string name="user_image_take_photo" msgid="467512954561638530">"Pildistage"</string>
<string name="user_image_choose_photo" msgid="1363820919146782908">"Valige pilt"</string>
diff --git a/packages/SettingsLib/res/values-eu/strings.xml b/packages/SettingsLib/res/values-eu/strings.xml
index 93506105d964..33e2314dd887 100644
--- a/packages/SettingsLib/res/values-eu/strings.xml
+++ b/packages/SettingsLib/res/values-eu/strings.xml
@@ -528,7 +528,7 @@
<string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Audio-gailu kableduna"</string>
<string name="help_label" msgid="3528360748637781274">"Laguntza eta iritziak"</string>
<string name="storage_category" msgid="2287342585424631813">"Biltegiratzea"</string>
- <string name="shared_data_title" msgid="1017034836800864953">"Partekatutako datuak"</string>
+ <string name="shared_data_title" msgid="1017034836800864953">"Datu partekatuak"</string>
<string name="shared_data_summary" msgid="5516326713822885652">"Ikusi eta aldatu partekatutako datuak"</string>
<string name="shared_data_no_blobs_text" msgid="3108114670341737434">"Ez dago erabiltzaile honen datu partekaturik."</string>
<string name="shared_data_query_failure_text" msgid="3489828881998773687">"Errore bat gertatu da datu partekatuak eskuratzean. Saiatu berriro."</string>
@@ -566,8 +566,7 @@
<string name="user_nickname" msgid="262624187455825083">"Goitizena"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"Gehitu gonbidatua"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"Kendu gonbidatua"</string>
- <!-- no translation found for guest_reset_guest (6110013010356013758) -->
- <skip />
+ <string name="guest_reset_guest" msgid="6110013010356013758">"Berrezarri gonbidatuentzako saioa"</string>
<string name="guest_nickname" msgid="6332276931583337261">"Gonbidatua"</string>
<string name="user_image_take_photo" msgid="467512954561638530">"Atera argazki bat"</string>
<string name="user_image_choose_photo" msgid="1363820919146782908">"Aukeratu irudi bat"</string>
diff --git a/packages/SettingsLib/res/values-fi/strings.xml b/packages/SettingsLib/res/values-fi/strings.xml
index 964162b34357..a11a00a5f65d 100644
--- a/packages/SettingsLib/res/values-fi/strings.xml
+++ b/packages/SettingsLib/res/values-fi/strings.xml
@@ -566,8 +566,7 @@
<string name="user_nickname" msgid="262624187455825083">"Lempinimi"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"Lisää vieras"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"Poista vieras"</string>
- <!-- no translation found for guest_reset_guest (6110013010356013758) -->
- <skip />
+ <string name="guest_reset_guest" msgid="6110013010356013758">"Nollaa vieras"</string>
<string name="guest_nickname" msgid="6332276931583337261">"Vieras"</string>
<string name="user_image_take_photo" msgid="467512954561638530">"Ota kuva"</string>
<string name="user_image_choose_photo" msgid="1363820919146782908">"Valitse kuva"</string>
diff --git a/packages/SettingsLib/res/values-gl/strings.xml b/packages/SettingsLib/res/values-gl/strings.xml
index 73f98ec23ccf..dba912ea3920 100644
--- a/packages/SettingsLib/res/values-gl/strings.xml
+++ b/packages/SettingsLib/res/values-gl/strings.xml
@@ -566,8 +566,7 @@
<string name="user_nickname" msgid="262624187455825083">"Alcume"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"Engadir convidado"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"Quitar convidado"</string>
- <!-- no translation found for guest_reset_guest (6110013010356013758) -->
- <skip />
+ <string name="guest_reset_guest" msgid="6110013010356013758">"Restablecer sesión de convidado"</string>
<string name="guest_nickname" msgid="6332276931583337261">"Convidado"</string>
<string name="user_image_take_photo" msgid="467512954561638530">"Tirar foto"</string>
<string name="user_image_choose_photo" msgid="1363820919146782908">"Escoller imaxe"</string>
diff --git a/packages/SettingsLib/res/values-hi/strings.xml b/packages/SettingsLib/res/values-hi/strings.xml
index 5620d946b999..bc74092efa8d 100644
--- a/packages/SettingsLib/res/values-hi/strings.xml
+++ b/packages/SettingsLib/res/values-hi/strings.xml
@@ -566,8 +566,7 @@
<string name="user_nickname" msgid="262624187455825083">"प्रचलित नाम"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"मेहमान जोड़ें"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"मेहमान हटाएं"</string>
- <!-- no translation found for guest_reset_guest (6110013010356013758) -->
- <skip />
+ <string name="guest_reset_guest" msgid="6110013010356013758">"मेहमान के तौर पर ब्राउज़ करने का सेशन रीसेट करें"</string>
<string name="guest_nickname" msgid="6332276931583337261">"मेहमान"</string>
<string name="user_image_take_photo" msgid="467512954561638530">"फ़ोटो खींचें"</string>
<string name="user_image_choose_photo" msgid="1363820919146782908">"कोई इमेज चुनें"</string>
diff --git a/packages/SettingsLib/res/values-hr/strings.xml b/packages/SettingsLib/res/values-hr/strings.xml
index 0ff35f890407..d18d34cb0037 100644
--- a/packages/SettingsLib/res/values-hr/strings.xml
+++ b/packages/SettingsLib/res/values-hr/strings.xml
@@ -567,8 +567,7 @@
<string name="user_nickname" msgid="262624187455825083">"Nadimak"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"Dodavanje gosta"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"Uklanjanje gosta"</string>
- <!-- no translation found for guest_reset_guest (6110013010356013758) -->
- <skip />
+ <string name="guest_reset_guest" msgid="6110013010356013758">"Poništi gostujuću sesiju"</string>
<string name="guest_nickname" msgid="6332276931583337261">"Gost"</string>
<string name="user_image_take_photo" msgid="467512954561638530">"Fotografiraj"</string>
<string name="user_image_choose_photo" msgid="1363820919146782908">"Odaberi sliku"</string>
diff --git a/packages/SettingsLib/res/values-hu/strings.xml b/packages/SettingsLib/res/values-hu/strings.xml
index 9bd4d1263abd..3ad3590ca728 100644
--- a/packages/SettingsLib/res/values-hu/strings.xml
+++ b/packages/SettingsLib/res/values-hu/strings.xml
@@ -566,8 +566,7 @@
<string name="user_nickname" msgid="262624187455825083">"Becenév"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"Vendég hozzáadása"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"Vendég munkamenet eltávolítása"</string>
- <!-- no translation found for guest_reset_guest (6110013010356013758) -->
- <skip />
+ <string name="guest_reset_guest" msgid="6110013010356013758">"Vendég munkamenet visszaállítása"</string>
<string name="guest_nickname" msgid="6332276931583337261">"Vendég"</string>
<string name="user_image_take_photo" msgid="467512954561638530">"Fotó készítése"</string>
<string name="user_image_choose_photo" msgid="1363820919146782908">"Kép kiválasztása"</string>
diff --git a/packages/SettingsLib/res/values-is/strings.xml b/packages/SettingsLib/res/values-is/strings.xml
index 662a67361b33..da92e7d4517f 100644
--- a/packages/SettingsLib/res/values-is/strings.xml
+++ b/packages/SettingsLib/res/values-is/strings.xml
@@ -566,8 +566,7 @@
<string name="user_nickname" msgid="262624187455825083">"Gælunafn"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"Bæta gesti við"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"Fjarlægja gest"</string>
- <!-- no translation found for guest_reset_guest (6110013010356013758) -->
- <skip />
+ <string name="guest_reset_guest" msgid="6110013010356013758">"Endurstilla gestastillingu"</string>
<string name="guest_nickname" msgid="6332276931583337261">"Gestur"</string>
<string name="user_image_take_photo" msgid="467512954561638530">"Taka mynd"</string>
<string name="user_image_choose_photo" msgid="1363820919146782908">"Velja mynd"</string>
diff --git a/packages/SettingsLib/res/values-it/strings.xml b/packages/SettingsLib/res/values-it/strings.xml
index 2c2d11fecda4..6f7565e3fb02 100644
--- a/packages/SettingsLib/res/values-it/strings.xml
+++ b/packages/SettingsLib/res/values-it/strings.xml
@@ -566,8 +566,7 @@
<string name="user_nickname" msgid="262624187455825083">"Nickname"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"Aggiungi ospite"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"Rimuovi ospite"</string>
- <!-- no translation found for guest_reset_guest (6110013010356013758) -->
- <skip />
+ <string name="guest_reset_guest" msgid="6110013010356013758">"Reimposta sessione Ospite"</string>
<string name="guest_nickname" msgid="6332276931583337261">"Ospite"</string>
<string name="user_image_take_photo" msgid="467512954561638530">"Scatta una foto"</string>
<string name="user_image_choose_photo" msgid="1363820919146782908">"Scegli un\'immagine"</string>
diff --git a/packages/SettingsLib/res/values-kk/strings.xml b/packages/SettingsLib/res/values-kk/strings.xml
index ddae3c72babb..70dd9e74929b 100644
--- a/packages/SettingsLib/res/values-kk/strings.xml
+++ b/packages/SettingsLib/res/values-kk/strings.xml
@@ -566,8 +566,7 @@
<string name="user_nickname" msgid="262624187455825083">"Лақап ат"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"Қонақ қосу"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"Қонақты жою"</string>
- <!-- no translation found for guest_reset_guest (6110013010356013758) -->
- <skip />
+ <string name="guest_reset_guest" msgid="6110013010356013758">"Қонақ сеансын әдепкі күйге қайтару"</string>
<string name="guest_nickname" msgid="6332276931583337261">"Қонақ"</string>
<string name="user_image_take_photo" msgid="467512954561638530">"Фотосуретке түсіру"</string>
<string name="user_image_choose_photo" msgid="1363820919146782908">"Сурет таңдау"</string>
diff --git a/packages/SettingsLib/res/values-km/strings.xml b/packages/SettingsLib/res/values-km/strings.xml
index d970e9590c36..26595f5cc067 100644
--- a/packages/SettingsLib/res/values-km/strings.xml
+++ b/packages/SettingsLib/res/values-km/strings.xml
@@ -566,8 +566,7 @@
<string name="user_nickname" msgid="262624187455825083">"ឈ្មោះ​ហៅក្រៅ"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"បញ្ចូល​ភ្ញៀវ"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"ដកភ្ញៀវចេញ"</string>
- <!-- no translation found for guest_reset_guest (6110013010356013758) -->
- <skip />
+ <string name="guest_reset_guest" msgid="6110013010356013758">"កំណត់​ភ្ញៀវឡើង​វិញ"</string>
<string name="guest_nickname" msgid="6332276931583337261">"ភ្ញៀវ"</string>
<string name="user_image_take_photo" msgid="467512954561638530">"ថតរូប"</string>
<string name="user_image_choose_photo" msgid="1363820919146782908">"ជ្រើសរើស​រូបភាព"</string>
diff --git a/packages/SettingsLib/res/values-kn/strings.xml b/packages/SettingsLib/res/values-kn/strings.xml
index 8bad32006594..b36ef8d2a2da 100644
--- a/packages/SettingsLib/res/values-kn/strings.xml
+++ b/packages/SettingsLib/res/values-kn/strings.xml
@@ -566,8 +566,7 @@
<string name="user_nickname" msgid="262624187455825083">"ಅಡ್ಡ ಹೆಸರು"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"ಅತಿಥಿಯನ್ನು ಸೇರಿಸಿ"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"ಅತಿಥಿಯನ್ನು ತೆಗೆದುಹಾಕಿ"</string>
- <!-- no translation found for guest_reset_guest (6110013010356013758) -->
- <skip />
+ <string name="guest_reset_guest" msgid="6110013010356013758">"ಅತಿಥಿಯನ್ನು ಮರುಹೊಂದಿಸಿ"</string>
<string name="guest_nickname" msgid="6332276931583337261">"ಅತಿಥಿ"</string>
<string name="user_image_take_photo" msgid="467512954561638530">"ಫೋಟೋ ತೆಗೆದುಕೊಳ್ಳಿ"</string>
<string name="user_image_choose_photo" msgid="1363820919146782908">"ಚಿತ್ರವನ್ನು ಆರಿಸಿ"</string>
diff --git a/packages/SettingsLib/res/values-lt/strings.xml b/packages/SettingsLib/res/values-lt/strings.xml
index 3383602753f1..ad0ad1fb28bf 100644
--- a/packages/SettingsLib/res/values-lt/strings.xml
+++ b/packages/SettingsLib/res/values-lt/strings.xml
@@ -568,8 +568,7 @@
<string name="user_nickname" msgid="262624187455825083">"Slapyvardis"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"Pridėti svečią"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"Pašalinti svečią"</string>
- <!-- no translation found for guest_reset_guest (6110013010356013758) -->
- <skip />
+ <string name="guest_reset_guest" msgid="6110013010356013758">"Iš naujo nustatyti svečią"</string>
<string name="guest_nickname" msgid="6332276931583337261">"Svečias"</string>
<string name="user_image_take_photo" msgid="467512954561638530">"Fotografuoti"</string>
<string name="user_image_choose_photo" msgid="1363820919146782908">"Pasirinkti vaizdą"</string>
diff --git a/packages/SettingsLib/res/values-lv/strings.xml b/packages/SettingsLib/res/values-lv/strings.xml
index d655afc7ae35..586de6fcfdf7 100644
--- a/packages/SettingsLib/res/values-lv/strings.xml
+++ b/packages/SettingsLib/res/values-lv/strings.xml
@@ -567,8 +567,7 @@
<string name="user_nickname" msgid="262624187455825083">"Segvārds"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"Pievienot viesi"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"Noņemt viesi"</string>
- <!-- no translation found for guest_reset_guest (6110013010356013758) -->
- <skip />
+ <string name="guest_reset_guest" msgid="6110013010356013758">"Atiestatīt viesa sesiju"</string>
<string name="guest_nickname" msgid="6332276931583337261">"Viesis"</string>
<string name="user_image_take_photo" msgid="467512954561638530">"Uzņemt fotoattēlu"</string>
<string name="user_image_choose_photo" msgid="1363820919146782908">"Izvēlēties attēlu"</string>
diff --git a/packages/SettingsLib/res/values-mk/strings.xml b/packages/SettingsLib/res/values-mk/strings.xml
index bd7f074f01a0..0d0f345af7c3 100644
--- a/packages/SettingsLib/res/values-mk/strings.xml
+++ b/packages/SettingsLib/res/values-mk/strings.xml
@@ -566,8 +566,7 @@
<string name="user_nickname" msgid="262624187455825083">"Прекар"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"Додајте гостин"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"Отстрани гостин"</string>
- <!-- no translation found for guest_reset_guest (6110013010356013758) -->
- <skip />
+ <string name="guest_reset_guest" msgid="6110013010356013758">"Ресетирајте го гостинот"</string>
<string name="guest_nickname" msgid="6332276931583337261">"Гостин"</string>
<string name="user_image_take_photo" msgid="467512954561638530">"Фотографирајте"</string>
<string name="user_image_choose_photo" msgid="1363820919146782908">"Одберете слика"</string>
diff --git a/packages/SettingsLib/res/values-ml/strings.xml b/packages/SettingsLib/res/values-ml/strings.xml
index 1e80ccd0f3ab..655be1a74c31 100644
--- a/packages/SettingsLib/res/values-ml/strings.xml
+++ b/packages/SettingsLib/res/values-ml/strings.xml
@@ -566,8 +566,7 @@
<string name="user_nickname" msgid="262624187455825083">"വിളിപ്പേര്"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"അതിഥിയെ ചേർക്കുക"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"അതിഥിയെ നീക്കം ചെയ്യുക"</string>
- <!-- no translation found for guest_reset_guest (6110013010356013758) -->
- <skip />
+ <string name="guest_reset_guest" msgid="6110013010356013758">"അതിഥിയെ റീസെറ്റ് ചെയ്യുക"</string>
<string name="guest_nickname" msgid="6332276931583337261">"അതിഥി"</string>
<string name="user_image_take_photo" msgid="467512954561638530">"ഒരു ഫോട്ടോ എടുക്കുക"</string>
<string name="user_image_choose_photo" msgid="1363820919146782908">"ഒരു ചിത്രം തിരഞ്ഞെടുക്കുക"</string>
diff --git a/packages/SettingsLib/res/values-mn/strings.xml b/packages/SettingsLib/res/values-mn/strings.xml
index 40b65efe275e..07ed369b8d36 100644
--- a/packages/SettingsLib/res/values-mn/strings.xml
+++ b/packages/SettingsLib/res/values-mn/strings.xml
@@ -566,8 +566,7 @@
<string name="user_nickname" msgid="262624187455825083">"Хоч"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"Зочин нэмэх"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"Зочин хасах"</string>
- <!-- no translation found for guest_reset_guest (6110013010356013758) -->
- <skip />
+ <string name="guest_reset_guest" msgid="6110013010356013758">"Зочныг шинэчлэх"</string>
<string name="guest_nickname" msgid="6332276931583337261">"Зочин"</string>
<string name="user_image_take_photo" msgid="467512954561638530">"Зураг авах"</string>
<string name="user_image_choose_photo" msgid="1363820919146782908">"Зураг сонгох"</string>
diff --git a/packages/SettingsLib/res/values-mr/strings.xml b/packages/SettingsLib/res/values-mr/strings.xml
index 6a46edee6ce5..fe8e8375a65a 100644
--- a/packages/SettingsLib/res/values-mr/strings.xml
+++ b/packages/SettingsLib/res/values-mr/strings.xml
@@ -566,8 +566,7 @@
<string name="user_nickname" msgid="262624187455825083">"टोपणनाव"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"अतिथी जोडा"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"अतिथी काढून टाका"</string>
- <!-- no translation found for guest_reset_guest (6110013010356013758) -->
- <skip />
+ <string name="guest_reset_guest" msgid="6110013010356013758">"अतिथी सेशन रीसेट करा"</string>
<string name="guest_nickname" msgid="6332276931583337261">"अतिथी"</string>
<string name="user_image_take_photo" msgid="467512954561638530">"फोटो काढा"</string>
<string name="user_image_choose_photo" msgid="1363820919146782908">"इमेज निवडा"</string>
diff --git a/packages/SettingsLib/res/values-my/strings.xml b/packages/SettingsLib/res/values-my/strings.xml
index 7156a8ef6548..b383ad84cadb 100644
--- a/packages/SettingsLib/res/values-my/strings.xml
+++ b/packages/SettingsLib/res/values-my/strings.xml
@@ -566,8 +566,7 @@
<string name="user_nickname" msgid="262624187455825083">"နာမည်ပြောင်"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"ဧည့်သည့် ထည့်ရန်"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"ဧည့်သည်ကို ဖယ်ထုတ်ရန်"</string>
- <!-- no translation found for guest_reset_guest (6110013010356013758) -->
- <skip />
+ <string name="guest_reset_guest" msgid="6110013010356013758">"ဧည့်သည်ကို ပြင်ဆင်သတ်မှတ်ရန်"</string>
<string name="guest_nickname" msgid="6332276931583337261">"ဧည့်သည်"</string>
<string name="user_image_take_photo" msgid="467512954561638530">"ဓာတ်ပုံရိုက်ရန်"</string>
<string name="user_image_choose_photo" msgid="1363820919146782908">"ပုံရွေးရန်"</string>
diff --git a/packages/SettingsLib/res/values-nb/strings.xml b/packages/SettingsLib/res/values-nb/strings.xml
index bb93a29feaa5..84c231faed46 100644
--- a/packages/SettingsLib/res/values-nb/strings.xml
+++ b/packages/SettingsLib/res/values-nb/strings.xml
@@ -566,8 +566,7 @@
<string name="user_nickname" msgid="262624187455825083">"Kallenavn"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"Legg til en gjest"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"Fjern gjesten"</string>
- <!-- no translation found for guest_reset_guest (6110013010356013758) -->
- <skip />
+ <string name="guest_reset_guest" msgid="6110013010356013758">"Tilbakestill gjest"</string>
<string name="guest_nickname" msgid="6332276931583337261">"Gjest"</string>
<string name="user_image_take_photo" msgid="467512954561638530">"Ta et bilde"</string>
<string name="user_image_choose_photo" msgid="1363820919146782908">"Velg et bilde"</string>
diff --git a/packages/SettingsLib/res/values-nl/strings.xml b/packages/SettingsLib/res/values-nl/strings.xml
index a33bbf3e2dd9..1837eabf2370 100644
--- a/packages/SettingsLib/res/values-nl/strings.xml
+++ b/packages/SettingsLib/res/values-nl/strings.xml
@@ -566,8 +566,7 @@
<string name="user_nickname" msgid="262624187455825083">"Bijnaam"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"Gast toevoegen"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"Gast verwijderen"</string>
- <!-- no translation found for guest_reset_guest (6110013010356013758) -->
- <skip />
+ <string name="guest_reset_guest" msgid="6110013010356013758">"Gastsessie resetten"</string>
<string name="guest_nickname" msgid="6332276931583337261">"Gast"</string>
<string name="user_image_take_photo" msgid="467512954561638530">"Foto maken"</string>
<string name="user_image_choose_photo" msgid="1363820919146782908">"Afbeelding kiezen"</string>
diff --git a/packages/SettingsLib/res/values-pl/strings.xml b/packages/SettingsLib/res/values-pl/strings.xml
index 5f410a86691b..bd77d881560f 100644
--- a/packages/SettingsLib/res/values-pl/strings.xml
+++ b/packages/SettingsLib/res/values-pl/strings.xml
@@ -568,8 +568,7 @@
<string name="user_nickname" msgid="262624187455825083">"Pseudonim"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"Dodaj gościa"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"Usuń gościa"</string>
- <!-- no translation found for guest_reset_guest (6110013010356013758) -->
- <skip />
+ <string name="guest_reset_guest" msgid="6110013010356013758">"Resetuj sesję gościa"</string>
<string name="guest_nickname" msgid="6332276931583337261">"Gość"</string>
<string name="user_image_take_photo" msgid="467512954561638530">"Zrób zdjęcie"</string>
<string name="user_image_choose_photo" msgid="1363820919146782908">"Wybierz obraz"</string>
diff --git a/packages/SettingsLib/res/values-pt-rBR/strings.xml b/packages/SettingsLib/res/values-pt-rBR/strings.xml
index 3c8d928a7213..e39b58bb8344 100644
--- a/packages/SettingsLib/res/values-pt-rBR/strings.xml
+++ b/packages/SettingsLib/res/values-pt-rBR/strings.xml
@@ -566,8 +566,7 @@
<string name="user_nickname" msgid="262624187455825083">"Apelido"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"Adicionar convidado"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"Remover convidado"</string>
- <!-- no translation found for guest_reset_guest (6110013010356013758) -->
- <skip />
+ <string name="guest_reset_guest" msgid="6110013010356013758">"Redefinir sessão de visitante"</string>
<string name="guest_nickname" msgid="6332276931583337261">"Convidado"</string>
<string name="user_image_take_photo" msgid="467512954561638530">"Tirar uma foto"</string>
<string name="user_image_choose_photo" msgid="1363820919146782908">"Escolher uma imagem"</string>
diff --git a/packages/SettingsLib/res/values-pt-rPT/strings.xml b/packages/SettingsLib/res/values-pt-rPT/strings.xml
index fc98aa732606..a5c0d1d58d40 100644
--- a/packages/SettingsLib/res/values-pt-rPT/strings.xml
+++ b/packages/SettingsLib/res/values-pt-rPT/strings.xml
@@ -566,8 +566,7 @@
<string name="user_nickname" msgid="262624187455825083">"Alcunha"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"Adicionar convidado"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"Remover convidado"</string>
- <!-- no translation found for guest_reset_guest (6110013010356013758) -->
- <skip />
+ <string name="guest_reset_guest" msgid="6110013010356013758">"Repor convidado"</string>
<string name="guest_nickname" msgid="6332276931583337261">"Convidado"</string>
<string name="user_image_take_photo" msgid="467512954561638530">"Tirar uma foto"</string>
<string name="user_image_choose_photo" msgid="1363820919146782908">"Escolher uma imagem"</string>
diff --git a/packages/SettingsLib/res/values-pt/strings.xml b/packages/SettingsLib/res/values-pt/strings.xml
index 3c8d928a7213..e39b58bb8344 100644
--- a/packages/SettingsLib/res/values-pt/strings.xml
+++ b/packages/SettingsLib/res/values-pt/strings.xml
@@ -566,8 +566,7 @@
<string name="user_nickname" msgid="262624187455825083">"Apelido"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"Adicionar convidado"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"Remover convidado"</string>
- <!-- no translation found for guest_reset_guest (6110013010356013758) -->
- <skip />
+ <string name="guest_reset_guest" msgid="6110013010356013758">"Redefinir sessão de visitante"</string>
<string name="guest_nickname" msgid="6332276931583337261">"Convidado"</string>
<string name="user_image_take_photo" msgid="467512954561638530">"Tirar uma foto"</string>
<string name="user_image_choose_photo" msgid="1363820919146782908">"Escolher uma imagem"</string>
diff --git a/packages/SettingsLib/res/values-ro/strings.xml b/packages/SettingsLib/res/values-ro/strings.xml
index 4db2f315a452..e1b0390fbace 100644
--- a/packages/SettingsLib/res/values-ro/strings.xml
+++ b/packages/SettingsLib/res/values-ro/strings.xml
@@ -567,8 +567,7 @@
<string name="user_nickname" msgid="262624187455825083">"Pseudonim"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"Adăugați un invitat"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"Ștergeți invitatul"</string>
- <!-- no translation found for guest_reset_guest (6110013010356013758) -->
- <skip />
+ <string name="guest_reset_guest" msgid="6110013010356013758">"Resetați sesiunea pentru invitați"</string>
<string name="guest_nickname" msgid="6332276931583337261">"Invitat"</string>
<string name="user_image_take_photo" msgid="467512954561638530">"Faceți o fotografie"</string>
<string name="user_image_choose_photo" msgid="1363820919146782908">"Alegeți o imagine"</string>
diff --git a/packages/SettingsLib/res/values-ru/strings.xml b/packages/SettingsLib/res/values-ru/strings.xml
index 0bcdc230c089..1e5fce5f3bc9 100644
--- a/packages/SettingsLib/res/values-ru/strings.xml
+++ b/packages/SettingsLib/res/values-ru/strings.xml
@@ -568,8 +568,7 @@
<string name="user_nickname" msgid="262624187455825083">"Псевдоним"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"Добавить гостя"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"Удалить аккаунт гостя"</string>
- <!-- no translation found for guest_reset_guest (6110013010356013758) -->
- <skip />
+ <string name="guest_reset_guest" msgid="6110013010356013758">"Сбросить гостевой сеанс"</string>
<string name="guest_nickname" msgid="6332276931583337261">"Гость"</string>
<string name="user_image_take_photo" msgid="467512954561638530">"Сделать снимок"</string>
<string name="user_image_choose_photo" msgid="1363820919146782908">"Выбрать фото"</string>
diff --git a/packages/SettingsLib/res/values-sk/strings.xml b/packages/SettingsLib/res/values-sk/strings.xml
index ef12ad36c5e1..09c0bf993f34 100644
--- a/packages/SettingsLib/res/values-sk/strings.xml
+++ b/packages/SettingsLib/res/values-sk/strings.xml
@@ -568,8 +568,7 @@
<string name="user_nickname" msgid="262624187455825083">"Prezývka"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"Pridať hosťa"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"Odobrať hosťa"</string>
- <!-- no translation found for guest_reset_guest (6110013010356013758) -->
- <skip />
+ <string name="guest_reset_guest" msgid="6110013010356013758">"Obnoviť reláciu hosťa"</string>
<string name="guest_nickname" msgid="6332276931583337261">"Hosť"</string>
<string name="user_image_take_photo" msgid="467512954561638530">"Odfotiť"</string>
<string name="user_image_choose_photo" msgid="1363820919146782908">"Vybrať obrázok"</string>
diff --git a/packages/SettingsLib/res/values-sl/strings.xml b/packages/SettingsLib/res/values-sl/strings.xml
index cbdfefcd424a..b698c19ff8b8 100644
--- a/packages/SettingsLib/res/values-sl/strings.xml
+++ b/packages/SettingsLib/res/values-sl/strings.xml
@@ -568,8 +568,7 @@
<string name="user_nickname" msgid="262624187455825083">"Vzdevek"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"Dodajanje gosta"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"Odstranitev gosta"</string>
- <!-- no translation found for guest_reset_guest (6110013010356013758) -->
- <skip />
+ <string name="guest_reset_guest" msgid="6110013010356013758">"Ponastavi gosta"</string>
<string name="guest_nickname" msgid="6332276931583337261">"Gost"</string>
<string name="user_image_take_photo" msgid="467512954561638530">"Fotografiranje"</string>
<string name="user_image_choose_photo" msgid="1363820919146782908">"Izberi sliko"</string>
diff --git a/packages/SettingsLib/res/values-sr/strings.xml b/packages/SettingsLib/res/values-sr/strings.xml
index 3859be937d47..b3c23b667a42 100644
--- a/packages/SettingsLib/res/values-sr/strings.xml
+++ b/packages/SettingsLib/res/values-sr/strings.xml
@@ -567,8 +567,7 @@
<string name="user_nickname" msgid="262624187455825083">"Надимак"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"Додај госта"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"Уклони госта"</string>
- <!-- no translation found for guest_reset_guest (6110013010356013758) -->
- <skip />
+ <string name="guest_reset_guest" msgid="6110013010356013758">"Ресетуј сесију госта"</string>
<string name="guest_nickname" msgid="6332276931583337261">"Гост"</string>
<string name="user_image_take_photo" msgid="467512954561638530">"Сликај"</string>
<string name="user_image_choose_photo" msgid="1363820919146782908">"Одабери слику"</string>
diff --git a/packages/SettingsLib/res/values-sv/strings.xml b/packages/SettingsLib/res/values-sv/strings.xml
index 7dcca0d2b611..124c063bea95 100644
--- a/packages/SettingsLib/res/values-sv/strings.xml
+++ b/packages/SettingsLib/res/values-sv/strings.xml
@@ -566,8 +566,7 @@
<string name="user_nickname" msgid="262624187455825083">"Smeknamn"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"Lägg till gäst"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"Ta bort gäst"</string>
- <!-- no translation found for guest_reset_guest (6110013010356013758) -->
- <skip />
+ <string name="guest_reset_guest" msgid="6110013010356013758">"Återställ gästsession"</string>
<string name="guest_nickname" msgid="6332276931583337261">"Gäst"</string>
<string name="user_image_take_photo" msgid="467512954561638530">"Ta ett foto"</string>
<string name="user_image_choose_photo" msgid="1363820919146782908">"Välj en bild"</string>
diff --git a/packages/SettingsLib/res/values-th/strings.xml b/packages/SettingsLib/res/values-th/strings.xml
index b7aff721c405..7f67b88aa837 100644
--- a/packages/SettingsLib/res/values-th/strings.xml
+++ b/packages/SettingsLib/res/values-th/strings.xml
@@ -452,7 +452,7 @@
<string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="7703677921000858479">"แท็บเล็ตอาจปิดเครื่องในไม่ช้า (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
<string name="power_remaining_duration_shutdown_imminent" product="device" msgid="4374784375644214578">"อุปกรณ์อาจปิดเครื่องในไม่ช้า (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
<string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
- <string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"อีก <xliff:g id="TIME">%1$s</xliff:g> จึงจะเต็ม"</string>
+ <string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"อีก <xliff:g id="TIME">%1$s</xliff:g>จึงจะเต็ม"</string>
<string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> - อีก <xliff:g id="TIME">%2$s</xliff:g> จึงจะเต็ม"</string>
<string name="power_charging_limited" msgid="7956120998372505295">"<xliff:g id="LEVEL">%1$s</xliff:g> - จำกัดการชาร์จชั่วคราว"</string>
<string name="battery_info_status_unknown" msgid="268625384868401114">"ไม่ทราบ"</string>
@@ -566,8 +566,7 @@
<string name="user_nickname" msgid="262624187455825083">"ชื่อเล่น"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"เพิ่มผู้ใช้ชั่วคราว"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"นำผู้ใช้ชั่วคราวออก"</string>
- <!-- no translation found for guest_reset_guest (6110013010356013758) -->
- <skip />
+ <string name="guest_reset_guest" msgid="6110013010356013758">"รีเซ็ตผู้เข้าร่วม"</string>
<string name="guest_nickname" msgid="6332276931583337261">"ผู้ใช้ชั่วคราว"</string>
<string name="user_image_take_photo" msgid="467512954561638530">"ถ่ายรูป"</string>
<string name="user_image_choose_photo" msgid="1363820919146782908">"เลือกรูปภาพ"</string>
diff --git a/packages/SettingsLib/res/values-tl/strings.xml b/packages/SettingsLib/res/values-tl/strings.xml
index 6d1f6abbdf96..cc7db29f3d32 100644
--- a/packages/SettingsLib/res/values-tl/strings.xml
+++ b/packages/SettingsLib/res/values-tl/strings.xml
@@ -566,8 +566,7 @@
<string name="user_nickname" msgid="262624187455825083">"Nickname"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"Magdagdag ng bisita"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"Alisin ang bisita"</string>
- <!-- no translation found for guest_reset_guest (6110013010356013758) -->
- <skip />
+ <string name="guest_reset_guest" msgid="6110013010356013758">"I-reset ang bisita"</string>
<string name="guest_nickname" msgid="6332276931583337261">"Bisita"</string>
<string name="user_image_take_photo" msgid="467512954561638530">"Kumuha ng larawan"</string>
<string name="user_image_choose_photo" msgid="1363820919146782908">"Pumili ng larawan"</string>
diff --git a/packages/SettingsLib/res/values-uk/strings.xml b/packages/SettingsLib/res/values-uk/strings.xml
index 82e481bd0613..2cb10763fcc9 100644
--- a/packages/SettingsLib/res/values-uk/strings.xml
+++ b/packages/SettingsLib/res/values-uk/strings.xml
@@ -568,8 +568,7 @@
<string name="user_nickname" msgid="262624187455825083">"Псевдонім"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"Додати гостя"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"Видалити гостя"</string>
- <!-- no translation found for guest_reset_guest (6110013010356013758) -->
- <skip />
+ <string name="guest_reset_guest" msgid="6110013010356013758">"Скинути сеанс у режимі \"Гість\""</string>
<string name="guest_nickname" msgid="6332276931583337261">"Гість"</string>
<string name="user_image_take_photo" msgid="467512954561638530">"Зробити фотографію"</string>
<string name="user_image_choose_photo" msgid="1363820919146782908">"Вибрати зображення"</string>
diff --git a/packages/SettingsLib/res/values-uz/strings.xml b/packages/SettingsLib/res/values-uz/strings.xml
index 7f4e30aa33c4..3e11124597d9 100644
--- a/packages/SettingsLib/res/values-uz/strings.xml
+++ b/packages/SettingsLib/res/values-uz/strings.xml
@@ -566,8 +566,7 @@
<string name="user_nickname" msgid="262624187455825083">"Nik"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"Mehmon kiritish"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"Mehmonni olib tashlash"</string>
- <!-- no translation found for guest_reset_guest (6110013010356013758) -->
- <skip />
+ <string name="guest_reset_guest" msgid="6110013010356013758">"Mehmon seansini tiklash"</string>
<string name="guest_nickname" msgid="6332276931583337261">"Mehmon"</string>
<string name="user_image_take_photo" msgid="467512954561638530">"Suratga olish"</string>
<string name="user_image_choose_photo" msgid="1363820919146782908">"Rasm tanlash"</string>
diff --git a/packages/SettingsLib/res/values-zu/strings.xml b/packages/SettingsLib/res/values-zu/strings.xml
index 2fe791a5a47c..0fa97e2011ce 100644
--- a/packages/SettingsLib/res/values-zu/strings.xml
+++ b/packages/SettingsLib/res/values-zu/strings.xml
@@ -566,8 +566,7 @@
<string name="user_nickname" msgid="262624187455825083">"Isiteketiso"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"Engeza isivakashi"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"Susa isihambeli"</string>
- <!-- no translation found for guest_reset_guest (6110013010356013758) -->
- <skip />
+ <string name="guest_reset_guest" msgid="6110013010356013758">"Setha kabusha isivakashi"</string>
<string name="guest_nickname" msgid="6332276931583337261">"Isihambeli"</string>
<string name="user_image_take_photo" msgid="467512954561638530">"Thatha isithombe"</string>
<string name="user_image_choose_photo" msgid="1363820919146782908">"Khetha isithombe"</string>
diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml
index 8c092ae37222..604310a9e905 100644
--- a/packages/SystemUI/AndroidManifest.xml
+++ b/packages/SystemUI/AndroidManifest.xml
@@ -454,6 +454,14 @@
android:finishOnCloseSystemDialogs="true">
</activity>
+ <!-- started from SensoryPrivacyService -->
+ <activity android:name=".sensorprivacy.television.TvUnblockSensorActivity"
+ android:exported="true"
+ android:permission="android.permission.MANAGE_SENSOR_PRIVACY"
+ android:theme="@style/BottomSheet"
+ android:finishOnCloseSystemDialogs="true">
+ </activity>
+
<!-- started from UsbDeviceSettingsManager -->
<activity android:name=".usb.UsbAccessoryUriActivity"
diff --git a/packages/SystemUI/res/anim/tv_bottom_sheet_button_state_list_animator.xml b/packages/SystemUI/res/anim/tv_bottom_sheet_button_state_list_animator.xml
new file mode 100644
index 000000000000..fc3b4ed6eecb
--- /dev/null
+++ b/packages/SystemUI/res/anim/tv_bottom_sheet_button_state_list_animator.xml
@@ -0,0 +1,52 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2021 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<selector
+ xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:state_focused="true">
+ <set>
+ <objectAnimator
+ android:duration="200"
+ android:propertyName="scaleX"
+ android:valueFrom="1.0"
+ android:valueTo="@dimen/bottom_sheet_button_selection_scaled"
+ android:valueType="floatType"/>
+ <objectAnimator
+ android:duration="200"
+ android:propertyName="scaleY"
+ android:valueFrom="1.0"
+ android:valueTo="@dimen/bottom_sheet_button_selection_scaled"
+ android:valueType="floatType"/>
+ </set>
+ </item>
+ <item android:state_focused="false">
+ <set>
+ <objectAnimator
+ android:duration="200"
+ android:propertyName="scaleX"
+ android:valueFrom="@dimen/bottom_sheet_button_selection_scaled"
+ android:valueTo="1.0"
+ android:valueType="floatType"/>
+ <objectAnimator
+ android:duration="200"
+ android:propertyName="scaleY"
+ android:valueFrom="@dimen/bottom_sheet_button_selection_scaled"
+ android:valueTo="1.0"
+ android:valueType="floatType"/>
+ </set>
+ </item>
+</selector> \ No newline at end of file
diff --git a/packages/SystemUI/res/anim/tv_bottom_sheet_enter.xml b/packages/SystemUI/res/anim/tv_bottom_sheet_enter.xml
new file mode 100644
index 000000000000..cace36d68b43
--- /dev/null
+++ b/packages/SystemUI/res/anim/tv_bottom_sheet_enter.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2021 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<set xmlns:android="http://schemas.android.com/apk/res/android"
+ android:interpolator="@android:interpolator/decelerate_quint">
+ <translate android:fromYDelta="100%"
+ android:toYDelta="0"
+ android:duration="900"/>
+</set> \ No newline at end of file
diff --git a/packages/SystemUI/res/anim/tv_bottom_sheet_exit.xml b/packages/SystemUI/res/anim/tv_bottom_sheet_exit.xml
new file mode 100644
index 000000000000..f7efe7cd2584
--- /dev/null
+++ b/packages/SystemUI/res/anim/tv_bottom_sheet_exit.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2021 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<set xmlns:android="http://schemas.android.com/apk/res/android"
+ android:interpolator="@android:interpolator/decelerate_quint">
+ <translate android:fromYDelta="0"
+ android:toYDelta="100%"
+ android:duration="500"/>
+</set> \ No newline at end of file
diff --git a/packages/SystemUI/res/color/bottom_sheet_button_background_color.xml b/packages/SystemUI/res/color/bottom_sheet_button_background_color.xml
new file mode 100644
index 000000000000..9b0bae09b326
--- /dev/null
+++ b/packages/SystemUI/res/color/bottom_sheet_button_background_color.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2021 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:state_focused="true"
+ android:color="@color/bottom_sheet_button_background_color_focused"/>
+ <item android:color="@color/bottom_sheet_button_background_color_unfocused"/>
+</selector> \ No newline at end of file
diff --git a/packages/SystemUI/res/color/bottom_sheet_button_text_color.xml b/packages/SystemUI/res/color/bottom_sheet_button_text_color.xml
new file mode 100644
index 000000000000..05248f17097b
--- /dev/null
+++ b/packages/SystemUI/res/color/bottom_sheet_button_text_color.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2021 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:state_focused="true"
+ android:color="@color/bottom_sheet_button_text_color_focused"/>
+ <item android:color="@color/bottom_sheet_button_text_color_unfocused"/>
+</selector> \ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/bottom_sheet_background.xml b/packages/SystemUI/res/drawable/bottom_sheet_background.xml
new file mode 100644
index 000000000000..87850a0d00ec
--- /dev/null
+++ b/packages/SystemUI/res/drawable/bottom_sheet_background.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2021 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle">
+ <solid android:color="@color/bottom_sheet_background_color"/>
+ <corners android:radius="@dimen/bottom_sheet_corner_radius"/>
+</shape> \ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/bottom_sheet_background_with_blur.xml b/packages/SystemUI/res/drawable/bottom_sheet_background_with_blur.xml
new file mode 100644
index 000000000000..cd2aa9c751d9
--- /dev/null
+++ b/packages/SystemUI/res/drawable/bottom_sheet_background_with_blur.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2021 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle">
+ <solid android:color="@color/bottom_sheet_background_color_with_blur"/>
+ <corners android:radius="@dimen/bottom_sheet_corner_radius"/>
+</shape> \ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/bottom_sheet_button_background.xml b/packages/SystemUI/res/drawable/bottom_sheet_button_background.xml
new file mode 100644
index 000000000000..585a6bc771f7
--- /dev/null
+++ b/packages/SystemUI/res/drawable/bottom_sheet_button_background.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2021 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle">
+ <solid android:color="@color/bottom_sheet_button_background_color"/>
+ <corners android:radius="@dimen/bottom_sheet_button_corner_radius"/>
+</shape> \ No newline at end of file
diff --git a/packages/SystemUI/res/layout/tv_bottom_sheet.xml b/packages/SystemUI/res/layout/tv_bottom_sheet.xml
new file mode 100644
index 000000000000..b69cdc76ae40
--- /dev/null
+++ b/packages/SystemUI/res/layout/tv_bottom_sheet.xml
@@ -0,0 +1,87 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2021 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<LinearLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/bottom_sheet"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:gravity="center_vertical"
+ android:orientation="horizontal"
+ android:minHeight="@dimen/bottom_sheet_min_height"
+ android:paddingHorizontal="@dimen/bottom_sheet_padding_horizontal"
+ android:paddingVertical="@dimen/bottom_sheet_padding_vertical">
+
+ <LinearLayout
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:minWidth="80dp"
+ android:gravity="center"
+ android:orientation="horizontal">
+ <ImageView
+ android:id="@+id/bottom_sheet_icon"
+ android:layout_width="@dimen/bottom_sheet_icon_size"
+ android:layout_height="@dimen/bottom_sheet_icon_size"
+ android:layout_gravity="center_vertical"
+ android:tint="@color/bottom_sheet_icon_color"/>
+ <ImageView
+ android:id="@+id/bottom_sheet_second_icon"
+ android:layout_width="@dimen/bottom_sheet_icon_size"
+ android:layout_height="@dimen/bottom_sheet_icon_size"
+ android:layout_marginStart="@dimen/bottom_sheet_icon_margin"
+ android:layout_gravity="center_vertical"
+ android:tint="@color/bottom_sheet_icon_color"/>
+ </LinearLayout>
+
+ <LinearLayout
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginStart="@dimen/bottom_sheet_padding_horizontal"
+ android:layout_weight="1"
+ android:orientation="vertical">
+ <TextView
+ android:id="@+id/bottom_sheet_title"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginBottom="@dimen/bottom_sheet_title_margin_bottom"
+ android:textAppearance="@style/BottomSheet.TitleText"/>
+
+ <TextView
+ android:id="@+id/bottom_sheet_body"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginBottom="@dimen/bottom_sheet_details_margin_bottom"
+ android:textAppearance="@style/BottomSheet.BodyText" />
+ </LinearLayout>
+
+ <LinearLayout
+ android:orientation="vertical"
+ android:layout_width="@dimen/bottom_sheet_actions_width"
+ android:layout_height="match_parent"
+ android:gravity="center">
+ <Button
+ android:id="@+id/bottom_sheet_positive_button"
+ style="@style/BottomSheet.ActionItem" />
+ <Space
+ android:layout_width="0dp"
+ android:layout_height="@dimen/bottom_sheet_actions_spacing" />
+ <Button
+ android:id="@+id/bottom_sheet_negative_button"
+ style="@style/BottomSheet.ActionItem" />
+ </LinearLayout>
+
+</LinearLayout>
diff --git a/packages/SystemUI/res/values-az/strings.xml b/packages/SystemUI/res/values-az/strings.xml
index c3b96a40023d..9502454d1c8c 100644
--- a/packages/SystemUI/res/values-az/strings.xml
+++ b/packages/SystemUI/res/values-az/strings.xml
@@ -1035,7 +1035,7 @@
<string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"Tam ekranı böyüdün"</string>
<string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"Ekran hissəsinin böyüdülməsi"</string>
<string name="magnification_mode_switch_click_label" msgid="2786203505805898199">"Dəyişdirici"</string>
- <string name="accessibility_floating_button_migration_tooltip" msgid="4431046858918714564">"Əlçatımlılıq düyməsi əlçatımlılıq jestini əvəz etdi\n\n"<annotation id="link">"Ayarlara baxın"</annotation></string>
+ <string name="accessibility_floating_button_migration_tooltip" msgid="4431046858918714564">"Jest xüsusi imkanlar düyməsinə dəyişdirildi\n\n"<annotation id="link">"Ayarlara baxın"</annotation></string>
<string name="accessibility_floating_button_switch_migration_tooltip" msgid="6248529129221218770">"Əlçatımlılıq jestindən düymə\n\n"<annotation id="link">"Ayarlarına"</annotation>" keçə bilərsiniz"</string>
<string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"Düyməni müvəqqəti gizlətmək üçün kənara çəkin"</string>
<string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"Yuxarıya sola köçürün"</string>
diff --git a/packages/SystemUI/res/values-be/strings.xml b/packages/SystemUI/res/values-be/strings.xml
index 2e98ad94383a..5afd979d34f5 100644
--- a/packages/SystemUI/res/values-be/strings.xml
+++ b/packages/SystemUI/res/values-be/strings.xml
@@ -484,12 +484,10 @@
<string name="user_add_user" msgid="4336657383006913022">"Дадаць карыстальніка"</string>
<string name="user_new_user_name" msgid="2019166282704195789">"Новы карыстальнік"</string>
<string name="guest_exit_guest_dialog_title" msgid="5015697561580641422">"Выдаліць госця?"</string>
- <!-- no translation found for guest_reset_guest_dialog_title (8904781614074479690) -->
- <skip />
+ <string name="guest_reset_guest_dialog_title" msgid="8904781614074479690">"Скінуць гасцявы сеанс?"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Усе праграмы і даныя гэтага сеанса будуць выдалены."</string>
<string name="guest_exit_guest_dialog_remove" msgid="7505817591242703757">"Выдаліць"</string>
- <!-- no translation found for guest_reset_guest_dialog_remove (4359825585658228699) -->
- <skip />
+ <string name="guest_reset_guest_dialog_remove" msgid="4359825585658228699">"Скінуць"</string>
<string name="guest_wipe_session_title" msgid="7147965814683990944">"З вяртаннем, госць!"</string>
<string name="guest_wipe_session_message" msgid="3393823610257065457">"Хочаце працягнуць сеанс?"</string>
<string name="guest_wipe_session_wipe" msgid="8056836584445473309">"Пачаць зноў"</string>
diff --git a/packages/SystemUI/res/values-bn/strings.xml b/packages/SystemUI/res/values-bn/strings.xml
index 9f71f43605ae..0eedd1ca13f1 100644
--- a/packages/SystemUI/res/values-bn/strings.xml
+++ b/packages/SystemUI/res/values-bn/strings.xml
@@ -1038,8 +1038,7 @@
<string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"স্ক্রিনের কিছুটা অংশ বড় করুন"</string>
<string name="magnification_mode_switch_click_label" msgid="2786203505805898199">"বদল করুন"</string>
<string name="accessibility_floating_button_migration_tooltip" msgid="4431046858918714564">"অ্যাক্সেসিবিলিটি জেসচার পরিবর্তন করে অ্যাক্সেসেবিলিটি বোতাম করা হয়েছে\n\n"<annotation id="link">"সেটিংস দেখুন"</annotation></string>
- <!-- no translation found for accessibility_floating_button_switch_migration_tooltip (6248529129221218770) -->
- <skip />
+ <string name="accessibility_floating_button_switch_migration_tooltip" msgid="6248529129221218770">"আপনি অ্যাক্সেসিবিলিটি জেসচারের বদলে \n\n"<annotation id="link">"সেটিংস"</annotation>" বোতামে সুইচ করতে পারেন"</string>
<string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"এটি অস্থায়ীভাবে লুকাতে বোতামটি কোণে সরান"</string>
<string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"উপরে বাঁদিকে সরান"</string>
<string name="accessibility_floating_button_action_move_top_right" msgid="6106225581993479711">"উপরে ডানদিকে সরান"</string>
diff --git a/packages/SystemUI/res/values-bs/strings.xml b/packages/SystemUI/res/values-bs/strings.xml
index 17dbbe95a010..615d34634789 100644
--- a/packages/SystemUI/res/values-bs/strings.xml
+++ b/packages/SystemUI/res/values-bs/strings.xml
@@ -482,12 +482,10 @@
<string name="user_add_user" msgid="4336657383006913022">"Dodaj korisnika"</string>
<string name="user_new_user_name" msgid="2019166282704195789">"Novi korisnik"</string>
<string name="guest_exit_guest_dialog_title" msgid="5015697561580641422">"Ukloniti gosta?"</string>
- <!-- no translation found for guest_reset_guest_dialog_title (8904781614074479690) -->
- <skip />
+ <string name="guest_reset_guest_dialog_title" msgid="8904781614074479690">"Poništiti gostujuću sesiju?"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Sve aplikacije i podaci iz ove sesije će se izbrisati."</string>
<string name="guest_exit_guest_dialog_remove" msgid="7505817591242703757">"Ukloni"</string>
- <!-- no translation found for guest_reset_guest_dialog_remove (4359825585658228699) -->
- <skip />
+ <string name="guest_reset_guest_dialog_remove" msgid="4359825585658228699">"Poništi"</string>
<string name="guest_wipe_session_title" msgid="7147965814683990944">"Zdravo! Lijepo je opet vidjeti goste."</string>
<string name="guest_wipe_session_message" msgid="3393823610257065457">"Želite li nastaviti sesiju?"</string>
<string name="guest_wipe_session_wipe" msgid="8056836584445473309">"Počni ispočetka"</string>
diff --git a/packages/SystemUI/res/values-de/strings.xml b/packages/SystemUI/res/values-de/strings.xml
index 274ca3a32a2c..17cb3b9f3c32 100644
--- a/packages/SystemUI/res/values-de/strings.xml
+++ b/packages/SystemUI/res/values-de/strings.xml
@@ -1038,8 +1038,7 @@
<string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"Teil des Bildschirms vergrößern"</string>
<string name="magnification_mode_switch_click_label" msgid="2786203505805898199">"Schalter"</string>
<string name="accessibility_floating_button_migration_tooltip" msgid="4431046858918714564">"Die Schaltfläche „Bedienungshilfen“ ersetzt die Touch-Geste für Bedienungshilfen\n\n"<annotation id="link">"Einstellungen aufrufen"</annotation></string>
- <!-- no translation found for accessibility_floating_button_switch_migration_tooltip (6248529129221218770) -->
- <skip />
+ <string name="accessibility_floating_button_switch_migration_tooltip" msgid="6248529129221218770">"Du kannst von der barrierefreien Geste zu einer Schaltfläche wechseln\n\n"<annotation id="link">"Einstellungen"</annotation></string>
<string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"Durch Ziehen an den Rand wird die Schaltfläche zeitweise ausgeblendet"</string>
<string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"Nach oben links verschieben"</string>
<string name="accessibility_floating_button_action_move_top_right" msgid="6106225581993479711">"Nach rechts oben verschieben"</string>
diff --git a/packages/SystemUI/res/values-et/strings.xml b/packages/SystemUI/res/values-et/strings.xml
index 662282106d1d..497845707e46 100644
--- a/packages/SystemUI/res/values-et/strings.xml
+++ b/packages/SystemUI/res/values-et/strings.xml
@@ -480,12 +480,10 @@
<string name="user_add_user" msgid="4336657383006913022">"Lisa kasutaja"</string>
<string name="user_new_user_name" msgid="2019166282704195789">"Uus kasutaja"</string>
<string name="guest_exit_guest_dialog_title" msgid="5015697561580641422">"Kas eemaldada külaline?"</string>
- <!-- no translation found for guest_reset_guest_dialog_title (8904781614074479690) -->
- <skip />
+ <string name="guest_reset_guest_dialog_title" msgid="8904781614074479690">"Kas lähtestada külastajaseanss?"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Seansi kõik rakendused ja andmed kustutatakse."</string>
<string name="guest_exit_guest_dialog_remove" msgid="7505817591242703757">"Eemalda"</string>
- <!-- no translation found for guest_reset_guest_dialog_remove (4359825585658228699) -->
- <skip />
+ <string name="guest_reset_guest_dialog_remove" msgid="4359825585658228699">"Lähtesta"</string>
<string name="guest_wipe_session_title" msgid="7147965814683990944">"Tere tulemast tagasi, külaline!"</string>
<string name="guest_wipe_session_message" msgid="3393823610257065457">"Kas soovite seansiga jätkata?"</string>
<string name="guest_wipe_session_wipe" msgid="8056836584445473309">"Alusta uuesti"</string>
diff --git a/packages/SystemUI/res/values-hr/strings.xml b/packages/SystemUI/res/values-hr/strings.xml
index 6f7aee23f190..abbbae7985d4 100644
--- a/packages/SystemUI/res/values-hr/strings.xml
+++ b/packages/SystemUI/res/values-hr/strings.xml
@@ -482,12 +482,10 @@
<string name="user_add_user" msgid="4336657383006913022">"Dodavanje korisnika"</string>
<string name="user_new_user_name" msgid="2019166282704195789">"Novi korisnik"</string>
<string name="guest_exit_guest_dialog_title" msgid="5015697561580641422">"Ukloniti gosta?"</string>
- <!-- no translation found for guest_reset_guest_dialog_title (8904781614074479690) -->
- <skip />
+ <string name="guest_reset_guest_dialog_title" msgid="8904781614074479690">"Poništiti gostujuću sesiju?"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Sve aplikacije i podaci u ovoj sesiji bit će izbrisani."</string>
<string name="guest_exit_guest_dialog_remove" msgid="7505817591242703757">"Ukloni"</string>
- <!-- no translation found for guest_reset_guest_dialog_remove (4359825585658228699) -->
- <skip />
+ <string name="guest_reset_guest_dialog_remove" msgid="4359825585658228699">"Poništi"</string>
<string name="guest_wipe_session_title" msgid="7147965814683990944">"Dobro došli natrag, gostu!"</string>
<string name="guest_wipe_session_message" msgid="3393823610257065457">"Želite li nastaviti sesiju?"</string>
<string name="guest_wipe_session_wipe" msgid="8056836584445473309">"Počni ispočetka"</string>
diff --git a/packages/SystemUI/res/values-hu/strings.xml b/packages/SystemUI/res/values-hu/strings.xml
index 800c9dc36a07..15106bb4c157 100644
--- a/packages/SystemUI/res/values-hu/strings.xml
+++ b/packages/SystemUI/res/values-hu/strings.xml
@@ -480,12 +480,10 @@
<string name="user_add_user" msgid="4336657383006913022">"Felhasználó hozzáadása"</string>
<string name="user_new_user_name" msgid="2019166282704195789">"Új felhasználó"</string>
<string name="guest_exit_guest_dialog_title" msgid="5015697561580641422">"Eltávolítja a vendég munkamenetet?"</string>
- <!-- no translation found for guest_reset_guest_dialog_title (8904781614074479690) -->
- <skip />
+ <string name="guest_reset_guest_dialog_title" msgid="8904781614074479690">"Visszaállítja a vendég munkamenetet?"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"A munkamenetben található összes alkalmazás és adat törlődni fog."</string>
<string name="guest_exit_guest_dialog_remove" msgid="7505817591242703757">"Eltávolítás"</string>
- <!-- no translation found for guest_reset_guest_dialog_remove (4359825585658228699) -->
- <skip />
+ <string name="guest_reset_guest_dialog_remove" msgid="4359825585658228699">"Visszaállítás"</string>
<string name="guest_wipe_session_title" msgid="7147965814683990944">"Örülünk, hogy visszatért, vendég!"</string>
<string name="guest_wipe_session_message" msgid="3393823610257065457">"Folytatja a munkamenetet?"</string>
<string name="guest_wipe_session_wipe" msgid="8056836584445473309">"Újrakezdés"</string>
diff --git a/packages/SystemUI/res/values-hy/strings.xml b/packages/SystemUI/res/values-hy/strings.xml
index deeeb209e1e3..2e2141ee075c 100644
--- a/packages/SystemUI/res/values-hy/strings.xml
+++ b/packages/SystemUI/res/values-hy/strings.xml
@@ -480,12 +480,10 @@
<string name="user_add_user" msgid="4336657383006913022">"Ավելացնել օգտատեր"</string>
<string name="user_new_user_name" msgid="2019166282704195789">"Նոր օգտատեր"</string>
<string name="guest_exit_guest_dialog_title" msgid="5015697561580641422">"Հեռացնե՞լ հյուրին"</string>
- <!-- no translation found for guest_reset_guest_dialog_title (8904781614074479690) -->
- <skip />
+ <string name="guest_reset_guest_dialog_title" msgid="8904781614074479690">"Վերակայե՞լ հյուրի աշխատաշրջանը"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Այս աշխատաշրջանի բոլոր ծրագրերն ու տվյալները կջնջվեն:"</string>
<string name="guest_exit_guest_dialog_remove" msgid="7505817591242703757">"Հեռացնել"</string>
- <!-- no translation found for guest_reset_guest_dialog_remove (4359825585658228699) -->
- <skip />
+ <string name="guest_reset_guest_dialog_remove" msgid="4359825585658228699">"Վերակայել"</string>
<string name="guest_wipe_session_title" msgid="7147965814683990944">"Բարի վերադարձ, հյուր"</string>
<string name="guest_wipe_session_message" msgid="3393823610257065457">"Շարունակե՞լ աշխատաշրջանը։"</string>
<string name="guest_wipe_session_wipe" msgid="8056836584445473309">"Վերսկսել"</string>
diff --git a/packages/SystemUI/res/values-in/strings.xml b/packages/SystemUI/res/values-in/strings.xml
index a6cb798a188e..53a3165776fd 100644
--- a/packages/SystemUI/res/values-in/strings.xml
+++ b/packages/SystemUI/res/values-in/strings.xml
@@ -480,12 +480,10 @@
<string name="user_add_user" msgid="4336657383006913022">"Tambahkan pengguna"</string>
<string name="user_new_user_name" msgid="2019166282704195789">"Pengguna baru"</string>
<string name="guest_exit_guest_dialog_title" msgid="5015697561580641422">"Hapus tamu?"</string>
- <!-- no translation found for guest_reset_guest_dialog_title (8904781614074479690) -->
- <skip />
+ <string name="guest_reset_guest_dialog_title" msgid="8904781614074479690">"Reset sesi tamu?"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Semua aplikasi dan data di sesi ini akan dihapus."</string>
<string name="guest_exit_guest_dialog_remove" msgid="7505817591242703757">"Hapus"</string>
- <!-- no translation found for guest_reset_guest_dialog_remove (4359825585658228699) -->
- <skip />
+ <string name="guest_reset_guest_dialog_remove" msgid="4359825585658228699">"Reset"</string>
<string name="guest_wipe_session_title" msgid="7147965814683990944">"Selamat datang kembali, tamu!"</string>
<string name="guest_wipe_session_message" msgid="3393823610257065457">"Lanjutkan sesi Anda?"</string>
<string name="guest_wipe_session_wipe" msgid="8056836584445473309">"Mulai ulang"</string>
diff --git a/packages/SystemUI/res/values-it/strings.xml b/packages/SystemUI/res/values-it/strings.xml
index 066cd9344e91..454b5bba4a49 100644
--- a/packages/SystemUI/res/values-it/strings.xml
+++ b/packages/SystemUI/res/values-it/strings.xml
@@ -480,12 +480,10 @@
<string name="user_add_user" msgid="4336657383006913022">"Aggiungi utente"</string>
<string name="user_new_user_name" msgid="2019166282704195789">"Nuovo utente"</string>
<string name="guest_exit_guest_dialog_title" msgid="5015697561580641422">"Rimuovere l\'ospite?"</string>
- <!-- no translation found for guest_reset_guest_dialog_title (8904781614074479690) -->
- <skip />
+ <string name="guest_reset_guest_dialog_title" msgid="8904781614074479690">"Reimpostare sessione Ospite?"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Tutte le app e i dati di questa sessione verranno eliminati."</string>
<string name="guest_exit_guest_dialog_remove" msgid="7505817591242703757">"Rimuovi"</string>
- <!-- no translation found for guest_reset_guest_dialog_remove (4359825585658228699) -->
- <skip />
+ <string name="guest_reset_guest_dialog_remove" msgid="4359825585658228699">"Reimposta"</string>
<string name="guest_wipe_session_title" msgid="7147965814683990944">"Ti ridiamo il benvenuto alla sessione Ospite."</string>
<string name="guest_wipe_session_message" msgid="3393823610257065457">"Vuoi continuare la sessione?"</string>
<string name="guest_wipe_session_wipe" msgid="8056836584445473309">"Ricomincia"</string>
diff --git a/packages/SystemUI/res/values-iw/strings.xml b/packages/SystemUI/res/values-iw/strings.xml
index b2f0fd259702..32c386d9993e 100644
--- a/packages/SystemUI/res/values-iw/strings.xml
+++ b/packages/SystemUI/res/values-iw/strings.xml
@@ -725,7 +725,7 @@
<string name="notification_channel_unsilenced" msgid="94878840742161152">"ההודעות אלה יישלחו כהתראות"</string>
<string name="inline_blocking_helper" msgid="2891486013649543452">"ההתראות האלה בדרך כלל נדחות על ידך. \nלהמשיך להציג אותן?"</string>
<string name="inline_done_button" msgid="6043094985588909584">"סיום"</string>
- <string name="inline_ok_button" msgid="603075490581280343">"החלה"</string>
+ <string name="inline_ok_button" msgid="603075490581280343">"אישור"</string>
<string name="inline_keep_showing" msgid="8736001253507073497">"שנמשיך להציג לך את ההתראות האלה?"</string>
<string name="inline_stop_button" msgid="2453460935438696090">"לא, אל תמשיכו"</string>
<string name="inline_deliver_silently_button" msgid="2714314213321223286">"הצגה ללא צליל"</string>
diff --git a/packages/SystemUI/res/values-ja/strings.xml b/packages/SystemUI/res/values-ja/strings.xml
index b1736534ffd1..dacdf2146540 100644
--- a/packages/SystemUI/res/values-ja/strings.xml
+++ b/packages/SystemUI/res/values-ja/strings.xml
@@ -480,12 +480,10 @@
<string name="user_add_user" msgid="4336657383006913022">"ユーザーを追加"</string>
<string name="user_new_user_name" msgid="2019166282704195789">"新しいユーザー"</string>
<string name="guest_exit_guest_dialog_title" msgid="5015697561580641422">"ゲストを削除しますか?"</string>
- <!-- no translation found for guest_reset_guest_dialog_title (8904781614074479690) -->
- <skip />
+ <string name="guest_reset_guest_dialog_title" msgid="8904781614074479690">"ゲストをリセットしますか?"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"このセッションでのアプリとデータはすべて削除されます。"</string>
<string name="guest_exit_guest_dialog_remove" msgid="7505817591242703757">"削除"</string>
- <!-- no translation found for guest_reset_guest_dialog_remove (4359825585658228699) -->
- <skip />
+ <string name="guest_reset_guest_dialog_remove" msgid="4359825585658228699">"リセット"</string>
<string name="guest_wipe_session_title" msgid="7147965814683990944">"おかえりなさい、ゲストさん"</string>
<string name="guest_wipe_session_message" msgid="3393823610257065457">"セッションを続行しますか?"</string>
<string name="guest_wipe_session_wipe" msgid="8056836584445473309">"最初から開始"</string>
diff --git a/packages/SystemUI/res/values-kk/strings.xml b/packages/SystemUI/res/values-kk/strings.xml
index 09d5f9f6e3af..8366b2f48927 100644
--- a/packages/SystemUI/res/values-kk/strings.xml
+++ b/packages/SystemUI/res/values-kk/strings.xml
@@ -480,12 +480,10 @@
<string name="user_add_user" msgid="4336657383006913022">"Пайдаланушы қосу"</string>
<string name="user_new_user_name" msgid="2019166282704195789">"Жаңа пайдаланушы"</string>
<string name="guest_exit_guest_dialog_title" msgid="5015697561580641422">"Қонақты жою керек пе?"</string>
- <!-- no translation found for guest_reset_guest_dialog_title (8904781614074479690) -->
- <skip />
+ <string name="guest_reset_guest_dialog_title" msgid="8904781614074479690">"Қонақ сеансы бастапқы күйге қайтарылсын ба?"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Осы сеанстағы барлық қолданбалар мен деректер жойылады."</string>
<string name="guest_exit_guest_dialog_remove" msgid="7505817591242703757">"Алып тастау"</string>
- <!-- no translation found for guest_reset_guest_dialog_remove (4359825585658228699) -->
- <skip />
+ <string name="guest_reset_guest_dialog_remove" msgid="4359825585658228699">"Бастапқы күйге қайтару"</string>
<string name="guest_wipe_session_title" msgid="7147965814683990944">"Қош келдіңіз, қонақ!"</string>
<string name="guest_wipe_session_message" msgid="3393823610257065457">"Сеансты жалғастыру керек пе?"</string>
<string name="guest_wipe_session_wipe" msgid="8056836584445473309">"Қайта бастау"</string>
@@ -668,7 +666,7 @@
<string name="enable_demo_mode" msgid="3180345364745966431">"Демо режимін қосу"</string>
<string name="show_demo_mode" msgid="3677956462273059726">"Демо режимін көрсету"</string>
<string name="status_bar_ethernet" msgid="5690979758988647484">"Ethernet"</string>
- <string name="status_bar_alarm" msgid="87160847643623352">"Дабыл"</string>
+ <string name="status_bar_alarm" msgid="87160847643623352">"Оятқыш"</string>
<string name="wallet_title" msgid="5369767670735827105">"Әмиян"</string>
<string name="wallet_empty_state_label" msgid="7776761245237530394">"Телефоныңызбен бұрынғыдан да жылдам әрі қауіпсіз сатып алу үшін параметрлерді орнатыңыз."</string>
<string name="wallet_app_button_label" msgid="7123784239111190992">"Барлығын көрсету"</string>
diff --git a/packages/SystemUI/res/values-km/strings.xml b/packages/SystemUI/res/values-km/strings.xml
index 065a49951dfb..3baa4e1411f1 100644
--- a/packages/SystemUI/res/values-km/strings.xml
+++ b/packages/SystemUI/res/values-km/strings.xml
@@ -480,12 +480,10 @@
<string name="user_add_user" msgid="4336657383006913022">"បញ្ចូល​អ្នកប្រើ"</string>
<string name="user_new_user_name" msgid="2019166282704195789">"អ្នកប្រើ​ថ្មី"</string>
<string name="guest_exit_guest_dialog_title" msgid="5015697561580641422">"ដកភ្ញៀវចេញឬ?"</string>
- <!-- no translation found for guest_reset_guest_dialog_title (8904781614074479690) -->
- <skip />
+ <string name="guest_reset_guest_dialog_title" msgid="8904781614074479690">"កំណត់​ភ្ញៀវឡើង​វិញឬ?"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"កម្មវិធី និងទិន្នន័យ​ទាំងអស់​ក្នុង​វគ្គ​នេះ​នឹង​ត្រូវ​លុប។"</string>
<string name="guest_exit_guest_dialog_remove" msgid="7505817591242703757">"ដកចេញ"</string>
- <!-- no translation found for guest_reset_guest_dialog_remove (4359825585658228699) -->
- <skip />
+ <string name="guest_reset_guest_dialog_remove" msgid="4359825585658228699">"កំណត់​ឡើងវិញ"</string>
<string name="guest_wipe_session_title" msgid="7147965814683990944">"សូម​ស្វាគមន៍​ការ​ត្រឡប់​មកវិញ, ភ្ញៀវ!"</string>
<string name="guest_wipe_session_message" msgid="3393823610257065457">"តើ​អ្នក​ចង់​បន្ត​វគ្គ​របស់​អ្នក​ទេ?"</string>
<string name="guest_wipe_session_wipe" msgid="8056836584445473309">"ចាប់ផ្ដើមសាជាថ្មី"</string>
diff --git a/packages/SystemUI/res/values-ko/strings.xml b/packages/SystemUI/res/values-ko/strings.xml
index 80415d531d39..ab80f7f3acdc 100644
--- a/packages/SystemUI/res/values-ko/strings.xml
+++ b/packages/SystemUI/res/values-ko/strings.xml
@@ -480,12 +480,10 @@
<string name="user_add_user" msgid="4336657383006913022">"사용자 추가"</string>
<string name="user_new_user_name" msgid="2019166282704195789">"신규 사용자"</string>
<string name="guest_exit_guest_dialog_title" msgid="5015697561580641422">"게스트를 삭제하시겠습니까?"</string>
- <!-- no translation found for guest_reset_guest_dialog_title (8904781614074479690) -->
- <skip />
+ <string name="guest_reset_guest_dialog_title" msgid="8904781614074479690">"게스트를 초기화하시겠습니까?"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"이 세션에 있는 모든 앱과 데이터가 삭제됩니다."</string>
<string name="guest_exit_guest_dialog_remove" msgid="7505817591242703757">"삭제"</string>
- <!-- no translation found for guest_reset_guest_dialog_remove (4359825585658228699) -->
- <skip />
+ <string name="guest_reset_guest_dialog_remove" msgid="4359825585658228699">"초기화"</string>
<string name="guest_wipe_session_title" msgid="7147965814683990944">"게스트 세션 진행"</string>
<string name="guest_wipe_session_message" msgid="3393823610257065457">"세션을 계속 진행하시겠습니까?"</string>
<string name="guest_wipe_session_wipe" msgid="8056836584445473309">"다시 시작"</string>
diff --git a/packages/SystemUI/res/values-ky/strings.xml b/packages/SystemUI/res/values-ky/strings.xml
index 2474fe1f25b5..037a765870d4 100644
--- a/packages/SystemUI/res/values-ky/strings.xml
+++ b/packages/SystemUI/res/values-ky/strings.xml
@@ -480,12 +480,10 @@
<string name="user_add_user" msgid="4336657383006913022">"Колдонуучу кошуу"</string>
<string name="user_new_user_name" msgid="2019166282704195789">"Жаңы колдонуучу"</string>
<string name="guest_exit_guest_dialog_title" msgid="5015697561580641422">"Конокту алып саласызбы?"</string>
- <!-- no translation found for guest_reset_guest_dialog_title (8904781614074479690) -->
- <skip />
+ <string name="guest_reset_guest_dialog_title" msgid="8904781614074479690">"Конок сеансын баштапкы абалга келтиресизби?"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Бул сеанстагы бардык колдонмолор жана маалыматтар өчүрүлөт."</string>
<string name="guest_exit_guest_dialog_remove" msgid="7505817591242703757">"Өчүрүү"</string>
- <!-- no translation found for guest_reset_guest_dialog_remove (4359825585658228699) -->
- <skip />
+ <string name="guest_reset_guest_dialog_remove" msgid="4359825585658228699">"Баштапкы абалга келтирүү"</string>
<string name="guest_wipe_session_title" msgid="7147965814683990944">"Кайтып келишиңиз менен!"</string>
<string name="guest_wipe_session_message" msgid="3393823610257065457">"Сеансыңызды улантасызбы?"</string>
<string name="guest_wipe_session_wipe" msgid="8056836584445473309">"Кайра баштоо"</string>
diff --git a/packages/SystemUI/res/values-lo/strings.xml b/packages/SystemUI/res/values-lo/strings.xml
index 106f7f20a5ba..4cdc8a5fcb4e 100644
--- a/packages/SystemUI/res/values-lo/strings.xml
+++ b/packages/SystemUI/res/values-lo/strings.xml
@@ -480,12 +480,10 @@
<string name="user_add_user" msgid="4336657383006913022">"ເພີ່ມຜູ້ໃຊ້"</string>
<string name="user_new_user_name" msgid="2019166282704195789">"ຜູ່ໃຊ້ໃໝ່"</string>
<string name="guest_exit_guest_dialog_title" msgid="5015697561580641422">"ລຶບ​ແຂກ​ບໍ?"</string>
- <!-- no translation found for guest_reset_guest_dialog_title (8904781614074479690) -->
- <skip />
+ <string name="guest_reset_guest_dialog_title" msgid="8904781614074479690">"ຣີເຊັດແຂກບໍ?"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"ແອັບຯ​ແລະ​ຂໍ້​ມູນ​ທັງ​ໝົດ​ໃນ​ເຊດ​ຊັນ​ນີ້​ຈະ​ຖືກ​ລຶບ​ອອກ."</string>
<string name="guest_exit_guest_dialog_remove" msgid="7505817591242703757">"ລຶບ​"</string>
- <!-- no translation found for guest_reset_guest_dialog_remove (4359825585658228699) -->
- <skip />
+ <string name="guest_reset_guest_dialog_remove" msgid="4359825585658228699">"ຣີເຊັດ"</string>
<string name="guest_wipe_session_title" msgid="7147965814683990944">"ຍິນ​ດີ​ຕ້ອນ​ຮັບ​ກັບ​ມາ, ຜູ້ຢ້ຽມຢາມ!"</string>
<string name="guest_wipe_session_message" msgid="3393823610257065457">"ທ່ານ​ຕ້ອງ​ການ​ສືບ​ຕໍ່​ເຊດ​ຊັນ​ຂອງ​ທ່ານບໍ່?"</string>
<string name="guest_wipe_session_wipe" msgid="8056836584445473309">"ເລີ່ມຕົ້ນໃຫມ່"</string>
diff --git a/packages/SystemUI/res/values-mk/strings.xml b/packages/SystemUI/res/values-mk/strings.xml
index 535da7a98f87..90f775bcd310 100644
--- a/packages/SystemUI/res/values-mk/strings.xml
+++ b/packages/SystemUI/res/values-mk/strings.xml
@@ -480,12 +480,10 @@
<string name="user_add_user" msgid="4336657383006913022">"Додај корисник"</string>
<string name="user_new_user_name" msgid="2019166282704195789">"Нов корисник"</string>
<string name="guest_exit_guest_dialog_title" msgid="5015697561580641422">"Да се отстрани гостинот?"</string>
- <!-- no translation found for guest_reset_guest_dialog_title (8904781614074479690) -->
- <skip />
+ <string name="guest_reset_guest_dialog_title" msgid="8904781614074479690">"Да се ресетира гостинот?"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Сите апликации и податоци во сесијата ќе се избришат."</string>
<string name="guest_exit_guest_dialog_remove" msgid="7505817591242703757">"Отстрани"</string>
- <!-- no translation found for guest_reset_guest_dialog_remove (4359825585658228699) -->
- <skip />
+ <string name="guest_reset_guest_dialog_remove" msgid="4359825585658228699">"Ресетирај"</string>
<string name="guest_wipe_session_title" msgid="7147965814683990944">"Добре дојде пак, гостине!"</string>
<string name="guest_wipe_session_message" msgid="3393823610257065457">"Дали сакате да продолжите со сесијата?"</string>
<string name="guest_wipe_session_wipe" msgid="8056836584445473309">"Почни одново"</string>
diff --git a/packages/SystemUI/res/values-mn/strings.xml b/packages/SystemUI/res/values-mn/strings.xml
index 8dae31d1c7f2..976c2dd420c8 100644
--- a/packages/SystemUI/res/values-mn/strings.xml
+++ b/packages/SystemUI/res/values-mn/strings.xml
@@ -480,12 +480,10 @@
<string name="user_add_user" msgid="4336657383006913022">"Хэрэглэгч нэмэх"</string>
<string name="user_new_user_name" msgid="2019166282704195789">"Шинэ хэрэглэгч"</string>
<string name="guest_exit_guest_dialog_title" msgid="5015697561580641422">"Зочныг хасах уу?"</string>
- <!-- no translation found for guest_reset_guest_dialog_title (8904781614074479690) -->
- <skip />
+ <string name="guest_reset_guest_dialog_title" msgid="8904781614074479690">"Зочныг шинэчлэх үү?"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Энэ харилцан үйлдлийн бүх апп болон дата устах болно."</string>
<string name="guest_exit_guest_dialog_remove" msgid="7505817591242703757">"Хасах"</string>
- <!-- no translation found for guest_reset_guest_dialog_remove (4359825585658228699) -->
- <skip />
+ <string name="guest_reset_guest_dialog_remove" msgid="4359825585658228699">"Шинэчлэх"</string>
<string name="guest_wipe_session_title" msgid="7147965814683990944">"Эргэн тавтай морилно уу!"</string>
<string name="guest_wipe_session_message" msgid="3393823610257065457">"Та үргэлжлүүлэхийг хүсэж байна уу?"</string>
<string name="guest_wipe_session_wipe" msgid="8056836584445473309">"Дахин эхлүүлэх"</string>
diff --git a/packages/SystemUI/res/values-mr/strings.xml b/packages/SystemUI/res/values-mr/strings.xml
index 3aae0640802f..84b559475019 100644
--- a/packages/SystemUI/res/values-mr/strings.xml
+++ b/packages/SystemUI/res/values-mr/strings.xml
@@ -1038,8 +1038,7 @@
<string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"स्क्रीनचा काही भाग मॅग्निफाय करा"</string>
<string name="magnification_mode_switch_click_label" msgid="2786203505805898199">"स्विच करा"</string>
<string name="accessibility_floating_button_migration_tooltip" msgid="4431046858918714564">"अ‍ॅक्सेसिबिलिटी जेश्चर हे आता अ‍ॅक्सेसिबिलिटी बटण आहे \n\n"<annotation id="link">"सेटिंग्ज पाहा"</annotation></string>
- <!-- no translation found for accessibility_floating_button_switch_migration_tooltip (6248529129221218770) -->
- <skip />
+ <string name="accessibility_floating_button_switch_migration_tooltip" msgid="6248529129221218770">"तुम्ही अ‍ॅक्सेसिबिलिटी जेश्चरवरून बटणवर स्विच करू शकता \n\n"<annotation id="link">"सेटिंग्ज"</annotation></string>
<string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"बटण तात्पुरते लपवण्यासाठी ते कोपर्‍यामध्ये हलवा"</string>
<string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"वर डावीकडे हलवा"</string>
<string name="accessibility_floating_button_action_move_top_right" msgid="6106225581993479711">"वर उजवीकडे हलवा"</string>
diff --git a/packages/SystemUI/res/values-my/strings.xml b/packages/SystemUI/res/values-my/strings.xml
index 9a8fc20fd6c4..efe716e9d04a 100644
--- a/packages/SystemUI/res/values-my/strings.xml
+++ b/packages/SystemUI/res/values-my/strings.xml
@@ -480,12 +480,10 @@
<string name="user_add_user" msgid="4336657383006913022">"အသုံးပြုသူ ထည့်ရန်"</string>
<string name="user_new_user_name" msgid="2019166282704195789">"အသုံးပြုသူ အသစ်"</string>
<string name="guest_exit_guest_dialog_title" msgid="5015697561580641422">"ဧည့်သည်ကို ဖယ်မလား။"</string>
- <!-- no translation found for guest_reset_guest_dialog_title (8904781614074479690) -->
- <skip />
+ <string name="guest_reset_guest_dialog_title" msgid="8904781614074479690">"ဧည့်သည်ကို ပြင်ဆင်သတ်မှတ်မလား။"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"ဒီချိတ်ဆက်မှု ထဲက အက်ပ်များ အားလုံး နှင့် ဒေတာကို ဖျက်ပစ်မည်။"</string>
<string name="guest_exit_guest_dialog_remove" msgid="7505817591242703757">"ဖယ်ထုတ်ပါ"</string>
- <!-- no translation found for guest_reset_guest_dialog_remove (4359825585658228699) -->
- <skip />
+ <string name="guest_reset_guest_dialog_remove" msgid="4359825585658228699">"ပြင်ဆင်သတ်မှတ်ရန်"</string>
<string name="guest_wipe_session_title" msgid="7147965814683990944">"ဧည့်သည်ကို ပြန်လည် ကြိုဆိုပါသည်။"</string>
<string name="guest_wipe_session_message" msgid="3393823610257065457">"သင်၏ စက်ရှင်ကို ဆက်လုပ်လိုပါသလား။"</string>
<string name="guest_wipe_session_wipe" msgid="8056836584445473309">"ပြန်စပါ"</string>
diff --git a/packages/SystemUI/res/values-ne/strings.xml b/packages/SystemUI/res/values-ne/strings.xml
index 0006f7f824a3..52e615519148 100644
--- a/packages/SystemUI/res/values-ne/strings.xml
+++ b/packages/SystemUI/res/values-ne/strings.xml
@@ -1038,8 +1038,7 @@
<string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"स्क्रिनको केही भाग म्याग्निफाइ गर्नुहोस्"</string>
<string name="magnification_mode_switch_click_label" msgid="2786203505805898199">"बदल्नुहोस्"</string>
<string name="accessibility_floating_button_migration_tooltip" msgid="4431046858918714564">"एक्सेसिबिलिटी इसाराका स्थानमा एक्सेसिबिलिटी बटन प्रयोग हुन थालेको छ\n\n"<annotation id="link">"सेटिङ हेर्नुहोस्"</annotation></string>
- <!-- no translation found for accessibility_floating_button_switch_migration_tooltip (6248529129221218770) -->
- <skip />
+ <string name="accessibility_floating_button_switch_migration_tooltip" msgid="6248529129221218770">"तपाईं एक्सेसिबिलिटी जेस्चरको साटो बटन प्रयोग गर्न सक्नुहुन्छ\n\n"<annotation id="link">"सेटिङ"</annotation></string>
<string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"यो बटन केही बेर नदेखिने पार्न किनारातिर सार्नुहोस्"</string>
<string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"सिरानको बायाँतिर सार्नुहोस्"</string>
<string name="accessibility_floating_button_action_move_top_right" msgid="6106225581993479711">"सिरानको दायाँतिर सार्नुहोस्"</string>
diff --git a/packages/SystemUI/res/values-nl/strings.xml b/packages/SystemUI/res/values-nl/strings.xml
index 944753ad570b..8bd41deb9499 100644
--- a/packages/SystemUI/res/values-nl/strings.xml
+++ b/packages/SystemUI/res/values-nl/strings.xml
@@ -480,12 +480,10 @@
<string name="user_add_user" msgid="4336657383006913022">"Gebruiker toevoegen"</string>
<string name="user_new_user_name" msgid="2019166282704195789">"Nieuwe gebruiker"</string>
<string name="guest_exit_guest_dialog_title" msgid="5015697561580641422">"Gast verwijderen?"</string>
- <!-- no translation found for guest_reset_guest_dialog_title (8904781614074479690) -->
- <skip />
+ <string name="guest_reset_guest_dialog_title" msgid="8904781614074479690">"Gastsessie resetten?"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Alle apps en gegevens in deze sessie worden verwijderd."</string>
<string name="guest_exit_guest_dialog_remove" msgid="7505817591242703757">"Verwijderen"</string>
- <!-- no translation found for guest_reset_guest_dialog_remove (4359825585658228699) -->
- <skip />
+ <string name="guest_reset_guest_dialog_remove" msgid="4359825585658228699">"Resetten"</string>
<string name="guest_wipe_session_title" msgid="7147965814683990944">"Welkom terug, gast!"</string>
<string name="guest_wipe_session_message" msgid="3393823610257065457">"Wil je doorgaan met je sessie?"</string>
<string name="guest_wipe_session_wipe" msgid="8056836584445473309">"Opnieuw starten"</string>
diff --git a/packages/SystemUI/res/values-or/strings.xml b/packages/SystemUI/res/values-or/strings.xml
index 1dcb1434bc29..003ce4c4b5ce 100644
--- a/packages/SystemUI/res/values-or/strings.xml
+++ b/packages/SystemUI/res/values-or/strings.xml
@@ -480,12 +480,10 @@
<string name="user_add_user" msgid="4336657383006913022">"ଉପଯୋଗକର୍ତ୍ତାଙ୍କୁ ଯୋଗ କରନ୍ତୁ"</string>
<string name="user_new_user_name" msgid="2019166282704195789">"ନୂଆ ଉପଯୋଗକର୍ତ୍ତା"</string>
<string name="guest_exit_guest_dialog_title" msgid="5015697561580641422">"ଅତିଥିଙ୍କୁ କାଢ଼ିଦେବେ?"</string>
- <!-- no translation found for guest_reset_guest_dialog_title (8904781614074479690) -->
- <skip />
+ <string name="guest_reset_guest_dialog_title" msgid="8904781614074479690">"ଅତିଥିଙ୍କୁ ରିସେଟ୍ କରିବେ?"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"ଏହି ସେସନର ସମସ୍ତ ଆପ୍‌ ଓ ଡାଟା ଡିଲିଟ୍‌ ହୋଇଯିବ।"</string>
<string name="guest_exit_guest_dialog_remove" msgid="7505817591242703757">"କାଢ଼ିଦିଅନ୍ତୁ"</string>
- <!-- no translation found for guest_reset_guest_dialog_remove (4359825585658228699) -->
- <skip />
+ <string name="guest_reset_guest_dialog_remove" msgid="4359825585658228699">"ରିସେଟ୍ କରନ୍ତୁ"</string>
<string name="guest_wipe_session_title" msgid="7147965814683990944">"ପୁଣି ସ୍ୱାଗତ, ଅତିଥି!"</string>
<string name="guest_wipe_session_message" msgid="3393823610257065457">"ଆପଣ ନିଜର ସେସନ୍ ଜାରି ରଖିବାକୁ ଚାହାଁନ୍ତି କି?"</string>
<string name="guest_wipe_session_wipe" msgid="8056836584445473309">"ଆରମ୍ଭ କରନ୍ତୁ"</string>
diff --git a/packages/SystemUI/res/values-pt-rBR/strings.xml b/packages/SystemUI/res/values-pt-rBR/strings.xml
index ad41e5535e6d..e4dbca5eb8e3 100644
--- a/packages/SystemUI/res/values-pt-rBR/strings.xml
+++ b/packages/SystemUI/res/values-pt-rBR/strings.xml
@@ -480,12 +480,10 @@
<string name="user_add_user" msgid="4336657383006913022">"Adicionar usuário"</string>
<string name="user_new_user_name" msgid="2019166282704195789">"Novo usuário"</string>
<string name="guest_exit_guest_dialog_title" msgid="5015697561580641422">"Remover visitante?"</string>
- <!-- no translation found for guest_reset_guest_dialog_title (8904781614074479690) -->
- <skip />
+ <string name="guest_reset_guest_dialog_title" msgid="8904781614074479690">"Redefinir sessão de visitante?"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Todos os apps e dados nesta sessão serão excluídos."</string>
<string name="guest_exit_guest_dialog_remove" msgid="7505817591242703757">"Remover"</string>
- <!-- no translation found for guest_reset_guest_dialog_remove (4359825585658228699) -->
- <skip />
+ <string name="guest_reset_guest_dialog_remove" msgid="4359825585658228699">"Redefinir"</string>
<string name="guest_wipe_session_title" msgid="7147965814683990944">"Você voltou, visitante!"</string>
<string name="guest_wipe_session_message" msgid="3393823610257065457">"Quer continuar a sessão?"</string>
<string name="guest_wipe_session_wipe" msgid="8056836584445473309">"Recomeçar"</string>
diff --git a/packages/SystemUI/res/values-pt-rPT/strings.xml b/packages/SystemUI/res/values-pt-rPT/strings.xml
index 738e91644681..a9cb3dc88fa1 100644
--- a/packages/SystemUI/res/values-pt-rPT/strings.xml
+++ b/packages/SystemUI/res/values-pt-rPT/strings.xml
@@ -480,12 +480,10 @@
<string name="user_add_user" msgid="4336657383006913022">"Adicionar utilizador"</string>
<string name="user_new_user_name" msgid="2019166282704195789">"Novo utilizador"</string>
<string name="guest_exit_guest_dialog_title" msgid="5015697561580641422">"Remover o convidado?"</string>
- <!-- no translation found for guest_reset_guest_dialog_title (8904781614074479690) -->
- <skip />
+ <string name="guest_reset_guest_dialog_title" msgid="8904781614074479690">"Pretende repor a sessão de convidado?"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Todas as apps e dados desta sessão serão eliminados."</string>
<string name="guest_exit_guest_dialog_remove" msgid="7505817591242703757">"Remover"</string>
- <!-- no translation found for guest_reset_guest_dialog_remove (4359825585658228699) -->
- <skip />
+ <string name="guest_reset_guest_dialog_remove" msgid="4359825585658228699">"Repor"</string>
<string name="guest_wipe_session_title" msgid="7147965814683990944">"Bem-vindo de volta, convidado!"</string>
<string name="guest_wipe_session_message" msgid="3393823610257065457">"Pretende continuar a sessão?"</string>
<string name="guest_wipe_session_wipe" msgid="8056836584445473309">"Recomeçar"</string>
diff --git a/packages/SystemUI/res/values-pt/strings.xml b/packages/SystemUI/res/values-pt/strings.xml
index ad41e5535e6d..e4dbca5eb8e3 100644
--- a/packages/SystemUI/res/values-pt/strings.xml
+++ b/packages/SystemUI/res/values-pt/strings.xml
@@ -480,12 +480,10 @@
<string name="user_add_user" msgid="4336657383006913022">"Adicionar usuário"</string>
<string name="user_new_user_name" msgid="2019166282704195789">"Novo usuário"</string>
<string name="guest_exit_guest_dialog_title" msgid="5015697561580641422">"Remover visitante?"</string>
- <!-- no translation found for guest_reset_guest_dialog_title (8904781614074479690) -->
- <skip />
+ <string name="guest_reset_guest_dialog_title" msgid="8904781614074479690">"Redefinir sessão de visitante?"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Todos os apps e dados nesta sessão serão excluídos."</string>
<string name="guest_exit_guest_dialog_remove" msgid="7505817591242703757">"Remover"</string>
- <!-- no translation found for guest_reset_guest_dialog_remove (4359825585658228699) -->
- <skip />
+ <string name="guest_reset_guest_dialog_remove" msgid="4359825585658228699">"Redefinir"</string>
<string name="guest_wipe_session_title" msgid="7147965814683990944">"Você voltou, visitante!"</string>
<string name="guest_wipe_session_message" msgid="3393823610257065457">"Quer continuar a sessão?"</string>
<string name="guest_wipe_session_wipe" msgid="8056836584445473309">"Recomeçar"</string>
diff --git a/packages/SystemUI/res/values-si/strings.xml b/packages/SystemUI/res/values-si/strings.xml
index 3a8b51c49117..6c82ad58a25f 100644
--- a/packages/SystemUI/res/values-si/strings.xml
+++ b/packages/SystemUI/res/values-si/strings.xml
@@ -480,12 +480,10 @@
<string name="user_add_user" msgid="4336657383006913022">"පරිශීලකයෙක් එක් කරන්න"</string>
<string name="user_new_user_name" msgid="2019166282704195789">"නව පරිශීලකයා"</string>
<string name="guest_exit_guest_dialog_title" msgid="5015697561580641422">"අමුත්තාන් ඉවත් කරන්නද?"</string>
- <!-- no translation found for guest_reset_guest_dialog_title (8904781614074479690) -->
- <skip />
+ <string name="guest_reset_guest_dialog_title" msgid="8904781614074479690">"ආගන්තුකයා යළි සකසන්නද?"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"මෙම සැසියේ සියළුම යෙදුම් සහ දත්ත මකාවී."</string>
<string name="guest_exit_guest_dialog_remove" msgid="7505817591242703757">"ඉවත් කරන්න"</string>
- <!-- no translation found for guest_reset_guest_dialog_remove (4359825585658228699) -->
- <skip />
+ <string name="guest_reset_guest_dialog_remove" msgid="4359825585658228699">"යළි සකසන්න"</string>
<string name="guest_wipe_session_title" msgid="7147965814683990944">"නැවත සාදරයෙන් පිළිගනිමු, අමුත්තා!"</string>
<string name="guest_wipe_session_message" msgid="3393823610257065457">"ඔබගේ සැසිය දිගටම කරගෙන යෑමට ඔබට අවශ්‍යද?"</string>
<string name="guest_wipe_session_wipe" msgid="8056836584445473309">"යළි මුල සිට අරඹන්න"</string>
diff --git a/packages/SystemUI/res/values-sv/strings.xml b/packages/SystemUI/res/values-sv/strings.xml
index 3ceef49a21e7..390a7bc268e3 100644
--- a/packages/SystemUI/res/values-sv/strings.xml
+++ b/packages/SystemUI/res/values-sv/strings.xml
@@ -480,12 +480,10 @@
<string name="user_add_user" msgid="4336657383006913022">"Lägg till användare"</string>
<string name="user_new_user_name" msgid="2019166282704195789">"Ny användare"</string>
<string name="guest_exit_guest_dialog_title" msgid="5015697561580641422">"Vill du ta bort gästen?"</string>
- <!-- no translation found for guest_reset_guest_dialog_title (8904781614074479690) -->
- <skip />
+ <string name="guest_reset_guest_dialog_title" msgid="8904781614074479690">"Vill du återställa gästsessionen?"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Alla appar och data i denna session kommer att raderas."</string>
<string name="guest_exit_guest_dialog_remove" msgid="7505817591242703757">"Ta bort"</string>
- <!-- no translation found for guest_reset_guest_dialog_remove (4359825585658228699) -->
- <skip />
+ <string name="guest_reset_guest_dialog_remove" msgid="4359825585658228699">"Återställ"</string>
<string name="guest_wipe_session_title" msgid="7147965814683990944">"Välkommen tillbaka som gäst!"</string>
<string name="guest_wipe_session_message" msgid="3393823610257065457">"Vill du fortsätta sessionen?"</string>
<string name="guest_wipe_session_wipe" msgid="8056836584445473309">"Börja om"</string>
diff --git a/packages/SystemUI/res/values-sw/strings.xml b/packages/SystemUI/res/values-sw/strings.xml
index 0a4e05923f89..99bf399b3c1b 100644
--- a/packages/SystemUI/res/values-sw/strings.xml
+++ b/packages/SystemUI/res/values-sw/strings.xml
@@ -480,12 +480,10 @@
<string name="user_add_user" msgid="4336657383006913022">"Ongeza mtumiaji"</string>
<string name="user_new_user_name" msgid="2019166282704195789">"Mtumiaji mpya"</string>
<string name="guest_exit_guest_dialog_title" msgid="5015697561580641422">"Ungependa kumwondoa mgeni?"</string>
- <!-- no translation found for guest_reset_guest_dialog_title (8904781614074479690) -->
- <skip />
+ <string name="guest_reset_guest_dialog_title" msgid="8904781614074479690">"Ungependa kubadilisha kipindi cha mgeni?"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Data na programu zote katika kipindi hiki zitafutwa."</string>
<string name="guest_exit_guest_dialog_remove" msgid="7505817591242703757">"Ondoa"</string>
- <!-- no translation found for guest_reset_guest_dialog_remove (4359825585658228699) -->
- <skip />
+ <string name="guest_reset_guest_dialog_remove" msgid="4359825585658228699">"Badilisha"</string>
<string name="guest_wipe_session_title" msgid="7147965814683990944">"Karibu tena mgeni!"</string>
<string name="guest_wipe_session_message" msgid="3393823610257065457">"Je, unataka kuendelea na kipindi chako?"</string>
<string name="guest_wipe_session_wipe" msgid="8056836584445473309">"Anza upya"</string>
diff --git a/packages/SystemUI/res/values-sw600dp/dimens.xml b/packages/SystemUI/res/values-sw600dp/dimens.xml
index 9f8e6364e55d..da80b85b38bf 100644
--- a/packages/SystemUI/res/values-sw600dp/dimens.xml
+++ b/packages/SystemUI/res/values-sw600dp/dimens.xml
@@ -36,10 +36,6 @@
<!-- On tablets this is just the close_handle_height -->
<dimen name="peek_height">@dimen/close_handle_height</dimen>
- <!-- The margin between the clock and the notifications on Keyguard. See
- keyguard_clock_height_fraction_* for the difference between min and max.-->
- <dimen name="keyguard_clock_notifications_margin">44dp</dimen>
-
<!-- Height of the status bar header bar when on Keyguard -->
<dimen name="status_bar_header_height_keyguard">60dp</dimen>
diff --git a/packages/SystemUI/res/values-television/colors.xml b/packages/SystemUI/res/values-television/colors.xml
index e5f3b4768fe2..e13c42e9ca3d 100644
--- a/packages/SystemUI/res/values-television/colors.xml
+++ b/packages/SystemUI/res/values-television/colors.xml
@@ -19,4 +19,19 @@
<resources>
<color name="volume_dialog_background_color">#E61F232B</color>
<color name="volume_dialog_background_color_above_blur">#C71F232B</color>
+
+ <color name="bottom_sheet_icon_color">#D2E3FC</color>
+
+ <color name="bottom_sheet_title_color">#E8F0FE</color>
+ <color name="bottom_sheet_body_color">#D2E3FC</color>
+
+ <color name="bottom_sheet_background_color">#1F232C</color>
+ <color name="bottom_sheet_background_color_with_blur">#AA1A2734</color>
+
+ <color name="bottom_sheet_button_background_color_focused">#E8F0FE</color>
+ <color name="bottom_sheet_button_background_color_unfocused">#0FE8EAED</color>
+
+ <color name="bottom_sheet_button_text_color_focused">#DB202124</color>
+ <color name="bottom_sheet_button_text_color_unfocused">#B5E8EAED</color>
+
</resources>
diff --git a/packages/SystemUI/res/values-television/dimens.xml b/packages/SystemUI/res/values-television/dimens.xml
index 7626db93dd76..3a1a3d923fcc 100644
--- a/packages/SystemUI/res/values-television/dimens.xml
+++ b/packages/SystemUI/res/values-television/dimens.xml
@@ -21,4 +21,27 @@
<dimen name="privacy_chip_icon_margin">3dp</dimen>
<dimen name="privacy_chip_icon_padding">8dp</dimen>
<dimen name="privacy_chip_icon_size">13dp</dimen>
+
+ <dimen name="bottom_sheet_padding_horizontal">32dp</dimen>
+ <dimen name="bottom_sheet_padding_vertical">24dp</dimen>
+
+ <dimen name="bottom_sheet_icon_size">42dp</dimen>
+ <dimen name="bottom_sheet_icon_margin">8dp</dimen>
+ <dimen name="bottom_sheet_title_margin_bottom">18dp</dimen>
+ <dimen name="bottom_sheet_details_margin_bottom">8dp</dimen>
+
+ <dimen name="bottom_sheet_actions_width">296dp</dimen>
+ <dimen name="bottom_sheet_actions_spacing">12dp</dimen>
+ <item name="bottom_sheet_button_selection_scaled" format="float" type="dimen">1.1</item>
+ <dimen name="bottom_sheet_button_width">232dp</dimen>
+ <dimen name="bottom_sheet_button_padding_horizontal">20dp</dimen>
+ <dimen name="bottom_sheet_button_padding_vertical">16dp</dimen>
+
+ <dimen name="bottom_sheet_corner_radius">24dp</dimen>
+ <dimen name="bottom_sheet_button_corner_radius">10dp</dimen>
+
+ <dimen name="bottom_sheet_min_height">208dp</dimen>
+ <dimen name="bottom_sheet_margin">24dp</dimen>
+ <dimen name="bottom_sheet_background_blur_radius">120dp</dimen>
+
</resources> \ No newline at end of file
diff --git a/packages/SystemUI/res/values-television/styles.xml b/packages/SystemUI/res/values-television/styles.xml
index 00217fb39b93..0fb789863bd9 100644
--- a/packages/SystemUI/res/values-television/styles.xml
+++ b/packages/SystemUI/res/values-television/styles.xml
@@ -28,4 +28,34 @@
<item name="android:textColorPrimaryInverse">@color/tv_volume_dialog_accent</item>
<item name="android:dialogCornerRadius">@dimen/volume_dialog_panel_width_half</item>
</style>
+
+ <style name="BottomSheet" parent="Theme.Leanback">
+ <item name="android:windowIsFloating">true</item>
+ <item name="android:windowActivityTransitions">true</item>
+ <item name="android:windowNoTitle">true</item>
+ <item name="android:windowIsTranslucent">true</item>
+ <item name="android:backgroundDimAmount">0.2</item>
+ </style>
+
+ <style name="BottomSheet.TitleText">
+ <item name="android:textSize">28sp</item>
+ <item name="android:textColor">@color/bottom_sheet_title_color</item>
+ </style>
+
+ <style name="BottomSheet.BodyText">
+ <item name="android:textSize">16sp</item>
+ <item name="android:textColor">@color/bottom_sheet_body_color</item>
+ </style>
+
+ <style name="BottomSheet.ActionItem">
+ <item name="android:layout_width">@dimen/bottom_sheet_button_width</item>
+ <item name="android:layout_height">wrap_content</item>
+ <item name="android:gravity">left|center_vertical</item>
+ <item name="android:textSize">16sp</item>
+ <item name="android:textColor">@color/bottom_sheet_button_text_color</item>
+ <item name="android:background">@drawable/bottom_sheet_button_background</item>
+ <item name="android:paddingHorizontal">@dimen/bottom_sheet_button_padding_horizontal</item>
+ <item name="android:paddingVertical">@dimen/bottom_sheet_button_padding_vertical</item>
+ <item name="android:stateListAnimator">@anim/tv_bottom_sheet_button_state_list_animator</item>
+ </style>
</resources>
diff --git a/packages/SystemUI/res/values-th/strings.xml b/packages/SystemUI/res/values-th/strings.xml
index d6eec3fd4fcf..b21d22faf958 100644
--- a/packages/SystemUI/res/values-th/strings.xml
+++ b/packages/SystemUI/res/values-th/strings.xml
@@ -480,12 +480,10 @@
<string name="user_add_user" msgid="4336657383006913022">"เพิ่มผู้ใช้"</string>
<string name="user_new_user_name" msgid="2019166282704195789">"ผู้ใช้ใหม่"</string>
<string name="guest_exit_guest_dialog_title" msgid="5015697561580641422">"ต้องการนำผู้ใช้ชั่วคราวออกไหม"</string>
- <!-- no translation found for guest_reset_guest_dialog_title (8904781614074479690) -->
- <skip />
+ <string name="guest_reset_guest_dialog_title" msgid="8904781614074479690">"รีเซ็ตผู้เข้าร่วมไหม"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"ระบบจะลบแอปและข้อมูลทั้งหมดในเซสชันนี้"</string>
<string name="guest_exit_guest_dialog_remove" msgid="7505817591242703757">"นำออก"</string>
- <!-- no translation found for guest_reset_guest_dialog_remove (4359825585658228699) -->
- <skip />
+ <string name="guest_reset_guest_dialog_remove" msgid="4359825585658228699">"รีเซ็ต"</string>
<string name="guest_wipe_session_title" msgid="7147965814683990944">"ยินดีต้อนรับผู้เข้าร่วมกลับมาอีกครั้ง"</string>
<string name="guest_wipe_session_message" msgid="3393823610257065457">"คุณต้องการอยู่ในเซสชันต่อไปไหม"</string>
<string name="guest_wipe_session_wipe" msgid="8056836584445473309">"เริ่มต้นใหม่"</string>
diff --git a/packages/SystemUI/res/values-tl/strings.xml b/packages/SystemUI/res/values-tl/strings.xml
index 0a7bdacc69c8..5b48488f18fe 100644
--- a/packages/SystemUI/res/values-tl/strings.xml
+++ b/packages/SystemUI/res/values-tl/strings.xml
@@ -480,12 +480,10 @@
<string name="user_add_user" msgid="4336657383006913022">"Magdagdag ng user"</string>
<string name="user_new_user_name" msgid="2019166282704195789">"Bagong user"</string>
<string name="guest_exit_guest_dialog_title" msgid="5015697561580641422">"Alisin ang bisita?"</string>
- <!-- no translation found for guest_reset_guest_dialog_title (8904781614074479690) -->
- <skip />
+ <string name="guest_reset_guest_dialog_title" msgid="8904781614074479690">"I-reset ang session ng bisita?"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Ide-delete ang lahat ng app at data sa session na ito."</string>
<string name="guest_exit_guest_dialog_remove" msgid="7505817591242703757">"Alisin"</string>
- <!-- no translation found for guest_reset_guest_dialog_remove (4359825585658228699) -->
- <skip />
+ <string name="guest_reset_guest_dialog_remove" msgid="4359825585658228699">"I-reset"</string>
<string name="guest_wipe_session_title" msgid="7147965814683990944">"Welcome ulit, bisita!"</string>
<string name="guest_wipe_session_message" msgid="3393823610257065457">"Gusto mo bang ipagpatuloy ang iyong session?"</string>
<string name="guest_wipe_session_wipe" msgid="8056836584445473309">"Magsimulang muli"</string>
diff --git a/packages/SystemUI/res/values-tr/strings.xml b/packages/SystemUI/res/values-tr/strings.xml
index 80e29fb5df6d..8a3d467fbe58 100644
--- a/packages/SystemUI/res/values-tr/strings.xml
+++ b/packages/SystemUI/res/values-tr/strings.xml
@@ -480,12 +480,10 @@
<string name="user_add_user" msgid="4336657383006913022">"Kullanıcı ekle"</string>
<string name="user_new_user_name" msgid="2019166282704195789">"Yeni kullanıcı"</string>
<string name="guest_exit_guest_dialog_title" msgid="5015697561580641422">"Misafir oturumu kaldırılsın mı?"</string>
- <!-- no translation found for guest_reset_guest_dialog_title (8904781614074479690) -->
- <skip />
+ <string name="guest_reset_guest_dialog_title" msgid="8904781614074479690">"Misafir oturumu sıfırlansın mı?"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Bu oturumdaki tüm uygulamalar ve veriler silinecek."</string>
<string name="guest_exit_guest_dialog_remove" msgid="7505817591242703757">"Kaldır"</string>
- <!-- no translation found for guest_reset_guest_dialog_remove (4359825585658228699) -->
- <skip />
+ <string name="guest_reset_guest_dialog_remove" msgid="4359825585658228699">"Sıfırla"</string>
<string name="guest_wipe_session_title" msgid="7147965814683990944">"Misafir kullanıcı, tekrar hoşgeldiniz"</string>
<string name="guest_wipe_session_message" msgid="3393823610257065457">"Oturumunuza devam etmek istiyor musunuz?"</string>
<string name="guest_wipe_session_wipe" msgid="8056836584445473309">"Baştan başla"</string>
diff --git a/packages/SystemUI/res/values-zh-rCN/strings.xml b/packages/SystemUI/res/values-zh-rCN/strings.xml
index 25cc331d993b..9592b2d6aa5c 100644
--- a/packages/SystemUI/res/values-zh-rCN/strings.xml
+++ b/packages/SystemUI/res/values-zh-rCN/strings.xml
@@ -480,12 +480,10 @@
<string name="user_add_user" msgid="4336657383006913022">"添加用户"</string>
<string name="user_new_user_name" msgid="2019166282704195789">"新用户"</string>
<string name="guest_exit_guest_dialog_title" msgid="5015697561580641422">"要移除访客吗?"</string>
- <!-- no translation found for guest_reset_guest_dialog_title (8904781614074479690) -->
- <skip />
+ <string name="guest_reset_guest_dialog_title" msgid="8904781614074479690">"要重置访客会话吗?"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"此会话中的所有应用和数据都将被删除。"</string>
<string name="guest_exit_guest_dialog_remove" msgid="7505817591242703757">"移除"</string>
- <!-- no translation found for guest_reset_guest_dialog_remove (4359825585658228699) -->
- <skip />
+ <string name="guest_reset_guest_dialog_remove" msgid="4359825585658228699">"重置"</string>
<string name="guest_wipe_session_title" msgid="7147965814683990944">"访客,欢迎回来!"</string>
<string name="guest_wipe_session_message" msgid="3393823610257065457">"要继续您的会话吗?"</string>
<string name="guest_wipe_session_wipe" msgid="8056836584445473309">"重新开始"</string>
diff --git a/packages/SystemUI/res/values-zh-rHK/strings.xml b/packages/SystemUI/res/values-zh-rHK/strings.xml
index 5c58081f5035..7be08d3fda5a 100644
--- a/packages/SystemUI/res/values-zh-rHK/strings.xml
+++ b/packages/SystemUI/res/values-zh-rHK/strings.xml
@@ -480,12 +480,10 @@
<string name="user_add_user" msgid="4336657383006913022">"加入使用者"</string>
<string name="user_new_user_name" msgid="2019166282704195789">"新使用者"</string>
<string name="guest_exit_guest_dialog_title" msgid="5015697561580641422">"移除訪客?"</string>
- <!-- no translation found for guest_reset_guest_dialog_title (8904781614074479690) -->
- <skip />
+ <string name="guest_reset_guest_dialog_title" msgid="8904781614074479690">"要重設訪客嗎?"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"這個工作階段中的所有應用程式和資料都會被刪除。"</string>
<string name="guest_exit_guest_dialog_remove" msgid="7505817591242703757">"移除"</string>
- <!-- no translation found for guest_reset_guest_dialog_remove (4359825585658228699) -->
- <skip />
+ <string name="guest_reset_guest_dialog_remove" msgid="4359825585658228699">"重設"</string>
<string name="guest_wipe_session_title" msgid="7147965814683990944">"訪客您好,歡迎回來!"</string>
<string name="guest_wipe_session_message" msgid="3393823610257065457">"您要繼續您的工作階段嗎?"</string>
<string name="guest_wipe_session_wipe" msgid="8056836584445473309">"重新開始"</string>
diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml
index 9678affa96a7..2a1bee5344ec 100644
--- a/packages/SystemUI/res/values/config.xml
+++ b/packages/SystemUI/res/values/config.xml
@@ -445,6 +445,9 @@
<!-- Adjust the theme on fully custom and decorated custom view notifications -->
<bool name="config_adjustThemeOnNotificationCustomViews">false</bool>
+ <!-- Notifications are sized to match the width of two (of 4) qs tiles in landscape. -->
+ <bool name="config_skinnyNotifsInLandscape">true</bool>
+
<!-- If true, enable the advance anti-falsing classifier on the lockscreen. On some devices it
does not work well, particularly with noisy touchscreens. Note that disabling it may
increase the rate of unintentional unlocks. -->
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index 3e4684c9b2d6..7525a9b1c19c 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -735,8 +735,8 @@
<!-- Minimum distance the user has to drag down to go to the full shade. -->
<dimen name="keyguard_drag_down_min_distance">100dp</dimen>
- <!-- The margin between the clock and the notifications on Keyguard.-->
- <dimen name="keyguard_clock_notifications_margin">30dp</dimen>
+ <!-- The margin between the status view and the notifications on Keyguard.-->
+ <dimen name="keyguard_status_view_bottom_margin">20dp</dimen>
<!-- Minimum margin between clock and status bar -->
<dimen name="keyguard_clock_top_margin">36dp</dimen>
<!-- The margin between top of clock and bottom of lock icon. -->
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitchController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitchController.java
index ef6212d4f354..a28d1747f2fe 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitchController.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitchController.java
@@ -205,6 +205,10 @@ public class KeyguardClockSwitchController extends ViewController<KeyguardClockS
}
}
+ int getNotificationIconAreaHeight() {
+ return mNotificationIconAreaController.getHeight();
+ }
+
@Override
protected void onViewDetached() {
if (CUSTOM_CLOCKS_ENABLED) {
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardStatusViewController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardStatusViewController.java
index 123c0e63d7d1..2096c310744d 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardStatusViewController.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardStatusViewController.java
@@ -187,10 +187,11 @@ public class KeyguardStatusViewController extends ViewController<KeyguardStatusV
}
/**
- * Get the height of the keyguard status view.
+ * Get the height of the keyguard status view without the notification icon area, as that's
+ * only visible on AOD.
*/
- public int getHeight() {
- return mView.getHeight();
+ public int getLockscreenHeight() {
+ return mView.getHeight() - mKeyguardClockSwitchController.getNotificationIconAreaHeight();
}
/**
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java
index ec930b0c41d1..11412f41f578 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java
@@ -67,6 +67,7 @@ import com.android.systemui.keyguard.KeyguardViewMediator;
import com.android.systemui.keyguard.ScreenLifecycle;
import com.android.systemui.plugins.FalsingManager;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
+import com.android.systemui.statusbar.LockscreenShadeTransitionController;
import com.android.systemui.statusbar.phone.StatusBar;
import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager;
import com.android.systemui.util.concurrency.DelayableExecutor;
@@ -111,6 +112,7 @@ public class UdfpsController implements DozeReceiver {
@NonNull private final FalsingManager mFalsingManager;
@NonNull private final PowerManager mPowerManager;
@NonNull private final AccessibilityManager mAccessibilityManager;
+ @NonNull private final LockscreenShadeTransitionController mLockscreenShadeTransitionController;
@Nullable private final UdfpsHbmProvider mHbmProvider;
// Currently the UdfpsController supports a single UDFPS sensor. If devices have multiple
// sensors, this, in addition to a lot of the code here, will be updated.
@@ -507,6 +509,7 @@ public class UdfpsController implements DozeReceiver {
@NonNull FalsingManager falsingManager,
@NonNull PowerManager powerManager,
@NonNull AccessibilityManager accessibilityManager,
+ @NonNull LockscreenShadeTransitionController lockscreenShadeTransitionController,
@NonNull ScreenLifecycle screenLifecycle,
@Nullable Vibrator vibrator,
@NonNull Optional<UdfpsHbmProvider> hbmProvider) {
@@ -529,6 +532,7 @@ public class UdfpsController implements DozeReceiver {
mFalsingManager = falsingManager;
mPowerManager = powerManager;
mAccessibilityManager = accessibilityManager;
+ mLockscreenShadeTransitionController = lockscreenShadeTransitionController;
mHbmProvider = hbmProvider.orElse(null);
screenLifecycle.addObserver(mScreenObserver);
mScreenOn = screenLifecycle.getScreenState() == ScreenLifecycle.SCREEN_ON;
@@ -716,6 +720,7 @@ public class UdfpsController implements DozeReceiver {
mFgExecutor,
mDumpManager,
mKeyguardViewMediator,
+ mLockscreenShadeTransitionController,
this
);
case IUdfpsOverlayController.REASON_AUTH_BP:
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardViewController.java b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardViewController.java
index 00888dfe48d3..35ca470df523 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardViewController.java
@@ -31,6 +31,7 @@ import com.android.systemui.R;
import com.android.systemui.dump.DumpManager;
import com.android.systemui.keyguard.KeyguardViewMediator;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
+import com.android.systemui.statusbar.LockscreenShadeTransitionController;
import com.android.systemui.statusbar.StatusBarState;
import com.android.systemui.statusbar.phone.KeyguardBouncer;
import com.android.systemui.statusbar.phone.StatusBar;
@@ -54,6 +55,7 @@ public class UdfpsKeyguardViewController extends UdfpsAnimationViewController<Ud
@NonNull private final KeyguardUpdateMonitor mKeyguardUpdateMonitor;
@NonNull private final DelayableExecutor mExecutor;
@NonNull private final KeyguardViewMediator mKeyguardViewMediator;
+ @NonNull private final LockscreenShadeTransitionController mLockScreenShadeTransitionController;
@NonNull private final UdfpsController mUdfpsController;
@Nullable private Runnable mCancelDelayedHintRunnable;
@@ -63,6 +65,7 @@ public class UdfpsKeyguardViewController extends UdfpsAnimationViewController<Ud
private boolean mFaceDetectRunning;
private boolean mHintShown;
private int mStatusBarState;
+ private float mTransitionToFullShadeProgress;
/**
* hidden amount of pin/pattern/password bouncer
@@ -81,12 +84,14 @@ public class UdfpsKeyguardViewController extends UdfpsAnimationViewController<Ud
@NonNull DelayableExecutor mainDelayableExecutor,
@NonNull DumpManager dumpManager,
@NonNull KeyguardViewMediator keyguardViewMediator,
+ @NonNull LockscreenShadeTransitionController transitionController,
@NonNull UdfpsController udfpsController) {
super(view, statusBarStateController, statusBar, dumpManager);
mKeyguardViewManager = statusBarKeyguardViewManager;
mKeyguardUpdateMonitor = keyguardUpdateMonitor;
mExecutor = mainDelayableExecutor;
mKeyguardViewMediator = keyguardViewMediator;
+ mLockScreenShadeTransitionController = transitionController;
mUdfpsController = udfpsController;
}
@@ -116,6 +121,7 @@ public class UdfpsKeyguardViewController extends UdfpsAnimationViewController<Ud
updatePauseAuth();
mKeyguardViewManager.setAlternateAuthInterceptor(mAlternateAuthInterceptor);
+ mLockScreenShadeTransitionController.setUdfpsKeyguardViewController(this);
}
@Override
@@ -127,6 +133,9 @@ public class UdfpsKeyguardViewController extends UdfpsAnimationViewController<Ud
mStatusBarStateController.removeCallback(mStateListener);
mKeyguardViewManager.removeAlternateAuthInterceptor(mAlternateAuthInterceptor);
mKeyguardUpdateMonitor.requestFaceAuthOnOccludingApp(false);
+ if (mLockScreenShadeTransitionController.getUdfpsKeyguardViewController() == this) {
+ mLockScreenShadeTransitionController.setUdfpsKeyguardViewController(null);
+ }
if (mCancelDelayedHintRunnable != null) {
mCancelDelayedHintRunnable.run();
@@ -256,11 +265,21 @@ public class UdfpsKeyguardViewController extends UdfpsAnimationViewController<Ud
}
}
+ /**
+ * Set the progress we're currently transitioning to the full shade. 0.0f means we're not
+ * transitioning yet, while 1.0f means we've fully dragged down.
+ */
+ public void setTransitionToFullShadeProgress(float progress) {
+ mTransitionToFullShadeProgress = progress;
+ updateAlpha();
+ }
+
private void updateAlpha() {
// fade icon on transition to showing bouncer
int alpha = mShowingUdfpsBouncer ? 255
: Math.abs((int) MathUtils.constrainedMap(0f, 255f, .4f, .7f,
mInputBouncerHiddenAmount));
+ alpha *= (1.0f - mTransitionToFullShadeProgress);
mView.setUnpausedAlpha(alpha);
}
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/DefaultActivityBinder.java b/packages/SystemUI/src/com/android/systemui/dagger/DefaultActivityBinder.java
index 2dbf30fdd289..de8ed7013ab2 100644
--- a/packages/SystemUI/src/com/android/systemui/dagger/DefaultActivityBinder.java
+++ b/packages/SystemUI/src/com/android/systemui/dagger/DefaultActivityBinder.java
@@ -25,6 +25,7 @@ import com.android.systemui.people.widget.LaunchConversationActivity;
import com.android.systemui.screenrecord.ScreenRecordDialog;
import com.android.systemui.screenshot.LongScreenshotActivity;
import com.android.systemui.sensorprivacy.SensorUseStartedActivity;
+import com.android.systemui.sensorprivacy.television.TvUnblockSensorActivity;
import com.android.systemui.settings.brightness.BrightnessDialog;
import com.android.systemui.statusbar.tv.notifications.TvNotificationPanelActivity;
import com.android.systemui.tuner.TunerActivity;
@@ -120,4 +121,10 @@ public abstract class DefaultActivityBinder {
@IntoMap
@ClassKey(SensorUseStartedActivity.class)
public abstract Activity bindSensorUseStartedActivity(SensorUseStartedActivity activity);
+
+ /** Inject into TvUnblockSensorActivity. */
+ @Binds
+ @IntoMap
+ @ClassKey(TvUnblockSensorActivity.class)
+ public abstract Activity bindTvUnblockSensorActivity(TvUnblockSensorActivity activity);
}
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java b/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java
index 7b34e52c16e8..455f3c0d6ac2 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java
@@ -71,7 +71,6 @@ public class DozeTriggers implements DozeMachine.Part {
* Assuming that the screen should start on.
*/
private static boolean sWakeDisplaySensorState = true;
- private Runnable mQuickPickupDozeCancellable;
private static final int PROXIMITY_TIMEOUT_DELAY_MS = 500;
@@ -279,14 +278,14 @@ public class DozeTriggers implements DozeMachine.Part {
boolean isWakeDisplayEvent = isQuickPickup || ((isWakeOnPresence || isWakeOnReach)
&& rawValues != null && rawValues.length > 0 && rawValues[0] != 0);
- if (isWakeOnPresence || isQuickPickup) {
- onWakeScreen(isQuickPickup || isWakeDisplayEvent,
+ if (isWakeOnPresence) {
+ onWakeScreen(isWakeDisplayEvent,
mMachine.isExecutingTransition() ? null : mMachine.getState(),
pulseReason);
} else if (isLongPress) {
requestPulse(pulseReason, true /* alreadyPerformedProxCheck */,
null /* onPulseSuppressedListener */);
- } else if (isWakeOnReach) {
+ } else if (isWakeOnReach || isQuickPickup) {
if (isWakeDisplayEvent) {
requestPulse(pulseReason, true /* alreadyPerformedProxCheck */,
null /* onPulseSuppressedListener */);
@@ -388,11 +387,7 @@ public class DozeTriggers implements DozeMachine.Part {
*/
private void onWakeScreen(boolean wake, @Nullable DozeMachine.State state, int reason) {
mDozeLog.traceWakeDisplay(wake, reason);
- final boolean isWakeOnPresence = reason == DozeLog.REASON_SENSOR_WAKE_UP;
- final boolean isQuickPickup = reason == DozeLog.REASON_SENSOR_QUICK_PICKUP;
- if (isWakeOnPresence) {
- sWakeDisplaySensorState = wake;
- }
+ sWakeDisplaySensorState = wake;
if (wake) {
proximityCheckThenCall((result) -> {
@@ -405,27 +400,13 @@ public class DozeTriggers implements DozeMachine.Part {
// Log sensor triggered
Optional.ofNullable(DozingUpdateUiEvent.fromReason(reason))
.ifPresent(mUiEventLogger::log);
-
- if (isQuickPickup) {
- // schedule runnable to go back to DOZE
- onQuickPickup();
- }
- } else if (state == DozeMachine.State.DOZE_AOD && isQuickPickup) {
- // elongate time in DOZE_AOD, schedule new runnable to go back to DOZE
- onQuickPickup();
}
- }, isQuickPickup /* alreadyPerformedProxCheck */, reason);
+ }, false /* alreadyPerformedProxCheck */, reason);
} else {
boolean paused = (state == DozeMachine.State.DOZE_AOD_PAUSED);
boolean pausing = (state == DozeMachine.State.DOZE_AOD_PAUSING);
- boolean pulse = (state == DozeMachine.State.DOZE_REQUEST_PULSE)
- || (state == DozeMachine.State.DOZE_PULSING)
- || (state == DozeMachine.State.DOZE_PULSING_BRIGHT);
- boolean docked = (state == DozeMachine.State.DOZE_AOD_DOCKED);
+
if (!pausing && !paused) {
- if (isQuickPickup && (pulse || docked)) {
- return;
- }
mMachine.requestState(DozeMachine.State.DOZE);
// log wake timeout
mUiEventLogger.log(DozingUpdateUiEvent.DOZING_UPDATE_WAKE_TIMEOUT);
@@ -433,15 +414,6 @@ public class DozeTriggers implements DozeMachine.Part {
}
}
- private void onQuickPickup() {
- cancelQuickPickupDelayableDoze();
- mQuickPickupDozeCancellable = mMainExecutor.executeDelayed(() -> {
- onWakeScreen(false,
- mMachine.isExecutingTransition() ? null : mMachine.getState(),
- DozeLog.REASON_SENSOR_QUICK_PICKUP);
- }, mDozeParameters.getQuickPickupAodDuration());
- }
-
@Override
public void transitionTo(DozeMachine.State oldState, DozeMachine.State newState) {
switch (newState) {
@@ -481,7 +453,6 @@ public class DozeTriggers implements DozeMachine.Part {
mDozeSensors.requestTemporaryDisable();
break;
case FINISH:
- cancelQuickPickupDelayableDoze();
mBroadcastReceiver.unregister(mBroadcastDispatcher);
mDozeHost.removeCallback(mHostCallback);
mDockManager.removeListener(mDockEventListener);
@@ -510,16 +481,6 @@ public class DozeTriggers implements DozeMachine.Part {
}
}
- /**
- * Cancels last scheduled Runnable that transitions to STATE_DOZE (blank screen) after
- * going into STATE_AOD (AOD screen) from the quick pickup gesture.
- */
- private void cancelQuickPickupDelayableDoze() {
- if (mQuickPickupDozeCancellable != null) {
- mQuickPickupDozeCancellable.run();
- mQuickPickupDozeCancellable = null;
- }
- }
private void checkTriggersAtInit() {
if (mUiModeManager.getCurrentModeType() == Configuration.UI_MODE_TYPE_CAR
diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaCarouselController.kt b/packages/SystemUI/src/com/android/systemui/media/MediaCarouselController.kt
index 3251ab2e4d50..3957a60c5b45 100644
--- a/packages/SystemUI/src/com/android/systemui/media/MediaCarouselController.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/MediaCarouselController.kt
@@ -32,6 +32,7 @@ import javax.inject.Provider
private const val TAG = "MediaCarouselController"
private val settingsIntent = Intent().setAction(ACTION_MEDIA_CONTROLS_SETTINGS)
+private const val DEBUG = false
/**
* Class that is responsible for keeping the view carousel up to date.
@@ -237,7 +238,7 @@ class MediaCarouselController @Inject constructor(
data: SmartspaceMediaData,
shouldPrioritize: Boolean
) {
- Log.d(TAG, "My Smartspace media update is here")
+ if (DEBUG) Log.d(TAG, "Loading Smartspace media update")
if (data.isActive) {
addSmartspaceMediaRecommendations(key, data, shouldPrioritize)
MediaPlayerData.getMediaPlayer(key, null)?.let {
@@ -266,7 +267,7 @@ class MediaCarouselController @Inject constructor(
}
override fun onSmartspaceMediaDataRemoved(key: String, immediately: Boolean) {
- Log.d(TAG, "My Smartspace media removal request is received")
+ if (DEBUG) Log.d(TAG, "My Smartspace media removal request is received")
if (immediately || visualStabilityManager.isReorderingAllowed) {
onMediaDataRemoved(key)
} else {
@@ -384,7 +385,7 @@ class MediaCarouselController @Inject constructor(
data: SmartspaceMediaData,
shouldPrioritize: Boolean
) {
- Log.d(TAG, "Updating smartspace target in carousel")
+ if (DEBUG) Log.d(TAG, "Updating smartspace target in carousel")
if (MediaPlayerData.getMediaPlayer(key, null) != null) {
Log.w(TAG, "Skip adding smartspace target in carousel")
return
diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaDataManager.kt b/packages/SystemUI/src/com/android/systemui/media/MediaDataManager.kt
index ed6f5505cbd1..df1b07f3e0b2 100644
--- a/packages/SystemUI/src/com/android/systemui/media/MediaDataManager.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/MediaDataManager.kt
@@ -453,7 +453,8 @@ class MediaDataManager(
if (smartspaceMediaData.targetId != key) {
return
}
- Log.d(TAG, "Dismissing Smartspace media target")
+
+ if (DEBUG) Log.d(TAG, "Dismissing Smartspace media target")
if (smartspaceMediaData.isActive) {
smartspaceMediaData = EMPTY_SMARTSPACE_MEDIA_DATA.copy(
targetId = smartspaceMediaData.targetId)
@@ -709,17 +710,19 @@ class MediaDataManager(
override fun onSmartspaceTargetsUpdated(targets: List<Parcelable>) {
if (!allowMediaRecommendations) {
+ if (DEBUG) Log.d(TAG, "Smartspace recommendation is disabled in Settings.")
return
}
val mediaTargets = targets.filterIsInstance<SmartspaceTarget>()
when (mediaTargets.size) {
0 -> {
- Log.d(TAG, "Empty Smartspace media target")
if (!smartspaceMediaData.isActive) {
return
}
- Log.d(TAG, "Set Smartspace media to be inactive for the data update")
+ if (DEBUG) {
+ Log.d(TAG, "Set Smartspace media to be inactive for the data update")
+ }
smartspaceMediaData = EMPTY_SMARTSPACE_MEDIA_DATA.copy(
targetId = smartspaceMediaData.targetId)
notifySmartspaceMediaDataRemoved(smartspaceMediaData.targetId, immediately = false)
@@ -728,13 +731,12 @@ class MediaDataManager(
val newMediaTarget = mediaTargets.get(0)
if (smartspaceMediaData.targetId == newMediaTarget.smartspaceTargetId) {
// The same Smartspace updates can be received. Skip the duplicate updates.
- Log.d(TAG, "Same Smartspace media update exists. Skip loading data.")
- } else {
- Log.d(TAG, "Forwarding Smartspace media update.")
- smartspaceMediaData = toSmartspaceMediaData(newMediaTarget, isActive = true)
- notifySmartspaceMediaDataLoaded(
- smartspaceMediaData.targetId, smartspaceMediaData)
+ return
}
+ if (DEBUG) Log.d(TAG, "Forwarding Smartspace media update.")
+ smartspaceMediaData = toSmartspaceMediaData(newMediaTarget, isActive = true)
+ notifySmartspaceMediaDataLoaded(
+ smartspaceMediaData.targetId, smartspaceMediaData)
}
else -> {
// There should NOT be more than 1 Smartspace media update. When it happens, it
@@ -883,7 +885,7 @@ class MediaDataManager(
private fun packageName(target: SmartspaceTarget): String? {
val recommendationList = target.iconGrid
if (recommendationList == null || recommendationList.isEmpty()) {
- Log.d(TAG, "Empty or media recommendation list.")
+ Log.w(TAG, "Empty or null media recommendation list.")
return null
}
for (recommendation in recommendationList) {
@@ -893,7 +895,7 @@ class MediaDataManager(
packageName -> return packageName }
}
}
- Log.d(TAG, "No valid package name is provided.")
+ Log.w(TAG, "No valid package name is provided.")
return null
}
diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaHierarchyManager.kt b/packages/SystemUI/src/com/android/systemui/media/MediaHierarchyManager.kt
index 3d1b4fbde56a..186f961ff1b6 100644
--- a/packages/SystemUI/src/com/android/systemui/media/MediaHierarchyManager.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/MediaHierarchyManager.kt
@@ -660,15 +660,11 @@ class MediaHierarchyManager @Inject constructor(
return true
}
- if (statusbarState == StatusBarState.KEYGUARD) {
- if (currentLocation == LOCATION_LOCKSCREEN &&
- previousLocation == LOCATION_QS ||
- (currentLocation == LOCATION_QS &&
- previousLocation == LOCATION_LOCKSCREEN)) {
- // We're always fading from lockscreen to keyguard in situations where the player
- // is already fully hidden
- return false
- }
+ if (statusbarState == StatusBarState.KEYGUARD && (currentLocation == LOCATION_LOCKSCREEN ||
+ previousLocation == LOCATION_LOCKSCREEN)) {
+ // We're always fading from lockscreen to keyguard in situations where the player
+ // is already fully hidden
+ return false
}
return mediaFrame.isShownNotFaded || animator.isRunning || animationPending
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSContainerImpl.java b/packages/SystemUI/src/com/android/systemui/qs/QSContainerImpl.java
index edfbed04f70d..6660081006cd 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSContainerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSContainerImpl.java
@@ -297,7 +297,7 @@ public class QSContainerImpl extends FrameLayout {
// start margin of next page).
qsPanelController.setPageMargin(mSideMargins);
} else if (view == mHeader) {
- // No content padding for the header.
+ quickStatusBarHeaderController.setContentMargins(mContentPadding, mContentPadding);
} else {
view.setPaddingRelative(
mContentPadding,
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
index 0bb0a3f7bad4..c70eaffcaeb6 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
@@ -425,7 +425,7 @@ public class QSPanel extends LinearLayout implements Tunable {
LinearLayout.LayoutParams layoutParams = (LayoutParams) hostView.getLayoutParams();
layoutParams.height = ViewGroup.LayoutParams.WRAP_CONTENT;
layoutParams.width = horizontal ? 0 : ViewGroup.LayoutParams.MATCH_PARENT;
- layoutParams.weight = horizontal ? 1.2f : 0;
+ layoutParams.weight = horizontal ? 1f : 0;
// Add any bottom margin, such that the total spacing is correct. This is only
// necessary if the view isn't horizontal, since otherwise the padding is
// carried in the parent of this view (to ensure correct vertical alignment)
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeaderController.java b/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeaderController.java
index cbdcad5cf385..76076f6c2761 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeaderController.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeaderController.java
@@ -177,7 +177,6 @@ class QuickStatusBarHeaderController extends ViewController<QuickStatusBarHeader
mView.onAttach(mIconManager, mQSExpansionPathInterpolator);
mDemoModeController.addCallback(mDemoModeReceiver);
- mHeaderQsPanelController.setContentMargins(0, 0);
}
@Override
@@ -253,6 +252,10 @@ class QuickStatusBarHeaderController extends ViewController<QuickStatusBarHeader
return mMicCameraIndicatorsEnabled || mLocationIndicatorsEnabled;
}
+ public void setContentMargins(int marginStart, int marginEnd) {
+ mHeaderQsPanelController.setContentMargins(marginStart, marginEnd);
+ }
+
private static class ClockDemoModeReceiver implements DemoMode {
private Clock mClockView;
diff --git a/packages/SystemUI/src/com/android/systemui/sensorprivacy/television/TvUnblockSensorActivity.java b/packages/SystemUI/src/com/android/systemui/sensorprivacy/television/TvUnblockSensorActivity.java
new file mode 100644
index 000000000000..9d101effa99f
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/sensorprivacy/television/TvUnblockSensorActivity.java
@@ -0,0 +1,145 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.sensorprivacy.television;
+
+import static android.hardware.SensorPrivacyManager.Sensors.CAMERA;
+import static android.hardware.SensorPrivacyManager.Sensors.MICROPHONE;
+
+import android.hardware.SensorPrivacyManager;
+import android.os.Bundle;
+import android.util.Log;
+import android.view.View;
+import android.widget.Button;
+import android.widget.ImageView;
+import android.widget.TextView;
+
+import com.android.systemui.R;
+import com.android.systemui.statusbar.policy.IndividualSensorPrivacyController;
+import com.android.systemui.tv.TvBottomSheetActivity;
+
+import javax.inject.Inject;
+
+/**
+ * Bottom sheet that is shown when the camera/mic sensors are blocked by the global toggle and
+ * allows the user to re-enable them.
+ */
+public class TvUnblockSensorActivity extends TvBottomSheetActivity {
+
+ private static final String TAG = TvUnblockSensorActivity.class.getSimpleName();
+
+ private static final int ALL_SENSORS = Integer.MAX_VALUE;
+ private int mSensor = -1;
+
+ private final IndividualSensorPrivacyController mSensorPrivacyController;
+ private IndividualSensorPrivacyController.Callback mSensorPrivacyCallback;
+
+ @Inject
+ public TvUnblockSensorActivity(
+ IndividualSensorPrivacyController individualSensorPrivacyController) {
+ mSensorPrivacyController = individualSensorPrivacyController;
+ }
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ boolean allSensors = getIntent().getBooleanExtra(SensorPrivacyManager.EXTRA_ALL_SENSORS,
+ false);
+ if (allSensors) {
+ mSensor = ALL_SENSORS;
+ } else {
+ mSensor = getIntent().getIntExtra(SensorPrivacyManager.EXTRA_SENSOR, -1);
+ }
+
+ if (mSensor == -1) {
+ Log.v(TAG, "Invalid extras");
+ finish();
+ return;
+ }
+
+ mSensorPrivacyCallback = (sensor, blocked) -> {
+ if (mSensor == ALL_SENSORS) {
+ if (!mSensorPrivacyController.isSensorBlocked(CAMERA)
+ && !mSensorPrivacyController.isSensorBlocked(MICROPHONE)) {
+ finish();
+ }
+ } else if (this.mSensor == sensor && !blocked) {
+ finish();
+ }
+ };
+
+ initUI();
+ }
+
+ private void initUI() {
+ TextView title = findViewById(R.id.bottom_sheet_title);
+ TextView content = findViewById(R.id.bottom_sheet_body);
+ ImageView icon = findViewById(R.id.bottom_sheet_icon);
+ // mic icon if both icons are shown
+ ImageView secondIcon = findViewById(R.id.bottom_sheet_second_icon);
+ Button unblockButton = findViewById(R.id.bottom_sheet_positive_button);
+ Button cancelButton = findViewById(R.id.bottom_sheet_negative_button);
+
+ switch (mSensor) {
+ case MICROPHONE:
+ title.setText(R.string.sensor_privacy_start_use_mic_dialog_title);
+ content.setText(R.string.sensor_privacy_start_use_mic_dialog_content);
+ icon.setImageResource(com.android.internal.R.drawable.perm_group_microphone);
+ secondIcon.setVisibility(View.GONE);
+ break;
+ case CAMERA:
+ title.setText(R.string.sensor_privacy_start_use_camera_dialog_title);
+ content.setText(R.string.sensor_privacy_start_use_camera_dialog_content);
+ icon.setImageResource(com.android.internal.R.drawable.perm_group_camera);
+ secondIcon.setVisibility(View.GONE);
+ break;
+ case ALL_SENSORS:
+ default:
+ title.setText(R.string.sensor_privacy_start_use_mic_camera_dialog_title);
+ content.setText(R.string.sensor_privacy_start_use_mic_camera_dialog_content);
+ icon.setImageResource(com.android.internal.R.drawable.perm_group_camera);
+ secondIcon.setImageResource(com.android.internal.R.drawable.perm_group_microphone);
+ break;
+ }
+ unblockButton.setText(
+ com.android.internal.R.string.sensor_privacy_start_use_dialog_turn_on_button);
+ unblockButton.setOnClickListener(v -> {
+ if (mSensor == ALL_SENSORS) {
+ mSensorPrivacyController.setSensorBlocked(CAMERA, false);
+ mSensorPrivacyController.setSensorBlocked(MICROPHONE, false);
+ } else {
+ mSensorPrivacyController.setSensorBlocked(mSensor, false);
+ }
+ });
+
+ cancelButton.setText(android.R.string.cancel);
+ cancelButton.setOnClickListener(v -> finish());
+ }
+
+ @Override
+ public void onResume() {
+ super.onResume();
+ mSensorPrivacyController.addCallback(mSensorPrivacyCallback);
+ }
+
+ @Override
+ public void onPause() {
+ mSensorPrivacyController.removeCallback(mSensorPrivacyCallback);
+ super.onPause();
+ }
+
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/LockscreenShadeTransitionController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/LockscreenShadeTransitionController.kt
index 4a4e990728f3..6f4a73ec4516 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/LockscreenShadeTransitionController.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/LockscreenShadeTransitionController.kt
@@ -18,6 +18,7 @@ import com.android.systemui.ExpandHelper
import com.android.systemui.Gefingerpoken
import com.android.systemui.R
import com.android.systemui.animation.Interpolators
+import com.android.systemui.biometrics.UdfpsKeyguardViewController
import com.android.systemui.classifier.Classifier
import com.android.systemui.classifier.FalsingCollector
import com.android.systemui.dagger.SysUISingleton
@@ -109,6 +110,11 @@ class LockscreenShadeTransitionController @Inject constructor(
private var nextHideKeyguardNeedsNoAnimation = false
/**
+ * The udfpsKeyguardViewController if it exists.
+ */
+ var udfpsKeyguardViewController: UdfpsKeyguardViewController? = null
+
+ /**
* The touch helper responsible for the drag down animation.
*/
val touchHelper = DragDownHelper(falsingManager, falsingCollector, this, context)
@@ -291,6 +297,7 @@ class LockscreenShadeTransitionController @Inject constructor(
// Fade out all content only visible on the lockscreen
notificationPanelController.setKeyguardOnlyContentAlpha(1.0f - scrimProgress)
depthController.transitionToFullShadeProgress = scrimProgress
+ udfpsKeyguardViewController?.setTransitionToFullShadeProgress(scrimProgress)
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/ExpandAnimationParameters.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/ExpandAnimationParameters.kt
index f1479a149a41..f19cf5d8d9c7 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/ExpandAnimationParameters.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/ExpandAnimationParameters.kt
@@ -22,11 +22,27 @@ class ExpandAnimationParameters(
)
var startTranslationZ = 0f
+
+ /**
+ * The top position of the notification at the start of the animation. This is needed in order
+ * to keep the notification at its place when launching a notification that is clipped rounded.
+ */
+ var startNotificationTop = 0f
var startClipTopAmount = 0
var parentStartClipTopAmount = 0
var progress = 0f
var linearProgress = 0f
+ /**
+ * The rounded top clipping at the beginning.
+ */
+ var startRoundedTopClipping = 0
+
+ /**
+ * The rounded top clipping of the parent notification at the start.
+ */
+ var parentStartRoundedTopClipping = 0
+
override val topChange: Int
get() {
// We need this compensation to ensure that the QS moves in sync.
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationLaunchAnimatorController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationLaunchAnimatorController.kt
index c248670c48db..1bbef2562d21 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationLaunchAnimatorController.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationLaunchAnimatorController.kt
@@ -40,6 +40,11 @@ class NotificationLaunchAnimatorController(
private val headsUpManager: HeadsUpManagerPhone,
private val notification: ExpandableNotificationRow
) : ActivityLaunchAnimator.Controller {
+
+ companion object {
+ const val ANIMATION_DURATION_TOP_ROUNDING = 100L
+ }
+
private val notificationEntry = notification.entry
private val notificationKey = notificationEntry.sbn.key
@@ -54,18 +59,37 @@ class NotificationLaunchAnimatorController(
val height = max(0, notification.actualHeight - notification.clipBottomAmount)
val location = notification.locationOnScreen
+ val clipStartLocation = notificationListContainer.getTopClippingStartLocation()
+ val roundedTopClipping = Math.max(clipStartLocation - location[1], 0)
+ val windowTop = location[1] + roundedTopClipping
+ val topCornerRadius = if (roundedTopClipping > 0) {
+ // Because the rounded Rect clipping is complex, we start the top rounding at
+ // 0, which is pretty close to matching the real clipping.
+ // We'd have to clipOut the overlaid drawable too with the outer rounded rect in case
+ // if we'd like to have this perfect, but this is close enough.
+ 0f
+ } else {
+ notification.currentBackgroundRadiusTop
+ }
val params = ExpandAnimationParameters(
- top = location[1],
+ top = windowTop,
bottom = location[1] + height,
left = location[0],
right = location[0] + notification.width,
- topCornerRadius = notification.currentBackgroundRadiusTop,
+ topCornerRadius = topCornerRadius,
bottomCornerRadius = notification.currentBackgroundRadiusBottom
)
params.startTranslationZ = notification.translationZ
+ params.startNotificationTop = notification.translationY
+ params.startRoundedTopClipping = roundedTopClipping
params.startClipTopAmount = notification.clipTopAmount
if (notification.isChildInGroup) {
+ params.startNotificationTop += notification.notificationParent.translationY
+ val parentRoundedClip = Math.max(clipStartLocation
+ - notification.notificationParent.locationOnScreen[1], 0)
+ params.parentStartRoundedTopClipping = parentRoundedClip
+
val parentClip = notification.notificationParent.clipTopAmount
params.parentStartClipTopAmount = parentClip
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java
index 9d56e9b6f855..76f9fe728f2f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java
@@ -35,6 +35,7 @@ import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.res.Configuration;
import android.content.res.Resources;
+import android.graphics.Canvas;
import android.graphics.Path;
import android.graphics.drawable.AnimatedVectorDrawable;
import android.graphics.drawable.AnimationDrawable;
@@ -85,6 +86,7 @@ import com.android.systemui.statusbar.RemoteInputController;
import com.android.systemui.statusbar.StatusBarIconView;
import com.android.systemui.statusbar.notification.AboveShelfChangedListener;
import com.android.systemui.statusbar.notification.ExpandAnimationParameters;
+import com.android.systemui.statusbar.notification.NotificationLaunchAnimatorController;
import com.android.systemui.statusbar.notification.NotificationUtils;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.collection.legacy.VisualStabilityManager;
@@ -133,7 +135,7 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
private boolean mUpdateBackgroundOnUpdate;
private boolean mNotificationTranslationFinished = false;
- private ArrayList<MenuItem> mSnoozedMenuItems;
+ private boolean mIsSnoozed;
/**
* Listener for when {@link ExpandableNotificationRow} is laid out.
@@ -252,6 +254,7 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
private OnExpandClickListener mOnExpandClickListener;
private View.OnClickListener mOnAppClickListener;
private View.OnClickListener mOnFeedbackClickListener;
+ private Path mExpandingClipPath;
// Listener will be called when receiving a long click event.
// Use #setLongPressPosition to optionally assign positional data with the long press.
@@ -836,6 +839,7 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
public void setIsChildInGroup(boolean isChildInGroup, ExpandableNotificationRow parent) {
if (mExpandAnimationRunning && !isChildInGroup && mNotificationParent != null) {
mNotificationParent.setChildIsExpanding(false);
+ mNotificationParent.setExpandingClipPath(null);
mNotificationParent.setExtraWidthForClipping(0.0f);
mNotificationParent.setMinimumHeightForClipping(0);
}
@@ -1105,8 +1109,7 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
false /* force */, false /* removeControls */, -1 /* x */, -1 /* y */,
false /* resetMenu */);
mNotificationGutsManager.openGuts(this, 0, 0, item);
- mSnoozedMenuItems = mMenuRow.getMenuItems(mMenuRow.getMenuView().getContext());
- mMenuRow.resetMenu();
+ mIsSnoozed = true;
};
}
@@ -1821,10 +1824,7 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
void onGutsClosed() {
updateContentAccessibilityImportanceForGuts(true /* isEnabled */);
- if (mSnoozedMenuItems != null && mSnoozedMenuItems.size() > 0) {
- mMenuRow.setMenuItems(mSnoozedMenuItems);
- mSnoozedMenuItems = null;
- }
+ mIsSnoozed = false;
}
/**
@@ -2036,7 +2036,22 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
setTranslationZ(translationZ);
float extraWidthForClipping = params.getWidth() - getWidth();
setExtraWidthForClipping(extraWidthForClipping);
- int top = params.getTop();
+ int top;
+ if (params.getStartRoundedTopClipping() > 0) {
+ // If we were clipping initially, let's interpolate from the start position to the
+ // top. Otherwise, we just take the top directly.
+ float expandProgress = Interpolators.FAST_OUT_SLOW_IN.getInterpolation(
+ params.getProgress(0,
+ NotificationLaunchAnimatorController.ANIMATION_DURATION_TOP_ROUNDING));
+ float startTop = params.getStartNotificationTop();
+ top = (int) Math.min(MathUtils.lerp(startTop,
+ params.getTop(), expandProgress),
+ startTop);
+ } else {
+ top = params.getTop();
+ }
+ int actualHeight = params.getBottom() - top;
+ setActualHeight(actualHeight);
int startClipTopAmount = params.getStartClipTopAmount();
int clipTopAmount = (int) MathUtils.lerp(startClipTopAmount, 0, params.getProgress());
if (mNotificationParent != null) {
@@ -2065,13 +2080,12 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
setClipTopAmount(clipTopAmount);
}
setTranslationY(top);
- setActualHeight(params.getHeight());
mTopRoundnessDuringExpandAnimation = params.getTopCornerRadius() / mOutlineRadius;
mBottomRoundnessDuringExpandAnimation = params.getBottomCornerRadius() / mOutlineRadius;
invalidateOutline();
- mBackgroundNormal.setExpandAnimationParams(params);
+ mBackgroundNormal.setExpandAnimationSize(params.getWidth(), actualHeight);
}
public void setExpandAnimationRunning(boolean expandAnimationRunning) {
@@ -2981,7 +2995,7 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
public void onInitializeAccessibilityNodeInfoInternal(AccessibilityNodeInfo info) {
super.onInitializeAccessibilityNodeInfoInternal(info);
info.addAction(AccessibilityNodeInfo.AccessibilityAction.ACTION_LONG_CLICK);
- if (canViewBeDismissed()) {
+ if (canViewBeDismissed() && !mIsSnoozed) {
info.addAction(AccessibilityNodeInfo.AccessibilityAction.ACTION_DISMISS);
}
boolean expandable = shouldShowPublic();
@@ -2997,7 +3011,7 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
isExpanded = isExpanded();
}
}
- if (expandable) {
+ if (expandable && !mIsSnoozed) {
if (isExpanded) {
info.addAction(AccessibilityNodeInfo.AccessibilityAction.ACTION_COLLAPSE);
} else {
@@ -3085,6 +3099,26 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
return super.childNeedsClipping(child);
}
+ /**
+ * Set a clip path to be set while expanding the notification. This is needed to nicely
+ * clip ourselves during the launch if we were clipped rounded in the beginning
+ */
+ public void setExpandingClipPath(Path path) {
+ mExpandingClipPath = path;
+ invalidate();
+ }
+
+ @Override
+ protected void dispatchDraw(Canvas canvas) {
+ canvas.save();
+ if (mExpandingClipPath != null && (mExpandAnimationRunning || mChildIsExpanding)) {
+ // If we're launching a notification, let's clip if a clip rounded to the clipPath
+ canvas.clipPath(mExpandingClipPath);
+ }
+ super.dispatchDraw(canvas);
+ canvas.restore();
+ }
+
@Override
protected void applyRoundness() {
super.applyRoundness();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationBackgroundView.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationBackgroundView.java
index 754de580cd61..0f615aa9356f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationBackgroundView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationBackgroundView.java
@@ -240,10 +240,10 @@ public class NotificationBackgroundView extends View {
invalidate();
}
- /** Set the current expand animation parameters. */
- public void setExpandAnimationParams(ExpandAnimationParameters params) {
- mActualHeight = params.getHeight();
- mActualWidth = params.getWidth();
+ /** Set the current expand animation size. */
+ public void setExpandAnimationSize(int actualWidth, int actualHeight) {
+ mActualHeight = actualHeight;
+ mActualWidth = actualWidth;
invalidate();
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/AmbientState.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/AmbientState.java
index 26606cda5582..197920f7be19 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/AmbientState.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/AmbientState.java
@@ -72,8 +72,6 @@ public class AmbientState {
private boolean mUnlockHintRunning;
private boolean mQsCustomizerShowing;
private int mIntrinsicPadding;
- private int mExpandAnimationTopChange;
- private ExpandableNotificationRow mExpandingNotification;
private float mHideAmount;
private boolean mAppearing;
private float mPulseHeight = MAX_PULSE_HEIGHT;
@@ -518,22 +516,6 @@ public class AmbientState {
return isDozing() && !isPulsing(row.getEntry());
}
- public void setExpandAnimationTopChange(int expandAnimationTopChange) {
- mExpandAnimationTopChange = expandAnimationTopChange;
- }
-
- public void setExpandingNotification(ExpandableNotificationRow row) {
- mExpandingNotification = row;
- }
-
- public ExpandableNotificationRow getExpandingNotification() {
- return mExpandingNotification;
- }
-
- public int getExpandAnimationTopChange() {
- return mExpandAnimationTopChange;
- }
-
/**
* @return {@code true } when shade is completely hidden: in AOD, ambient display or when
* bypassing.
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationListContainer.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationListContainer.java
index 2a2e733f78a1..7a5c18896e5f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationListContainer.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationListContainer.java
@@ -200,4 +200,11 @@ public interface NotificationListContainer extends
default void setWillExpand(boolean willExpand) {}
void setNotificationActivityStarter(NotificationActivityStarter notificationActivityStarter);
+
+ /**
+ * @return the start location where we start clipping notifications.
+ */
+ default int getTopClippingStartLocation() {
+ return 0;
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
index f0201cb3482d..a9d61f1c5c4f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
@@ -77,6 +77,7 @@ import com.android.settingslib.Utils;
import com.android.systemui.Dumpable;
import com.android.systemui.ExpandHelper;
import com.android.systemui.R;
+import com.android.systemui.animation.ActivityLaunchAnimator;
import com.android.systemui.animation.Interpolators;
import com.android.systemui.plugins.statusbar.NotificationSwipeActionHelper;
import com.android.systemui.statusbar.CommandQueue;
@@ -90,6 +91,7 @@ import com.android.systemui.statusbar.StatusBarState;
import com.android.systemui.statusbar.notification.ExpandAnimationParameters;
import com.android.systemui.statusbar.notification.FakeShadowView;
import com.android.systemui.statusbar.notification.NotificationActivityStarter;
+import com.android.systemui.statusbar.notification.NotificationLaunchAnimatorController;
import com.android.systemui.statusbar.notification.NotificationUtils;
import com.android.systemui.statusbar.notification.ShadeViewRefactor;
import com.android.systemui.statusbar.notification.ShadeViewRefactor.RefactorComponent;
@@ -111,6 +113,7 @@ import com.android.systemui.statusbar.phone.UnlockedScreenOffAnimationController
import com.android.systemui.statusbar.policy.HeadsUpUtil;
import com.android.systemui.statusbar.policy.ScrollAdapter;
import com.android.systemui.util.Assert;
+import com.android.systemui.util.leak.RotationUtils;
import java.io.FileDescriptor;
import java.io.PrintWriter;
@@ -421,6 +424,9 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable
animateScroll();
};
private int mCornerRadius;
+ private int mMinimumPaddings;
+ private int mQsTilePadding;
+ private boolean mSkinnyNotifsInLandscape;
private int mSidePaddings;
private final Rect mBackgroundAnimationRect = new Rect();
private ArrayList<BiConsumer<Float, Float>> mExpandedHeightListeners = new ArrayList<>();
@@ -467,6 +473,12 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable
private final Path mRoundedClipPath = new Path();
/**
+ * The clip Path used to clip the launching notification. This may be different
+ * from the normal path, as the views launch animation could start clipped.
+ */
+ private final Path mLaunchedNotificationClipPath = new Path();
+
+ /**
* Should we use rounded rect clipping right now
*/
private boolean mShouldUseRoundedRectClipping = false;
@@ -489,6 +501,26 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable
private boolean mLaunchingNotification;
/**
+ * Does the launching notification need to be clipped
+ */
+ private boolean mLaunchingNotificationNeedsToBeClipped;
+
+ /**
+ * The current launch animation params when launching a notification
+ */
+ private ExpandAnimationParameters mLaunchAnimationParams;
+
+ /**
+ * Corner radii of the launched notification if it's clipped
+ */
+ private float[] mLaunchedNotificationRadii = new float[8];
+
+ /**
+ * The notification that is being launched currently.
+ */
+ private ExpandableNotificationRow mExpandingNotificationRow;
+
+ /**
* Do notifications dismiss with normal transitioning
*/
private boolean mDismissUsingRowTranslationX = true;
@@ -896,7 +928,10 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable
R.dimen.min_top_overscroll_to_qs);
mStatusBarHeight = res.getDimensionPixelSize(R.dimen.status_bar_height);
mBottomMargin = res.getDimensionPixelSize(R.dimen.notification_panel_margin_bottom);
- mSidePaddings = res.getDimensionPixelSize(R.dimen.notification_side_paddings);
+ mMinimumPaddings = res.getDimensionPixelSize(R.dimen.notification_side_paddings);
+ mQsTilePadding = res.getDimensionPixelOffset(R.dimen.qs_tile_margin_horizontal);
+ mSkinnyNotifsInLandscape = res.getBoolean(R.bool.config_skinnyNotifsInLandscape);
+ mSidePaddings = mMinimumPaddings; // Updated in onMeasure by updateSidePadding()
mMinInteractionHeight = res.getDimensionPixelSize(
R.dimen.notification_min_interaction_height);
mCornerRadius = res.getDimensionPixelSize(R.dimen.notification_corner_radius);
@@ -906,6 +941,21 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable
com.android.internal.R.dimen.quick_qs_offset_height);
}
+ void updateSidePadding(int viewWidth) {
+ if (viewWidth == 0 || !mSkinnyNotifsInLandscape) {
+ mSidePaddings = mMinimumPaddings;
+ return;
+ }
+ // Portrait is easy, just use the dimen for paddings
+ if (RotationUtils.getRotation(mContext) == RotationUtils.ROTATION_NONE) {
+ mSidePaddings = mMinimumPaddings;
+ return;
+ }
+ final int innerWidth = viewWidth - mMinimumPaddings * 2;
+ final int qsTileWidth = (innerWidth - mQsTilePadding * 3) / 4;
+ mSidePaddings = mMinimumPaddings + qsTileWidth + mQsTilePadding;
+ }
+
void updateCornerRadius() {
int newRadius = getResources().getDimensionPixelSize(R.dimen.notification_corner_radius);
if (mCornerRadius != newRadius) {
@@ -966,6 +1016,7 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int width = MeasureSpec.getSize(widthMeasureSpec);
+ updateSidePadding(width);
int childWidthSpec = MeasureSpec.makeMeasureSpec(width - mSidePaddings * 2,
MeasureSpec.getMode(widthMeasureSpec));
// Don't constrain the height of the children so we know how big they'd like to be
@@ -2117,7 +2168,7 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable
@ShadeViewRefactor(RefactorComponent.STATE_RESOLVER)
private void updateContentHeight() {
- final float scrimTopPadding = mAmbientState.isOnKeyguard() ? 0 : mSidePaddings;
+ final float scrimTopPadding = mAmbientState.isOnKeyguard() ? 0 : mMinimumPaddings;
int height = (int) scrimTopPadding;
float previousPaddingRequest = mPaddingBetweenElements;
int numShownItems = 0;
@@ -2726,6 +2777,9 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable
* @return the amount of scrolling needed to start clipping notifications.
*/
private int getScrollAmountToScrollBoundary() {
+ if (mShouldUseSplitNotificationShade) {
+ return mSidePaddings;
+ }
return mTopPadding - mQsScrollBoundaryPosition;
}
@@ -2869,7 +2923,16 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable
@ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
void setExpandingNotification(ExpandableNotificationRow row) {
- mAmbientState.setExpandingNotification(row);
+ if (mExpandingNotificationRow != null && row == null) {
+ // Let's unset the clip path being set during launch
+ mExpandingNotificationRow.setExpandingClipPath(null);
+ ExpandableNotificationRow parent = mExpandingNotificationRow.getNotificationParent();
+ if (parent != null) {
+ parent.setExpandingClipPath(null);
+ }
+ }
+ mExpandingNotificationRow = row;
+ updateLaunchedNotificationClipPath();
requestChildrenUpdate();
}
@@ -2879,10 +2942,10 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable
@ShadeViewRefactor(RefactorComponent.STATE_RESOLVER)
public void applyExpandAnimationParams(ExpandAnimationParameters params) {
- mAmbientState.setExpandAnimationTopChange(params == null ? 0 : params.getTopChange());
-
- // Disable clipping for launches
+ // Modify the clipping for launching notifications
+ mLaunchAnimationParams = params;
setLaunchingNotification(params != null);
+ updateLaunchedNotificationClipPath();
requestChildrenUpdate();
}
@@ -5330,7 +5393,15 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable
return;
}
mLaunchingNotification = launching;
- updateUseRoundedRectClipping();
+ mLaunchingNotificationNeedsToBeClipped = mLaunchAnimationParams != null
+ && (mLaunchAnimationParams.getStartRoundedTopClipping() > 0
+ || mLaunchAnimationParams.getParentStartRoundedTopClipping() > 0);
+ if (!mLaunchingNotificationNeedsToBeClipped || !mLaunchingNotification) {
+ mLaunchedNotificationClipPath.reset();
+ }
+ // When launching notifications, we're clipping the children individually instead of in
+ // dispatchDraw
+ invalidate();
}
/**
@@ -5340,22 +5411,97 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable
// We don't want to clip notifications when QS is expanded, because incoming heads up on
// the bottom would be clipped otherwise
boolean qsAllowsClipping = mQsExpansionFraction < 0.5f || mShouldUseSplitNotificationShade;
- boolean clip = !mLaunchingNotification && mIsExpanded && qsAllowsClipping;
+ boolean clip = mIsExpanded && qsAllowsClipping;
if (clip != mShouldUseRoundedRectClipping) {
mShouldUseRoundedRectClipping = clip;
invalidate();
}
}
+ /**
+ * Update the clip path for launched notifications in case they were originally clipped
+ */
+ private void updateLaunchedNotificationClipPath() {
+ if (!mLaunchingNotificationNeedsToBeClipped || !mLaunchingNotification
+ || mExpandingNotificationRow == null) {
+ return;
+ }
+ int left = Math.min(mLaunchAnimationParams.getLeft(), mRoundedRectClippingLeft);
+ int right = Math.max(mLaunchAnimationParams.getRight(), mRoundedRectClippingRight);
+ int bottom = Math.max(mLaunchAnimationParams.getBottom(), mRoundedRectClippingBottom);
+ float expandProgress = Interpolators.FAST_OUT_SLOW_IN.getInterpolation(
+ mLaunchAnimationParams.getProgress(0,
+ NotificationLaunchAnimatorController.ANIMATION_DURATION_TOP_ROUNDING));
+ int top = (int) Math.min(MathUtils.lerp(mRoundedRectClippingTop,
+ mLaunchAnimationParams.getTop(), expandProgress),
+ mRoundedRectClippingTop);
+ float topRadius = mLaunchAnimationParams.getTopCornerRadius();
+ float bottomRadius = mLaunchAnimationParams.getBottomCornerRadius();
+ mLaunchedNotificationRadii[0] = topRadius;
+ mLaunchedNotificationRadii[1] = topRadius;
+ mLaunchedNotificationRadii[2] = topRadius;
+ mLaunchedNotificationRadii[3] = topRadius;
+ mLaunchedNotificationRadii[4] = bottomRadius;
+ mLaunchedNotificationRadii[5] = bottomRadius;
+ mLaunchedNotificationRadii[6] = bottomRadius;
+ mLaunchedNotificationRadii[7] = bottomRadius;
+ mLaunchedNotificationClipPath.reset();
+ mLaunchedNotificationClipPath.addRoundRect(left, top, right, bottom,
+ mLaunchedNotificationRadii, Path.Direction.CW);
+ // Offset into notification clip coordinates instead of parent ones.
+ // This is needed since the notification changes in translationZ, where clipping via
+ // canvas dispatching won't work.
+ ExpandableNotificationRow expandingRow = mExpandingNotificationRow;
+ if (expandingRow.getNotificationParent() != null) {
+ expandingRow = expandingRow.getNotificationParent();
+ }
+ mLaunchedNotificationClipPath.offset(
+ -expandingRow.getLeft() - expandingRow.getTranslationX(),
+ -expandingRow.getTop() - expandingRow.getTranslationY());
+ expandingRow.setExpandingClipPath(mLaunchedNotificationClipPath);
+ if (mShouldUseRoundedRectClipping) {
+ invalidate();
+ }
+ }
+
@Override
protected void dispatchDraw(Canvas canvas) {
- if (mShouldUseRoundedRectClipping) {
+ if (mShouldUseRoundedRectClipping && !mLaunchingNotification) {
+ // When launching notifications, we're clipping the children individually instead of in
+ // dispatchDraw
// Let's clip rounded.
canvas.clipPath(mRoundedClipPath);
}
super.dispatchDraw(canvas);
}
+ @Override
+ protected boolean drawChild(Canvas canvas, View child, long drawingTime) {
+ if (mShouldUseRoundedRectClipping && mLaunchingNotification) {
+ // Let's clip children individually during notification launch
+ canvas.save();
+ ExpandableView expandableView = (ExpandableView) child;
+ Path clipPath;
+ if (expandableView.isExpandAnimationRunning()
+ || ((ExpandableView) child).hasExpandingChild()) {
+ // When launching the notification, it is not clipped by this layout, but by the
+ // view itself. This is because the view is Translating in Z, where this clipPath
+ // wouldn't apply.
+ clipPath = null;
+ } else {
+ clipPath = mRoundedClipPath;
+ }
+ if (clipPath != null) {
+ canvas.clipPath(clipPath);
+ }
+ boolean result = super.drawChild(canvas, child, drawingTime);
+ canvas.restore();
+ return result;
+ } else {
+ return super.drawChild(canvas, child, drawingTime);
+ }
+ }
+
/**
* Calculate the total translation needed when dismissing.
*/
@@ -5370,6 +5516,13 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable
}
/**
+ * @return the start location where we start clipping notifications.
+ */
+ public int getTopClippingStartLocation() {
+ return mIsExpanded ? mQsScrollBoundaryPosition : 0;
+ }
+
+ /**
* A listener that is notified when the empty space below the notifications is clicked on
*/
@ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java
index 495eda772219..e71f7dbb008b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java
@@ -1533,6 +1533,11 @@ public class NotificationStackScrollLayoutController {
}
@Override
+ public int getTopClippingStartLocation() {
+ return mView.getTopClippingStartLocation();
+ }
+
+ @Override
public View getContainerChildAt(int i) {
return mView.getContainerChildAt(i);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithm.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithm.java
index 3e4177d32a34..fa5011e8802f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithm.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithm.java
@@ -40,9 +40,9 @@ public class KeyguardClockPositionAlgorithm {
private static float CLOCK_HEIGHT_WEIGHT = 0.7f;
/**
- * Margin between the bottom of the clock and the notification shade.
+ * Margin between the bottom of the status view and the notification shade.
*/
- private int mClockNotificationsMargin;
+ private int mStatusViewBottomMargin;
/**
* Height of the parent view - display size in px.
@@ -153,8 +153,8 @@ public class KeyguardClockPositionAlgorithm {
* Refreshes the dimension values.
*/
public void loadDimens(Resources res) {
- mClockNotificationsMargin = res.getDimensionPixelSize(
- R.dimen.keyguard_clock_notifications_margin);
+ mStatusViewBottomMargin = res.getDimensionPixelSize(
+ R.dimen.keyguard_status_view_bottom_margin);
mContainerTopPadding =
res.getDimensionPixelSize(R.dimen.keyguard_clock_top_margin) / 2;
@@ -181,7 +181,7 @@ public class KeyguardClockPositionAlgorithm {
mNotificationStackHeight = notificationStackHeight;
mPanelExpansion = panelExpansion;
mHeight = parentHeight;
- mKeyguardStatusHeight = keyguardStatusHeight;
+ mKeyguardStatusHeight = keyguardStatusHeight + mStatusViewBottomMargin;
mUserSwitchHeight = userSwitchHeight;
mUserSwitchPreferredY = userSwitchPreferredY;
mHasCustomClock = hasCustomClock;
@@ -221,40 +221,15 @@ public class KeyguardClockPositionAlgorithm {
public float getMinStackScrollerPadding() {
return mBypassEnabled ? mUnlockedStackScrollerPadding
- : mMinTopMargin + mKeyguardStatusHeight + mClockNotificationsMargin;
- }
-
- private int getMaxClockY() {
- return mHeight / 2 - mKeyguardStatusHeight - mClockNotificationsMargin;
+ : mMinTopMargin + mKeyguardStatusHeight;
}
private int getExpandedPreferredClockY() {
return mMinTopMargin + mUserSwitchHeight;
}
- /**
- * Vertically align the clock and the shade in the available space considering only
- * a percentage of the clock height defined by {@code CLOCK_HEIGHT_WEIGHT}.
- * @return Clock Y in pixels.
- */
- public int getExpandedClockPosition() {
- final int availableHeight = mMaxShadeBottom - mMinTopMargin;
- final int containerCenter = mMinTopMargin + availableHeight / 2;
-
- float y = containerCenter
- - (mKeyguardStatusHeight + mUserSwitchHeight) * CLOCK_HEIGHT_WEIGHT
- - mClockNotificationsMargin - mNotificationStackHeight / 2;
- if (y < mMinTopMargin) {
- y = mMinTopMargin;
- }
-
- // Don't allow the clock base to be under half of the screen
- final float maxClockY = getMaxClockY();
- if (y > maxClockY) {
- y = maxClockY;
- }
-
- return (int) y;
+ public int getLockscreenStatusViewHeight() {
+ return mKeyguardStatusHeight;
}
private int getClockY(float panelExpansion, float darkAmount) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconAreaController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconAreaController.java
index 6b864c9c35df..41af80e02b5a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconAreaController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconAreaController.java
@@ -602,6 +602,10 @@ public class NotificationIconAreaController implements
updateAodIconColors();
}
+ public int getHeight() {
+ return mAodIcons == null ? 0 : mAodIcons.getHeight();
+ }
+
public void appearAodIcons() {
if (mAodIcons == null) {
return;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java
index aaddfca4b685..f461d944d2c2 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java
@@ -1260,7 +1260,7 @@ public class NotificationPanelViewController extends PanelViewController {
mNotificationStackScrollLayoutController.getIntrinsicContentHeight(),
expandedFraction,
totalHeight,
- mKeyguardStatusViewController.getHeight(),
+ mKeyguardStatusViewController.getLockscreenHeight(),
userIconHeight,
userSwitcherPreferredY, hasCustomClock(),
hasVisibleNotifications, darkamount, mOverStretchAmount,
@@ -2669,14 +2669,6 @@ public class NotificationPanelViewController extends PanelViewController {
@Override
protected int getMaxPanelHeight() {
- if (mKeyguardBypassController.getBypassEnabled() && mBarState == KEYGUARD) {
- return getMaxPanelHeightBypass();
- } else {
- return getMaxPanelHeightNonBypass();
- }
- }
-
- private int getMaxPanelHeightNonBypass() {
int min = mStatusBarMinHeight;
if (!(mBarState == KEYGUARD)
&& mNotificationStackScrollLayoutController.getNotGoneChildCount() == 0) {
@@ -2701,16 +2693,6 @@ public class NotificationPanelViewController extends PanelViewController {
return maxHeight;
}
- private int getMaxPanelHeightBypass() {
- int position =
- mClockPositionAlgorithm.getExpandedClockPosition()
- + mKeyguardStatusViewController.getHeight();
- if (mNotificationStackScrollLayoutController.getVisibleNotificationCount() != 0) {
- position += mShelfHeight / 2.0f + mDarkIconSize / 2.0f;
- }
- return position;
- }
-
public boolean isInSettings() {
return mQsExpanded;
}
@@ -2782,11 +2764,8 @@ public class NotificationPanelViewController extends PanelViewController {
maxHeight += mNotificationStackScrollLayoutController.getTopPaddingOverflow();
if (mBarState == KEYGUARD) {
- int
- minKeyguardPanelBottom =
- mClockPositionAlgorithm.getExpandedClockPosition()
- + mKeyguardStatusViewController.getHeight()
- + mNotificationStackScrollLayoutController.getIntrinsicContentHeight();
+ int minKeyguardPanelBottom = mClockPositionAlgorithm.getLockscreenStatusViewHeight()
+ + mNotificationStackScrollLayoutController.getIntrinsicContentHeight();
return Math.max(maxHeight, minKeyguardPanelBottom);
} else {
return maxHeight;
@@ -3336,7 +3315,7 @@ public class NotificationPanelViewController extends PanelViewController {
}
if (mKeyguardBypassController.getBypassEnabled() && isOnKeyguard()) {
// The expandedHeight is always the full panel Height when bypassing
- expandedHeight = getMaxPanelHeightNonBypass();
+ expandedHeight = getMaxPanelHeight();
}
mNotificationStackScrollLayoutController.setExpandedHeight(expandedHeight);
updateKeyguardBottomAreaAlpha();
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 7a1e5cf1770b..cfcea9684c3b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
@@ -551,11 +551,11 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, Dump
*/
public void setNotificationsBounds(float left, float top, float right, float bottom) {
if (mClipsQsScrim) {
- // notification scrim's rounded corners are anti-aliased, but clipping of the QS scrim
- // can't be and it's causing jagged corners. That's why notification scrim needs
- // to overlap QS scrim by one pixel - both vertically (top - 1) and
- // horizontally (left - 1 and right + 1), see: b/186644628
- mNotificationsScrim.setDrawableBounds(left - 1, top - 1, right + 1, bottom);
+ // notification scrim's rounded corners are anti-aliased, but clipping of the QS/behind
+ // scrim can't be and it's causing jagged corners. That's why notification scrim needs
+ // to overlap QS scrim by one pixel horizontally (left - 1 and right + 1)
+ // see: b/186644628
+ mNotificationsScrim.setDrawableBounds(left - 1, top, right + 1, bottom);
mScrimBehind.setBottomEdgePosition((int) top);
} else {
mNotificationsScrim.setDrawableBounds(left, top, right, bottom);
@@ -1242,6 +1242,9 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, Dump
pw.println(mDefaultScrimAlpha);
pw.print(" mExpansionFraction=");
pw.println(mPanelExpansion);
+
+ pw.print(" mState.getMaxLightRevealScrimAlpha=");
+ pw.println(mState.getMaxLightRevealScrimAlpha());
}
public void setWallpaperSupportsAmbientMode(boolean wallpaperSupportsAmbientMode) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimState.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimState.java
index e52e1fa5f39f..06811932ac0c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimState.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimState.java
@@ -197,7 +197,7 @@ public enum ScrimState {
}
@Override
- public float getBehindAlpha() {
+ public float getMaxLightRevealScrimAlpha() {
return mWallpaperSupportsAmbientMode && !mHasBackdrop ? 0f : 1f;
}
@@ -220,18 +220,11 @@ public enum ScrimState {
mBlankScreen = mDisplayRequiresBlanking;
mAnimationDuration = mWakeLockScreenSensorActive
? ScrimController.ANIMATION_DURATION_LONG : ScrimController.ANIMATION_DURATION;
-
- // Wake sensor will show the wallpaper, let's fade from black. Otherwise it will
- // feel like the screen is flashing if the wallpaper is light.
- if (mWakeLockScreenSensorActive && previousState == AOD) {
- updateScrimColor(mScrimBehind, 1f /* alpha */, Color.BLACK);
- }
}
-
@Override
- public float getBehindAlpha() {
+ public float getMaxLightRevealScrimAlpha() {
return mWakeLockScreenSensorActive ? ScrimController.WAKE_SENSOR_SCRIM_ALPHA
- : AOD.getBehindAlpha();
+ : AOD.getMaxLightRevealScrimAlpha();
}
},
@@ -351,6 +344,10 @@ public enum ScrimState {
return mBehindAlpha;
}
+ public float getMaxLightRevealScrimAlpha() {
+ return 1f;
+ }
+
public float getNotifAlpha() {
return mNotifAlpha;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
index 5d2fe523c803..3f07785520cf 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -1473,9 +1473,7 @@ public class StatusBar extends SystemUI implements DemoMode,
* @param why the reason for the wake up
*/
public void wakeUpIfDozing(long time, View where, String why) {
- if (mDozing && !(mKeyguardViewMediator.isAnimatingScreenOff()
- || mUnlockedScreenOffAnimationController
- .isScreenOffLightRevealAnimationPlaying())) {
+ if (mDozing && !mUnlockedScreenOffAnimationController.isScreenOffAnimationPlaying()) {
mPowerManager.wakeUp(
time, PowerManager.WAKE_REASON_GESTURE, "com.android.systemui:" + why);
mWakeUpComingFromTouch = true;
@@ -4444,6 +4442,8 @@ public class StatusBar extends SystemUI implements DemoMode,
} else {
mScrimController.transitionTo(ScrimState.UNLOCKED, mUnlockScrimCallback);
}
+ updateLightRevealScrimVisibility();
+
Trace.endSection();
}
@@ -4894,6 +4894,7 @@ public class StatusBar extends SystemUI implements DemoMode,
return;
}
+ mLightRevealScrim.setAlpha(mScrimController.getState().getMaxLightRevealScrimAlpha());
if (mFeatureFlags.useNewLockscreenAnimations()
&& (mDozeParameters.getAlwaysOn() || mDozeParameters.isQuickPickupEnabled())) {
mLightRevealScrim.setVisibility(View.VISIBLE);
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 52bf2d577776..9a04d39c4e9e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/UnlockedScreenOffAnimationController.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/UnlockedScreenOffAnimationController.kt
@@ -172,7 +172,8 @@ class UnlockedScreenOffAnimationController @Inject constructor(
// We currently draw both the light reveal scrim, and the AOD UI, in the shade. If it's
// already expanded and showing notifications/QS, the animation looks really messy. For now,
// disable it if the notification panel is expanded.
- if (statusBar.notificationPanelViewController.isFullyExpanded) {
+ if (!this::statusBar.isInitialized ||
+ statusBar.notificationPanelViewController.isFullyExpanded) {
return false
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java
index ce080752b5cc..2ac5c1eeae8e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java
@@ -387,15 +387,8 @@ public class MobileSignalController extends SignalController<MobileState, Mobile
int qsTypeIcon = 0;
IconState qsIcon = null;
CharSequence description = null;
- // Mobile icon will only be shown in the statusbar in 2 scenarios
- // 1. Mobile is the default network, and it is validated
- // 2. Mobile is the default network, it is not validated and there is no other
- // non-Carrier WiFi networks available.
- boolean maybeShowIcons = (mCurrentState.inetCondition == 1)
- || (mCurrentState.inetCondition == 0
- && !mNetworkController.isNonCarrierWifiNetworkAvailable());
// Only send data sim callbacks to QS.
- if (mCurrentState.dataSim && mCurrentState.isDefault && maybeShowIcons) {
+ if (mCurrentState.dataSim && mCurrentState.isDefault) {
qsTypeIcon =
(showDataIcon || mConfig.alwaysShowDataRatIcon) ? icons.qsDataType : 0;
qsIcon = new IconState(mCurrentState.enabled
@@ -408,7 +401,7 @@ public class MobileSignalController extends SignalController<MobileState, Mobile
boolean activityOut = mCurrentState.dataConnected
&& !mCurrentState.carrierNetworkChangeMode
&& mCurrentState.activityOut;
- showDataIcon &= mCurrentState.dataSim && mCurrentState.isDefault && maybeShowIcons;
+ showDataIcon &= mCurrentState.dataSim && mCurrentState.isDefault;
boolean showTriangle = showDataIcon && !mCurrentState.airplaneMode;
int typeIcon = (showDataIcon || mConfig.alwaysShowDataRatIcon) ? icons.dataType : 0;
showDataIcon |= mCurrentState.roaming;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/WifiSignalController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/WifiSignalController.java
index 753def0b0f1c..2406db3ee58f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/WifiSignalController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/WifiSignalController.java
@@ -109,17 +109,10 @@ public class WifiSignalController extends
contentDescription += ("," + mContext.getString(R.string.data_connection_no_internet));
}
if (mProviderModel) {
- // WiFi icon will only be shown in the statusbar in 2 scenarios
- // 1. WiFi is the default network, and it is validated
- // 2. WiFi is the default network, it is not validated and there is no other
- // non-Carrier WiFi networks available.
- boolean maybeShowIcons = (mCurrentState.inetCondition == 1)
- || (mCurrentState.inetCondition == 0
- && !mNetworkController.isNonCarrierWifiNetworkAvailable());
IconState statusIcon = new IconState(
- wifiVisible && maybeShowIcons, getCurrentIconId(), contentDescription);
+ wifiVisible, getCurrentIconId(), contentDescription);
IconState qsIcon = null;
- if ((mCurrentState.isDefault && maybeShowIcons) || (!mNetworkController.isRadioOn()
+ if (mCurrentState.isDefault || (!mNetworkController.isRadioOn()
&& !mNetworkController.isEthernetDefault())) {
qsIcon = new IconState(mCurrentState.connected,
mWifiTracker.isCaptivePortal ? R.drawable.ic_qs_wifi_disconnected
@@ -158,15 +151,8 @@ public class WifiSignalController extends
if (mCurrentState.inetCondition == 0) {
dataContentDescription = mContext.getString(R.string.data_connection_no_internet);
}
- // Mobile icon will only be shown in the statusbar in 2 scenarios
- // 1. Mobile is the default network, and it is validated
- // 2. Mobile is the default network, it is not validated and there is no other
- // non-Carrier WiFi networks available.
- boolean maybeShowIcons = (mCurrentState.inetCondition == 1)
- || (mCurrentState.inetCondition == 0
- && !mNetworkController.isNonCarrierWifiNetworkAvailable());
boolean sbVisible = mCurrentState.enabled && mCurrentState.connected
- && maybeShowIcons && mCurrentState.isDefault;
+ && mCurrentState.isDefault;
IconState statusIcon =
new IconState(sbVisible, getCurrentIconIdForCarrierWifi(), contentDescription);
int typeIcon = sbVisible ? icons.dataType : 0;
diff --git a/packages/SystemUI/src/com/android/systemui/tv/TvBottomSheetActivity.java b/packages/SystemUI/src/com/android/systemui/tv/TvBottomSheetActivity.java
new file mode 100644
index 000000000000..2b7a33260248
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/tv/TvBottomSheetActivity.java
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.tv;
+
+import android.app.Activity;
+import android.graphics.PixelFormat;
+import android.graphics.drawable.Drawable;
+import android.os.Bundle;
+import android.util.DisplayMetrics;
+import android.util.Log;
+import android.view.Gravity;
+import android.view.WindowManager;
+
+import com.android.systemui.R;
+
+import java.util.function.Consumer;
+
+/**
+ * Generic bottom sheet with up to two icons in the beginning and two buttons.
+ */
+public abstract class TvBottomSheetActivity extends Activity {
+
+ private static final String TAG = TvBottomSheetActivity.class.getSimpleName();
+ private Drawable mBackgroundWithBlur;
+ private Drawable mBackgroundWithoutBlur;
+
+ private final Consumer<Boolean> mBlurConsumer = this::onBlurChanged;
+
+ private void onBlurChanged(boolean enabled) {
+ Log.v(TAG, "blur enabled: " + enabled);
+ getWindow().setBackgroundDrawable(enabled ? mBackgroundWithBlur : mBackgroundWithoutBlur);
+ }
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.tv_bottom_sheet);
+
+ overridePendingTransition(R.anim.tv_bottom_sheet_enter, 0);
+
+ mBackgroundWithBlur = getResources()
+ .getDrawable(R.drawable.bottom_sheet_background_with_blur);
+ mBackgroundWithoutBlur = getResources().getDrawable(R.drawable.bottom_sheet_background);
+
+ DisplayMetrics metrics = getResources().getDisplayMetrics();
+ int screenWidth = metrics.widthPixels;
+ int screenHeight = metrics.heightPixels;
+ int marginPx = getResources().getDimensionPixelSize(R.dimen.bottom_sheet_margin);
+
+ WindowManager.LayoutParams windowParams = getWindow().getAttributes();
+ windowParams.width = screenWidth - marginPx * 2;
+ windowParams.height = WindowManager.LayoutParams.WRAP_CONTENT;
+ windowParams.gravity = Gravity.BOTTOM | Gravity.CENTER_HORIZONTAL;
+ windowParams.horizontalMargin = 0f;
+ windowParams.verticalMargin = (float) marginPx / screenHeight;
+ windowParams.format = PixelFormat.TRANSPARENT;
+ windowParams.type = WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG;
+ windowParams.flags |= WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON;
+ windowParams.flags |= WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED;
+ getWindow().setAttributes(windowParams);
+ getWindow().setElevation(getWindow().getElevation() + 5);
+ getWindow().setBackgroundBlurRadius(getResources().getDimensionPixelSize(
+ R.dimen.bottom_sheet_background_blur_radius));
+ }
+
+ @Override
+ public void onAttachedToWindow() {
+ super.onAttachedToWindow();
+ getWindowManager().addCrossWindowBlurEnabledListener(mBlurConsumer);
+ }
+
+ @Override
+ public void onDetachedFromWindow() {
+ getWindowManager().removeCrossWindowBlurEnabledListener(mBlurConsumer);
+ super.onDetachedFromWindow();
+ }
+
+ @Override
+ public void finish() {
+ super.finish();
+ overridePendingTransition(0, R.anim.tv_bottom_sheet_exit);
+ }
+
+}
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 41f987727860..0c750a179358 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerTest.java
@@ -53,6 +53,7 @@ import com.android.systemui.keyguard.KeyguardViewMediator;
import com.android.systemui.keyguard.ScreenLifecycle;
import com.android.systemui.plugins.FalsingManager;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
+import com.android.systemui.statusbar.LockscreenShadeTransitionController;
import com.android.systemui.statusbar.phone.StatusBar;
import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager;
import com.android.systemui.util.concurrency.FakeExecutor;
@@ -117,6 +118,8 @@ public class UdfpsControllerTest extends SysuiTestCase {
@Mock
private AccessibilityManager mAccessibilityManager;
@Mock
+ private LockscreenShadeTransitionController mLockscreenShadeTransitionController;
+ @Mock
private ScreenLifecycle mScreenLifecycle;
@Mock
private Vibrator mVibrator;
@@ -176,6 +179,7 @@ public class UdfpsControllerTest extends SysuiTestCase {
mFalsingManager,
mPowerManager,
mAccessibilityManager,
+ mLockscreenShadeTransitionController,
mScreenLifecycle,
mVibrator,
Optional.of(mHbmProvider));
diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsKeyguardViewControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsKeyguardViewControllerTest.java
index 5923de6719a8..f62587c6e87c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsKeyguardViewControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsKeyguardViewControllerTest.java
@@ -35,6 +35,7 @@ import com.android.systemui.SysuiTestCase;
import com.android.systemui.dump.DumpManager;
import com.android.systemui.keyguard.KeyguardViewMediator;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
+import com.android.systemui.statusbar.LockscreenShadeTransitionController;
import com.android.systemui.statusbar.StatusBarState;
import com.android.systemui.statusbar.phone.StatusBar;
import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager;
@@ -65,6 +66,8 @@ public class UdfpsKeyguardViewControllerTest extends SysuiTestCase {
@Mock
private StatusBarKeyguardViewManager mStatusBarKeyguardViewManager;
@Mock
+ private LockscreenShadeTransitionController mLockscreenShadeTransitionController;
+ @Mock
private DumpManager mDumpManager;
@Mock
private DelayableExecutor mExecutor;
@@ -106,6 +109,7 @@ public class UdfpsKeyguardViewControllerTest extends SysuiTestCase {
mExecutor,
mDumpManager,
mKeyguardViewMediator,
+ mLockscreenShadeTransitionController,
mUdfpsController);
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeTriggersTest.java b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeTriggersTest.java
index a11b9cf357a8..10997fab081f 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeTriggersTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeTriggersTest.java
@@ -209,33 +209,14 @@ public class DozeTriggersTest extends SysuiTestCase {
// WHEN quick pick up is triggered
mTriggers.onSensor(DozeLog.REASON_SENSOR_QUICK_PICKUP, 100, 100, null);
- // THEN device goes into aod (shows clock with black background)
- verify(mMachine).requestState(DOZE_AOD);
+ // THEN request pulse
+ verify(mMachine).requestPulse(anyInt());
// THEN a log is taken that quick pick up was triggered
verify(mUiEventLogger).log(DozingUpdateUiEvent.DOZING_UPDATE_QUICK_PICKUP);
}
@Test
- public void testQuickPickupTimeOutAfterExecutables() {
- // GIVEN quick pickup is triggered when device is in DOZE
- when(mMachine.getState()).thenReturn(DozeMachine.State.DOZE);
- mTriggers.onSensor(DozeLog.REASON_SENSOR_QUICK_PICKUP, 100, 100, null);
- verify(mMachine).requestState(DOZE_AOD);
- verify(mMachine, never()).requestState(DozeMachine.State.DOZE);
-
- // WHEN next executable is run
- mExecutor.advanceClockToLast();
- mExecutor.runAllReady();
-
- // THEN device goes back into DOZE
- verify(mMachine).requestState(DozeMachine.State.DOZE);
-
- // THEN a log is taken that wake up timeout expired
- verify(mUiEventLogger).log(DozingUpdateUiEvent.DOZING_UPDATE_WAKE_TIMEOUT);
- }
-
- @Test
public void testOnSensor_Fingerprint() {
// GIVEN dozing state
when(mMachine.getState()).thenReturn(DOZE_AOD);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ScrimControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ScrimControllerTest.java
index e55361e750b1..678b193073c2 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ScrimControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ScrimControllerTest.java
@@ -312,6 +312,8 @@ public class ScrimControllerTest extends SysuiTestCase {
mScrimBehind, true,
mScrimForBubble, false
));
+
+ assertEquals(1f, mScrimController.getState().getMaxLightRevealScrimAlpha(), 0f);
}
@Test
@@ -321,8 +323,9 @@ public class ScrimControllerTest extends SysuiTestCase {
assertScrimAlpha(Map.of(
mScrimInFront, TRANSPARENT,
- mScrimBehind, OPAQUE,
+ mScrimBehind, TRANSPARENT,
mNotificationsScrim, TRANSPARENT));
+ assertEquals(1f, mScrimController.getState().getMaxLightRevealScrimAlpha(), 0f);
assertScrimTinted(Map.of(
mScrimInFront, true,
@@ -340,6 +343,7 @@ public class ScrimControllerTest extends SysuiTestCase {
assertScrimAlpha(Map.of(
mScrimInFront, TRANSPARENT,
mScrimBehind, TRANSPARENT));
+ assertEquals(0f, mScrimController.getState().getMaxLightRevealScrimAlpha(), 0f);
// Pulsing notification should conserve AOD wallpaper.
mScrimController.transitionTo(ScrimState.PULSING);
@@ -348,6 +352,7 @@ public class ScrimControllerTest extends SysuiTestCase {
assertScrimAlpha(Map.of(
mScrimInFront, TRANSPARENT,
mScrimBehind, TRANSPARENT));
+ assertEquals(0f, mScrimController.getState().getMaxLightRevealScrimAlpha(), 0f);
}
@Test
@@ -359,7 +364,8 @@ public class ScrimControllerTest extends SysuiTestCase {
assertScrimAlpha(Map.of(
mScrimInFront, TRANSPARENT,
- mScrimBehind, OPAQUE));
+ mScrimBehind, TRANSPARENT));
+ assertEquals(1f, mScrimController.getState().getMaxLightRevealScrimAlpha(), 0f);
assertScrimTinted(Map.of(
mScrimInFront, true,
@@ -378,7 +384,8 @@ public class ScrimControllerTest extends SysuiTestCase {
assertScrimAlpha(Map.of(
mScrimInFront, TRANSPARENT,
- mScrimBehind, OPAQUE));
+ mScrimBehind, TRANSPARENT));
+ assertEquals(1f, mScrimController.getState().getMaxLightRevealScrimAlpha(), 0f);
assertScrimTinted(Map.of(
mScrimInFront, true,
@@ -403,13 +410,15 @@ public class ScrimControllerTest extends SysuiTestCase {
finishAnimationsImmediately();
assertScrimAlpha(Map.of(
mScrimInFront, SEMI_TRANSPARENT,
- mScrimBehind, OPAQUE));
+ mScrimBehind, TRANSPARENT));
+ assertEquals(1f, mScrimController.getState().getMaxLightRevealScrimAlpha(), 0f);
// ... and that if we set it while we're in AOD, it does take immediate effect.
mScrimController.setAodFrontScrimAlpha(1f);
assertScrimAlpha(Map.of(
mScrimInFront, OPAQUE,
- mScrimBehind, OPAQUE));
+ mScrimBehind, TRANSPARENT));
+ assertEquals(1f, mScrimController.getState().getMaxLightRevealScrimAlpha(), 0f);
// ... and make sure we recall the previous front scrim alpha even if we transition away
// for a bit.
@@ -418,7 +427,8 @@ public class ScrimControllerTest extends SysuiTestCase {
finishAnimationsImmediately();
assertScrimAlpha(Map.of(
mScrimInFront, OPAQUE,
- mScrimBehind, OPAQUE));
+ mScrimBehind, TRANSPARENT));
+ assertEquals(1f, mScrimController.getState().getMaxLightRevealScrimAlpha(), 0f);
// ... and alpha updates should be completely ignored if always_on is off.
// Passing it forward would mess up the wake-up transition.
@@ -448,23 +458,28 @@ public class ScrimControllerTest extends SysuiTestCase {
finishAnimationsImmediately();
assertScrimAlpha(Map.of(
mScrimInFront, OPAQUE,
- mScrimBehind, OPAQUE));
+ mScrimBehind, TRANSPARENT));
+ assertEquals(1f, mScrimController.getState().getMaxLightRevealScrimAlpha(), 0f);
// ... but will take effect after docked
when(mDockManager.isDocked()).thenReturn(true);
mScrimController.transitionTo(ScrimState.KEYGUARD);
mScrimController.setAodFrontScrimAlpha(0.5f);
mScrimController.transitionTo(ScrimState.AOD);
+ finishAnimationsImmediately();
assertScrimAlpha(Map.of(
mScrimInFront, SEMI_TRANSPARENT,
- mScrimBehind, OPAQUE));
+ mScrimBehind, TRANSPARENT));
+ assertEquals(1f, mScrimController.getState().getMaxLightRevealScrimAlpha(), 0f);
// ... and that if we set it while we're in AOD, it does take immediate effect after docked.
mScrimController.setAodFrontScrimAlpha(1f);
+ finishAnimationsImmediately();
assertScrimAlpha(Map.of(
mScrimInFront, OPAQUE,
- mScrimBehind, OPAQUE));
+ mScrimBehind, TRANSPARENT));
+ assertEquals(1f, mScrimController.getState().getMaxLightRevealScrimAlpha(), 0f);
// Reset value since enums are static.
mScrimController.setAodFrontScrimAlpha(0f);
@@ -480,7 +495,8 @@ public class ScrimControllerTest extends SysuiTestCase {
finishAnimationsImmediately();
assertScrimAlpha(Map.of(
mScrimInFront, TRANSPARENT,
- mScrimBehind, OPAQUE));
+ mScrimBehind, TRANSPARENT));
+ assertEquals(1f, mScrimController.getState().getMaxLightRevealScrimAlpha(), 0f);
mScrimController.transitionTo(ScrimState.PULSING);
finishAnimationsImmediately();
@@ -489,7 +505,8 @@ public class ScrimControllerTest extends SysuiTestCase {
// Pulse callback should have been invoked
assertScrimAlpha(Map.of(
mScrimInFront, TRANSPARENT,
- mScrimBehind, OPAQUE));
+ mScrimBehind, TRANSPARENT));
+ assertEquals(1f, mScrimController.getState().getMaxLightRevealScrimAlpha(), 0f);
assertScrimTinted(Map.of(
mScrimInFront, true,
@@ -503,13 +520,16 @@ public class ScrimControllerTest extends SysuiTestCase {
// Front scrim should be semi-transparent
assertScrimAlpha(Map.of(
mScrimInFront, SEMI_TRANSPARENT,
- mScrimBehind, OPAQUE));
+ mScrimBehind, TRANSPARENT));
+ assertEquals(1f, mScrimController.getState().getMaxLightRevealScrimAlpha(), 0f);
mScrimController.setWakeLockScreenSensorActive(true);
finishAnimationsImmediately();
assertScrimAlpha(Map.of(
mScrimInFront, SEMI_TRANSPARENT,
- mScrimBehind, SEMI_TRANSPARENT));
+ mScrimBehind, TRANSPARENT));
+ assertEquals(ScrimController.WAKE_SENSOR_SCRIM_ALPHA,
+ mScrimController.getState().getMaxLightRevealScrimAlpha(), 0f);
// Reset value since enums are static.
mScrimController.setAodFrontScrimAlpha(0f);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerWifiTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerWifiTest.java
index 521b958ab891..bd9d1a7fd657 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerWifiTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerWifiTest.java
@@ -238,9 +238,7 @@ public class NetworkControllerWifiTest extends NetworkControllerBaseTest {
mNetworkController.setNoNetworksAvailable(false);
setWifiStateForVcn(true, testSsid);
setWifiLevelForVcn(0);
- // Connected, but still not validated - does not show
- //verifyLastWifiIcon(false, WifiIcons.WIFI_SIGNAL_STRENGTH[0][0]);
- verifyLastMobileDataIndicatorsForVcn(false, 0, 0, false);
+ verifyLastMobileDataIndicatorsForVcn(true, 0, TelephonyIcons.ICON_CWF, false);
mNetworkController.setNoNetworksAvailable(true);
for (int testLevel = 0; testLevel < WifiIcons.WIFI_LEVEL_COUNT; testLevel++) {
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
index 241a0dbac758..f63198866b08 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
@@ -872,18 +872,32 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub
"userId=" + userId);
}
+ final int resolvedUserId;
+ final List<AccessibilityServiceInfo> serviceInfos;
synchronized (mLock) {
// We treat calls from a profile as if made by its parent as profiles
// share the accessibility state of the parent. The call below
// performs the current profile parent resolution.
- final int resolvedUserId = mSecurityPolicy
+ resolvedUserId = mSecurityPolicy
.resolveCallingUserIdEnforcingPermissionsLocked(userId);
+ serviceInfos = new ArrayList<>(
+ getUserStateLocked(resolvedUserId).mInstalledServices);
+ }
- if (Binder.getCallingPid() == OWN_PROCESS_ID) {
- return new ArrayList<>(getUserStateLocked(resolvedUserId).mInstalledServices);
+ if (Binder.getCallingPid() == OWN_PROCESS_ID) {
+ return serviceInfos;
+ }
+ final PackageManagerInternal pm = LocalServices.getService(
+ PackageManagerInternal.class);
+ final int callingUid = Binder.getCallingUid();
+ for (int i = serviceInfos.size() - 1; i >= 0; i--) {
+ final AccessibilityServiceInfo serviceInfo = serviceInfos.get(i);
+ if (pm.filterAppAccess(serviceInfo.getComponentName().getPackageName(), callingUid,
+ resolvedUserId)) {
+ serviceInfos.remove(i);
}
- return getUserStateLocked(resolvedUserId).mInstalledServices;
}
+ return serviceInfos;
}
@Override
diff --git a/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java b/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
index acbf4875ae8d..5aec6aa99c12 100644
--- a/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
+++ b/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
@@ -409,6 +409,8 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku
// If the set of providers has been modified, notify each active AppWidgetHost
scheduleNotifyGroupHostsForProvidersChangedLocked(userId);
+ // Possibly notify any new components of widget id changes
+ mBackupRestoreController.widgetComponentsChanged(userId);
}
}
}
@@ -2471,8 +2473,8 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku
}
@Override
- public void restoreStarting(int userId) {
- mBackupRestoreController.restoreStarting(userId);
+ public void systemRestoreStarting(int userId) {
+ mBackupRestoreController.systemRestoreStarting(userId);
}
@Override
@@ -2481,8 +2483,8 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku
}
@Override
- public void restoreFinished(int userId) {
- mBackupRestoreController.restoreFinished(userId);
+ public void systemRestoreFinished(int userId) {
+ mBackupRestoreController.systemRestoreFinished(userId);
}
@SuppressWarnings("deprecation")
@@ -4272,6 +4274,9 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku
private final HashMap<Host, ArrayList<RestoreUpdateRecord>> mUpdatesByHost =
new HashMap<>();
+ @GuardedBy("mLock")
+ private boolean mHasSystemRestoreFinished;
+
public List<String> getWidgetParticipants(int userId) {
if (DEBUG) {
Slog.i(TAG, "Getting widget participants for user: " + userId);
@@ -4375,12 +4380,13 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku
return stream.toByteArray();
}
- public void restoreStarting(int userId) {
+ public void systemRestoreStarting(int userId) {
if (DEBUG) {
- Slog.i(TAG, "Restore starting for user: " + userId);
+ Slog.i(TAG, "System restore starting for user: " + userId);
}
synchronized (mLock) {
+ mHasSystemRestoreFinished = false;
// We're starting a new "system" restore operation, so any widget restore
// state that we see from here on is intended to replace the current
// widget configuration of any/all of the affected apps.
@@ -4542,26 +4548,90 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku
}
}
- // Called once following the conclusion of a restore operation. This is when we
+ // Called once following the conclusion of a system restore operation. This is when we
// send out updates to apps involved in widget-state restore telling them about
- // the new widget ID space.
- public void restoreFinished(int userId) {
+ // the new widget ID space. Apps that are not yet installed will be notifed when they are.
+ public void systemRestoreFinished(int userId) {
if (DEBUG) {
- Slog.i(TAG, "restoreFinished for " + userId);
+ Slog.i(TAG, "systemRestoreFinished for " + userId);
}
+ synchronized (mLock) {
+ mHasSystemRestoreFinished = true;
+ maybeSendWidgetRestoreBroadcastsLocked(userId);
+ }
+ }
- final UserHandle userHandle = new UserHandle(userId);
+ // Called when widget components (hosts or providers) are added or changed. If system
+ // restore has completed, we use this opportunity to tell the apps to update to the new
+ // widget ID space. If system restore is still in progress, we delay the updates until
+ // the end, to allow all participants to restore their state before updating widget IDs.
+ public void widgetComponentsChanged(int userId) {
synchronized (mLock) {
- // Build the providers' broadcasts and send them off
- Set<Map.Entry<Provider, ArrayList<RestoreUpdateRecord>>> providerEntries
- = mUpdatesByProvider.entrySet();
- for (Map.Entry<Provider, ArrayList<RestoreUpdateRecord>> e : providerEntries) {
- // For each provider there's a list of affected IDs
- Provider provider = e.getKey();
+ if (mHasSystemRestoreFinished) {
+ maybeSendWidgetRestoreBroadcastsLocked(userId);
+ }
+ }
+ }
+
+ // Called following the conclusion of a restore operation and when widget components
+ // are added or changed. This is when we send out updates to apps involved in widget-state
+ // restore telling them about the new widget ID space.
+ @GuardedBy("mLock")
+ private void maybeSendWidgetRestoreBroadcastsLocked(int userId) {
+ if (DEBUG) {
+ Slog.i(TAG, "maybeSendWidgetRestoreBroadcasts for " + userId);
+ }
+
+ final UserHandle userHandle = new UserHandle(userId);
+ // Build the providers' broadcasts and send them off
+ Set<Map.Entry<Provider, ArrayList<RestoreUpdateRecord>>> providerEntries
+ = mUpdatesByProvider.entrySet();
+ for (Map.Entry<Provider, ArrayList<RestoreUpdateRecord>> e : providerEntries) {
+ // For each provider there's a list of affected IDs
+ Provider provider = e.getKey();
+ if (provider.zombie) {
+ // Provider not installed, we can't send them broadcasts yet.
+ // We'll be called again when the provider is installed.
+ continue;
+ }
+ ArrayList<RestoreUpdateRecord> updates = e.getValue();
+ final int pending = countPendingUpdates(updates);
+ if (DEBUG) {
+ Slog.i(TAG, "Provider " + provider + " pending: " + pending);
+ }
+ if (pending > 0) {
+ int[] oldIds = new int[pending];
+ int[] newIds = new int[pending];
+ final int N = updates.size();
+ int nextPending = 0;
+ for (int i = 0; i < N; i++) {
+ RestoreUpdateRecord r = updates.get(i);
+ if (!r.notified) {
+ r.notified = true;
+ oldIds[nextPending] = r.oldId;
+ newIds[nextPending] = r.newId;
+ nextPending++;
+ if (DEBUG) {
+ Slog.i(TAG, " " + r.oldId + " => " + r.newId);
+ }
+ }
+ }
+ sendWidgetRestoreBroadcastLocked(
+ AppWidgetManager.ACTION_APPWIDGET_RESTORED,
+ provider, null, oldIds, newIds, userHandle);
+ }
+ }
+
+ // same thing per host
+ Set<Map.Entry<Host, ArrayList<RestoreUpdateRecord>>> hostEntries
+ = mUpdatesByHost.entrySet();
+ for (Map.Entry<Host, ArrayList<RestoreUpdateRecord>> e : hostEntries) {
+ Host host = e.getKey();
+ if (host.id.uid != UNKNOWN_UID) {
ArrayList<RestoreUpdateRecord> updates = e.getValue();
final int pending = countPendingUpdates(updates);
if (DEBUG) {
- Slog.i(TAG, "Provider " + provider + " pending: " + pending);
+ Slog.i(TAG, "Host " + host + " pending: " + pending);
}
if (pending > 0) {
int[] oldIds = new int[pending];
@@ -4581,43 +4651,8 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku
}
}
sendWidgetRestoreBroadcastLocked(
- AppWidgetManager.ACTION_APPWIDGET_RESTORED,
- provider, null, oldIds, newIds, userHandle);
- }
- }
-
- // same thing per host
- Set<Map.Entry<Host, ArrayList<RestoreUpdateRecord>>> hostEntries
- = mUpdatesByHost.entrySet();
- for (Map.Entry<Host, ArrayList<RestoreUpdateRecord>> e : hostEntries) {
- Host host = e.getKey();
- if (host.id.uid != UNKNOWN_UID) {
- ArrayList<RestoreUpdateRecord> updates = e.getValue();
- final int pending = countPendingUpdates(updates);
- if (DEBUG) {
- Slog.i(TAG, "Host " + host + " pending: " + pending);
- }
- if (pending > 0) {
- int[] oldIds = new int[pending];
- int[] newIds = new int[pending];
- final int N = updates.size();
- int nextPending = 0;
- for (int i = 0; i < N; i++) {
- RestoreUpdateRecord r = updates.get(i);
- if (!r.notified) {
- r.notified = true;
- oldIds[nextPending] = r.oldId;
- newIds[nextPending] = r.newId;
- nextPending++;
- if (DEBUG) {
- Slog.i(TAG, " " + r.oldId + " => " + r.newId);
- }
- }
- }
- sendWidgetRestoreBroadcastLocked(
- AppWidgetManager.ACTION_APPWIDGET_HOST_RESTORED,
- null, host, oldIds, newIds, userHandle);
- }
+ AppWidgetManager.ACTION_APPWIDGET_HOST_RESTORED,
+ null, host, oldIds, newIds, userHandle);
}
}
}
diff --git a/services/backup/java/com/android/server/backup/restore/PerformUnifiedRestoreTask.java b/services/backup/java/com/android/server/backup/restore/PerformUnifiedRestoreTask.java
index 261ebe69a15e..f07bac8cd762 100644
--- a/services/backup/java/com/android/server/backup/restore/PerformUnifiedRestoreTask.java
+++ b/services/backup/java/com/android/server/backup/restore/PerformUnifiedRestoreTask.java
@@ -381,7 +381,7 @@ public class PerformUnifiedRestoreTask implements BackupRestoreTask {
// If we're starting a full-system restore, set up to begin widget ID remapping
if (mIsSystemRestore) {
- AppWidgetBackupBridge.restoreStarting(mUserId);
+ AppWidgetBackupBridge.systemRestoreStarting(mUserId);
}
try {
@@ -1133,8 +1133,10 @@ public class PerformUnifiedRestoreTask implements BackupRestoreTask {
restoreAgentTimeoutMillis);
}
- // Kick off any work that may be needed regarding app widget restores
- AppWidgetBackupBridge.restoreFinished(mUserId);
+ if (mIsSystemRestore) {
+ // Kick off any work that may be needed regarding app widget restores
+ AppWidgetBackupBridge.systemRestoreFinished(mUserId);
+ }
// If this was a full-system restore, record the ancestral
// dataset information
diff --git a/services/core/java/com/android/server/VpnManagerService.java b/services/core/java/com/android/server/VpnManagerService.java
index 26ecee8f21ab..70176a0fefeb 100644
--- a/services/core/java/com/android/server/VpnManagerService.java
+++ b/services/core/java/com/android/server/VpnManagerService.java
@@ -38,6 +38,7 @@ import android.net.VpnManager;
import android.net.VpnService;
import android.net.util.NetdService;
import android.os.Binder;
+import android.os.Build;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.INetworkManagementService;
@@ -348,9 +349,17 @@ public class VpnManagerService extends IVpnManager.Stub {
/**
* Start legacy VPN, controlling native daemons as needed. Creates a
* secondary thread to perform connection work, returning quickly.
+ *
+ * Legacy VPN is deprecated starting from Android S. So this API shouldn't be called if the
+ * initial SDK version of device is Android S+. Otherwise, UnsupportedOperationException will be
+ * thrown.
*/
+ @SuppressWarnings("AndroidFrameworkCompatChange") // This is not an app-visible API.
@Override
public void startLegacyVpn(VpnProfile profile) {
+ if (Build.VERSION.DEVICE_INITIAL_SDK_INT >= Build.VERSION_CODES.S) {
+ throw new UnsupportedOperationException("Legacy VPN is deprecated");
+ }
int user = UserHandle.getUserId(mDeps.getCallingUid());
// Note that if the caller is not system (uid >= Process.FIRST_APPLICATION_UID),
// the code might not work well since getActiveNetwork might return null if the uid is
diff --git a/services/core/java/com/android/server/appop/DiscreteRegistry.java b/services/core/java/com/android/server/appop/DiscreteRegistry.java
index 49469cc8a597..1e32129dcee1 100644
--- a/services/core/java/com/android/server/appop/DiscreteRegistry.java
+++ b/services/core/java/com/android/server/appop/DiscreteRegistry.java
@@ -16,6 +16,7 @@
package com.android.server.appop;
+import static android.app.AppOpsManager.ATTRIBUTION_CHAIN_ID_NONE;
import static android.app.AppOpsManager.FILTER_BY_ATTRIBUTION_TAG;
import static android.app.AppOpsManager.FILTER_BY_OP_NAMES;
import static android.app.AppOpsManager.FILTER_BY_PACKAGE_NAME;
@@ -58,7 +59,9 @@ import com.android.internal.util.XmlUtils;
import java.io.File;
import java.io.FileInputStream;
+import java.io.FileNotFoundException;
import java.io.FileOutputStream;
+import java.io.IOException;
import java.io.PrintWriter;
import java.text.SimpleDateFormat;
import java.time.Duration;
@@ -138,6 +141,7 @@ final class DiscreteRegistry {
private static final String TAG_HISTORY = "h";
private static final String ATTR_VERSION = "v";
+ private static final String ATTR_LARGEST_CHAIN_ID = "lc";
private static final int CURRENT_VERSION = 1;
private static final String TAG_UID = "u";
@@ -182,6 +186,16 @@ final class DiscreteRegistry {
DiscreteRegistry(Object inMemoryLock) {
mInMemoryLock = inMemoryLock;
+ synchronized (mOnDiskLock) {
+ mDiscreteAccessDir = new File(
+ new File(Environment.getDataSystemDirectory(), "appops"),
+ "discrete");
+ createDiscreteAccessDirLocked();
+ int largestChainId = readLargestChainIdFromDiskLocked();
+ synchronized (mInMemoryLock) {
+ mDiscreteOps = new DiscreteOps(largestChainId);
+ }
+ }
}
void systemReady() {
@@ -190,15 +204,6 @@ final class DiscreteRegistry {
setDiscreteHistoryParameters(p);
});
setDiscreteHistoryParameters(DeviceConfig.getProperties(DeviceConfig.NAMESPACE_PRIVACY));
- synchronized (mOnDiskLock) {
- synchronized (mInMemoryLock) {
- mDiscreteAccessDir = new File(
- new File(Environment.getDataSystemDirectory(), "appops"),
- "discrete");
- createDiscreteAccessDirLocked();
- mDiscreteOps = new DiscreteOps();
- }
- }
}
private void setDiscreteHistoryParameters(DeviceConfig.Properties p) {
@@ -251,7 +256,7 @@ final class DiscreteRegistry {
DiscreteOps discreteOps;
synchronized (mInMemoryLock) {
discreteOps = mDiscreteOps;
- mDiscreteOps = new DiscreteOps();
+ mDiscreteOps = new DiscreteOps(discreteOps.mChainIdOffset);
mCachedOps = null;
}
deleteOldDiscreteHistoryFilesLocked();
@@ -275,6 +280,50 @@ final class DiscreteRegistry {
return;
}
+ private int readLargestChainIdFromDiskLocked() {
+ final File[] files = mDiscreteAccessDir.listFiles();
+ if (files != null && files.length > 0) {
+ File latestFile = null;
+ long latestFileTimestamp = 0;
+ for (File f : files) {
+ final String fileName = f.getName();
+ if (!fileName.endsWith(DISCRETE_HISTORY_FILE_SUFFIX)) {
+ continue;
+ }
+ long timestamp = Long.valueOf(fileName.substring(0,
+ fileName.length() - DISCRETE_HISTORY_FILE_SUFFIX.length()));
+ if (latestFileTimestamp < timestamp) {
+ latestFile = f;
+ latestFileTimestamp = timestamp;
+ }
+ }
+ if (latestFile == null) {
+ return 0;
+ }
+ FileInputStream stream;
+ try {
+ stream = new FileInputStream(latestFile);
+ } catch (FileNotFoundException e) {
+ return 0;
+ }
+ try {
+ TypedXmlPullParser parser = Xml.resolvePullParser(stream);
+ XmlUtils.beginDocument(parser, TAG_HISTORY);
+
+ final int largestChainId = parser.getAttributeInt(null, ATTR_LARGEST_CHAIN_ID, 0);
+ return largestChainId;
+ } catch (Throwable t) {
+ return 0;
+ } finally {
+ try {
+ stream.close();
+ } catch (IOException e) { }
+ }
+ } else {
+ return 0;
+ }
+ }
+
private void readDiscreteOpsFromDisk(DiscreteOps discreteOps) {
synchronized (mOnDiskLock) {
long beginTimeMillis = Instant.now().minus(sDiscreteHistoryCutoff,
@@ -301,7 +350,7 @@ final class DiscreteRegistry {
void clearHistory() {
synchronized (mOnDiskLock) {
synchronized (mInMemoryLock) {
- mDiscreteOps = new DiscreteOps();
+ mDiscreteOps = new DiscreteOps(0);
}
clearOnDiskHistoryLocked();
}
@@ -341,6 +390,10 @@ final class DiscreteRegistry {
: new String[]{AppOpsManager.opToPublicName(dumpOp)};
discreteOps.filter(0, Instant.now().toEpochMilli(), filter, uidFilter, packageNameFilter,
opNamesFilter, attributionTagFilter, OP_FLAGS_ALL);
+ pw.print(prefix);
+ pw.print("Largest chain id: ");
+ pw.print(mDiscreteOps.mLargestChainId);
+ pw.println();
discreteOps.dump(pw, sdf, date, prefix, nDiscreteOps);
}
@@ -351,14 +404,14 @@ final class DiscreteRegistry {
}
private DiscreteOps getAllDiscreteOps() {
- DiscreteOps discreteOps = new DiscreteOps();
+ DiscreteOps discreteOps = new DiscreteOps(0);
synchronized (mOnDiskLock) {
synchronized (mInMemoryLock) {
discreteOps.merge(mDiscreteOps);
}
if (mCachedOps == null) {
- mCachedOps = new DiscreteOps();
+ mCachedOps = new DiscreteOps(0);
readDiscreteOpsFromDisk(mCachedOps);
}
discreteOps.merge(mCachedOps);
@@ -368,9 +421,13 @@ final class DiscreteRegistry {
private final class DiscreteOps {
ArrayMap<Integer, DiscreteUidOps> mUids;
+ int mChainIdOffset;
+ int mLargestChainId;
- DiscreteOps() {
+ DiscreteOps(int chainIdOffset) {
mUids = new ArrayMap<>();
+ mChainIdOffset = chainIdOffset;
+ mLargestChainId = chainIdOffset;
}
boolean isEmpty() {
@@ -378,6 +435,7 @@ final class DiscreteRegistry {
}
void merge(DiscreteOps other) {
+ mLargestChainId = max(mLargestChainId, other.mLargestChainId);
int nUids = other.mUids.size();
for (int i = 0; i < nUids; i++) {
int uid = other.mUids.keyAt(i);
@@ -390,6 +448,17 @@ final class DiscreteRegistry {
@Nullable String attributionTag, @AppOpsManager.OpFlags int flags,
@AppOpsManager.UidState int uidState, long accessTime, long accessDuration,
@AppOpsManager.AttributionFlags int attributionFlags, int attributionChainId) {
+ if (attributionChainId != ATTRIBUTION_CHAIN_ID_NONE) {
+ attributionChainId += mChainIdOffset;
+ if (attributionChainId < 0) {
+ attributionChainId -= mChainIdOffset;
+ mChainIdOffset = 0;
+ mLargestChainId = attributionChainId;
+ }
+ if (attributionChainId > mLargestChainId) {
+ mLargestChainId = attributionChainId;
+ }
+ }
getOrCreateDiscreteUidOps(uid).addDiscreteAccess(op, packageName, attributionTag, flags,
uidState, accessTime, accessDuration, attributionFlags, attributionChainId);
}
@@ -442,6 +511,7 @@ final class DiscreteRegistry {
out.startDocument(null, true);
out.startTag(null, TAG_HISTORY);
out.attributeInt(null, ATTR_VERSION, CURRENT_VERSION);
+ out.attributeInt(null, ATTR_LARGEST_CHAIN_ID, mLargestChainId);
int nUids = mUids.size();
for (int i = 0; i < nUids; i++) {
@@ -476,8 +546,13 @@ final class DiscreteRegistry {
}
private void readFromFile(File f, long beginTimeMillis) {
+ FileInputStream stream;
+ try {
+ stream = new FileInputStream(f);
+ } catch (FileNotFoundException e) {
+ return;
+ }
try {
- FileInputStream stream = new FileInputStream(f);
TypedXmlPullParser parser = Xml.resolvePullParser(stream);
XmlUtils.beginDocument(parser, TAG_HISTORY);
@@ -487,7 +562,6 @@ final class DiscreteRegistry {
if (version != CURRENT_VERSION) {
throw new IllegalStateException("Dropping unsupported discrete history " + f);
}
-
int depth = parser.getDepth();
while (XmlUtils.nextElementWithin(parser, depth)) {
if (TAG_UID.equals(parser.getName())) {
@@ -498,8 +572,12 @@ final class DiscreteRegistry {
} catch (Throwable t) {
Slog.e(TAG, "Failed to read file " + f.getName() + " " + t.getMessage() + " "
+ Arrays.toString(t.getStackTrace()));
+ } finally {
+ try {
+ stream.close();
+ } catch (IOException e) {
+ }
}
-
}
}
diff --git a/services/core/java/com/android/server/appop/HistoricalRegistry.java b/services/core/java/com/android/server/appop/HistoricalRegistry.java
index dd5df503d936..62472b5f1d75 100644
--- a/services/core/java/com/android/server/appop/HistoricalRegistry.java
+++ b/services/core/java/com/android/server/appop/HistoricalRegistry.java
@@ -209,6 +209,7 @@ final class HistoricalRegistry {
mMode = other.mMode;
mBaseSnapshotInterval = other.mBaseSnapshotInterval;
mIntervalCompressionMultiplier = other.mIntervalCompressionMultiplier;
+ mDiscreteRegistry = other.mDiscreteRegistry;
}
void systemReady(@NonNull ContentResolver resolver) {
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/AidlConversionUtils.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/AidlConversionUtils.java
index f1f94564c35d..0ae2e381cf14 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/AidlConversionUtils.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/AidlConversionUtils.java
@@ -80,8 +80,7 @@ final class AidlConversionUtils {
// No framework constant available
return BiometricFingerprintConstants.FINGERPRINT_ACQUIRED_UNKNOWN;
} else if (aidlAcquiredInfo == AcquiredInfo.IMMOBILE) {
- // No framework constant available
- return BiometricFingerprintConstants.FINGERPRINT_ACQUIRED_UNKNOWN;
+ return BiometricFingerprintConstants.FINGERPRINT_ACQUIRED_IMMOBILE;
} else if (aidlAcquiredInfo == AcquiredInfo.RETRYING_CAPTURE) {
// No framework constant available
return BiometricFingerprintConstants.FINGERPRINT_ACQUIRED_UNKNOWN;
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index a3f3a3a503c8..9151e4e1779a 100755
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -140,6 +140,7 @@ import android.app.INotificationManager;
import android.app.ITransientNotification;
import android.app.ITransientNotificationCallback;
import android.app.IUriGrantsManager;
+import android.app.KeyguardManager;
import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationChannelGroup;
@@ -549,6 +550,8 @@ public class NotificationManagerService extends SystemService {
// Used for rate limiting toasts by package.
private MultiRateLimiter mToastRateLimiter;
+ private KeyguardManager mKeyguardManager;
+
// The last key in this list owns the hardware.
ArrayList<String> mLights = new ArrayList<>();
@@ -2008,6 +2011,11 @@ public class NotificationManagerService extends SystemService {
}
@VisibleForTesting
+ void setKeyguardManager(KeyguardManager keyguardManager) {
+ mKeyguardManager = keyguardManager;
+ }
+
+ @VisibleForTesting
ShortcutHelper getShortcutHelper() {
return mShortcutHelper;
}
@@ -2653,6 +2661,7 @@ public class NotificationManagerService extends SystemService {
mAudioManager = (AudioManager) getContext().getSystemService(Context.AUDIO_SERVICE);
mAudioManagerInternal = getLocalService(AudioManagerInternal.class);
mWindowManagerInternal = LocalServices.getService(WindowManagerInternal.class);
+ mKeyguardManager = getContext().getSystemService(KeyguardManager.class);
mZenModeHelper.onSystemReady();
RoleObserver roleObserver = new RoleObserver(getContext(),
getContext().getSystemService(RoleManager.class),
@@ -7388,7 +7397,6 @@ public class NotificationManagerService extends SystemService {
boolean beep = false;
boolean blink = false;
- final Notification notification = record.getSbn().getNotification();
final String key = record.getKey();
// Should this notification make noise, vibe, or use the LED?
@@ -7410,7 +7418,7 @@ public class NotificationManagerService extends SystemService {
if (!record.isUpdate
&& record.getImportance() > IMPORTANCE_MIN
&& !suppressedByDnd) {
- sendAccessibilityEvent(notification, record.getSbn().getPackageName());
+ sendAccessibilityEvent(record);
sentAccessibilityEvent = true;
}
@@ -7433,7 +7441,7 @@ public class NotificationManagerService extends SystemService {
boolean hasAudibleAlert = hasValidSound || hasValidVibrate;
if (hasAudibleAlert && !shouldMuteNotificationLocked(record)) {
if (!sentAccessibilityEvent) {
- sendAccessibilityEvent(notification, record.getSbn().getPackageName());
+ sendAccessibilityEvent(record);
sentAccessibilityEvent = true;
}
if (DBG) Slog.v(TAG, "Interrupting!");
@@ -8261,17 +8269,30 @@ public class NotificationManagerService extends SystemService {
return (x < low) ? low : ((x > high) ? high : x);
}
- void sendAccessibilityEvent(Notification notification, CharSequence packageName) {
+ void sendAccessibilityEvent(NotificationRecord record) {
if (!mAccessibilityManager.isEnabled()) {
return;
}
- AccessibilityEvent event =
+ final Notification notification = record.getNotification();
+ final CharSequence packageName = record.getSbn().getPackageName();
+ final AccessibilityEvent event =
AccessibilityEvent.obtain(AccessibilityEvent.TYPE_NOTIFICATION_STATE_CHANGED);
event.setPackageName(packageName);
event.setClassName(Notification.class.getName());
- event.setParcelableData(notification);
- CharSequence tickerText = notification.tickerText;
+ final int visibilityOverride = record.getPackageVisibilityOverride();
+ final int notifVisibility = visibilityOverride == NotificationManager.VISIBILITY_NO_OVERRIDE
+ ? notification.visibility : visibilityOverride;
+ final int userId = record.getUser().getIdentifier();
+ final boolean needPublic = userId >= 0 && mKeyguardManager.isDeviceLocked(userId);
+ if (needPublic && notifVisibility != Notification.VISIBILITY_PUBLIC) {
+ // Emit the public version if we're on the lockscreen and this notification isn't
+ // publicly visible.
+ event.setParcelableData(notification.publicVersion);
+ } else {
+ event.setParcelableData(notification);
+ }
+ final CharSequence tickerText = notification.tickerText;
if (!TextUtils.isEmpty(tickerText)) {
event.getText().add(tickerText);
}
diff --git a/services/core/java/com/android/server/pm/PackageDexOptimizer.java b/services/core/java/com/android/server/pm/PackageDexOptimizer.java
index 5fd8e3c6e302..44f7d8869322 100644
--- a/services/core/java/com/android/server/pm/PackageDexOptimizer.java
+++ b/services/core/java/com/android/server/pm/PackageDexOptimizer.java
@@ -177,8 +177,10 @@ public class PackageDexOptimizer {
private int performDexOptLI(AndroidPackage pkg, @NonNull PackageSetting pkgSetting,
String[] targetInstructionSets, CompilerStats.PackageStats packageStats,
PackageDexUsage.PackageUseInfo packageUseInfo, DexoptOptions options) {
+ // ClassLoader only refers non-native (jar) shared libraries and must ignore
+ // native (so) shared libraries. See also LoadedApk#createSharedLibraryLoader().
final List<SharedLibraryInfo> sharedLibraries = pkgSetting.getPkgState()
- .getUsesLibraryInfos();
+ .getNonNativeUsesLibraryInfos();
final String[] instructionSets = targetInstructionSets != null ?
targetInstructionSets : getAppDexInstructionSets(
AndroidPackageUtils.getPrimaryCpuAbi(pkg, pkgSetting),
diff --git a/services/core/java/com/android/server/pm/PackageInstallerService.java b/services/core/java/com/android/server/pm/PackageInstallerService.java
index 60a757118222..d2ed08f66944 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerService.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerService.java
@@ -157,6 +157,7 @@ public class PackageInstallerService extends IPackageInstaller.Stub implements
private volatile boolean mOkToSendBroadcasts = false;
private volatile boolean mBypassNextStagedInstallerCheck = false;
+ private volatile boolean mBypassNextAllowedApexUpdateCheck = false;
/**
* File storing persisted {@link #mSessions} metadata.
@@ -650,6 +651,13 @@ public class PackageInstallerService extends IPackageInstaller.Stub implements
throw new IllegalArgumentException(
"Non-staged APEX session doesn't support INSTALL_ENABLE_ROLLBACK");
}
+ if (isCalledBySystemOrShell(callingUid) || mBypassNextAllowedApexUpdateCheck) {
+ params.installFlags |= PackageManager.INSTALL_DISABLE_ALLOWED_APEX_UPDATE_CHECK;
+ } else {
+ // Only specific APEX updates (installed through ADB, or for CTS tests) can disable
+ // allowed APEX update check.
+ params.installFlags &= ~PackageManager.INSTALL_DISABLE_ALLOWED_APEX_UPDATE_CHECK;
+ }
}
if ((params.installFlags & PackageManager.INSTALL_INSTANT_APP) != 0
@@ -674,6 +682,8 @@ public class PackageInstallerService extends IPackageInstaller.Stub implements
}
mBypassNextStagedInstallerCheck = false;
+ mBypassNextAllowedApexUpdateCheck = false;
+
if (!params.isMultiPackage) {
// Only system components can circumvent runtime permissions when installing.
if ((params.installFlags & PackageManager.INSTALL_GRANT_RUNTIME_PERMISSIONS) != 0
@@ -1106,6 +1116,14 @@ public class PackageInstallerService extends IPackageInstaller.Stub implements
mBypassNextStagedInstallerCheck = value;
}
+ @Override
+ public void bypassNextAllowedApexUpdateCheck(boolean value) {
+ if (!isCalledBySystemOrShell(Binder.getCallingUid())) {
+ throw new SecurityException("Caller not allowed to bypass allowed apex update check");
+ }
+ mBypassNextAllowedApexUpdateCheck = value;
+ }
+
/**
* Set an installer to allow for the unlimited silent updates.
*/
diff --git a/services/core/java/com/android/server/pm/PackageInstallerSession.java b/services/core/java/com/android/server/pm/PackageInstallerSession.java
index 4b0eb6546888..acc83cfd05b6 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerSession.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerSession.java
@@ -147,6 +147,7 @@ import com.android.internal.util.FrameworkStatsLog;
import com.android.internal.util.IndentingPrintWriter;
import com.android.internal.util.Preconditions;
import com.android.server.LocalServices;
+import com.android.server.SystemConfig;
import com.android.server.pm.Installer.InstallerException;
import com.android.server.pm.dex.DexManager;
import com.android.server.pm.parsing.pkg.AndroidPackage;
@@ -2238,6 +2239,26 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
.setAdmin(mInstallSource.installerPackageName)
.write();
}
+
+ // Check if APEX update is allowed. We do this check in handleInstall, since this is one of
+ // the places that:
+ // * Shared between staged and non-staged APEX update flows.
+ // * Only is called after boot completes.
+ // The later is important, since isApexUpdateAllowed check depends on the
+ // ModuleInfoProvider, which is only populated after device has booted.
+ if (isApexSession()) {
+ boolean checkApexUpdateAllowed =
+ (params.installFlags & PackageManager.INSTALL_DISABLE_ALLOWED_APEX_UPDATE_CHECK)
+ == 0;
+ synchronized (mLock) {
+ if (checkApexUpdateAllowed && !isApexUpdateAllowed(mPackageName)) {
+ onSessionValidationFailure(PackageManager.INSTALL_FAILED_VERIFICATION_FAILURE,
+ "Update of APEX package " + mPackageName + " is not allowed");
+ return;
+ }
+ }
+ }
+
if (params.isStaged) {
mStagingManager.commitSession(mStagedSession);
// TODO(b/136257624): CTS test fails if we don't send session finished broadcast, even
@@ -2776,6 +2797,11 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
return sessionContains((s) -> !s.isApexSession());
}
+ private boolean isApexUpdateAllowed(String apexPackageName) {
+ return mPm.getModuleInfo(apexPackageName, 0) != null
+ || SystemConfig.getInstance().getAllowedVendorApexes().contains(apexPackageName);
+ }
+
/**
* Validate apex install.
* <p>
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 463520fb2608..b0a662b3514d 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -21480,6 +21480,8 @@ public class PackageManagerService extends IPackageManager.Stub
// for the uninstall-updates case and restricted profiles, remember the per-
// user handle installed state
int[] allUsers;
+ final int freezeUser;
+ final SparseArray<Pair<Integer, String>> enabledStateAndCallerPerUser;
/** enabled state of the uninstalled application */
synchronized (mLock) {
uninstalledPs = mSettings.getPackageLPr(packageName);
@@ -21524,16 +21526,23 @@ public class PackageManagerService extends IPackageManager.Stub
}
info.origUsers = uninstalledPs.queryInstalledUsers(allUsers, true);
- }
- final int freezeUser;
- if (isUpdatedSystemApp(uninstalledPs)
- && ((deleteFlags & PackageManager.DELETE_SYSTEM_APP) == 0)) {
- // We're downgrading a system app, which will apply to all users, so
- // freeze them all during the downgrade
- freezeUser = UserHandle.USER_ALL;
- } else {
- freezeUser = removeUser;
+ if (isUpdatedSystemApp(uninstalledPs)
+ && ((deleteFlags & PackageManager.DELETE_SYSTEM_APP) == 0)) {
+ // We're downgrading a system app, which will apply to all users, so
+ // freeze them all during the downgrade
+ freezeUser = UserHandle.USER_ALL;
+ enabledStateAndCallerPerUser = new SparseArray<>();
+ for (int i = 0; i < allUsers.length; i++) {
+ PackageUserState userState = uninstalledPs.readUserState(allUsers[i]);
+ Pair<Integer, String> enabledStateAndCaller =
+ new Pair<>(userState.enabled, userState.lastDisableAppCaller);
+ enabledStateAndCallerPerUser.put(allUsers[i], enabledStateAndCaller);
+ }
+ } else {
+ freezeUser = removeUser;
+ enabledStateAndCallerPerUser = null;
+ }
}
synchronized (mInstallLock) {
@@ -21602,6 +21611,19 @@ public class PackageManagerService extends IPackageManager.Stub
}
}
}
+ if (enabledStateAndCallerPerUser != null) {
+ synchronized (mLock) {
+ for (int i = 0; i < allUsers.length; i++) {
+ Pair<Integer, String> enabledStateAndCaller =
+ enabledStateAndCallerPerUser.get(allUsers[i]);
+ getPackageSetting(packageName)
+ .setEnabled(enabledStateAndCaller.first,
+ allUsers[i],
+ enabledStateAndCaller.second);
+ }
+ mSettings.writeAllUsersPackageRestrictionsLPr();
+ }
+ }
}
return res ? PackageManager.DELETE_SUCCEEDED : PackageManager.DELETE_FAILED_INTERNAL_ERROR;
diff --git a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
index 49559f299fa0..1aa80a953d6c 100644
--- a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
+++ b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
@@ -307,6 +307,8 @@ class PackageManagerShellCommand extends ShellCommand {
return runLogVisibility();
case "bypass-staged-installer-check":
return runBypassStagedInstallerCheck();
+ case "bypass-allowed-apex-update-check":
+ return runBypassAllowedApexUpdateCheck();
case "set-silent-updates-policy":
return runSetSilentUpdatesPolicy();
default: {
@@ -424,6 +426,20 @@ class PackageManagerShellCommand extends ShellCommand {
}
}
+ private int runBypassAllowedApexUpdateCheck() {
+ final PrintWriter pw = getOutPrintWriter();
+ try {
+ mInterface.getPackageInstaller()
+ .bypassNextAllowedApexUpdateCheck(Boolean.parseBoolean(getNextArg()));
+ return 0;
+ } catch (RemoteException e) {
+ pw.println("Failure ["
+ + e.getClass().getName() + " - "
+ + e.getMessage() + "]");
+ return -1;
+ }
+ }
+
private int uninstallSystemUpdates(String packageName) {
final PrintWriter pw = getOutPrintWriter();
boolean failedUninstalls = false;
diff --git a/services/core/java/com/android/server/pm/pkg/PackageStateUnserialized.java b/services/core/java/com/android/server/pm/pkg/PackageStateUnserialized.java
index 05879ec9545e..fad0aefd3c0a 100644
--- a/services/core/java/com/android/server/pm/pkg/PackageStateUnserialized.java
+++ b/services/core/java/com/android/server/pm/pkg/PackageStateUnserialized.java
@@ -28,6 +28,7 @@ import com.android.server.pm.PackageSetting;
import java.util.ArrayList;
import java.util.List;
+import java.util.stream.Collectors;
/**
* For use by {@link PackageSetting} to maintain functionality that used to exist in
@@ -110,6 +111,10 @@ public class PackageStateUnserialized {
this.overrideSeInfo = other.overrideSeInfo;
}
+ public @NonNull List<SharedLibraryInfo> getNonNativeUsesLibraryInfos() {
+ return getUsesLibraryInfos().stream()
+ .filter((l) -> !l.isNative()).collect(Collectors.toList());
+ }
// Code below generated by codegen v1.0.14.
diff --git a/services/core/java/com/android/server/vibrator/VibrationSettings.java b/services/core/java/com/android/server/vibrator/VibrationSettings.java
index f756434e981a..885f0e4c78ab 100644
--- a/services/core/java/com/android/server/vibrator/VibrationSettings.java
+++ b/services/core/java/com/android/server/vibrator/VibrationSettings.java
@@ -353,6 +353,7 @@ final class VibrationSettings {
+ ", mLowPowerMode=" + mLowPowerMode
+ ", mZenMode=" + Settings.Global.zenModeToString(mZenMode)
+ ", mProcStatesCache=" + mUidObserver.mProcStatesCache
+ + ", mHapticChannelMaxVibrationAmplitude=" + getHapticChannelMaxVibrationAmplitude()
+ ", mHapticFeedbackIntensity="
+ intensityToString(getCurrentIntensity(VibrationAttributes.USAGE_TOUCH))
+ ", mHapticFeedbackDefaultIntensity="
@@ -411,6 +412,12 @@ final class VibrationSettings {
}
}
+ private float getHapticChannelMaxVibrationAmplitude() {
+ synchronized (mLock) {
+ return mVibrator == null ? Float.NaN : mVibrator.getHapticChannelMaximumAmplitude();
+ }
+ }
+
private int getSystemSetting(String settingName, int defaultValue) {
return Settings.System.getIntForUser(mContext.getContentResolver(),
settingName, defaultValue, UserHandle.USER_CURRENT);
diff --git a/services/core/java/com/android/server/vibrator/VibrationThread.java b/services/core/java/com/android/server/vibrator/VibrationThread.java
index 150fde99b706..45d511159e11 100644
--- a/services/core/java/com/android/server/vibrator/VibrationThread.java
+++ b/services/core/java/com/android/server/vibrator/VibrationThread.java
@@ -844,7 +844,12 @@ final class VibrationThread extends Thread implements IBinder.DeathRecipient {
public List<Step> play() {
Trace.traceBegin(Trace.TRACE_TAG_VIBRATOR, "ComposePrimitivesStep");
try {
- int segmentCount = effect.getSegments().size();
+ // Load the next PrimitiveSegments to create a single compose call to the vibrator,
+ // limited to the vibrator composition maximum size.
+ int limit = controller.getVibratorInfo().getCompositionSizeMax();
+ int segmentCount = limit > 0
+ ? Math.min(effect.getSegments().size(), segmentIndex + limit)
+ : effect.getSegments().size();
List<PrimitiveSegment> primitives = new ArrayList<>();
for (int i = segmentIndex; i < segmentCount; i++) {
VibrationEffectSegment segment = effect.getSegments().get(i);
@@ -896,7 +901,12 @@ final class VibrationThread extends Thread implements IBinder.DeathRecipient {
public List<Step> play() {
Trace.traceBegin(Trace.TRACE_TAG_VIBRATOR, "ComposePwleStep");
try {
- int segmentCount = effect.getSegments().size();
+ // Load the next RampSegments to create a single composePwle call to the vibrator,
+ // limited to the vibrator PWLE maximum size.
+ int limit = controller.getVibratorInfo().getPwleSizeMax();
+ int segmentCount = limit > 0
+ ? Math.min(effect.getSegments().size(), segmentIndex + limit)
+ : effect.getSegments().size();
List<RampSegment> pwles = new ArrayList<>();
for (int i = segmentIndex; i < segmentCount; i++) {
VibrationEffectSegment segment = effect.getSegments().get(i);
diff --git a/services/core/java/com/android/server/vibrator/VibratorController.java b/services/core/java/com/android/server/vibrator/VibratorController.java
index 5dceac2d066c..001d5c440d58 100644
--- a/services/core/java/com/android/server/vibrator/VibratorController.java
+++ b/services/core/java/com/android/server/vibrator/VibratorController.java
@@ -30,19 +30,24 @@ import android.util.Slog;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.util.Preconditions;
import libcore.util.NativeAllocationRegistry;
/** Controls a single vibrator. */
final class VibratorController {
private static final String TAG = "VibratorController";
+ // TODO(b/167947076): load suggested range from config
+ private static final int SUGGESTED_FREQUENCY_SAFE_RANGE = 200;
private final Object mLock = new Object();
private final NativeWrapper mNativeWrapper;
- private final VibratorInfo mVibratorInfo;
+ private final VibratorInfo.Builder mVibratorInfoBuilder;
@GuardedBy("mLock")
+ private VibratorInfo mVibratorInfo;
+ @GuardedBy("mLock")
+ private boolean mVibratorInfoLoaded;
+ @GuardedBy("mLock")
private final RemoteCallbackList<IVibratorStateListener> mVibratorStateListeners =
new RemoteCallbackList<>();
@GuardedBy("mLock")
@@ -66,10 +71,10 @@ final class VibratorController {
NativeWrapper nativeWrapper) {
mNativeWrapper = nativeWrapper;
mNativeWrapper.init(vibratorId, listener);
- // TODO(b/167947076): load suggested range from config
- mVibratorInfo = mNativeWrapper.getInfo(/* suggestedFrequencyRange= */ 200);
- Preconditions.checkNotNull(mVibratorInfo, "Failed to retrieve data for vibrator %d",
- vibratorId);
+ mVibratorInfoBuilder = new VibratorInfo.Builder(vibratorId);
+ mVibratorInfoLoaded = mNativeWrapper.getInfo(SUGGESTED_FREQUENCY_SAFE_RANGE,
+ mVibratorInfoBuilder);
+ mVibratorInfo = mVibratorInfoBuilder.build();
}
/** Register state listener for this vibrator. */
@@ -103,7 +108,15 @@ final class VibratorController {
/** Return the {@link VibratorInfo} representing the vibrator controlled by this instance. */
public VibratorInfo getVibratorInfo() {
- return mVibratorInfo;
+ synchronized (mLock) {
+ if (!mVibratorInfoLoaded) {
+ // Try to load the vibrator metadata that has failed in the last attempt.
+ mVibratorInfoLoaded = mNativeWrapper.getInfo(SUGGESTED_FREQUENCY_SAFE_RANGE,
+ mVibratorInfoBuilder);
+ mVibratorInfo = mVibratorInfoBuilder.build();
+ }
+ return mVibratorInfo;
+ }
}
/**
@@ -361,7 +374,8 @@ final class VibratorController {
private static native void alwaysOnDisable(long nativePtr, long id);
- private static native VibratorInfo getInfo(long nativePtr, float suggestedFrequencyRange);
+ private static native boolean getInfo(long nativePtr, float suggestedFrequencyRange,
+ VibratorInfo.Builder infoBuilder);
private long mNativePtr = 0;
@@ -428,9 +442,11 @@ final class VibratorController {
alwaysOnDisable(mNativePtr, id);
}
- /** Return device vibrator metadata. */
- public VibratorInfo getInfo(float suggestedFrequencyRange) {
- return getInfo(mNativePtr, suggestedFrequencyRange);
+ /**
+ * Loads device vibrator metadata and returns true if all metadata was loaded successfully.
+ */
+ public boolean getInfo(float suggestedFrequencyRange, VibratorInfo.Builder infoBuilder) {
+ return getInfo(mNativePtr, suggestedFrequencyRange, infoBuilder);
}
}
}
diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java
index 55d1920681c5..b156e12a1ce8 100644
--- a/services/core/java/com/android/server/wm/ActivityRecord.java
+++ b/services/core/java/com/android/server/wm/ActivityRecord.java
@@ -677,8 +677,6 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
private boolean mInSizeCompatModeForBounds = false;
// Whether the aspect ratio restrictions applied to the activity bounds in applyAspectRatio().
- // TODO(b/182268157): Aspect ratio can also be applie in resolveFixedOrientationConfiguration
- // but that isn't reflected in this boolean.
private boolean mIsAspectRatioApplied = false;
// Bounds populated in resolveFixedOrientationConfiguration when this activity is letterboxed
@@ -7266,41 +7264,48 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
}
final Rect parentBounds = newParentConfig.windowConfiguration.getBounds();
- final int parentWidth = parentBounds.width();
- final int parentHeight = parentBounds.height();
- float aspect = Math.max(parentWidth, parentHeight)
- / (float) Math.min(parentWidth, parentHeight);
+ final Rect parentAppBounds = newParentConfig.windowConfiguration.getAppBounds();
+ final Rect containingBounds = new Rect();
+ final Rect containingAppBounds = new Rect();
+ // Need to shrink the containing bounds into a square because the parent orientation does
+ // not match the activity requested orientation.
+ if (forcedOrientation == ORIENTATION_LANDSCAPE) {
+ // Shrink height to match width. Position height within app bounds.
+ final int bottom = Math.min(parentAppBounds.top + parentBounds.width(),
+ parentAppBounds.bottom);
+ containingBounds.set(parentBounds.left, parentAppBounds.top, parentBounds.right,
+ bottom);
+ containingAppBounds.set(parentAppBounds.left, parentAppBounds.top,
+ parentAppBounds.right, bottom);
+ } else {
+ // Shrink width to match height. Position width within app bounds.
+ final int right = Math.min(parentAppBounds.left + parentBounds.height(),
+ parentAppBounds.right);
+ containingBounds.set(parentAppBounds.left, parentBounds.top, right,
+ parentBounds.bottom);
+ containingAppBounds.set(parentAppBounds.left, parentAppBounds.top, right,
+ parentAppBounds.bottom);
+ }
+
+ Rect mTmpFullBounds = new Rect(resolvedBounds);
+ resolvedBounds.set(containingBounds);
// Override from config_fixedOrientationLetterboxAspectRatio or via ADB with
// set-fixed-orientation-letterbox-aspect-ratio.
final float letterboxAspectRatioOverride =
mWmService.mLetterboxConfiguration.getFixedOrientationLetterboxAspectRatio();
- aspect = letterboxAspectRatioOverride > MIN_FIXED_ORIENTATION_LETTERBOX_ASPECT_RATIO
- ? letterboxAspectRatioOverride : aspect;
-
- // Adjust the fixed orientation letterbox bounds to fit the app request aspect ratio in
- // order to use the extra available space.
- final float maxAspectRatio = info.getMaxAspectRatio();
- final float minAspectRatio = info.getMinAspectRatio();
- if (aspect > maxAspectRatio && maxAspectRatio != 0) {
- aspect = maxAspectRatio;
- } else if (aspect < minAspectRatio) {
- aspect = minAspectRatio;
- }
-
- // Store the current bounds to be able to revert to size compat mode values below if needed.
- Rect mTmpFullBounds = new Rect(resolvedBounds);
+ final float desiredAspectRatio =
+ letterboxAspectRatioOverride > MIN_FIXED_ORIENTATION_LETTERBOX_ASPECT_RATIO
+ ? letterboxAspectRatioOverride : computeAspectRatio(parentBounds);
+ // Apply aspect ratio to resolved bounds
+ mIsAspectRatioApplied = applyAspectRatio(resolvedBounds, containingAppBounds,
+ containingBounds, desiredAspectRatio, true);
+
+ // Vertically center if orientation is landscape. Bounds will later be horizontally centered
+ // in {@link updateResolvedBoundsHorizontalPosition()} regardless of orientation.
if (forcedOrientation == ORIENTATION_LANDSCAPE) {
- final int height = (int) Math.rint(parentWidth / aspect);
- final int top = parentBounds.centerY() - height / 2;
- resolvedBounds.set(parentBounds.left, top, parentBounds.right, top + height);
- } else {
- final int width = (int) Math.rint(parentHeight / aspect);
- final Rect parentAppBounds = newParentConfig.windowConfiguration.getAppBounds();
- final int left = width <= parentAppBounds.width()
- // Avoid overlapping with the horizontal decor area when possible.
- ? parentAppBounds.left : parentBounds.centerX() - width / 2;
- resolvedBounds.set(left, parentBounds.top, left + width, parentBounds.bottom);
+ final int offsetY = parentBounds.centerY() - resolvedBounds.centerY();
+ resolvedBounds.offset(0, offsetY);
}
if (mCompatDisplayInsets != null) {
@@ -7342,8 +7347,6 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
// then they should be aligned later in #updateResolvedBoundsHorizontalPosition().
if (!mTmpBounds.isEmpty()) {
resolvedBounds.set(mTmpBounds);
- // Exclude the horizontal decor area.
- resolvedBounds.left = parentAppBounds.left;
}
if (!resolvedBounds.isEmpty() && !resolvedBounds.equals(parentBounds)) {
// Compute the configuration based on the resolved bounds. If aspect ratio doesn't
@@ -7404,13 +7407,6 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
mIsAspectRatioApplied =
applyAspectRatio(resolvedBounds, containingAppBounds, containingBounds);
}
- // If the bounds are restricted by fixed aspect ratio, the resolved bounds should be put in
- // the container app bounds. Otherwise the entire container bounds are available.
- final boolean fillContainer = resolvedBounds.equals(containingBounds);
- if (!fillContainer) {
- // The horizontal position should not cover insets.
- resolvedBounds.left = containingAppBounds.left;
- }
// Use resolvedBounds to compute other override configurations such as appBounds. The bounds
// are calculated in compat container space. The actual position on screen will be applied
@@ -7477,6 +7473,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
// Align to top of parent (bounds) - this is a UX choice and exclude the horizontal decor
// if needed. Horizontal position is adjusted in updateResolvedBoundsHorizontalPosition.
// Above coordinates are in "@" space, now place "*" and "#" to screen space.
+ final boolean fillContainer = resolvedBounds.equals(containingBounds);
final int screenPosX = fillContainer ? containerBounds.left : containerAppBounds.left;
final int screenPosY = containerBounds.top;
if (screenPosX != 0 || screenPosY != 0) {
@@ -7713,6 +7710,12 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
return true;
}
+ private boolean applyAspectRatio(Rect outBounds, Rect containingAppBounds,
+ Rect containingBounds) {
+ return applyAspectRatio(outBounds, containingAppBounds, containingBounds,
+ 0 /* desiredAspectRatio */, false /* fixedOrientationLetterboxed */);
+ }
+
/**
* Applies aspect ratio restrictions to outBounds. If no restrictions, then no change is
* made to outBounds.
@@ -7721,17 +7724,19 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
*/
// TODO(b/36505427): Consider moving this method and similar ones to ConfigurationContainer.
private boolean applyAspectRatio(Rect outBounds, Rect containingAppBounds,
- Rect containingBounds) {
+ Rect containingBounds, float desiredAspectRatio, boolean fixedOrientationLetterboxed) {
final float maxAspectRatio = info.getMaxAspectRatio();
final Task rootTask = getRootTask();
final float minAspectRatio = info.getMinAspectRatio();
if (task == null || rootTask == null
- || (inMultiWindowMode() && !shouldCreateCompatDisplayInsets())
- || (maxAspectRatio == 0 && minAspectRatio == 0)
+ || (inMultiWindowMode() && !shouldCreateCompatDisplayInsets()
+ && !fixedOrientationLetterboxed)
+ || (maxAspectRatio < 1 && minAspectRatio < 1 && desiredAspectRatio < 1)
|| isInVrUiMode(getConfiguration())) {
- // We don't enforce aspect ratio if the activity task is in multiwindow unless it
- // is in size-compat mode. We also don't set it if we are in VR mode.
+ // We don't enforce aspect ratio if the activity task is in multiwindow unless it is in
+ // size-compat mode or is letterboxed from fixed orientation. We also don't set it if we
+ // are in VR mode.
return false;
}
@@ -7739,20 +7744,30 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
final int containingAppHeight = containingAppBounds.height();
final float containingRatio = computeAspectRatio(containingAppBounds);
+ if (desiredAspectRatio < 1) {
+ desiredAspectRatio = containingRatio;
+ }
+
+ if (maxAspectRatio >= 1 && desiredAspectRatio > maxAspectRatio) {
+ desiredAspectRatio = maxAspectRatio;
+ } else if (minAspectRatio >= 1 && desiredAspectRatio < minAspectRatio) {
+ desiredAspectRatio = minAspectRatio;
+ }
+
int activityWidth = containingAppWidth;
int activityHeight = containingAppHeight;
- if (containingRatio > maxAspectRatio && maxAspectRatio != 0) {
+ if (containingRatio > desiredAspectRatio) {
if (containingAppWidth < containingAppHeight) {
// Width is the shorter side, so we use that to figure-out what the max. height
// should be given the aspect ratio.
- activityHeight = (int) ((activityWidth * maxAspectRatio) + 0.5f);
+ activityHeight = (int) ((activityWidth * desiredAspectRatio) + 0.5f);
} else {
// Height is the shorter side, so we use that to figure-out what the max. width
// should be given the aspect ratio.
- activityWidth = (int) ((activityHeight * maxAspectRatio) + 0.5f);
+ activityWidth = (int) ((activityHeight * desiredAspectRatio) + 0.5f);
}
- } else if (containingRatio < minAspectRatio) {
+ } else if (containingRatio < desiredAspectRatio) {
boolean adjustWidth;
switch (getRequestedConfigurationOrientation()) {
case ORIENTATION_LANDSCAPE:
@@ -7780,9 +7795,9 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
break;
}
if (adjustWidth) {
- activityWidth = (int) ((activityHeight / minAspectRatio) + 0.5f);
+ activityWidth = (int) ((activityHeight / desiredAspectRatio) + 0.5f);
} else {
- activityHeight = (int) ((activityWidth / minAspectRatio) + 0.5f);
+ activityHeight = (int) ((activityWidth / desiredAspectRatio) + 0.5f);
}
}
@@ -7806,6 +7821,13 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
}
outBounds.set(containingBounds.left, containingBounds.top, right, bottom);
+ // If the bounds are restricted by fixed aspect ratio, then out bounds should be put in the
+ // container app bounds. Otherwise the entire container bounds are available.
+ if (!outBounds.equals(containingBounds)) {
+ // The horizontal position should not cover insets.
+ outBounds.left = containingAppBounds.left;
+ }
+
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 565f99f80890..325f10f65af2 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -974,10 +974,7 @@ class Task extends WindowContainer<WindowContainer> {
}
void removeIfPossible(String reason) {
- final boolean isRootTask = isRootTask();
- if (!isRootTask) {
- mAtmService.getLockTaskController().clearLockedTask(this);
- }
+ mAtmService.getLockTaskController().clearLockedTask(this);
if (shouldDeferRemoval()) {
if (DEBUG_ROOT_TASK) Slog.i(TAG,
"removeTask:" + reason + " deferring removing taskId=" + mTaskId);
diff --git a/services/core/java/com/android/server/wm/WindowStateAnimator.java b/services/core/java/com/android/server/wm/WindowStateAnimator.java
index 9a6e4448966d..4471f6c91190 100644
--- a/services/core/java/com/android/server/wm/WindowStateAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowStateAnimator.java
@@ -683,8 +683,9 @@ class WindowStateAnimator {
}
// We don't apply animation for application main window here since this window type
- // should be controlled by AppWindowToken in general.
- if (mAttrType != TYPE_BASE_APPLICATION) {
+ // should be controlled by ActivityRecord in general. Wallpaper is also excluded because
+ // WallpaperController should handle it.
+ if (mAttrType != TYPE_BASE_APPLICATION && !mIsWallpaper) {
applyAnimationLocked(transit, true);
}
diff --git a/services/core/jni/com_android_server_vibrator_VibratorController.cpp b/services/core/jni/com_android_server_vibrator_VibratorController.cpp
index 698e3f75d0ed..9029fe7cca66 100644
--- a/services/core/jni/com_android_server_vibrator_VibratorController.cpp
+++ b/services/core/jni/com_android_server_vibrator_VibratorController.cpp
@@ -41,8 +41,18 @@ static JavaVM* sJvm = nullptr;
static jmethodID sMethodIdOnComplete;
static jclass sFrequencyMappingClass;
static jmethodID sFrequencyMappingCtor;
-static jclass sVibratorInfoClass;
-static jmethodID sVibratorInfoCtor;
+static struct {
+ jmethodID setCapabilities;
+ jmethodID setSupportedEffects;
+ jmethodID setSupportedBraking;
+ jmethodID setPwlePrimitiveDurationMax;
+ jmethodID setPwleSizeMax;
+ jmethodID setSupportedPrimitive;
+ jmethodID setPrimitiveDelayMax;
+ jmethodID setCompositionSizeMax;
+ jmethodID setQFactor;
+ jmethodID setFrequencyMapping;
+} sVibratorInfoBuilderClassInfo;
static struct {
jfieldID id;
jfieldID scale;
@@ -352,68 +362,88 @@ static void vibratorAlwaysOnDisable(JNIEnv* env, jclass /* clazz */, jlong ptr,
wrapper->halCall<void>(alwaysOnDisableFn, "alwaysOnDisable");
}
-static jobject vibratorGetInfo(JNIEnv* env, jclass /* clazz */, jlong ptr,
- jfloat suggestedSafeRange) {
+static jboolean vibratorGetInfo(JNIEnv* env, jclass /* clazz */, jlong ptr,
+ jfloat suggestedSafeRange, jobject vibratorInfoBuilder) {
VibratorControllerWrapper* wrapper = reinterpret_cast<VibratorControllerWrapper*>(ptr);
if (wrapper == nullptr) {
ALOGE("vibratorGetInfo failed because native wrapper was not initialized");
- return nullptr;
+ return JNI_FALSE;
}
vibrator::Info info = wrapper->getVibratorInfo();
- jlong capabilities =
- static_cast<jlong>(info.capabilities.valueOr(vibrator::Capabilities::NONE));
- jfloat minFrequency = static_cast<jfloat>(info.minFrequency.valueOr(NAN));
- jfloat resonantFrequency = static_cast<jfloat>(info.resonantFrequency.valueOr(NAN));
- jfloat frequencyResolution = static_cast<jfloat>(info.frequencyResolution.valueOr(NAN));
- jfloat qFactor = static_cast<jfloat>(info.qFactor.valueOr(NAN));
- jintArray supportedEffects = nullptr;
- jintArray supportedBraking = nullptr;
- jintArray supportedPrimitives = nullptr;
- jintArray primitiveDurations = nullptr;
- jfloatArray maxAmplitudes = nullptr;
-
+ if (info.capabilities.isOk()) {
+ env->CallObjectMethod(vibratorInfoBuilder, sVibratorInfoBuilderClassInfo.setCapabilities,
+ static_cast<jlong>(info.capabilities.value()));
+ }
if (info.supportedEffects.isOk()) {
std::vector<aidl::Effect> effects = info.supportedEffects.value();
- supportedEffects = env->NewIntArray(effects.size());
+ jintArray supportedEffects = env->NewIntArray(effects.size());
env->SetIntArrayRegion(supportedEffects, 0, effects.size(),
reinterpret_cast<jint*>(effects.data()));
+ env->CallObjectMethod(vibratorInfoBuilder,
+ sVibratorInfoBuilderClassInfo.setSupportedEffects, supportedEffects);
}
if (info.supportedBraking.isOk()) {
std::vector<aidl::Braking> braking = info.supportedBraking.value();
- supportedBraking = env->NewIntArray(braking.size());
+ jintArray supportedBraking = env->NewIntArray(braking.size());
env->SetIntArrayRegion(supportedBraking, 0, braking.size(),
reinterpret_cast<jint*>(braking.data()));
+ env->CallObjectMethod(vibratorInfoBuilder,
+ sVibratorInfoBuilderClassInfo.setSupportedBraking, supportedBraking);
}
- if (info.supportedPrimitives.isOk()) {
- std::vector<aidl::CompositePrimitive> primitives = info.supportedPrimitives.value();
- supportedPrimitives = env->NewIntArray(primitives.size());
- env->SetIntArrayRegion(supportedPrimitives, 0, primitives.size(),
- reinterpret_cast<jint*>(primitives.data()));
+ if (info.pwlePrimitiveDurationMax.isOk()) {
+ env->CallObjectMethod(vibratorInfoBuilder,
+ sVibratorInfoBuilderClassInfo.setPwlePrimitiveDurationMax,
+ static_cast<jint>(info.pwlePrimitiveDurationMax.value().count()));
+ }
+ if (info.pwleSizeMax.isOk()) {
+ // Use (pwleMaxSize - 1) to account for a possible extra braking segment added by the
+ // vibratorPerformPwleEffect method.
+ env->CallObjectMethod(vibratorInfoBuilder, sVibratorInfoBuilderClassInfo.setPwleSizeMax,
+ static_cast<jint>(info.pwleSizeMax.value() - 1));
}
- if (info.primitiveDurations.isOk()) {
- std::vector<int32_t> durations;
- for (auto duration : info.primitiveDurations.value()) {
- durations.push_back(duration.count());
+ if (info.supportedPrimitives.isOk()) {
+ auto durations = info.primitiveDurations.valueOr({});
+ for (auto& primitive : info.supportedPrimitives.value()) {
+ auto primitiveIdx = static_cast<size_t>(primitive);
+ auto duration = durations.size() > primitiveIdx ? durations[primitiveIdx].count() : 0;
+ env->CallObjectMethod(vibratorInfoBuilder,
+ sVibratorInfoBuilderClassInfo.setSupportedPrimitive,
+ static_cast<jint>(primitive), static_cast<jint>(duration));
}
- primitiveDurations = env->NewIntArray(durations.size());
- env->SetIntArrayRegion(primitiveDurations, 0, durations.size(),
- reinterpret_cast<jint*>(durations.data()));
}
+ if (info.primitiveDelayMax.isOk()) {
+ env->CallObjectMethod(vibratorInfoBuilder,
+ sVibratorInfoBuilderClassInfo.setPrimitiveDelayMax,
+ static_cast<jint>(info.primitiveDelayMax.value().count()));
+ }
+ if (info.compositionSizeMax.isOk()) {
+ env->CallObjectMethod(vibratorInfoBuilder,
+ sVibratorInfoBuilderClassInfo.setCompositionSizeMax,
+ static_cast<jint>(info.compositionSizeMax.value()));
+ }
+ if (info.qFactor.isOk()) {
+ env->CallObjectMethod(vibratorInfoBuilder, sVibratorInfoBuilderClassInfo.setQFactor,
+ static_cast<jfloat>(info.qFactor.value()));
+ }
+
+ jfloat minFrequency = static_cast<jfloat>(info.minFrequency.valueOr(NAN));
+ jfloat resonantFrequency = static_cast<jfloat>(info.resonantFrequency.valueOr(NAN));
+ jfloat frequencyResolution = static_cast<jfloat>(info.frequencyResolution.valueOr(NAN));
+ jfloatArray maxAmplitudes = nullptr;
if (info.maxAmplitudes.isOk()) {
std::vector<float> amplitudes = info.maxAmplitudes.value();
maxAmplitudes = env->NewFloatArray(amplitudes.size());
env->SetFloatArrayRegion(maxAmplitudes, 0, amplitudes.size(),
reinterpret_cast<jfloat*>(amplitudes.data()));
}
-
jobject frequencyMapping = env->NewObject(sFrequencyMappingClass, sFrequencyMappingCtor,
minFrequency, resonantFrequency, frequencyResolution,
suggestedSafeRange, maxAmplitudes);
+ env->CallObjectMethod(vibratorInfoBuilder, sVibratorInfoBuilderClassInfo.setFrequencyMapping,
+ frequencyMapping);
- return env->NewObject(sVibratorInfoClass, sVibratorInfoCtor, wrapper->getVibratorId(),
- capabilities, supportedEffects, supportedBraking, supportedPrimitives,
- primitiveDurations, qFactor, frequencyMapping);
+ return info.checkAndLogFailure("vibratorGetInfo") ? JNI_FALSE : JNI_TRUE;
}
static const JNINativeMethod method_table[] = {
@@ -433,7 +463,7 @@ static const JNINativeMethod method_table[] = {
{"setExternalControl", "(JZ)V", (void*)vibratorSetExternalControl},
{"alwaysOnEnable", "(JJJJ)V", (void*)vibratorAlwaysOnEnable},
{"alwaysOnDisable", "(JJ)V", (void*)vibratorAlwaysOnDisable},
- {"getInfo", "(JF)Landroid/os/VibratorInfo;", (void*)vibratorGetInfo},
+ {"getInfo", "(JFLandroid/os/VibratorInfo$Builder;)Z", (void*)vibratorGetInfo},
};
int register_android_server_vibrator_VibratorController(JavaVM* jvm, JNIEnv* env) {
@@ -459,11 +489,38 @@ int register_android_server_vibrator_VibratorController(JavaVM* jvm, JNIEnv* env
sFrequencyMappingClass = static_cast<jclass>(env->NewGlobalRef(frequencyMappingClass));
sFrequencyMappingCtor = GetMethodIDOrDie(env, sFrequencyMappingClass, "<init>", "(FFFF[F)V");
- jclass vibratorInfoClass = FindClassOrDie(env, "android/os/VibratorInfo");
- sVibratorInfoClass = (jclass)env->NewGlobalRef(vibratorInfoClass);
- sVibratorInfoCtor =
- GetMethodIDOrDie(env, sVibratorInfoClass, "<init>",
- "(IJ[I[I[I[IFLandroid/os/VibratorInfo$FrequencyMapping;)V");
+ jclass vibratorInfoBuilderClass = FindClassOrDie(env, "android/os/VibratorInfo$Builder");
+ sVibratorInfoBuilderClassInfo.setCapabilities =
+ GetMethodIDOrDie(env, vibratorInfoBuilderClass, "setCapabilities",
+ "(J)Landroid/os/VibratorInfo$Builder;");
+ sVibratorInfoBuilderClassInfo.setSupportedEffects =
+ GetMethodIDOrDie(env, vibratorInfoBuilderClass, "setSupportedEffects",
+ "([I)Landroid/os/VibratorInfo$Builder;");
+ sVibratorInfoBuilderClassInfo.setSupportedBraking =
+ GetMethodIDOrDie(env, vibratorInfoBuilderClass, "setSupportedBraking",
+ "([I)Landroid/os/VibratorInfo$Builder;");
+ sVibratorInfoBuilderClassInfo.setPwlePrimitiveDurationMax =
+ GetMethodIDOrDie(env, vibratorInfoBuilderClass, "setPwlePrimitiveDurationMax",
+ "(I)Landroid/os/VibratorInfo$Builder;");
+ sVibratorInfoBuilderClassInfo.setPwleSizeMax =
+ GetMethodIDOrDie(env, vibratorInfoBuilderClass, "setPwleSizeMax",
+ "(I)Landroid/os/VibratorInfo$Builder;");
+ sVibratorInfoBuilderClassInfo.setSupportedPrimitive =
+ GetMethodIDOrDie(env, vibratorInfoBuilderClass, "setSupportedPrimitive",
+ "(II)Landroid/os/VibratorInfo$Builder;");
+ sVibratorInfoBuilderClassInfo.setPrimitiveDelayMax =
+ GetMethodIDOrDie(env, vibratorInfoBuilderClass, "setPrimitiveDelayMax",
+ "(I)Landroid/os/VibratorInfo$Builder;");
+ sVibratorInfoBuilderClassInfo.setCompositionSizeMax =
+ GetMethodIDOrDie(env, vibratorInfoBuilderClass, "setCompositionSizeMax",
+ "(I)Landroid/os/VibratorInfo$Builder;");
+ sVibratorInfoBuilderClassInfo.setQFactor =
+ GetMethodIDOrDie(env, vibratorInfoBuilderClass, "setQFactor",
+ "(F)Landroid/os/VibratorInfo$Builder;");
+ sVibratorInfoBuilderClassInfo.setFrequencyMapping =
+ GetMethodIDOrDie(env, vibratorInfoBuilderClass, "setFrequencyMapping",
+ "(Landroid/os/VibratorInfo$FrequencyMapping;)"
+ "Landroid/os/VibratorInfo$Builder;");
return jniRegisterNativeMethods(env,
"com/android/server/vibrator/VibratorController$NativeWrapper",
diff --git a/services/tests/mockingservicestests/src/com/android/server/DeviceIdleControllerTest.java b/services/tests/mockingservicestests/src/com/android/server/DeviceIdleControllerTest.java
index e99113d1296f..acf50b4569c6 100644
--- a/services/tests/mockingservicestests/src/com/android/server/DeviceIdleControllerTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/DeviceIdleControllerTest.java
@@ -323,6 +323,8 @@ public class DeviceIdleControllerTest {
when(mPowerManager.newWakeLock(anyInt(), anyString())).thenReturn(mWakeLock);
doNothing().when(mWakeLock).acquire();
doNothing().when(mAlarmManager).set(anyInt(), anyLong(), anyString(), any(), any());
+ doNothing().when(mAlarmManager)
+ .setWindow(anyInt(), anyLong(), anyLong(), anyString(), any(), any());
doReturn(mock(Sensor.class)).when(mSensorManager)
.getDefaultSensor(eq(Sensor.TYPE_SIGNIFICANT_MOTION), eq(true));
doReturn(true).when(mSensorManager).registerListener(any(), any(), anyInt());
@@ -1043,24 +1045,28 @@ public class DeviceIdleControllerTest {
mDeviceIdleController.stepLightIdleStateLocked("testing");
verifyLightStateConditions(LIGHT_STATE_IDLE);
inOrder.verify(mDeviceIdleController).scheduleLightAlarmLocked(
- longThat(l -> l == mConstants.LIGHT_IDLE_TIMEOUT));
+ longThat(l -> l == mConstants.LIGHT_IDLE_TIMEOUT),
+ longThat(l -> l == mConstants.LIGHT_IDLE_TIMEOUT_INITIAL_FLEX));
// Should just alternate between IDLE and IDLE_MAINTENANCE now.
mDeviceIdleController.stepLightIdleStateLocked("testing");
verifyLightStateConditions(LIGHT_STATE_IDLE_MAINTENANCE);
inOrder.verify(mDeviceIdleController).scheduleLightAlarmLocked(
- longThat(l -> l >= mConstants.LIGHT_IDLE_MAINTENANCE_MIN_BUDGET));
+ longThat(l -> l >= mConstants.LIGHT_IDLE_MAINTENANCE_MIN_BUDGET),
+ longThat(l -> l == mConstants.FLEX_TIME_SHORT));
mDeviceIdleController.stepLightIdleStateLocked("testing");
verifyLightStateConditions(LIGHT_STATE_IDLE);
inOrder.verify(mDeviceIdleController).scheduleLightAlarmLocked(
- longThat(l -> l > mConstants.LIGHT_IDLE_TIMEOUT));
+ longThat(l -> l > mConstants.LIGHT_IDLE_TIMEOUT),
+ longThat(l -> l > mConstants.LIGHT_IDLE_TIMEOUT_INITIAL_FLEX));
mDeviceIdleController.stepLightIdleStateLocked("testing");
verifyLightStateConditions(LIGHT_STATE_IDLE_MAINTENANCE);
inOrder.verify(mDeviceIdleController).scheduleLightAlarmLocked(
- longThat(l -> l >= mConstants.LIGHT_IDLE_MAINTENANCE_MIN_BUDGET));
+ longThat(l -> l >= mConstants.LIGHT_IDLE_MAINTENANCE_MIN_BUDGET),
+ longThat(l -> l == mConstants.FLEX_TIME_SHORT));
// Test that motion doesn't reset the idle timeout.
mDeviceIdleController.handleMotionDetectedLocked(50, "test");
@@ -1068,7 +1074,8 @@ public class DeviceIdleControllerTest {
mDeviceIdleController.stepLightIdleStateLocked("testing");
verifyLightStateConditions(LIGHT_STATE_IDLE);
inOrder.verify(mDeviceIdleController).scheduleLightAlarmLocked(
- longThat(l -> l > mConstants.LIGHT_IDLE_TIMEOUT));
+ longThat(l -> l > mConstants.LIGHT_IDLE_TIMEOUT),
+ longThat(l -> l > mConstants.LIGHT_IDLE_TIMEOUT_INITIAL_FLEX));
}
///////////////// EXIT conditions ///////////////////
@@ -1824,9 +1831,9 @@ public class DeviceIdleControllerTest {
.forClass(AlarmManager.OnAlarmListener.class);
final ArgumentCaptor<AlarmManager.OnAlarmListener> motionRegistrationAlarmListener =
ArgumentCaptor.forClass(AlarmManager.OnAlarmListener.class);
- doNothing().when(mAlarmManager).set(anyInt(), anyLong(), eq("DeviceIdleController.motion"),
- motionAlarmListener.capture(), any());
- doNothing().when(mAlarmManager).set(anyInt(), anyLong(),
+ doNothing().when(mAlarmManager).setWindow(anyInt(), anyLong(), anyLong(),
+ eq("DeviceIdleController.motion"), motionAlarmListener.capture(), any());
+ doNothing().when(mAlarmManager).setWindow(anyInt(), anyLong(), anyLong(),
eq("DeviceIdleController.motion_registration"),
motionRegistrationAlarmListener.capture(), any());
@@ -1900,9 +1907,9 @@ public class DeviceIdleControllerTest {
mInjector.nowElapsed += mConstants.QUICK_DOZE_DELAY_TIMEOUT;
final ArgumentCaptor<AlarmManager.OnAlarmListener> alarmListener = ArgumentCaptor
.forClass(AlarmManager.OnAlarmListener.class);
- doNothing().when(mAlarmManager)
- .set(anyInt(), anyLong(), eq("DeviceIdleController.motion"), any(), any());
- doNothing().when(mAlarmManager).set(anyInt(), anyLong(),
+ doNothing().when(mAlarmManager).setWindow(
+ anyInt(), anyLong(), anyLong(), eq("DeviceIdleController.motion"), any(), any());
+ doNothing().when(mAlarmManager).setWindow(anyInt(), anyLong(), anyLong(),
eq("DeviceIdleController.motion_registration"),
alarmListener.capture(), any());
ArgumentCaptor<TriggerEventListener> listenerCaptor =
@@ -1944,9 +1951,9 @@ public class DeviceIdleControllerTest {
mInjector.nowElapsed += mConstants.QUICK_DOZE_DELAY_TIMEOUT;
final ArgumentCaptor<AlarmManager.OnAlarmListener> alarmListener = ArgumentCaptor
.forClass(AlarmManager.OnAlarmListener.class);
- doNothing().when(mAlarmManager)
- .set(anyInt(), anyLong(), eq("DeviceIdleController.motion"), any(), any());
- doNothing().when(mAlarmManager).set(anyInt(), anyLong(),
+ doNothing().when(mAlarmManager).setWindow(
+ anyInt(), anyLong(), anyLong(), eq("DeviceIdleController.motion"), any(), any());
+ doNothing().when(mAlarmManager).setWindow(anyInt(), anyLong(), anyLong(),
eq("DeviceIdleController.motion_registration"),
alarmListener.capture(), any());
ArgumentCaptor<SensorEventListener> listenerCaptor =
diff --git a/services/tests/servicestests/src/com/android/server/appsearch/AppSearchImplPlatformTest.java b/services/tests/servicestests/src/com/android/server/appsearch/AppSearchImplPlatformTest.java
index aadaba4d2fce..f4f907355aee 100644
--- a/services/tests/servicestests/src/com/android/server/appsearch/AppSearchImplPlatformTest.java
+++ b/services/tests/servicestests/src/com/android/server/appsearch/AppSearchImplPlatformTest.java
@@ -127,8 +127,8 @@ public class AppSearchImplPlatformTest {
"database",
Collections.singletonList(new AppSearchSchema.Builder("schema1").build()),
mVisibilityStore,
- /*schemasNotPlatformSurfaceable=*/ Collections.singletonList("schema1"),
- /*schemasPackageAccessible=*/ ImmutableMap.of(
+ /*schemasNotDisplayedBySystem=*/ Collections.singletonList("schema1"),
+ /*schemasVisibleToPackages=*/ ImmutableMap.of(
"schema1",
ImmutableList.of(new PackageIdentifier(packageNameFoo, sha256CertFoo))),
/*forceOverride=*/ false,
@@ -159,8 +159,8 @@ public class AppSearchImplPlatformTest {
new AppSearchSchema.Builder("schema1").build(),
new AppSearchSchema.Builder("schema2").build()),
mVisibilityStore,
- /*schemasNotPlatformSurfaceable=*/ Collections.singletonList("schema1"),
- /*schemasPackageAccessible=*/ ImmutableMap.of(
+ /*schemasNotDisplayedBySystem=*/ Collections.singletonList("schema1"),
+ /*schemasVisibleToPackages=*/ ImmutableMap.of(
"schema1",
ImmutableList.of(new PackageIdentifier(packageNameFoo, sha256CertFoo))),
/*forceOverride=*/ false,
@@ -233,8 +233,8 @@ public class AppSearchImplPlatformTest {
"database",
Collections.singletonList(new AppSearchSchema.Builder("schema1").build()),
mVisibilityStore,
- /*schemasNotPlatformSurfaceable=*/ Collections.singletonList("schema1"),
- /*schemasPackageAccessible=*/ ImmutableMap.of(
+ /*schemasNotDisplayedBySystem=*/ Collections.singletonList("schema1"),
+ /*schemasVisibleToPackages=*/ ImmutableMap.of(
"schema1",
ImmutableList.of(new PackageIdentifier(packageNameFoo, sha256CertFoo))),
/*forceOverride=*/ false,
@@ -263,8 +263,8 @@ public class AppSearchImplPlatformTest {
"database",
/*schemas=*/ Collections.emptyList(),
mVisibilityStore,
- /*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
- /*schemasPackageAccessible=*/ Collections.emptyMap(),
+ /*schemasNotDisplayedBySystem=*/ Collections.emptyList(),
+ /*schemasVisibleToPackages=*/ Collections.emptyMap(),
/*forceOverride=*/ true,
/*schemaVersion=*/ 0);
@@ -292,8 +292,8 @@ public class AppSearchImplPlatformTest {
"database",
Collections.singletonList(new AppSearchSchema.Builder("schema1").build()),
mVisibilityStore,
- /*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
- /*schemasPackageAccessible=*/ Collections.emptyMap(),
+ /*schemasNotDisplayedBySystem=*/ Collections.emptyList(),
+ /*schemasVisibleToPackages=*/ Collections.emptyMap(),
/*forceOverride=*/ false,
/*schemaVersion=*/ 0);
@@ -327,8 +327,8 @@ public class AppSearchImplPlatformTest {
"database",
Collections.singletonList(new AppSearchSchema.Builder("Schema").build()),
mVisibilityStore,
- /*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
- /*schemasPackageAccessible=*/ Collections.emptyMap(),
+ /*schemasNotDisplayedBySystem=*/ Collections.emptyList(),
+ /*schemasVisibleToPackages=*/ Collections.emptyMap(),
/*forceOverride=*/ false,
/*schemaVersion=*/ 0);
@@ -355,8 +355,8 @@ public class AppSearchImplPlatformTest {
"database",
Collections.singletonList(new AppSearchSchema.Builder("Schema").build()),
mVisibilityStore,
- /*schemasNotPlatformSurfaceable=*/ Collections.singletonList("Schema"),
- /*schemasPackageAccessible=*/ Collections.emptyMap(),
+ /*schemasNotDisplayedBySystem=*/ Collections.singletonList("Schema"),
+ /*schemasVisibleToPackages=*/ Collections.emptyMap(),
/*forceOverride=*/ false,
/*schemaVersion=*/ 0);
@@ -370,7 +370,7 @@ public class AppSearchImplPlatformTest {
}
@Test
- public void testSetSchema_defaultNotPackageAccessible() throws Exception {
+ public void testSetSchema_defaultNotVisibleToPackages() throws Exception {
String packageName = "com.package";
// Make sure package doesn't global query privileges
@@ -384,8 +384,8 @@ public class AppSearchImplPlatformTest {
"database",
Collections.singletonList(new AppSearchSchema.Builder("Schema").build()),
mVisibilityStore,
- /*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
- /*schemasPackageAccessible=*/ Collections.emptyMap(),
+ /*schemasNotDisplayedBySystem=*/ Collections.emptyList(),
+ /*schemasVisibleToPackages=*/ Collections.emptyMap(),
/*forceOverride=*/ false,
/*schemaVersion=*/ 0);
assertThat(mVisibilityStore
@@ -399,7 +399,7 @@ public class AppSearchImplPlatformTest {
}
@Test
- public void testSetSchema_packageAccessible() throws Exception {
+ public void testSetSchema_visibleToPackages() throws Exception {
// Values for a "foo" client
String packageNameFoo = "packageFoo";
byte[] sha256CertFoo = new byte[] {10};
@@ -423,8 +423,8 @@ public class AppSearchImplPlatformTest {
"database",
Collections.singletonList(new AppSearchSchema.Builder("Schema").build()),
mVisibilityStore,
- /*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
- /*schemasPackageAccessible=*/ ImmutableMap.of(
+ /*schemasNotDisplayedBySystem=*/ Collections.emptyList(),
+ /*schemasVisibleToPackages=*/ ImmutableMap.of(
"Schema",
ImmutableList.of(new PackageIdentifier(packageNameFoo, sha256CertFoo))),
/*forceOverride=*/ false,
diff --git a/services/tests/servicestests/src/com/android/server/appsearch/VisibilityStoreTest.java b/services/tests/servicestests/src/com/android/server/appsearch/VisibilityStoreTest.java
index b67ebe423eab..183cb8603c33 100644
--- a/services/tests/servicestests/src/com/android/server/appsearch/VisibilityStoreTest.java
+++ b/services/tests/servicestests/src/com/android/server/appsearch/VisibilityStoreTest.java
@@ -132,7 +132,7 @@ public class VisibilityStoreTest {
}
@Test
- public void testSetVisibility_platformSurfaceable() throws Exception {
+ public void testSetVisibility_displayedBySystem() throws Exception {
// Make sure we have global query privileges
PackageManager mockPackageManager = getMockPackageManager(mContext.getUser());
when(mockPackageManager
@@ -143,9 +143,9 @@ public class VisibilityStoreTest {
mVisibilityStore.setVisibility(
"package",
"database",
- /*schemasNotPlatformSurfaceable=*/ ImmutableSet.of(
+ /*schemasNotDisplayedBySystem=*/ ImmutableSet.of(
"prefix/schema1", "prefix/schema2"),
- /*schemasPackageAccessible=*/ Collections.emptyMap());
+ /*schemasVisibleToPackages=*/ Collections.emptyMap());
assertThat(
mVisibilityStore.isSchemaSearchableByCaller(
"package",
@@ -168,9 +168,9 @@ public class VisibilityStoreTest {
mVisibilityStore.setVisibility(
"package",
"database",
- /*schemasNotPlatformSurfaceable=*/ ImmutableSet.of(
+ /*schemasNotDisplayedBySystem=*/ ImmutableSet.of(
"prefix/schema1", "prefix/schema3"),
- /*schemasPackageAccessible=*/ Collections.emptyMap());
+ /*schemasVisibleToPackages=*/ Collections.emptyMap());
assertThat(
mVisibilityStore.isSchemaSearchableByCaller(
"package",
@@ -200,8 +200,8 @@ public class VisibilityStoreTest {
mVisibilityStore.setVisibility(
"package",
"database",
- /*schemasNotPlatformSurfaceable=*/ Collections.emptySet(),
- /*schemasPackageAccessible=*/ Collections.emptyMap());
+ /*schemasNotDisplayedBySystem=*/ Collections.emptySet(),
+ /*schemasVisibleToPackages=*/ Collections.emptyMap());
assertThat(
mVisibilityStore.isSchemaSearchableByCaller(
"package",
@@ -229,7 +229,7 @@ public class VisibilityStoreTest {
}
@Test
- public void testSetVisibility_packageAccessible() throws Exception {
+ public void testSetVisibility_visibleToPackages() throws Exception {
// Values for a "foo" client
String packageNameFoo = "packageFoo";
byte[] sha256CertFoo = new byte[] {10};
@@ -272,8 +272,8 @@ public class VisibilityStoreTest {
mVisibilityStore.setVisibility(
"package",
"database",
- /*schemasNotPlatformSurfaceable=*/ Collections.emptySet(),
- /*schemasPackageAccessible=*/ ImmutableMap.of(
+ /*schemasNotDisplayedBySystem=*/ Collections.emptySet(),
+ /*schemasVisibleToPackages=*/ ImmutableMap.of(
"prefix/schemaFoo",
ImmutableList.of(new PackageIdentifier(packageNameFoo, sha256CertFoo)),
"prefix/schemaBar",
@@ -339,8 +339,8 @@ public class VisibilityStoreTest {
mVisibilityStore.setVisibility(
"package",
"database",
- /*schemasNotPlatformSurfaceable=*/ Collections.emptySet(),
- /*schemasPackageAccessible=*/ ImmutableMap.of(
+ /*schemasNotDisplayedBySystem=*/ Collections.emptySet(),
+ /*schemasVisibleToPackages=*/ ImmutableMap.of(
"prefix/schemaFoo",
ImmutableList.of(new PackageIdentifier(packageNameFoo, sha256CertFoo))));
@@ -392,8 +392,8 @@ public class VisibilityStoreTest {
mVisibilityStore.setVisibility(
"package",
"database",
- /*schemasNotPlatformSurfaceable=*/ Collections.emptySet(),
- /*schemasPackageAccessible=*/ ImmutableMap.of(
+ /*schemasNotDisplayedBySystem=*/ Collections.emptySet(),
+ /*schemasVisibleToPackages=*/ ImmutableMap.of(
"prefix/schemaFoo",
ImmutableList.of(new PackageIdentifier(packageNameFoo, sha256CertFoo))));
@@ -425,8 +425,8 @@ public class VisibilityStoreTest {
mVisibilityStore.setVisibility(
/*packageName=*/ "",
/*databaseName=*/ "",
- /*schemasNotPlatformSurfaceable=*/ Collections.emptySet(),
- /*schemasPackageAccessible=*/ ImmutableMap.of(
+ /*schemasNotDisplayedBySystem=*/ Collections.emptySet(),
+ /*schemasVisibleToPackages=*/ ImmutableMap.of(
"schema",
ImmutableList.of(new PackageIdentifier(packageNameFoo, sha256CertFoo))));
diff --git a/services/tests/servicestests/src/com/android/server/appsearch/external/localstorage/AppSearchImplTest.java b/services/tests/servicestests/src/com/android/server/appsearch/external/localstorage/AppSearchImplTest.java
index f032402f47a0..02bb168dbde6 100644
--- a/services/tests/servicestests/src/com/android/server/appsearch/external/localstorage/AppSearchImplTest.java
+++ b/services/tests/servicestests/src/com/android/server/appsearch/external/localstorage/AppSearchImplTest.java
@@ -22,7 +22,7 @@ import static com.android.server.appsearch.external.localstorage.util.PrefixUtil
import static com.google.common.truth.Truth.assertThat;
-import static org.testng.Assert.expectThrows;
+import static org.junit.Assert.assertThrows;
import android.app.appsearch.AppSearchResult;
import android.app.appsearch.AppSearchSchema;
@@ -34,6 +34,7 @@ import android.app.appsearch.SetSchemaResponse;
import android.app.appsearch.StorageInfo;
import android.app.appsearch.exceptions.AppSearchException;
import android.content.Context;
+import android.os.Process;
import android.util.ArrayMap;
import android.util.ArraySet;
@@ -55,7 +56,6 @@ import com.android.server.appsearch.proto.SearchSpecProto;
import com.android.server.appsearch.proto.StatusProto;
import com.android.server.appsearch.proto.StringIndexingConfig;
import com.android.server.appsearch.proto.TermMatchType;
-import com.android.server.appsearch.visibilitystore.VisibilityStore;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
@@ -391,7 +391,7 @@ public class AppSearchImplTest {
DocumentProto.Builder actualDocument = documentProto.toBuilder();
AppSearchException e =
- expectThrows(
+ assertThrows(
AppSearchException.class, () -> removePrefixesFromDocument(actualDocument));
assertThat(e).hasMessageThat().contains("Found unexpected multiple prefix names");
}
@@ -416,7 +416,7 @@ public class AppSearchImplTest {
DocumentProto.Builder actualDocument = documentProto.toBuilder();
AppSearchException e =
- expectThrows(
+ assertThrows(
AppSearchException.class, () -> removePrefixesFromDocument(actualDocument));
assertThat(e).hasMessageThat().contains("Found unexpected multiple prefix names");
}
@@ -431,8 +431,8 @@ public class AppSearchImplTest {
"database",
schemas,
/*visibilityStore=*/ null,
- /*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
- /*schemasPackageAccessible=*/ Collections.emptyMap(),
+ /*schemasNotDisplayedBySystem=*/ Collections.emptyList(),
+ /*schemasVisibleToPackages=*/ Collections.emptyMap(),
/*forceOverride=*/ false,
/*version=*/ 0);
@@ -480,8 +480,8 @@ public class AppSearchImplTest {
"database1",
schemas,
/*visibilityStore=*/ null,
- /*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
- /*schemasPackageAccessible=*/ Collections.emptyMap(),
+ /*schemasNotDisplayedBySystem=*/ Collections.emptyList(),
+ /*schemasVisibleToPackages=*/ Collections.emptyMap(),
/*forceOverride=*/ false,
/*version=*/ 0);
@@ -499,7 +499,7 @@ public class AppSearchImplTest {
new SearchSpec.Builder().addFilterSchemas("Type1").build(),
context.getPackageName(),
/*visibilityStore=*/ null,
- VisibilityStore.NO_OP_UID,
+ Process.INVALID_UID,
/*callerHasSystemAccess=*/ false,
/*logger=*/ null);
assertThat(results.getResults()).hasSize(1);
@@ -513,7 +513,7 @@ public class AppSearchImplTest {
.setSchema(context.getPackageName() + "$database1/Type1")
.build();
AppSearchException e =
- expectThrows(
+ assertThrows(
AppSearchException.class,
() -> PrefixUtil.getPrefix(invalidDoc.getNamespace()));
assertThat(e)
@@ -538,10 +538,8 @@ public class AppSearchImplTest {
assertThat(initStats.hasDeSync()).isFalse();
assertThat(initStats.getDocumentStoreRecoveryCause())
.isEqualTo(InitializeStats.RECOVERY_CAUSE_NONE);
- // TODO(b/187879464): There should not be a recovery here, but icing lib reports one if the
- // doc had no tokens. Once the mentioned bug is fixed, uncomment this.
- // assertThat(initStats.getIndexRestorationCause())
- // .isEqualTo(InitializeStats.RECOVERY_CAUSE_NONE);
+ assertThat(initStats.getIndexRestorationCause())
+ .isEqualTo(InitializeStats.RECOVERY_CAUSE_NONE);
assertThat(initStats.getSchemaStoreRecoveryCause())
.isEqualTo(InitializeStats.RECOVERY_CAUSE_NONE);
assertThat(initStats.getDocumentStoreDataStatus())
@@ -558,7 +556,7 @@ public class AppSearchImplTest {
new SearchSpec.Builder().addFilterSchemas("Type1").build(),
context.getPackageName(),
/*visibilityStore=*/ null,
- VisibilityStore.NO_OP_UID,
+ Process.INVALID_UID,
/*callerHasSystemAccess=*/ false,
/*logger=*/ null);
assertThat(results.getResults()).isEmpty();
@@ -569,8 +567,8 @@ public class AppSearchImplTest {
"database1",
Collections.singletonList(new AppSearchSchema.Builder("Type1").build()),
/*visibilityStore=*/ null,
- /*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
- /*schemasPackageAccessible=*/ Collections.emptyMap(),
+ /*schemasNotDisplayedBySystem=*/ Collections.emptyList(),
+ /*schemasVisibleToPackages=*/ Collections.emptyMap(),
/*forceOverride=*/ false,
/*version=*/ 0);
@@ -585,7 +583,7 @@ public class AppSearchImplTest {
new SearchSpec.Builder().addFilterSchemas("Type1").build(),
context.getPackageName(),
/*visibilityStore=*/ null,
- VisibilityStore.NO_OP_UID,
+ Process.INVALID_UID,
/*callerHasSystemAccess=*/ false,
/*logger=*/ null);
assertThat(results.getResults()).hasSize(1);
@@ -604,8 +602,8 @@ public class AppSearchImplTest {
"database",
schemas,
/*visibilityStore=*/ null,
- /*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
- /*schemasPackageAccessible=*/ Collections.emptyMap(),
+ /*schemasNotDisplayedBySystem=*/ Collections.emptyList(),
+ /*schemasVisibleToPackages=*/ Collections.emptyMap(),
/*forceOverride=*/ false,
/*version=*/ 0);
@@ -638,8 +636,8 @@ public class AppSearchImplTest {
"database1",
schemas,
/*visibilityStore=*/ null,
- /*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
- /*schemasPackageAccessible=*/ Collections.emptyMap(),
+ /*schemasNotDisplayedBySystem=*/ Collections.emptyList(),
+ /*schemasVisibleToPackages=*/ Collections.emptyMap(),
/*forceOverride=*/ false,
/*version=*/ 0);
mAppSearchImpl.setSchema(
@@ -647,8 +645,8 @@ public class AppSearchImplTest {
"database2",
schemas,
/*visibilityStore=*/ null,
- /*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
- /*schemasPackageAccessible=*/ Collections.emptyMap(),
+ /*schemasNotDisplayedBySystem=*/ Collections.emptyList(),
+ /*schemasVisibleToPackages=*/ Collections.emptyMap(),
/*forceOverride=*/ false,
/*version=*/ 0);
@@ -692,8 +690,8 @@ public class AppSearchImplTest {
"database",
schemas,
/*visibilityStore=*/ null,
- /*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
- /*schemasPackageAccessible=*/ Collections.emptyMap(),
+ /*schemasNotDisplayedBySystem=*/ Collections.emptyList(),
+ /*schemasVisibleToPackages=*/ Collections.emptyMap(),
/*forceOverride=*/ false,
/*version=*/ 0);
@@ -734,8 +732,8 @@ public class AppSearchImplTest {
"database1",
schema1,
/*visibilityStore=*/ null,
- /*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
- /*schemasPackageAccessible=*/ Collections.emptyMap(),
+ /*schemasNotDisplayedBySystem=*/ Collections.emptyList(),
+ /*schemasVisibleToPackages=*/ Collections.emptyMap(),
/*forceOverride=*/ false,
/*version=*/ 0);
@@ -747,8 +745,8 @@ public class AppSearchImplTest {
"database2",
schema2,
/*visibilityStore=*/ null,
- /*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
- /*schemasPackageAccessible=*/ Collections.emptyMap(),
+ /*schemasNotDisplayedBySystem=*/ Collections.emptyList(),
+ /*schemasVisibleToPackages=*/ Collections.emptyMap(),
/*forceOverride=*/ false,
/*version=*/ 0);
@@ -790,8 +788,8 @@ public class AppSearchImplTest {
"database1",
schema1,
/*visibilityStore=*/ null,
- /*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
- /*schemasPackageAccessible=*/ Collections.emptyMap(),
+ /*schemasNotDisplayedBySystem=*/ Collections.emptyList(),
+ /*schemasVisibleToPackages=*/ Collections.emptyMap(),
/*forceOverride=*/ false,
/*version=*/ 0);
@@ -803,8 +801,8 @@ public class AppSearchImplTest {
"database2",
schema2,
/*visibilityStore=*/ null,
- /*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
- /*schemasPackageAccessible=*/ Collections.emptyMap(),
+ /*schemasNotDisplayedBySystem=*/ Collections.emptyList(),
+ /*schemasVisibleToPackages=*/ Collections.emptyMap(),
/*forceOverride=*/ false,
/*version=*/ 0);
@@ -851,7 +849,7 @@ public class AppSearchImplTest {
searchSpec,
/*callerPackageName=*/ "",
/*visibilityStore=*/ null,
- VisibilityStore.NO_OP_UID,
+ Process.INVALID_UID,
/*callerHasSystemAccess=*/ false,
/*logger=*/ null);
assertThat(searchResultPage.getResults()).isEmpty();
@@ -893,8 +891,8 @@ public class AppSearchImplTest {
"database1",
schemas,
/*visibilityStore=*/ null,
- /*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
- /*schemasPackageAccessible=*/ Collections.emptyMap(),
+ /*schemasNotDisplayedBySystem=*/ Collections.emptyList(),
+ /*schemasVisibleToPackages=*/ Collections.emptyMap(),
/*forceOverride=*/ false,
/*version=*/ 0);
@@ -938,8 +936,8 @@ public class AppSearchImplTest {
"database1",
oldSchemas,
/*visibilityStore=*/ null,
- /*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
- /*schemasPackageAccessible=*/ Collections.emptyMap(),
+ /*schemasNotDisplayedBySystem=*/ Collections.emptyList(),
+ /*schemasVisibleToPackages=*/ Collections.emptyMap(),
/*forceOverride=*/ false,
/*version=*/ 0);
@@ -954,8 +952,8 @@ public class AppSearchImplTest {
"database1",
newSchemas,
/*visibilityStore=*/ null,
- /*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
- /*schemasPackageAccessible=*/ Collections.emptyMap(),
+ /*schemasNotDisplayedBySystem=*/ Collections.emptyList(),
+ /*schemasVisibleToPackages=*/ Collections.emptyMap(),
/*forceOverride=*/ true,
/*version=*/ 0);
assertThat(setSchemaResponse.getDeletedTypes()).containsExactly("Text");
@@ -977,8 +975,8 @@ public class AppSearchImplTest {
"database1",
schemas,
/*visibilityStore=*/ null,
- /*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
- /*schemasPackageAccessible=*/ Collections.emptyMap(),
+ /*schemasNotDisplayedBySystem=*/ Collections.emptyList(),
+ /*schemasVisibleToPackages=*/ Collections.emptyMap(),
/*forceOverride=*/ false,
/*version=*/ 0);
@@ -1010,8 +1008,8 @@ public class AppSearchImplTest {
"database1",
finalSchemas,
/*visibilityStore=*/ null,
- /*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
- /*schemasPackageAccessible=*/ Collections.emptyMap(),
+ /*schemasNotDisplayedBySystem=*/ Collections.emptyList(),
+ /*schemasVisibleToPackages=*/ Collections.emptyMap(),
/*forceOverride=*/ false,
/*version=*/ 0);
@@ -1024,8 +1022,8 @@ public class AppSearchImplTest {
"database1",
finalSchemas,
/*visibilityStore=*/ null,
- /*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
- /*schemasPackageAccessible=*/ Collections.emptyMap(),
+ /*schemasNotDisplayedBySystem=*/ Collections.emptyList(),
+ /*schemasVisibleToPackages=*/ Collections.emptyMap(),
/*forceOverride=*/ true,
/*version=*/ 0);
@@ -1062,8 +1060,8 @@ public class AppSearchImplTest {
"database1",
schemas,
/*visibilityStore=*/ null,
- /*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
- /*schemasPackageAccessible=*/ Collections.emptyMap(),
+ /*schemasNotDisplayedBySystem=*/ Collections.emptyList(),
+ /*schemasVisibleToPackages=*/ Collections.emptyMap(),
/*forceOverride=*/ false,
/*version=*/ 0);
mAppSearchImpl.setSchema(
@@ -1071,8 +1069,8 @@ public class AppSearchImplTest {
"database2",
schemas,
/*visibilityStore=*/ null,
- /*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
- /*schemasPackageAccessible=*/ Collections.emptyMap(),
+ /*schemasNotDisplayedBySystem=*/ Collections.emptyList(),
+ /*schemasVisibleToPackages=*/ Collections.emptyMap(),
/*forceOverride=*/ false,
/*version=*/ 0);
@@ -1111,8 +1109,8 @@ public class AppSearchImplTest {
"database1",
schemas,
/*visibilityStore=*/ null,
- /*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
- /*schemasPackageAccessible=*/ Collections.emptyMap(),
+ /*schemasNotDisplayedBySystem=*/ Collections.emptyList(),
+ /*schemasVisibleToPackages=*/ Collections.emptyMap(),
/*forceOverride=*/ true,
/*version=*/ 0);
@@ -1156,8 +1154,8 @@ public class AppSearchImplTest {
"database",
schema,
/*visibilityStore=*/ null,
- /*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
- /*schemasPackageAccessible=*/ Collections.emptyMap(),
+ /*schemasNotDisplayedBySystem=*/ Collections.emptyList(),
+ /*schemasVisibleToPackages=*/ Collections.emptyMap(),
/*forceOverride=*/ false,
/*version=*/ 0);
@@ -1218,8 +1216,8 @@ public class AppSearchImplTest {
"database",
schema,
/*visibilityStore=*/ null,
- /*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
- /*schemasPackageAccessible=*/ Collections.emptyMap(),
+ /*schemasNotDisplayedBySystem=*/ Collections.emptyList(),
+ /*schemasVisibleToPackages=*/ Collections.emptyMap(),
/*forceOverride=*/ false,
/*version=*/ 0);
mAppSearchImpl.setSchema(
@@ -1227,8 +1225,8 @@ public class AppSearchImplTest {
"database",
schema,
/*visibilityStore=*/ null,
- /*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
- /*schemasPackageAccessible=*/ Collections.emptyMap(),
+ /*schemasNotDisplayedBySystem=*/ Collections.emptyList(),
+ /*schemasVisibleToPackages=*/ Collections.emptyMap(),
/*forceOverride=*/ false,
/*version=*/ 0);
@@ -1273,8 +1271,8 @@ public class AppSearchImplTest {
"database1",
Collections.singletonList(new AppSearchSchema.Builder("schema").build()),
/*visibilityStore=*/ null,
- /*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
- /*schemasPackageAccessible=*/ Collections.emptyMap(),
+ /*schemasNotDisplayedBySystem=*/ Collections.emptyList(),
+ /*schemasVisibleToPackages=*/ Collections.emptyMap(),
/*forceOverride=*/ false,
/*version=*/ 0);
assertThat(mAppSearchImpl.getPackageToDatabases())
@@ -1287,8 +1285,8 @@ public class AppSearchImplTest {
"database2",
Collections.singletonList(new AppSearchSchema.Builder("schema").build()),
/*visibilityStore=*/ null,
- /*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
- /*schemasPackageAccessible=*/ Collections.emptyMap(),
+ /*schemasNotDisplayedBySystem=*/ Collections.emptyList(),
+ /*schemasVisibleToPackages=*/ Collections.emptyMap(),
/*forceOverride=*/ false,
/*version=*/ 0);
assertThat(mAppSearchImpl.getPackageToDatabases())
@@ -1301,8 +1299,8 @@ public class AppSearchImplTest {
"database1",
Collections.singletonList(new AppSearchSchema.Builder("schema").build()),
/*visibilityStore=*/ null,
- /*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
- /*schemasPackageAccessible=*/ Collections.emptyMap(),
+ /*schemasNotDisplayedBySystem=*/ Collections.emptyList(),
+ /*schemasVisibleToPackages=*/ Collections.emptyMap(),
/*forceOverride=*/ false,
/*version=*/ 0);
assertThat(mAppSearchImpl.getPackageToDatabases())
@@ -1360,8 +1358,8 @@ public class AppSearchImplTest {
"database",
schemas,
/*visibilityStore=*/ null,
- /*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
- /*schemasPackageAccessible=*/ Collections.emptyMap(),
+ /*schemasNotDisplayedBySystem=*/ Collections.emptyList(),
+ /*schemasVisibleToPackages=*/ Collections.emptyMap(),
/*forceOverride=*/ false,
/*version=*/ 0);
@@ -1511,8 +1509,8 @@ public class AppSearchImplTest {
"database",
schemas,
/*visibilityStore=*/ null,
- /*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
- /*schemasPackageAccessible=*/ Collections.emptyMap(),
+ /*schemasNotDisplayedBySystem=*/ Collections.emptyList(),
+ /*schemasVisibleToPackages=*/ Collections.emptyMap(),
/*forceOverride=*/ false,
/*version=*/ 0);
@@ -1534,8 +1532,8 @@ public class AppSearchImplTest {
"database",
schemas,
/*visibilityStore=*/ null,
- /*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
- /*schemasPackageAccessible=*/ Collections.emptyMap(),
+ /*schemasNotDisplayedBySystem=*/ Collections.emptyList(),
+ /*schemasVisibleToPackages=*/ Collections.emptyMap(),
/*forceOverride=*/ false,
/*version=*/ 0);
@@ -1550,8 +1548,8 @@ public class AppSearchImplTest {
"database",
schemas,
/*visibilityStore=*/ null,
- /*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
- /*schemasPackageAccessible=*/ Collections.emptyMap(),
+ /*schemasNotDisplayedBySystem=*/ Collections.emptyList(),
+ /*schemasVisibleToPackages=*/ Collections.emptyMap(),
/*forceOverride=*/ false,
/*version=*/ 0);
@@ -1599,8 +1597,8 @@ public class AppSearchImplTest {
"database",
schemas,
/*visibilityStore=*/ null,
- /*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
- /*schemasPackageAccessible=*/ Collections.emptyMap(),
+ /*schemasNotDisplayedBySystem=*/ Collections.emptyList(),
+ /*schemasVisibleToPackages=*/ Collections.emptyMap(),
/*forceOverride=*/ false,
/*version=*/ 0);
@@ -1622,8 +1620,8 @@ public class AppSearchImplTest {
"database1",
schemas,
/*visibilityStore=*/ null,
- /*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
- /*schemasPackageAccessible=*/ Collections.emptyMap(),
+ /*schemasNotDisplayedBySystem=*/ Collections.emptyList(),
+ /*schemasVisibleToPackages=*/ Collections.emptyMap(),
/*forceOverride=*/ false,
/*version=*/ 0);
@@ -1644,8 +1642,8 @@ public class AppSearchImplTest {
"database1",
schemas,
/*visibilityStore=*/ null,
- /*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
- /*schemasPackageAccessible=*/ Collections.emptyMap(),
+ /*schemasNotDisplayedBySystem=*/ Collections.emptyList(),
+ /*schemasVisibleToPackages=*/ Collections.emptyMap(),
/*forceOverride=*/ false,
/*version=*/ 0);
mAppSearchImpl.setSchema(
@@ -1653,8 +1651,8 @@ public class AppSearchImplTest {
"database2",
schemas,
/*visibilityStore=*/ null,
- /*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
- /*schemasPackageAccessible=*/ Collections.emptyMap(),
+ /*schemasNotDisplayedBySystem=*/ Collections.emptyList(),
+ /*schemasVisibleToPackages=*/ Collections.emptyMap(),
/*forceOverride=*/ false,
/*version=*/ 0);
@@ -1700,15 +1698,15 @@ public class AppSearchImplTest {
"database",
schemas,
/*visibilityStore=*/ null,
- /*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
- /*schemasPackageAccessible=*/ Collections.emptyMap(),
+ /*schemasNotDisplayedBySystem=*/ Collections.emptyList(),
+ /*schemasVisibleToPackages=*/ Collections.emptyMap(),
/*forceOverride=*/ false,
/*version=*/ 0);
appSearchImpl.close();
// Check all our public APIs
- expectThrows(
+ assertThrows(
IllegalStateException.class,
() ->
appSearchImpl.setSchema(
@@ -1716,15 +1714,15 @@ public class AppSearchImplTest {
"database",
schemas,
/*visibilityStore=*/ null,
- /*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
- /*schemasPackageAccessible=*/ Collections.emptyMap(),
+ /*schemasNotDisplayedBySystem=*/ Collections.emptyList(),
+ /*schemasVisibleToPackages=*/ Collections.emptyMap(),
/*forceOverride=*/ false,
/*version=*/ 0));
- expectThrows(
+ assertThrows(
IllegalStateException.class, () -> appSearchImpl.getSchema("package", "database"));
- expectThrows(
+ assertThrows(
IllegalStateException.class,
() ->
appSearchImpl.putDocument(
@@ -1733,13 +1731,13 @@ public class AppSearchImplTest {
new GenericDocument.Builder<>("namespace", "id", "type").build(),
/*logger=*/ null));
- expectThrows(
+ assertThrows(
IllegalStateException.class,
() ->
appSearchImpl.getDocument(
"package", "database", "namespace", "id", Collections.emptyMap()));
- expectThrows(
+ assertThrows(
IllegalStateException.class,
() ->
appSearchImpl.query(
@@ -1749,7 +1747,7 @@ public class AppSearchImplTest {
new SearchSpec.Builder().build(),
/*logger=*/ null));
- expectThrows(
+ assertThrows(
IllegalStateException.class,
() ->
appSearchImpl.globalQuery(
@@ -1757,19 +1755,19 @@ public class AppSearchImplTest {
new SearchSpec.Builder().build(),
"package",
/*visibilityStore=*/ null,
- VisibilityStore.NO_OP_UID,
+ Process.INVALID_UID,
/*callerHasSystemAccess=*/ false,
/*logger=*/ null));
- expectThrows(
+ assertThrows(
IllegalStateException.class,
() -> appSearchImpl.getNextPage(/*nextPageToken=*/ 1L));
- expectThrows(
+ assertThrows(
IllegalStateException.class,
() -> appSearchImpl.invalidateNextPageToken(/*nextPageToken=*/ 1L));
- expectThrows(
+ assertThrows(
IllegalStateException.class,
() ->
appSearchImpl.reportUsage(
@@ -1780,7 +1778,7 @@ public class AppSearchImplTest {
/*usageTimestampMillis=*/ 1000L,
/*systemUsage=*/ false));
- expectThrows(
+ assertThrows(
IllegalStateException.class,
() ->
appSearchImpl.remove(
@@ -1790,7 +1788,7 @@ public class AppSearchImplTest {
"id",
/*removeStatsBuilder=*/ null));
- expectThrows(
+ assertThrows(
IllegalStateException.class,
() ->
appSearchImpl.removeByQuery(
@@ -1800,15 +1798,15 @@ public class AppSearchImplTest {
new SearchSpec.Builder().build(),
/*removeStatsBuilder=*/ null));
- expectThrows(
+ assertThrows(
IllegalStateException.class,
() -> appSearchImpl.getStorageInfoForPackage("package"));
- expectThrows(
+ assertThrows(
IllegalStateException.class,
() -> appSearchImpl.getStorageInfoForDatabase("package", "database"));
- expectThrows(
+ assertThrows(
IllegalStateException.class,
() -> appSearchImpl.persistToDisk(PersistType.Code.FULL));
}
@@ -1827,8 +1825,8 @@ public class AppSearchImplTest {
"database",
schemas,
/*visibilityStore=*/ null,
- /*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
- /*schemasPackageAccessible=*/ Collections.emptyMap(),
+ /*schemasNotDisplayedBySystem=*/ Collections.emptyList(),
+ /*schemasVisibleToPackages=*/ Collections.emptyMap(),
/*forceOverride=*/ false,
/*version=*/ 0);
@@ -1866,8 +1864,8 @@ public class AppSearchImplTest {
"database",
schemas,
/*visibilityStore=*/ null,
- /*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
- /*schemasPackageAccessible=*/ Collections.emptyMap(),
+ /*schemasNotDisplayedBySystem=*/ Collections.emptyList(),
+ /*schemasVisibleToPackages=*/ Collections.emptyMap(),
/*forceOverride=*/ false,
/*version=*/ 0);
@@ -1892,7 +1890,7 @@ public class AppSearchImplTest {
// Delete the first document
appSearchImpl.remove("package", "database", "namespace1", "id1", /*statsBuilder=*/ null);
appSearchImpl.persistToDisk(PersistType.Code.LITE);
- expectThrows(
+ assertThrows(
AppSearchException.class,
() ->
appSearchImpl.getDocument(
@@ -1909,7 +1907,7 @@ public class AppSearchImplTest {
// Only the second document should be retrievable from another instance.
AppSearchImpl appSearchImpl2 =
AppSearchImpl.create(appsearchDir, /*initStatsBuilder=*/ null, ALWAYS_OPTIMIZE);
- expectThrows(
+ assertThrows(
AppSearchException.class,
() ->
appSearchImpl2.getDocument(
@@ -1938,8 +1936,8 @@ public class AppSearchImplTest {
"database",
schemas,
/*visibilityStore=*/ null,
- /*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
- /*schemasPackageAccessible=*/ Collections.emptyMap(),
+ /*schemasNotDisplayedBySystem=*/ Collections.emptyList(),
+ /*schemasVisibleToPackages=*/ Collections.emptyMap(),
/*forceOverride=*/ false,
/*version=*/ 0);
@@ -1972,7 +1970,7 @@ public class AppSearchImplTest {
.build(),
/*statsBuilder=*/ null);
appSearchImpl.persistToDisk(PersistType.Code.LITE);
- expectThrows(
+ assertThrows(
AppSearchException.class,
() ->
appSearchImpl.getDocument(
@@ -1989,7 +1987,7 @@ public class AppSearchImplTest {
// Only the second document should be retrievable from another instance.
AppSearchImpl appSearchImpl2 =
AppSearchImpl.create(appsearchDir, /*initStatsBuilder=*/ null, ALWAYS_OPTIMIZE);
- expectThrows(
+ assertThrows(
AppSearchException.class,
() ->
appSearchImpl2.getDocument(
diff --git a/services/tests/servicestests/src/com/android/server/appsearch/external/localstorage/AppSearchLoggerTest.java b/services/tests/servicestests/src/com/android/server/appsearch/external/localstorage/AppSearchLoggerTest.java
index f20e8c6d13a9..9b75561fd2ec 100644
--- a/services/tests/servicestests/src/com/android/server/appsearch/external/localstorage/AppSearchLoggerTest.java
+++ b/services/tests/servicestests/src/com/android/server/appsearch/external/localstorage/AppSearchLoggerTest.java
@@ -25,6 +25,7 @@ import android.app.appsearch.AppSearchSchema;
import android.app.appsearch.GenericDocument;
import android.app.appsearch.SearchResultPage;
import android.app.appsearch.SearchSpec;
+import android.app.appsearch.exceptions.AppSearchException;
import com.android.server.appsearch.external.localstorage.stats.CallStats;
import com.android.server.appsearch.external.localstorage.stats.InitializeStats;
@@ -32,17 +33,24 @@ import com.android.server.appsearch.external.localstorage.stats.PutDocumentStats
import com.android.server.appsearch.external.localstorage.stats.RemoveStats;
import com.android.server.appsearch.external.localstorage.stats.SearchStats;
import com.android.server.appsearch.proto.DeleteStatsProto;
+import com.android.server.appsearch.proto.DocumentProto;
import com.android.server.appsearch.proto.InitializeStatsProto;
import com.android.server.appsearch.proto.PutDocumentStatsProto;
+import com.android.server.appsearch.proto.PutResultProto;
import com.android.server.appsearch.proto.QueryStatsProto;
import com.android.server.appsearch.proto.ScoringSpecProto;
+import com.android.server.appsearch.proto.StatusProto;
import com.android.server.appsearch.proto.TermMatchType;
+import com.google.common.collect.ImmutableList;
+
+import org.junit.Assert;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
+import java.io.File;
import java.util.Collections;
import java.util.List;
@@ -279,7 +287,7 @@ public class AppSearchLoggerTest {
// Testing actual logging
//
@Test
- public void testLoggingStats_initialize() throws Exception {
+ public void testLoggingStats_initializeWithoutDocuments_success() throws Exception {
// Create an unused AppSearchImpl to generated an InitializeStats.
InitializeStats.Builder initStatsBuilder = new InitializeStats.Builder();
AppSearchImpl.create(mTemporaryFolder.newFolder(), initStatsBuilder, ALWAYS_OPTIMIZE);
@@ -295,25 +303,139 @@ public class AppSearchLoggerTest {
.isEqualTo(InitializeStatsProto.DocumentStoreDataStatus.NO_DATA_LOSS_VALUE);
assertThat(iStats.getDocumentCount()).isEqualTo(0);
assertThat(iStats.getSchemaTypeCount()).isEqualTo(0);
+ assertThat(iStats.hasReset()).isEqualTo(false);
+ assertThat(iStats.getResetStatusCode()).isEqualTo(AppSearchResult.RESULT_OK);
}
@Test
- public void testLoggingStats_putDocument() throws Exception {
- // Insert schema
+ public void testLoggingStats_initializeWithDocuments_success() throws Exception {
final String testPackageName = "testPackage";
final String testDatabase = "testDatabase";
+ final File folder = mTemporaryFolder.newFolder();
+
+ AppSearchImpl appSearchImpl =
+ AppSearchImpl.create(folder, /*initStatsBuilder=*/ null, ALWAYS_OPTIMIZE);
List<AppSearchSchema> schemas =
- Collections.singletonList(new AppSearchSchema.Builder("type").build());
+ ImmutableList.of(
+ new AppSearchSchema.Builder("Type1").build(),
+ new AppSearchSchema.Builder("Type2").build());
+ appSearchImpl.setSchema(
+ testPackageName,
+ testDatabase,
+ schemas,
+ /*visibilityStore=*/ null,
+ /*schemasNotDisplayedBySystem=*/ Collections.emptyList(),
+ /*schemasVisibleToPackages=*/ Collections.emptyMap(),
+ /*forceOverride=*/ false,
+ /*version=*/ 0);
+ GenericDocument doc1 = new GenericDocument.Builder<>("namespace", "id1", "Type1").build();
+ GenericDocument doc2 = new GenericDocument.Builder<>("namespace", "id2", "Type1").build();
+ appSearchImpl.putDocument(testPackageName, testDatabase, doc1, mLogger);
+ appSearchImpl.putDocument(testPackageName, testDatabase, doc2, mLogger);
+ appSearchImpl.close();
+
+ // Create another appsearchImpl on the same folder
+ InitializeStats.Builder initStatsBuilder = new InitializeStats.Builder();
+ AppSearchImpl.create(folder, initStatsBuilder, ALWAYS_OPTIMIZE);
+ InitializeStats iStats = initStatsBuilder.build();
+
+ assertThat(iStats).isNotNull();
+ assertThat(iStats.getStatusCode()).isEqualTo(AppSearchResult.RESULT_OK);
+ // Total latency captured in LocalStorage
+ assertThat(iStats.getTotalLatencyMillis()).isEqualTo(0);
+ assertThat(iStats.hasDeSync()).isFalse();
+ assertThat(iStats.getNativeLatencyMillis()).isGreaterThan(0);
+ assertThat(iStats.getDocumentStoreDataStatus())
+ .isEqualTo(InitializeStatsProto.DocumentStoreDataStatus.NO_DATA_LOSS_VALUE);
+ assertThat(iStats.getDocumentCount()).isEqualTo(2);
+ assertThat(iStats.getSchemaTypeCount()).isEqualTo(2);
+ assertThat(iStats.hasReset()).isEqualTo(false);
+ assertThat(iStats.getResetStatusCode()).isEqualTo(AppSearchResult.RESULT_OK);
+ }
+
+ @Test
+ public void testLoggingStats_initialize_failure() throws Exception {
+ final String testPackageName = "testPackage";
+ final String testDatabase = "testDatabase";
+ final File folder = mTemporaryFolder.newFolder();
+
+ AppSearchImpl appSearchImpl =
+ AppSearchImpl.create(folder, /*initStatsBuilder=*/ null, ALWAYS_OPTIMIZE);
+
+ List<AppSearchSchema> schemas =
+ ImmutableList.of(
+ new AppSearchSchema.Builder("Type1").build(),
+ new AppSearchSchema.Builder("Type2").build());
+ appSearchImpl.setSchema(
+ testPackageName,
+ testDatabase,
+ schemas,
+ /*visibilityStore=*/ null,
+ /*schemasNotDisplayedBySystem=*/ Collections.emptyList(),
+ /*schemasVisibleToPackages=*/ Collections.emptyMap(),
+ /*forceOverride=*/ false,
+ /*version=*/ 0);
+
+ // Insert a valid doc
+ GenericDocument doc1 = new GenericDocument.Builder<>("namespace", "id1", "Type1").build();
+ appSearchImpl.putDocument(testPackageName, testDatabase, doc1, mLogger);
+
+ // Insert the invalid doc with an invalid namespace right into icing
+ DocumentProto invalidDoc =
+ DocumentProto.newBuilder()
+ .setNamespace("invalidNamespace")
+ .setUri("id2")
+ .setSchema(String.format("%s$%s/Type1", testPackageName, testDatabase))
+ .build();
+ PutResultProto putResultProto = appSearchImpl.mIcingSearchEngineLocked.put(invalidDoc);
+ assertThat(putResultProto.getStatus().getCode()).isEqualTo(StatusProto.Code.OK);
+ appSearchImpl.close();
+
+ // Create another appsearchImpl on the same folder
+ InitializeStats.Builder initStatsBuilder = new InitializeStats.Builder();
+ AppSearchImpl.create(folder, initStatsBuilder, ALWAYS_OPTIMIZE);
+ InitializeStats iStats = initStatsBuilder.build();
+
+ // Some of other fields are already covered by AppSearchImplTest#testReset()
+ assertThat(iStats).isNotNull();
+ assertThat(iStats.getStatusCode()).isEqualTo(AppSearchResult.RESULT_INTERNAL_ERROR);
+ assertThat(iStats.hasReset()).isTrue();
+ }
+
+ @Test
+ public void testLoggingStats_putDocument_success() throws Exception {
+ // Insert schema
+ final String testPackageName = "testPackage";
+ final String testDatabase = "testDatabase";
+ AppSearchSchema testSchema =
+ new AppSearchSchema.Builder("type")
+ .addProperty(
+ new AppSearchSchema.StringPropertyConfig.Builder("subject")
+ .setCardinality(
+ AppSearchSchema.PropertyConfig.CARDINALITY_OPTIONAL)
+ .setIndexingType(
+ AppSearchSchema.StringPropertyConfig
+ .INDEXING_TYPE_PREFIXES)
+ .setTokenizerType(
+ AppSearchSchema.StringPropertyConfig
+ .TOKENIZER_TYPE_PLAIN)
+ .build())
+ .build();
+ List<AppSearchSchema> schemas = Collections.singletonList(testSchema);
mAppSearchImpl.setSchema(
testPackageName,
testDatabase,
schemas,
/*visibilityStore=*/ null,
- /*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
- /*schemasPackageAccessible=*/ Collections.emptyMap(),
+ /*schemasNotDisplayedBySystem=*/ Collections.emptyList(),
+ /*schemasVisibleToPackages=*/ Collections.emptyMap(),
/*forceOverride=*/ false,
/*version=*/ 0);
- GenericDocument document = new GenericDocument.Builder<>("namespace", "id", "type").build();
+
+ GenericDocument document =
+ new GenericDocument.Builder<>("namespace", "id", "type")
+ .setPropertyString("subject", "testPut example1")
+ .build();
mAppSearchImpl.putDocument(testPackageName, testDatabase, document, mLogger);
@@ -322,43 +444,119 @@ public class AppSearchLoggerTest {
assertThat(pStats.getPackageName()).isEqualTo(testPackageName);
assertThat(pStats.getDatabase()).isEqualTo(testDatabase);
assertThat(pStats.getStatusCode()).isEqualTo(AppSearchResult.RESULT_OK);
- // The rest of native stats have been tested in testCopyNativeStats
+ // The latency related native stats have been tested in testCopyNativeStats
assertThat(pStats.getNativeDocumentSizeBytes()).isGreaterThan(0);
+ assertThat(pStats.getNativeNumTokensIndexed()).isGreaterThan(0);
}
@Test
- public void testLoggingStats_search() throws Exception {
+ public void testLoggingStats_putDocument_failure() throws Exception {
// Insert schema
final String testPackageName = "testPackage";
final String testDatabase = "testDatabase";
- List<AppSearchSchema> schemas =
- Collections.singletonList(new AppSearchSchema.Builder("type").build());
+ AppSearchSchema testSchema =
+ new AppSearchSchema.Builder("type")
+ .addProperty(
+ new AppSearchSchema.StringPropertyConfig.Builder("subject")
+ .setCardinality(
+ AppSearchSchema.PropertyConfig.CARDINALITY_OPTIONAL)
+ .setIndexingType(
+ AppSearchSchema.StringPropertyConfig
+ .INDEXING_TYPE_PREFIXES)
+ .setTokenizerType(
+ AppSearchSchema.StringPropertyConfig
+ .TOKENIZER_TYPE_PLAIN)
+ .build())
+ .build();
+ List<AppSearchSchema> schemas = Collections.singletonList(testSchema);
mAppSearchImpl.setSchema(
testPackageName,
testDatabase,
schemas,
/*visibilityStore=*/ null,
- /*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
- /*schemasPackageAccessible=*/ Collections.emptyMap(),
+ /*schemasNotDisplayedBySystem=*/ Collections.emptyList(),
+ /*schemasVisibleToPackages=*/ Collections.emptyMap(),
/*forceOverride=*/ false,
/*version=*/ 0);
- GenericDocument document = new GenericDocument.Builder<>("namespace", "id", "type").build();
- mAppSearchImpl.putDocument(testPackageName, testDatabase, document, mLogger);
+ GenericDocument document =
+ new GenericDocument.Builder<>("namespace", "id", "type")
+ .setPropertyString("nonExist", "testPut example1")
+ .build();
+
+ // We mainly want to check the status code in stats. So we don't need to inspect the
+ // exception here.
+ Assert.assertThrows(
+ AppSearchException.class,
+ () -> mAppSearchImpl.putDocument(testPackageName, testDatabase, document, mLogger));
+
+ PutDocumentStats pStats = mLogger.mPutDocumentStats;
+ assertThat(pStats).isNotNull();
+ assertThat(pStats.getPackageName()).isEqualTo(testPackageName);
+ assertThat(pStats.getDatabase()).isEqualTo(testDatabase);
+ assertThat(pStats.getStatusCode()).isEqualTo(AppSearchResult.RESULT_NOT_FOUND);
+ }
+
+ @Test
+ public void testLoggingStats_search_success() throws Exception {
+ // Insert schema
+ final String testPackageName = "testPackage";
+ final String testDatabase = "testDatabase";
+ AppSearchSchema testSchema =
+ new AppSearchSchema.Builder("type")
+ .addProperty(
+ new AppSearchSchema.StringPropertyConfig.Builder("subject")
+ .setCardinality(
+ AppSearchSchema.PropertyConfig.CARDINALITY_OPTIONAL)
+ .setIndexingType(
+ AppSearchSchema.StringPropertyConfig
+ .INDEXING_TYPE_PREFIXES)
+ .setTokenizerType(
+ AppSearchSchema.StringPropertyConfig
+ .TOKENIZER_TYPE_PLAIN)
+ .build())
+ .build();
+ List<AppSearchSchema> schemas = Collections.singletonList(testSchema);
+ mAppSearchImpl.setSchema(
+ testPackageName,
+ testDatabase,
+ schemas,
+ /*visibilityStore=*/ null,
+ /*schemasNotDisplayedBySystem=*/ Collections.emptyList(),
+ /*schemasVisibleToPackages=*/ Collections.emptyMap(),
+ /*forceOverride=*/ false,
+ /*version=*/ 0);
+ GenericDocument document1 =
+ new GenericDocument.Builder<>("namespace", "id1", "type")
+ .setPropertyString("subject", "testPut example1")
+ .build();
+ GenericDocument document2 =
+ new GenericDocument.Builder<>("namespace", "id2", "type")
+ .setPropertyString("subject", "testPut example2")
+ .build();
+ GenericDocument document3 =
+ new GenericDocument.Builder<>("namespace", "id3", "type")
+ .setPropertyString("subject", "testPut 3")
+ .build();
+ mAppSearchImpl.putDocument(testPackageName, testDatabase, document1, mLogger);
+ mAppSearchImpl.putDocument(testPackageName, testDatabase, document2, mLogger);
+ mAppSearchImpl.putDocument(testPackageName, testDatabase, document3, mLogger);
// No query filters specified. package2 should only get its own documents back.
SearchSpec searchSpec =
- new SearchSpec.Builder().setTermMatch(TermMatchType.Code.PREFIX_VALUE).build();
+ new SearchSpec.Builder()
+ .setTermMatch(TermMatchType.Code.PREFIX_VALUE)
+ .setRankingStrategy(SearchSpec.RANKING_STRATEGY_CREATION_TIMESTAMP)
+ .build();
+ String queryStr = "testPut e";
SearchResultPage searchResultPage =
mAppSearchImpl.query(
- testPackageName,
- testDatabase,
- /*QueryExpression=*/ "",
- searchSpec,
- /*logger=*/ mLogger);
+ testPackageName, testDatabase, queryStr, searchSpec, /*logger=*/ mLogger);
- assertThat(searchResultPage.getResults()).hasSize(1);
- assertThat(searchResultPage.getResults().get(0).getGenericDocument()).isEqualTo(document);
+ assertThat(searchResultPage.getResults()).hasSize(2);
+ // The ranking strategy is LIFO
+ assertThat(searchResultPage.getResults().get(0).getGenericDocument()).isEqualTo(document2);
+ assertThat(searchResultPage.getResults().get(1).getGenericDocument()).isEqualTo(document1);
SearchStats sStats = mLogger.mSearchStats;
@@ -368,17 +566,59 @@ public class AppSearchLoggerTest {
assertThat(sStats.getStatusCode()).isEqualTo(AppSearchResult.RESULT_OK);
assertThat(sStats.getTotalLatencyMillis()).isGreaterThan(0);
assertThat(sStats.getVisibilityScope()).isEqualTo(SearchStats.VISIBILITY_SCOPE_LOCAL);
- assertThat(sStats.getTermCount()).isEqualTo(0);
- // assertThat(sStats.getNativeQueryLength()).isEqualTo(0);
+ assertThat(sStats.getTermCount()).isEqualTo(2);
+ assertThat(sStats.getQueryLength()).isEqualTo(queryStr.length());
assertThat(sStats.getFilteredNamespaceCount()).isEqualTo(1);
assertThat(sStats.getFilteredSchemaTypeCount()).isEqualTo(1);
- assertThat(sStats.getCurrentPageReturnedResultCount()).isEqualTo(1);
+ assertThat(sStats.getCurrentPageReturnedResultCount()).isEqualTo(2);
assertThat(sStats.isFirstPage()).isTrue();
- assertThat(sStats.getScoredDocumentCount()).isEqualTo(1);
+ assertThat(sStats.getRankingStrategy())
+ .isEqualTo(SearchSpec.RANKING_STRATEGY_CREATION_TIMESTAMP);
+ assertThat(sStats.getScoredDocumentCount()).isEqualTo(2);
+ assertThat(sStats.getResultWithSnippetsCount()).isEqualTo(0);
+ }
+
+ @Test
+ public void testLoggingStats_search_failure() throws Exception {
+ final String testPackageName = "testPackage";
+ final String testDatabase = "testDatabase";
+ List<AppSearchSchema> schemas =
+ ImmutableList.of(
+ new AppSearchSchema.Builder("Type1").build(),
+ new AppSearchSchema.Builder("Type2").build());
+ mAppSearchImpl.setSchema(
+ testPackageName,
+ testDatabase,
+ schemas,
+ /*visibilityStore=*/ null,
+ /*schemasNotDisplayedBySystem=*/ Collections.emptyList(),
+ /*schemasVisibleToPackages=*/ Collections.emptyMap(),
+ /*forceOverride=*/ false,
+ /*version=*/ 0);
+
+ SearchSpec searchSpec =
+ new SearchSpec.Builder()
+ .setTermMatch(TermMatchType.Code.PREFIX_VALUE)
+ .setRankingStrategy(SearchSpec.RANKING_STRATEGY_CREATION_TIMESTAMP)
+ .addFilterPackageNames("anotherPackage")
+ .build();
+
+ mAppSearchImpl.query(
+ testPackageName,
+ testPackageName,
+ /* queryExpression= */ "",
+ searchSpec,
+ /*logger=*/ mLogger);
+
+ SearchStats sStats = mLogger.mSearchStats;
+ assertThat(sStats).isNotNull();
+ assertThat(sStats.getPackageName()).isEqualTo(testPackageName);
+ assertThat(sStats.getDatabase()).isEqualTo(testPackageName);
+ assertThat(sStats.getStatusCode()).isEqualTo(AppSearchResult.RESULT_SECURITY_ERROR);
}
@Test
- public void testLoggingStats_remove() throws Exception {
+ public void testLoggingStats_remove_success() throws Exception {
// Insert schema
final String testPackageName = "testPackage";
final String testDatabase = "testDatabase";
@@ -391,8 +631,8 @@ public class AppSearchLoggerTest {
testDatabase,
schemas,
/*visibilityStore=*/ null,
- /*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
- /*schemasPackageAccessible=*/ Collections.emptyMap(),
+ /*schemasNotDisplayedBySystem=*/ Collections.emptyList(),
+ /*schemasVisibleToPackages=*/ Collections.emptyMap(),
/*forceOverride=*/ false,
/*version=*/ 0);
GenericDocument document =
@@ -406,12 +646,59 @@ public class AppSearchLoggerTest {
assertThat(rStats.getPackageName()).isEqualTo(testPackageName);
assertThat(rStats.getDatabase()).isEqualTo(testDatabase);
// delete by namespace + id
+ assertThat(rStats.getStatusCode()).isEqualTo(AppSearchResult.RESULT_OK);
assertThat(rStats.getDeleteType()).isEqualTo(DeleteStatsProto.DeleteType.Code.SINGLE_VALUE);
assertThat(rStats.getDeletedDocumentCount()).isEqualTo(1);
}
@Test
- public void testLoggingStats_removeByQuery() throws Exception {
+ public void testLoggingStats_remove_failure() throws Exception {
+ // Insert schema
+ final String testPackageName = "testPackage";
+ final String testDatabase = "testDatabase";
+ final String testNamespace = "testNameSpace";
+ final String testId = "id";
+ List<AppSearchSchema> schemas =
+ Collections.singletonList(new AppSearchSchema.Builder("type").build());
+ mAppSearchImpl.setSchema(
+ testPackageName,
+ testDatabase,
+ schemas,
+ /*visibilityStore=*/ null,
+ /*schemasNotDisplayedBySystem=*/ Collections.emptyList(),
+ /*schemasVisibleToPackages=*/ Collections.emptyMap(),
+ /*forceOverride=*/ false,
+ /*version=*/ 0);
+
+ GenericDocument document =
+ new GenericDocument.Builder<>(testNamespace, testId, "type").build();
+ mAppSearchImpl.putDocument(testPackageName, testDatabase, document, /*logger=*/ null);
+
+ RemoveStats.Builder rStatsBuilder = new RemoveStats.Builder(testPackageName, testDatabase);
+
+ // We mainly want to check the status code in stats. So we don't need to inspect the
+ // exception here.
+ Assert.assertThrows(
+ AppSearchException.class,
+ () ->
+ mAppSearchImpl.remove(
+ testPackageName,
+ testDatabase,
+ testNamespace,
+ "invalidId",
+ rStatsBuilder));
+
+ RemoveStats rStats = rStatsBuilder.build();
+ assertThat(rStats.getPackageName()).isEqualTo(testPackageName);
+ assertThat(rStats.getDatabase()).isEqualTo(testDatabase);
+ assertThat(rStats.getStatusCode()).isEqualTo(AppSearchResult.RESULT_NOT_FOUND);
+ // delete by namespace + id
+ assertThat(rStats.getDeleteType()).isEqualTo(DeleteStatsProto.DeleteType.Code.SINGLE_VALUE);
+ assertThat(rStats.getDeletedDocumentCount()).isEqualTo(0);
+ }
+
+ @Test
+ public void testLoggingStats_removeByQuery_success() throws Exception {
// Insert schema
final String testPackageName = "testPackage";
final String testDatabase = "testDatabase";
@@ -423,8 +710,8 @@ public class AppSearchLoggerTest {
testDatabase,
schemas,
/*visibilityStore=*/ null,
- /*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
- /*schemasPackageAccessible=*/ Collections.emptyMap(),
+ /*schemasNotDisplayedBySystem=*/ Collections.emptyList(),
+ /*schemasVisibleToPackages=*/ Collections.emptyMap(),
/*forceOverride=*/ false,
/*version=*/ 0);
GenericDocument document1 =
@@ -444,6 +731,7 @@ public class AppSearchLoggerTest {
assertThat(rStats.getPackageName()).isEqualTo(testPackageName);
assertThat(rStats.getDatabase()).isEqualTo(testDatabase);
+ assertThat(rStats.getStatusCode()).isEqualTo(AppSearchResult.RESULT_OK);
// delete by query
assertThat(rStats.getDeleteType()).isEqualTo(DeleteStatsProto.DeleteType.Code.QUERY_VALUE);
assertThat(rStats.getDeletedDocumentCount()).isEqualTo(2);
diff --git a/services/tests/servicestests/src/com/android/server/appsearch/external/localstorage/converter/SnippetTest.java b/services/tests/servicestests/src/com/android/server/appsearch/external/localstorage/converter/SnippetTest.java
index d3feb12912ad..64a670dcdb38 100644
--- a/services/tests/servicestests/src/com/android/server/appsearch/external/localstorage/converter/SnippetTest.java
+++ b/services/tests/servicestests/src/com/android/server/appsearch/external/localstorage/converter/SnippetTest.java
@@ -46,7 +46,6 @@ public class SnippetTest {
PREFIX,
Collections.singletonMap(PREFIX + SCHEMA_TYPE, SCHEMA_TYPE_CONFIG_PROTO));
- // TODO(tytytyww): Add tests for Double and Long Snippets.
@Test
public void testSingleStringSnippet() {
final String propertyKeyString = "content";
@@ -112,7 +111,6 @@ public class SnippetTest {
assertThat(match.getSnippet()).isEqualTo(window);
}
- // TODO(tytytyww): Add tests for Double and Long Snippets.
@Test
public void testNoSnippets() {
final String propertyKeyString = "content";
diff --git a/services/tests/servicestests/src/com/android/server/appsearch/external/localstorage/stats/AppSearchStatsTest.java b/services/tests/servicestests/src/com/android/server/appsearch/external/localstorage/stats/AppSearchStatsTest.java
index 6d9068675a72..57d994155d5b 100644
--- a/services/tests/servicestests/src/com/android/server/appsearch/external/localstorage/stats/AppSearchStatsTest.java
+++ b/services/tests/servicestests/src/com/android/server/appsearch/external/localstorage/stats/AppSearchStatsTest.java
@@ -254,14 +254,25 @@ public class AppSearchStatsTest {
@Test
public void testAppSearchStats_SetSchemaStats() {
+ SchemaMigrationStats schemaMigrationStats =
+ new SchemaMigrationStats.Builder()
+ .setGetSchemaLatencyMillis(1)
+ .setQueryAndTransformLatencyMillis(2)
+ .setFirstSetSchemaLatencyMillis(3)
+ .setSecondSetSchemaLatencyMillis(4)
+ .setSaveDocumentLatencyMillis(5)
+ .setMigratedDocumentCount(6)
+ .setSavedDocumentCount(7)
+ .build();
int nativeLatencyMillis = 1;
int newTypeCount = 2;
int compatibleTypeChangeCount = 3;
int indexIncompatibleTypeChangeCount = 4;
int backwardsIncompatibleTypeChangeCount = 5;
- final SetSchemaStats sStats =
+ SetSchemaStats sStats =
new SetSchemaStats.Builder(TEST_PACKAGE_NAME, TEST_DATA_BASE)
.setStatusCode(TEST_STATUS_CODE)
+ .setSchemaMigrationStats(schemaMigrationStats)
.setTotalLatencyMillis(TEST_TOTAL_LATENCY_MILLIS)
.setNativeLatencyMillis(nativeLatencyMillis)
.setNewTypeCount(newTypeCount)
@@ -274,6 +285,7 @@ public class AppSearchStatsTest {
assertThat(sStats.getPackageName()).isEqualTo(TEST_PACKAGE_NAME);
assertThat(sStats.getDatabase()).isEqualTo(TEST_DATA_BASE);
assertThat(sStats.getStatusCode()).isEqualTo(TEST_STATUS_CODE);
+ assertThat(sStats.getSchemaMigrationStats()).isEqualTo(schemaMigrationStats);
assertThat(sStats.getTotalLatencyMillis()).isEqualTo(TEST_TOTAL_LATENCY_MILLIS);
assertThat(sStats.getNativeLatencyMillis()).isEqualTo(nativeLatencyMillis);
assertThat(sStats.getNewTypeCount()).isEqualTo(newTypeCount);
@@ -285,6 +297,35 @@ public class AppSearchStatsTest {
}
@Test
+ public void testAppSearchStats_SchemaMigrationStats() {
+ int getSchemaLatency = 1;
+ int queryAndTransformLatency = 2;
+ int firstSetSchemaLatency = 3;
+ int secondSetSchemaLatency = 4;
+ int saveDocumentLatency = 5;
+ int migratedDocumentCount = 6;
+ int savedDocumentCount = 7;
+ SchemaMigrationStats sStats =
+ new SchemaMigrationStats.Builder()
+ .setGetSchemaLatencyMillis(getSchemaLatency)
+ .setQueryAndTransformLatencyMillis(queryAndTransformLatency)
+ .setFirstSetSchemaLatencyMillis(firstSetSchemaLatency)
+ .setSecondSetSchemaLatencyMillis(secondSetSchemaLatency)
+ .setSaveDocumentLatencyMillis(saveDocumentLatency)
+ .setMigratedDocumentCount(migratedDocumentCount)
+ .setSavedDocumentCount(savedDocumentCount)
+ .build();
+
+ assertThat(sStats.getGetSchemaLatencyMillis()).isEqualTo(getSchemaLatency);
+ assertThat(sStats.getQueryAndTransformLatencyMillis()).isEqualTo(queryAndTransformLatency);
+ assertThat(sStats.getFirstSetSchemaLatencyMillis()).isEqualTo(firstSetSchemaLatency);
+ assertThat(sStats.getSecondSetSchemaLatencyMillis()).isEqualTo(secondSetSchemaLatency);
+ assertThat(sStats.getSaveDocumentLatencyMillis()).isEqualTo(saveDocumentLatency);
+ assertThat(sStats.getMigratedDocumentCount()).isEqualTo(migratedDocumentCount);
+ assertThat(sStats.getSavedDocumentCount()).isEqualTo(savedDocumentCount);
+ }
+
+ @Test
public void testAppSearchStats_RemoveStats() {
int nativeLatencyMillis = 1;
@RemoveStats.DeleteType int deleteType = 2;
diff --git a/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java b/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java
index 7df2dd6988bf..019254d542b2 100644
--- a/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java
@@ -649,7 +649,7 @@ public abstract class BaseShortcutManagerTest extends InstrumentationTestCase {
protected class MockAppSearchManager implements IAppSearchManager {
- protected Map<String, List<PackageIdentifier>> mSchemasPackageAccessible =
+ protected Map<String, List<PackageIdentifier>> mSchemasVisibleToPackages =
new ArrayMap<>(1);
private Map<String, Map<String, GenericDocument>> mDocumentMap = new ArrayMap<>(1);
@@ -659,19 +659,19 @@ public abstract class BaseShortcutManagerTest extends InstrumentationTestCase {
@Override
public void setSchema(String packageName, String databaseName, List<Bundle> schemaBundles,
- List<String> schemasNotPlatformSurfaceable,
- Map<String, List<Bundle>> schemasPackageAccessibleBundles, boolean forceOverride,
+ List<String> schemasNotDisplayedBySystem,
+ Map<String, List<Bundle>> schemasVisibleToPackagesBundles, boolean forceOverride,
int version, UserHandle userHandle, long binderCallStartTimeMillis,
IAppSearchResultCallback callback) throws RemoteException {
for (Map.Entry<String, List<Bundle>> entry :
- schemasPackageAccessibleBundles.entrySet()) {
+ schemasVisibleToPackagesBundles.entrySet()) {
final String key = entry.getKey();
final List<PackageIdentifier> packageIdentifiers;
- if (!mSchemasPackageAccessible.containsKey(key)) {
+ if (!mSchemasVisibleToPackages.containsKey(key)) {
packageIdentifiers = new ArrayList<>(entry.getValue().size());
- mSchemasPackageAccessible.put(key, packageIdentifiers);
+ mSchemasVisibleToPackages.put(key, packageIdentifiers);
} else {
- packageIdentifiers = mSchemasPackageAccessible.get(key);
+ packageIdentifiers = mSchemasVisibleToPackages.get(key);
}
for (int i = 0; i < entry.getValue().size(); i++) {
packageIdentifiers.add(new PackageIdentifier(entry.getValue().get(i)));
diff --git a/services/tests/servicestests/src/com/android/server/systemconfig/SystemConfigTest.java b/services/tests/servicestests/src/com/android/server/systemconfig/SystemConfigTest.java
index 17d99e652726..9044b27d4994 100644
--- a/services/tests/servicestests/src/com/android/server/systemconfig/SystemConfigTest.java
+++ b/services/tests/servicestests/src/com/android/server/systemconfig/SystemConfigTest.java
@@ -222,6 +222,64 @@ public class SystemConfigTest {
}
/**
+ * Tests that readPermissions works correctly with {@link SystemConfig#ALLOW_VENDOR_APEX}
+ * permission flag for the tag: {@code allowed-vendor-apex}.
+ */
+ @Test
+ public void readPermissions_allowVendorApex_parsesVendorApexAllowList()
+ throws IOException {
+ final String contents =
+ "<config>\n"
+ + " <allowed-vendor-apex package=\"com.android.apex1\" />\n"
+ + "</config>";
+ final File folder = createTempSubfolder("folder");
+ createTempFile(folder, "vendor-apex-allowlist.xml", contents);
+
+ mSysConfig.readPermissions(folder, /* Grant all permission flags */ ~0);
+
+ assertThat(mSysConfig.getAllowedVendorApexes()).containsExactly("com.android.apex1");
+ }
+
+ /**
+ * Tests that readPermissions works correctly with {@link SystemConfig#ALLOW_VENDOR_APEX}
+ * permission flag for the tag: {@code allowed-vendor-apex}.
+ */
+ @Test
+ public void readPermissions_allowVendorApex_parsesVendorApexAllowList_noPackage()
+ throws IOException {
+ final String contents =
+ "<config>\n"
+ + " <allowed-vendor-apex/>\n"
+ + "</config>";
+ final File folder = createTempSubfolder("folder");
+ createTempFile(folder, "vendor-apex-allowlist.xml", contents);
+
+ mSysConfig.readPermissions(folder, /* Grant all permission flags */ ~0);
+
+ assertThat(mSysConfig.getAllowedVendorApexes()).isEmpty();
+ }
+
+
+ /**
+ * Tests that readPermissions works correctly without {@link SystemConfig#ALLOW_VENDOR_APEX}
+ * permission flag for the tag: {@code allowed-oem-apex}.
+ */
+ @Test
+ public void readPermissions_notAllowVendorApex_doesNotParseVendorApexAllowList()
+ throws IOException {
+ final String contents =
+ "<config>\n"
+ + " <allowed-vendor-apex package=\"com.android.apex1\" />\n"
+ + "</config>";
+ final File folder = createTempSubfolder("folder");
+ createTempFile(folder, "vendor-apex-allowlist.xml", contents);
+
+ mSysConfig.readPermissions(folder, /* Grant all but ALLOW_VENDOR_APEX flag */ ~0x400);
+
+ assertThat(mSysConfig.getAllowedVendorApexes()).isEmpty();
+ }
+
+ /**
* Creates folderName/fileName in the mTemporaryFolder and fills it with the contents.
*
* @param folderName subdirectory of mTemporaryFolder to put the file, creating if needed
diff --git a/services/tests/servicestests/src/com/android/server/vibrator/FakeVibratorControllerProvider.java b/services/tests/servicestests/src/com/android/server/vibrator/FakeVibratorControllerProvider.java
index 058575817acf..0449e4450d06 100644
--- a/services/tests/servicestests/src/com/android/server/vibrator/FakeVibratorControllerProvider.java
+++ b/services/tests/servicestests/src/com/android/server/vibrator/FakeVibratorControllerProvider.java
@@ -56,6 +56,8 @@ final class FakeVibratorControllerProvider {
private int[] mSupportedEffects;
private int[] mSupportedBraking;
private int[] mSupportedPrimitives;
+ private int mCompositionSizeMax;
+ private int mPwleSizeMax;
private float mMinFrequency = Float.NaN;
private float mResonantFrequency = Float.NaN;
private float mFrequencyResolution = Float.NaN;
@@ -151,12 +153,22 @@ final class FakeVibratorControllerProvider {
}
@Override
- public VibratorInfo getInfo(float suggestedFrequencyRange) {
- VibratorInfo.FrequencyMapping frequencyMapping = new VibratorInfo.FrequencyMapping(
- mMinFrequency, mResonantFrequency, mFrequencyResolution,
- suggestedFrequencyRange, mMaxAmplitudes);
- return new VibratorInfo(vibratorId, mCapabilities, mSupportedEffects, mSupportedBraking,
- mSupportedPrimitives, null, mQFactor, frequencyMapping);
+ public boolean getInfo(float suggestedFrequencyRange, VibratorInfo.Builder infoBuilder) {
+ infoBuilder.setCapabilities(mCapabilities);
+ infoBuilder.setSupportedBraking(mSupportedBraking);
+ infoBuilder.setPwleSizeMax(mPwleSizeMax);
+ infoBuilder.setSupportedEffects(mSupportedEffects);
+ if (mSupportedPrimitives != null) {
+ for (int primitive : mSupportedPrimitives) {
+ infoBuilder.setSupportedPrimitive(primitive, EFFECT_DURATION);
+ }
+ }
+ infoBuilder.setCompositionSizeMax(mCompositionSizeMax);
+ infoBuilder.setQFactor(mQFactor);
+ infoBuilder.setFrequencyMapping(new VibratorInfo.FrequencyMapping(mMinFrequency,
+ mResonantFrequency, mFrequencyResolution, suggestedFrequencyRange,
+ mMaxAmplitudes));
+ return true;
}
private void applyLatency() {
@@ -236,6 +248,16 @@ final class FakeVibratorControllerProvider {
mSupportedPrimitives = primitives;
}
+ /** Set the max number of primitives allowed in a composition by the fake vibrator hardware. */
+ public void setCompositionSizeMax(int compositionSizeMax) {
+ mCompositionSizeMax = compositionSizeMax;
+ }
+
+ /** Set the max number of PWLEs allowed in a composition by the fake vibrator hardware. */
+ public void setPwleSizeMax(int pwleSizeMax) {
+ mPwleSizeMax = pwleSizeMax;
+ }
+
/** Set the resonant frequency of the fake vibrator hardware. */
public void setResonantFrequency(float frequencyHz) {
mResonantFrequency = frequencyHz;
diff --git a/services/tests/servicestests/src/com/android/server/vibrator/VibrationThreadTest.java b/services/tests/servicestests/src/com/android/server/vibrator/VibrationThreadTest.java
index f02e2f081e3b..b8fdb552e453 100644
--- a/services/tests/servicestests/src/com/android/server/vibrator/VibrationThreadTest.java
+++ b/services/tests/servicestests/src/com/android/server/vibrator/VibrationThreadTest.java
@@ -356,7 +356,8 @@ public class VibrationThreadTest {
@Test
public void vibrate_singleVibratorComposed_runsVibration() throws Exception {
- mVibratorProviders.get(VIBRATOR_ID).setCapabilities(IVibrator.CAP_COMPOSE_EFFECTS);
+ FakeVibratorControllerProvider fakeVibrator = mVibratorProviders.get(VIBRATOR_ID);
+ fakeVibrator.setCapabilities(IVibrator.CAP_COMPOSE_EFFECTS);
long vibrationId = 1;
VibrationEffect effect = VibrationEffect.startComposition()
@@ -374,7 +375,7 @@ public class VibrationThreadTest {
assertEquals(Arrays.asList(
expectedPrimitive(VibrationEffect.Composition.PRIMITIVE_CLICK, 1, 0),
expectedPrimitive(VibrationEffect.Composition.PRIMITIVE_TICK, 0.5f, 0)),
- mVibratorProviders.get(VIBRATOR_ID).getEffectSegments());
+ fakeVibrator.getEffectSegments());
}
@Test
@@ -395,6 +396,27 @@ public class VibrationThreadTest {
}
@Test
+ public void vibrate_singleVibratorLargeComposition_splitsVibratorComposeCalls() {
+ FakeVibratorControllerProvider fakeVibrator = mVibratorProviders.get(VIBRATOR_ID);
+ fakeVibrator.setCapabilities(IVibrator.CAP_COMPOSE_EFFECTS);
+ fakeVibrator.setCompositionSizeMax(2);
+
+ long vibrationId = 1;
+ VibrationEffect effect = VibrationEffect.startComposition()
+ .addPrimitive(VibrationEffect.Composition.PRIMITIVE_CLICK, 1f)
+ .addPrimitive(VibrationEffect.Composition.PRIMITIVE_TICK, 0.5f)
+ .addPrimitive(VibrationEffect.Composition.PRIMITIVE_SPIN, 0.8f)
+ .compose();
+ VibrationThread thread = startThreadAndDispatcher(vibrationId, effect);
+ waitForCompletion(thread);
+
+ verify(mThreadCallbacks).onVibrationEnded(eq(vibrationId), eq(Vibration.Status.FINISHED));
+ // Vibrator compose called twice.
+ verify(mControllerCallbacks, times(2)).onComplete(eq(VIBRATOR_ID), eq(vibrationId));
+ assertEquals(3, fakeVibrator.getEffectSegments().size());
+ }
+
+ @Test
public void vibrate_singleVibratorComposedEffects_runsDifferentVibrations() throws Exception {
mVibratorProviders.get(VIBRATOR_ID).setSupportedEffects(VibrationEffect.EFFECT_CLICK);
mVibratorProviders.get(VIBRATOR_ID).setSupportedPrimitives(
@@ -432,12 +454,13 @@ public class VibrationThreadTest {
@Test
public void vibrate_singleVibratorPwle_runsComposePwle() throws Exception {
- mVibratorProviders.get(VIBRATOR_ID).setCapabilities(IVibrator.CAP_COMPOSE_PWLE_EFFECTS);
- mVibratorProviders.get(VIBRATOR_ID).setSupportedBraking(Braking.CLAB);
- mVibratorProviders.get(VIBRATOR_ID).setMinFrequency(100);
- mVibratorProviders.get(VIBRATOR_ID).setResonantFrequency(150);
- mVibratorProviders.get(VIBRATOR_ID).setFrequencyResolution(50);
- mVibratorProviders.get(VIBRATOR_ID).setMaxAmplitudes(
+ FakeVibratorControllerProvider fakeVibrator = mVibratorProviders.get(VIBRATOR_ID);
+ fakeVibrator.setCapabilities(IVibrator.CAP_COMPOSE_PWLE_EFFECTS);
+ fakeVibrator.setSupportedBraking(Braking.CLAB);
+ fakeVibrator.setMinFrequency(100);
+ fakeVibrator.setResonantFrequency(150);
+ fakeVibrator.setFrequencyResolution(50);
+ fakeVibrator.setMaxAmplitudes(
0.5f /* 100Hz*/, 1 /* 150Hz */, 0.6f /* 200Hz */);
long vibrationId = 1;
@@ -462,8 +485,34 @@ public class VibrationThreadTest {
expectedRamp(/* amplitude= */ 0.6f, /* frequency= */ 200, /* duration= */ 30),
expectedRamp(/* StartAmplitude= */ 0.6f, /* endAmplitude= */ 0.5f,
/* startFrequency= */ 200, /* endFrequency= */ 100, /* duration= */ 40)),
- mVibratorProviders.get(VIBRATOR_ID).getEffectSegments());
- assertEquals(Arrays.asList(Braking.CLAB), mVibratorProviders.get(VIBRATOR_ID).getBraking());
+ fakeVibrator.getEffectSegments());
+ assertEquals(Arrays.asList(Braking.CLAB), fakeVibrator.getBraking());
+ }
+
+ @Test
+ public void vibrate_singleVibratorLargePwle_splitsVibratorComposeCalls() {
+ FakeVibratorControllerProvider fakeVibrator = mVibratorProviders.get(VIBRATOR_ID);
+ fakeVibrator.setCapabilities(IVibrator.CAP_COMPOSE_PWLE_EFFECTS);
+ fakeVibrator.setMinFrequency(100);
+ fakeVibrator.setResonantFrequency(150);
+ fakeVibrator.setFrequencyResolution(50);
+ fakeVibrator.setMaxAmplitudes(1, 1, 1);
+ fakeVibrator.setPwleSizeMax(2);
+
+ long vibrationId = 1;
+ VibrationEffect effect = VibrationEffect.startWaveform()
+ .addStep(1, 10)
+ .addRamp(0, 20)
+ .addStep(0.8f, 1, 30)
+ .addRamp(0.6f, -1, 40)
+ .build();
+ VibrationThread thread = startThreadAndDispatcher(vibrationId, effect);
+ waitForCompletion(thread);
+
+ verify(mThreadCallbacks).onVibrationEnded(eq(vibrationId), eq(Vibration.Status.FINISHED));
+ // Vibrator compose called twice.
+ verify(mControllerCallbacks, times(2)).onComplete(eq(VIBRATOR_ID), eq(vibrationId));
+ assertEquals(4, fakeVibrator.getEffectSegments().size());
}
@Test
diff --git a/services/tests/servicestests/src/com/android/server/vibrator/VibratorControllerTest.java b/services/tests/servicestests/src/com/android/server/vibrator/VibratorControllerTest.java
index 9e98e7d0410c..a732bd18676a 100644
--- a/services/tests/servicestests/src/com/android/server/vibrator/VibratorControllerTest.java
+++ b/services/tests/servicestests/src/com/android/server/vibrator/VibratorControllerTest.java
@@ -298,11 +298,13 @@ public class VibratorControllerTest {
private void mockVibratorCapabilities(int capabilities) {
VibratorInfo.FrequencyMapping frequencyMapping = new VibratorInfo.FrequencyMapping(
Float.NaN, Float.NaN, Float.NaN, Float.NaN, null);
- when(mNativeWrapperMock.getInfo(anyFloat())).thenReturn(
- new VibratorInfo.Builder(VIBRATOR_ID)
- .setCapabilities(capabilities)
- .setFrequencyMapping(frequencyMapping)
- .build());
+ when(mNativeWrapperMock.getInfo(anyFloat(), any(VibratorInfo.Builder.class)))
+ .then(invocation -> {
+ ((VibratorInfo.Builder) invocation.getArgument(1))
+ .setCapabilities(capabilities)
+ .setFrequencyMapping(frequencyMapping);
+ return true;
+ });
}
private PrebakedSegment createPrebaked(int effectId, int effectStrength) {
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/BuzzBeepBlinkTest.java b/services/tests/uiservicestests/src/com/android/server/notification/BuzzBeepBlinkTest.java
index 3862d754b8f5..71c05b5c46f7 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/BuzzBeepBlinkTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/BuzzBeepBlinkTest.java
@@ -48,6 +48,7 @@ import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.app.ActivityManager;
+import android.app.KeyguardManager;
import android.app.Notification;
import android.app.Notification.Builder;
import android.app.NotificationChannel;
@@ -111,6 +112,8 @@ public class BuzzBeepBlinkTest extends UiServiceTestCase {
NotificationUsageStats mUsageStats;
@Mock
IAccessibilityManager mAccessibilityService;
+ @Mock
+ KeyguardManager mKeyguardManager;
NotificationRecordLoggerFake mNotificationRecordLogger = new NotificationRecordLoggerFake();
private InstanceIdSequence mNotificationInstanceIdSequence = new InstanceIdSequenceFake(
1 << 30);
@@ -153,6 +156,7 @@ public class BuzzBeepBlinkTest extends UiServiceTestCase {
when(mAudioManager.getRingerModeInternal()).thenReturn(AudioManager.RINGER_MODE_NORMAL);
when(mUsageStats.isAlertRateLimited(any())).thenReturn(false);
when(mVibrator.hasFrequencyControl()).thenReturn(false);
+ when(mKeyguardManager.isDeviceLocked(anyInt())).thenReturn(false);
long serviceReturnValue = IntPair.of(
AccessibilityManager.STATE_FLAG_ACCESSIBILITY_ENABLED,
@@ -174,6 +178,7 @@ public class BuzzBeepBlinkTest extends UiServiceTestCase {
mService.setScreenOn(false);
mService.setUsageStats(mUsageStats);
mService.setAccessibilityManager(accessibilityManager);
+ mService.setKeyguardManager(mKeyguardManager);
mService.mScreenOn = false;
mService.mInCallStateOffHook = false;
mService.mNotificationPulseEnabled = true;
@@ -496,6 +501,94 @@ public class BuzzBeepBlinkTest extends UiServiceTestCase {
}
@Test
+ public void testLockedPrivateA11yRedaction() throws Exception {
+ NotificationRecord r = getBeepyNotification();
+ r.setPackageVisibilityOverride(NotificationManager.VISIBILITY_NO_OVERRIDE);
+ r.getNotification().visibility = Notification.VISIBILITY_PRIVATE;
+ when(mKeyguardManager.isDeviceLocked(anyInt())).thenReturn(true);
+ AccessibilityManager accessibilityManager = Mockito.mock(AccessibilityManager.class);
+ when(accessibilityManager.isEnabled()).thenReturn(true);
+ mService.setAccessibilityManager(accessibilityManager);
+
+ mService.buzzBeepBlinkLocked(r);
+
+ ArgumentCaptor<AccessibilityEvent> eventCaptor =
+ ArgumentCaptor.forClass(AccessibilityEvent.class);
+
+ verify(accessibilityManager, times(1))
+ .sendAccessibilityEvent(eventCaptor.capture());
+
+ AccessibilityEvent event = eventCaptor.getValue();
+ assertEquals(r.getNotification().publicVersion, event.getParcelableData());
+ }
+
+ @Test
+ public void testLockedOverridePrivateA11yRedaction() throws Exception {
+ NotificationRecord r = getBeepyNotification();
+ r.setPackageVisibilityOverride(Notification.VISIBILITY_PRIVATE);
+ r.getNotification().visibility = Notification.VISIBILITY_PUBLIC;
+ when(mKeyguardManager.isDeviceLocked(anyInt())).thenReturn(true);
+ AccessibilityManager accessibilityManager = Mockito.mock(AccessibilityManager.class);
+ when(accessibilityManager.isEnabled()).thenReturn(true);
+ mService.setAccessibilityManager(accessibilityManager);
+
+ mService.buzzBeepBlinkLocked(r);
+
+ ArgumentCaptor<AccessibilityEvent> eventCaptor =
+ ArgumentCaptor.forClass(AccessibilityEvent.class);
+
+ verify(accessibilityManager, times(1))
+ .sendAccessibilityEvent(eventCaptor.capture());
+
+ AccessibilityEvent event = eventCaptor.getValue();
+ assertEquals(r.getNotification().publicVersion, event.getParcelableData());
+ }
+
+ @Test
+ public void testLockedPublicA11yNoRedaction() throws Exception {
+ NotificationRecord r = getBeepyNotification();
+ r.setPackageVisibilityOverride(NotificationManager.VISIBILITY_NO_OVERRIDE);
+ r.getNotification().visibility = Notification.VISIBILITY_PUBLIC;
+ when(mKeyguardManager.isDeviceLocked(anyInt())).thenReturn(true);
+ AccessibilityManager accessibilityManager = Mockito.mock(AccessibilityManager.class);
+ when(accessibilityManager.isEnabled()).thenReturn(true);
+ mService.setAccessibilityManager(accessibilityManager);
+
+ mService.buzzBeepBlinkLocked(r);
+
+ ArgumentCaptor<AccessibilityEvent> eventCaptor =
+ ArgumentCaptor.forClass(AccessibilityEvent.class);
+
+ verify(accessibilityManager, times(1))
+ .sendAccessibilityEvent(eventCaptor.capture());
+
+ AccessibilityEvent event = eventCaptor.getValue();
+ assertEquals(r.getNotification(), event.getParcelableData());
+ }
+
+ @Test
+ public void testUnlockedPrivateA11yNoRedaction() throws Exception {
+ NotificationRecord r = getBeepyNotification();
+ r.setPackageVisibilityOverride(NotificationManager.VISIBILITY_NO_OVERRIDE);
+ r.getNotification().visibility = Notification.VISIBILITY_PRIVATE;
+ when(mKeyguardManager.isDeviceLocked(anyInt())).thenReturn(false);
+ AccessibilityManager accessibilityManager = Mockito.mock(AccessibilityManager.class);
+ when(accessibilityManager.isEnabled()).thenReturn(true);
+ mService.setAccessibilityManager(accessibilityManager);
+
+ mService.buzzBeepBlinkLocked(r);
+
+ ArgumentCaptor<AccessibilityEvent> eventCaptor =
+ ArgumentCaptor.forClass(AccessibilityEvent.class);
+
+ verify(accessibilityManager, times(1))
+ .sendAccessibilityEvent(eventCaptor.capture());
+
+ AccessibilityEvent event = eventCaptor.getValue();
+ assertEquals(r.getNotification(), event.getParcelableData());
+ }
+
+ @Test
public void testBeepInsistently() throws Exception {
NotificationRecord r = getInsistentBeepyNotification();
diff --git a/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java b/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java
index 4e261deb67f6..4872ec511ccc 100644
--- a/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java
@@ -401,6 +401,7 @@ public class SizeCompatTests extends WindowTestsBase {
assertFitted();
final Rect currentBounds = mActivity.getWindowConfiguration().getBounds();
+ final Rect currentAppBounds = mActivity.getWindowConfiguration().getAppBounds();
final Rect originalBounds = new Rect(mActivity.getWindowConfiguration().getBounds());
final int notchHeight = 100;
@@ -428,8 +429,8 @@ public class SizeCompatTests extends WindowTestsBase {
// Because the display cannot rotate, the portrait activity will fit the short side of
// display with keeping portrait bounds [200, 0 - 700, 1000] in center.
assertEquals(newDisplayBounds.height(), currentBounds.height());
- assertEquals(currentBounds.height() * newDisplayBounds.height() / newDisplayBounds.width(),
- currentBounds.width());
+ assertEquals(currentAppBounds.height() * newDisplayBounds.height()
+ / newDisplayBounds.width(), currentAppBounds.width());
assertFitted();
// The appBounds should be [200, 100 - 700, 1000].
final Rect appBounds = mActivity.getWindowConfiguration().getAppBounds();
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskTests.java b/services/tests/wmtests/src/com/android/server/wm/TaskTests.java
index d93ebb383b3b..0ebff1d253ef 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskTests.java
@@ -60,6 +60,7 @@ import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.ArgumentMatchers.same;
+import static org.mockito.Mockito.atLeast;
import static org.mockito.Mockito.clearInvocations;
import static org.mockito.Mockito.never;
@@ -121,8 +122,8 @@ public class TaskTests extends WindowTestsBase {
@Test
public void testRemoveContainer() {
- final Task taskController1 = createTask(mDisplayContent);
- final Task task = createTaskInRootTask(taskController1, 0 /* userId */);
+ final Task rootTask = createTask(mDisplayContent);
+ final Task task = createTaskInRootTask(rootTask, 0 /* userId */);
final ActivityRecord activity = createActivityRecord(mDisplayContent, task);
task.removeIfPossible();
@@ -130,12 +131,14 @@ public class TaskTests extends WindowTestsBase {
assertNull(task.getParent());
assertEquals(0, task.getChildCount());
assertNull(activity.getParent());
+ verify(mAtm.getLockTaskController(), atLeast(1)).clearLockedTask(task);
+ verify(mAtm.getLockTaskController(), atLeast(1)).clearLockedTask(rootTask);
}
@Test
public void testRemoveContainer_deferRemoval() {
- final Task taskController1 = createTask(mDisplayContent);
- final Task task = createTaskInRootTask(taskController1, 0 /* userId */);
+ final Task rootTask = createTask(mDisplayContent);
+ final Task task = createTaskInRootTask(rootTask, 0 /* userId */);
final ActivityRecord activity = createActivityRecord(mDisplayContent, task);
doReturn(true).when(task).shouldDeferRemoval();
diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/HotwordDetectionConnection.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/HotwordDetectionConnection.java
index 17303a4aa7e1..beaca68b9a37 100644
--- a/services/voiceinteraction/java/com/android/server/voiceinteraction/HotwordDetectionConnection.java
+++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/HotwordDetectionConnection.java
@@ -29,11 +29,7 @@ import android.content.Context;
import android.content.Intent;
import android.hardware.soundtrigger.IRecognitionStatusCallback;
import android.hardware.soundtrigger.SoundTrigger;
-import android.media.AudioAttributes;
import android.media.AudioFormat;
-import android.media.AudioManager;
-import android.media.AudioRecord;
-import android.media.MediaRecorder;
import android.os.Binder;
import android.os.Bundle;
import android.os.IBinder;
@@ -66,12 +62,16 @@ import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
+import java.time.Duration;
+import java.time.Instant;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.function.Function;
/**
* A class that provides the communication with the HotwordDetectionService.
@@ -81,33 +81,38 @@ final class HotwordDetectionConnection {
// TODO (b/177502877): Set the Debug flag to false before shipping.
private static final boolean DEBUG = true;
- // Number of bytes per sample of audio (which is a short).
- private static final int BYTES_PER_SAMPLE = 2;
// TODO: These constants need to be refined.
private static final long VALIDATION_TIMEOUT_MILLIS = 3000;
- private static final long VOICE_INTERACTION_TIMEOUT_TO_OPEN_MIC_MILLIS = 2000;
- private static final int MAX_STREAMING_SECONDS = 10;
- private static final int MICROPHONE_BUFFER_LENGTH_SECONDS = 8;
- private static final int HOTWORD_AUDIO_LENGTH_SECONDS = 3;
private static final long MAX_UPDATE_TIMEOUT_MILLIS = 6000;
+ private static final Duration MAX_UPDATE_TIMEOUT_DURATION =
+ Duration.ofMillis(MAX_UPDATE_TIMEOUT_MILLIS);
private final Executor mAudioCopyExecutor = Executors.newCachedThreadPool();
// TODO: This may need to be a Handler(looper)
private final ScheduledExecutorService mScheduledExecutorService =
Executors.newSingleThreadScheduledExecutor();
- private final AtomicBoolean mUpdateStateFinish = new AtomicBoolean(false);
+ private final AtomicBoolean mUpdateStateAfterStartFinished = new AtomicBoolean(false);
+ private final @NonNull ServiceConnectionFactory mServiceConnectionFactory;
final Object mLock;
final int mVoiceInteractionServiceUid;
final ComponentName mDetectionComponentName;
final int mUser;
final Context mContext;
- final @NonNull ServiceConnector<IHotwordDetectionService> mRemoteHotwordDetectionService;
- boolean mBound;
volatile HotwordDetectionServiceIdentity mIdentity;
+ private IHotwordRecognitionStatusCallback mCallback;
+ private IMicrophoneHotwordDetectionVoiceInteractionCallback mSoftwareCallback;
+ private Instant mLastRestartInstant;
+
+ private ScheduledFuture<?> mCancellationTaskFuture;
@GuardedBy("mLock")
private ParcelFileDescriptor mCurrentAudioSink;
+ @GuardedBy("mLock")
+ private boolean mValidatingDspTrigger = false;
+ @GuardedBy("mLock")
+ private boolean mPerformingSoftwareHotwordDetection;
+ private @NonNull ServiceConnection mRemoteHotwordDetectionService;
HotwordDetectionConnection(Object lock, Context context, int voiceInteractionServiceUid,
ComponentName serviceName, int userId, boolean bindInstantServiceAllowed,
@@ -121,50 +126,36 @@ final class HotwordDetectionConnection {
final Intent intent = new Intent(HotwordDetectionService.SERVICE_INTERFACE);
intent.setComponent(mDetectionComponentName);
- mRemoteHotwordDetectionService = new ServiceConnector.Impl<IHotwordDetectionService>(
- mContext, intent, bindInstantServiceAllowed ? Context.BIND_ALLOW_INSTANT : 0, mUser,
- IHotwordDetectionService.Stub::asInterface) {
- @Override // from ServiceConnector.Impl
- protected void onServiceConnectionStatusChanged(IHotwordDetectionService service,
- boolean connected) {
- if (DEBUG) {
- Slog.d(TAG, "onServiceConnectionStatusChanged connected = " + connected);
- }
- synchronized (mLock) {
- mBound = connected;
- }
- }
+ mServiceConnectionFactory = new ServiceConnectionFactory(intent, bindInstantServiceAllowed);
- @Override
- protected long getAutoDisconnectTimeoutMs() {
- return -1;
- }
+ mRemoteHotwordDetectionService = mServiceConnectionFactory.create();
- @Override
- public void binderDied() {
- super.binderDied();
- Slog.w(TAG, "binderDied");
- try {
- callback.onError(-1);
- } catch (RemoteException e) {
- Slog.w(TAG, "Failed to report onError status: " + e);
- }
- }
- };
- mRemoteHotwordDetectionService.connect();
if (callback == null) {
updateStateLocked(options, sharedMemory);
return;
}
- updateAudioFlinger();
- updateContentCaptureManager();
- updateStateWithCallbackLocked(options, sharedMemory, callback);
+ mCallback = callback;
+
+ mLastRestartInstant = Instant.now();
+ updateStateAfterProcessStart(options, sharedMemory);
+
+ // TODO(volnov): we need to be smarter here, e.g. schedule it a bit more often, but wait
+ // until the current session is closed.
+ mCancellationTaskFuture = mScheduledExecutorService.scheduleAtFixedRate(() -> {
+ if (DEBUG) {
+ Slog.i(TAG, "Time to restart the process, TTL has passed");
+ }
+
+ synchronized (mLock) {
+ restartProcessLocked();
+ }
+ }, 30, 30, TimeUnit.MINUTES);
}
- private void updateStateWithCallbackLocked(PersistableBundle options,
- SharedMemory sharedMemory, IHotwordRecognitionStatusCallback callback) {
+ private void updateStateAfterProcessStart(
+ PersistableBundle options, SharedMemory sharedMemory) {
if (DEBUG) {
- Slog.d(TAG, "updateStateWithCallbackLocked");
+ Slog.d(TAG, "updateStateAfterProcessStart");
}
mRemoteHotwordDetectionService.postAsync(service -> {
AndroidFuture<Void> future = new AndroidFuture<>();
@@ -183,21 +174,21 @@ final class HotwordDetectionConnection {
mIdentity =
new HotwordDetectionServiceIdentity(uid, mVoiceInteractionServiceUid);
future.complete(null);
+ if (mUpdateStateAfterStartFinished.getAndSet(true)) {
+ Slog.w(TAG, "call callback after timeout");
+ return;
+ }
+ int status = bundle != null ? bundle.getInt(
+ KEY_INITIALIZATION_STATUS,
+ INITIALIZATION_STATUS_UNKNOWN)
+ : INITIALIZATION_STATUS_UNKNOWN;
+ // Add the protection to avoid unexpected status
+ if (status > HotwordDetectionService.getMaxCustomInitializationStatus()
+ && status != INITIALIZATION_STATUS_UNKNOWN) {
+ status = INITIALIZATION_STATUS_UNKNOWN;
+ }
try {
- if (mUpdateStateFinish.getAndSet(true)) {
- Slog.w(TAG, "call callback after timeout");
- return;
- }
- int status = bundle != null ? bundle.getInt(
- KEY_INITIALIZATION_STATUS,
- INITIALIZATION_STATUS_UNKNOWN)
- : INITIALIZATION_STATUS_UNKNOWN;
- // Add the protection to avoid unexpected status
- if (status > HotwordDetectionService.getMaxCustomInitializationStatus()
- && status != INITIALIZATION_STATUS_UNKNOWN) {
- status = INITIALIZATION_STATUS_UNKNOWN;
- }
- callback.onStatusReported(status);
+ mCallback.onStatusReported(status);
} catch (RemoteException e) {
Slog.w(TAG, "Failed to report initialization status: " + e);
}
@@ -214,13 +205,13 @@ final class HotwordDetectionConnection {
.whenComplete((res, err) -> {
if (err instanceof TimeoutException) {
Slog.w(TAG, "updateState timed out");
+ if (mUpdateStateAfterStartFinished.getAndSet(true)) {
+ return;
+ }
try {
- if (mUpdateStateFinish.getAndSet(true)) {
- return;
- }
- callback.onStatusReported(INITIALIZATION_STATUS_UNKNOWN);
+ mCallback.onStatusReported(INITIALIZATION_STATUS_UNKNOWN);
} catch (RemoteException e) {
- Slog.w(TAG, "Failed to report initialization status: " + e);
+ Slog.w(TAG, "Failed to report initialization status UNKNOWN", e);
}
} else if (err != null) {
Slog.w(TAG, "Failed to update state: " + err);
@@ -230,27 +221,9 @@ final class HotwordDetectionConnection {
});
}
- private void updateAudioFlinger() {
- // TODO: Consider using a proxy that limits the exposed API surface.
- IBinder audioFlinger = ServiceManager.getService("media.audio_flinger");
- if (audioFlinger == null) {
- throw new IllegalStateException("Service media.audio_flinger wasn't found.");
- }
- mRemoteHotwordDetectionService.post(service -> service.updateAudioFlinger(audioFlinger));
- }
-
- private void updateContentCaptureManager() {
- IBinder b = ServiceManager
- .getService(Context.CONTENT_CAPTURE_MANAGER_SERVICE);
- IContentCaptureManager binderService = IContentCaptureManager.Stub.asInterface(b);
- mRemoteHotwordDetectionService.post(
- service -> service.updateContentCaptureManager(binderService,
- new ContentCaptureOptions(null)));
- }
-
private boolean isBound() {
synchronized (mLock) {
- return mBound;
+ return mRemoteHotwordDetectionService.isBound();
}
}
@@ -258,18 +231,25 @@ final class HotwordDetectionConnection {
if (DEBUG) {
Slog.d(TAG, "cancelLocked");
}
- if (mBound) {
+ if (mRemoteHotwordDetectionService.isBound()) {
mRemoteHotwordDetectionService.unbind();
- mBound = false;
LocalServices.getService(PermissionManagerServiceInternal.class)
.setHotwordDetectionServiceProvider(null);
mIdentity = null;
}
+ mCancellationTaskFuture.cancel(/* may interrupt */ true);
}
void updateStateLocked(PersistableBundle options, SharedMemory sharedMemory) {
- mRemoteHotwordDetectionService.run(
- service -> service.updateState(options, sharedMemory, null /* callback */));
+ // Prevent doing the init late, so restart is handled equally to a clean process start.
+ // TODO(b/191742511): this logic needs a test
+ if (!mUpdateStateAfterStartFinished.get()
+ && Instant.now().minus(MAX_UPDATE_TIMEOUT_DURATION).isBefore(mLastRestartInstant)) {
+ updateStateAfterProcessStart(options, sharedMemory);
+ } else {
+ mRemoteHotwordDetectionService.run(
+ service -> service.updateState(options, sharedMemory, null /* callback */));
+ }
}
void startListeningFromMic(
@@ -278,7 +258,20 @@ final class HotwordDetectionConnection {
if (DEBUG) {
Slog.d(TAG, "startListeningFromMic");
}
+ mSoftwareCallback = callback;
+
+ synchronized (mLock) {
+ if (mPerformingSoftwareHotwordDetection) {
+ Slog.i(TAG, "Hotword validation is already in progress, ignoring.");
+ return;
+ }
+ mPerformingSoftwareHotwordDetection = true;
+
+ startListeningFromMicLocked();
+ }
+ }
+ private void startListeningFromMicLocked() {
// TODO: consider making this a non-anonymous class.
IDspHotwordDetectionCallback internalCallback = new IDspHotwordDetectionCallback.Stub() {
@Override
@@ -286,15 +279,22 @@ final class HotwordDetectionConnection {
if (DEBUG) {
Slog.d(TAG, "onDetected");
}
- callback.onDetected(result, null, null);
+ synchronized (mLock) {
+ if (mPerformingSoftwareHotwordDetection) {
+ mSoftwareCallback.onDetected(result, null, null);
+ mPerformingSoftwareHotwordDetection = false;
+ } else {
+ Slog.i(TAG, "Hotword detection has already completed");
+ }
+ }
}
@Override
public void onRejected(HotwordRejectedResult result) throws RemoteException {
if (DEBUG) {
- Slog.d(TAG, "onRejected");
+ Slog.wtf(TAG, "onRejected");
}
- // onRejected isn't allowed here
+ // onRejected isn't allowed here, and we are not expecting it.
}
};
@@ -315,6 +315,7 @@ final class HotwordDetectionConnection {
if (DEBUG) {
Slog.d(TAG, "startListeningFromExternalSource");
}
+
handleExternalSourceHotwordDetection(
audioStream,
audioFormat,
@@ -326,16 +327,25 @@ final class HotwordDetectionConnection {
if (DEBUG) {
Slog.d(TAG, "stopListening");
}
+ synchronized (mLock) {
+ stopListeningLocked();
+ }
+ }
- mRemoteHotwordDetectionService.run(service -> service.stopDetection());
+ private void stopListeningLocked() {
+ if (!mPerformingSoftwareHotwordDetection) {
+ Slog.i(TAG, "Hotword detection is not running");
+ return;
+ }
+ mPerformingSoftwareHotwordDetection = false;
- synchronized (mLock) {
- if (mCurrentAudioSink != null) {
- Slog.i(TAG, "Closing audio stream to hotword detector: stopping requested");
- bestEffortClose(mCurrentAudioSink);
- }
- mCurrentAudioSink = null;
+ mRemoteHotwordDetectionService.run(IHotwordDetectionService::stopDetection);
+
+ if (mCurrentAudioSink != null) {
+ Slog.i(TAG, "Closing audio stream to hotword detector: stopping requested");
+ bestEffortClose(mCurrentAudioSink);
}
+ mCurrentAudioSink = null;
}
void triggerHardwareRecognitionEventForTestLocked(
@@ -358,7 +368,14 @@ final class HotwordDetectionConnection {
if (DEBUG) {
Slog.d(TAG, "onDetected");
}
- externalCallback.onKeyphraseDetected(recognitionEvent, result);
+ synchronized (mLock) {
+ if (mValidatingDspTrigger) {
+ mValidatingDspTrigger = false;
+ externalCallback.onKeyphraseDetected(recognitionEvent, result);
+ } else {
+ Slog.i(TAG, "Ignored hotword detected since trigger has been handled");
+ }
+ }
}
@Override
@@ -366,16 +383,26 @@ final class HotwordDetectionConnection {
if (DEBUG) {
Slog.d(TAG, "onRejected");
}
- externalCallback.onRejected(result);
+ synchronized (mLock) {
+ if (mValidatingDspTrigger) {
+ mValidatingDspTrigger = false;
+ externalCallback.onRejected(result);
+ } else {
+ Slog.i(TAG, "Ignored hotword rejected since trigger has been handled");
+ }
+ }
}
};
- mRemoteHotwordDetectionService.run(
- service -> service.detectFromDspSource(
- recognitionEvent,
- recognitionEvent.getCaptureFormat(),
- VALIDATION_TIMEOUT_MILLIS,
- internalCallback));
+ synchronized (mLock) {
+ mValidatingDspTrigger = true;
+ mRemoteHotwordDetectionService.run(
+ service -> service.detectFromDspSource(
+ recognitionEvent,
+ recognitionEvent.getCaptureFormat(),
+ VALIDATION_TIMEOUT_MILLIS,
+ internalCallback));
+ }
}
private void detectFromDspSource(SoundTrigger.KeyphraseRecognitionEvent recognitionEvent,
@@ -391,7 +418,14 @@ final class HotwordDetectionConnection {
if (DEBUG) {
Slog.d(TAG, "onDetected");
}
- externalCallback.onKeyphraseDetected(recognitionEvent, result);
+ synchronized (mLock) {
+ if (!mValidatingDspTrigger) {
+ Slog.i(TAG, "Ignoring #onDetected due to a process restart");
+ return;
+ }
+ mValidatingDspTrigger = false;
+ externalCallback.onKeyphraseDetected(recognitionEvent, result);
+ }
}
@Override
@@ -399,16 +433,88 @@ final class HotwordDetectionConnection {
if (DEBUG) {
Slog.d(TAG, "onRejected");
}
- externalCallback.onRejected(result);
+ synchronized (mLock) {
+ if (!mValidatingDspTrigger) {
+ Slog.i(TAG, "Ignoring #onRejected due to a process restart");
+ return;
+ }
+ mValidatingDspTrigger = false;
+ externalCallback.onRejected(result);
+ }
}
};
- mRemoteHotwordDetectionService.run(
- service -> service.detectFromDspSource(
- recognitionEvent,
- recognitionEvent.getCaptureFormat(),
- VALIDATION_TIMEOUT_MILLIS,
- internalCallback));
+ synchronized (mLock) {
+ mValidatingDspTrigger = true;
+ mRemoteHotwordDetectionService.run(
+ service -> service.detectFromDspSource(
+ recognitionEvent,
+ recognitionEvent.getCaptureFormat(),
+ VALIDATION_TIMEOUT_MILLIS,
+ internalCallback));
+ }
+ }
+
+ void forceRestart() {
+ if (DEBUG) {
+ Slog.i(TAG, "Requested to restart the service internally. Performing the restart");
+ }
+ synchronized (mLock) {
+ restartProcessLocked();
+ }
+ }
+
+ private void restartProcessLocked() {
+ if (DEBUG) {
+ Slog.i(TAG, "Restarting hotword detection process");
+ }
+
+ ServiceConnection oldConnection = mRemoteHotwordDetectionService;
+
+ // TODO(volnov): this can be done after connect() has been successful.
+ if (mValidatingDspTrigger) {
+ // We're restarting the process while it's processing a DSP trigger, so report a
+ // rejection. This also allows the Interactor to startReco again
+ try {
+ mCallback.onRejected(new HotwordRejectedResult.Builder().build());
+ } catch (RemoteException e) {
+ Slog.w(TAG, "Failed to call #rejected");
+ }
+ mValidatingDspTrigger = false;
+ }
+
+ mUpdateStateAfterStartFinished.set(false);
+ mLastRestartInstant = Instant.now();
+
+ // Recreate connection to reset the cache.
+ mRemoteHotwordDetectionService = mServiceConnectionFactory.create();
+
+ if (DEBUG) {
+ Slog.i(TAG, "Started the new process, issuing #onProcessRestarted");
+ }
+ try {
+ mCallback.onProcessRestarted();
+ } catch (RemoteException e) {
+ Slog.w(TAG, "Failed to communicate #onProcessRestarted", e);
+ }
+
+ // Restart listening from microphone if the hotword process has been restarted.
+ if (mPerformingSoftwareHotwordDetection) {
+ Slog.i(TAG, "Process restarted: calling startRecognition() again");
+ startListeningFromMicLocked();
+ }
+
+ if (mCurrentAudioSink != null) {
+ Slog.i(TAG, "Closing external audio stream to hotword detector: process restarted");
+ bestEffortClose(mCurrentAudioSink);
+ mCurrentAudioSink = null;
+ }
+
+ if (DEBUG) {
+ Slog.i(TAG, "#onProcessRestarted called, unbinding from the old process");
+ }
+ oldConnection.ignoreConnectionStatusEvents();
+ oldConnection.unbind();
}
static final class SoundTriggerCallback extends IRecognitionStatusCallback.Stub {
@@ -462,139 +568,13 @@ final class HotwordDetectionConnection {
}
}
- // TODO: figure out if we need to let the client configure some of the parameters.
- private static AudioRecord createAudioRecord(
- @NonNull SoundTrigger.KeyphraseRecognitionEvent recognitionEvent) {
- int sampleRate = recognitionEvent.getCaptureFormat().getSampleRate();
- return new AudioRecord(
- new AudioAttributes.Builder()
- .setInternalCapturePreset(MediaRecorder.AudioSource.HOTWORD).build(),
- recognitionEvent.getCaptureFormat(),
- getBufferSizeInBytes(
- sampleRate,
- MAX_STREAMING_SECONDS,
- recognitionEvent.getCaptureFormat().getChannelCount()),
- recognitionEvent.getCaptureSession());
- }
-
- @Nullable
- private AudioRecord createMicAudioRecord(AudioFormat audioFormat) {
- if (DEBUG) {
- Slog.i(TAG, "#createAudioRecord");
- }
- try {
- AudioRecord audioRecord = new AudioRecord(
- new AudioAttributes.Builder()
- .setInternalCapturePreset(MediaRecorder.AudioSource.HOTWORD).build(),
- audioFormat,
- getBufferSizeInBytes(
- audioFormat.getSampleRate(),
- MICROPHONE_BUFFER_LENGTH_SECONDS,
- audioFormat.getChannelCount()),
- AudioManager.AUDIO_SESSION_ID_GENERATE);
-
- if (audioRecord.getState() != AudioRecord.STATE_INITIALIZED) {
- Slog.w(TAG, "Failed to initialize AudioRecord");
- audioRecord.release();
- return null;
- }
-
- return audioRecord;
- } catch (IllegalArgumentException e) {
- Slog.e(TAG, "Failed to create AudioRecord", e);
- return null;
- }
- }
-
- @Nullable
- private AudioRecord createFakeAudioRecord() {
- if (DEBUG) {
- Slog.i(TAG, "#createFakeAudioRecord");
- }
- try {
- AudioRecord audioRecord = new AudioRecord.Builder()
- .setAudioFormat(new AudioFormat.Builder()
- .setSampleRate(32000)
- .setEncoding(AudioFormat.ENCODING_PCM_16BIT)
- .setChannelMask(AudioFormat.CHANNEL_IN_MONO).build())
- .setAudioAttributes(new AudioAttributes.Builder()
- .setInternalCapturePreset(MediaRecorder.AudioSource.HOTWORD).build())
- .setBufferSizeInBytes(
- AudioRecord.getMinBufferSize(32000,
- AudioFormat.CHANNEL_IN_MONO,
- AudioFormat.ENCODING_PCM_16BIT) * 2)
- .build();
-
- if (audioRecord.getState() != AudioRecord.STATE_INITIALIZED) {
- Slog.w(TAG, "Failed to initialize AudioRecord");
- audioRecord.release();
- return null;
- }
- return audioRecord;
- } catch (IllegalArgumentException e) {
- Slog.e(TAG, "Failed to create AudioRecord", e);
- }
- return null;
- }
-
- /**
- * Returns the number of bytes required to store {@code bufferLengthSeconds} of audio sampled at
- * {@code sampleRate} Hz, using the format returned by DSP audio capture.
- */
- private static int getBufferSizeInBytes(
- int sampleRate, int bufferLengthSeconds, int intChannelCount) {
- return BYTES_PER_SAMPLE * sampleRate * bufferLengthSeconds * intChannelCount;
- }
-
- private static Pair<ParcelFileDescriptor, ParcelFileDescriptor> createPipe() {
- ParcelFileDescriptor[] fileDescriptors;
- try {
- fileDescriptors = ParcelFileDescriptor.createPipe();
- } catch (IOException e) {
- Slog.e(TAG, "Failed to create audio stream pipe", e);
- return null;
- }
-
- return Pair.create(fileDescriptors[0], fileDescriptors[1]);
- }
-
public void dump(String prefix, PrintWriter pw) {
- pw.print(prefix); pw.print("mBound="); pw.println(mBound);
- }
-
- private interface AudioReader extends Closeable {
- int read(byte[] dest, int offset, int length) throws IOException;
-
- static AudioReader createFromInputStream(InputStream is) {
- return new AudioReader() {
- @Override
- public int read(byte[] dest, int offset, int length) throws IOException {
- return is.read(dest, offset, length);
- }
-
- @Override
- public void close() throws IOException {
- is.close();
- }
- };
- }
-
- static AudioReader createFromAudioRecord(AudioRecord record) {
- record.startRecording();
-
- return new AudioReader() {
- @Override
- public int read(byte[] dest, int offset, int length) throws IOException {
- return record.read(dest, offset, length);
- }
-
- @Override
- public void close() throws IOException {
- record.stop();
- record.release();
- }
- };
- }
+ pw.print(prefix);
+ pw.print("mBound=" + mRemoteHotwordDetectionService.isBound());
+ pw.print(", mValidatingDspTrigger=" + mValidatingDspTrigger);
+ pw.print(", mPerformingSoftwareHotwordDetection=" + mPerformingSoftwareHotwordDetection);
+ pw.print(", mRestartCount=" + mServiceConnectionFactory.mRestartCount);
+ pw.println(", mLastRestartInstant=" + mLastRestartInstant);
}
private void handleExternalSourceHotwordDetection(
@@ -605,8 +585,7 @@ final class HotwordDetectionConnection {
if (DEBUG) {
Slog.d(TAG, "#handleExternalSourceHotwordDetection");
}
- AudioReader audioSource = AudioReader.createFromInputStream(
- new ParcelFileDescriptor.AutoCloseInputStream(audioStream));
+ InputStream audioSource = new ParcelFileDescriptor.AutoCloseInputStream(audioStream);
Pair<ParcelFileDescriptor, ParcelFileDescriptor> clientPipe = createPipe();
if (clientPipe == null) {
@@ -621,7 +600,7 @@ final class HotwordDetectionConnection {
}
mAudioCopyExecutor.execute(() -> {
- try (AudioReader source = audioSource;
+ try (InputStream source = audioSource;
OutputStream fos =
new ParcelFileDescriptor.AutoCloseOutputStream(serviceAudioSink)) {
@@ -681,6 +660,150 @@ final class HotwordDetectionConnection {
}));
}
+ private class ServiceConnectionFactory {
+ private final Intent mIntent;
+ private final int mBindingFlags;
+
+ private int mRestartCount = 0;
+
+ ServiceConnectionFactory(@NonNull Intent intent, boolean bindInstantServiceAllowed) {
+ mIntent = intent;
+ mBindingFlags = bindInstantServiceAllowed ? Context.BIND_ALLOW_INSTANT : 0;
+ }
+
+ ServiceConnection create() {
+ ServiceConnection connection =
+ new ServiceConnection(mContext, mIntent, mBindingFlags, mUser,
+ IHotwordDetectionService.Stub::asInterface, ++mRestartCount);
+ connection.connect();
+
+ updateAudioFlinger(connection);
+ updateContentCaptureManager(connection);
+ return connection;
+ }
+ }
+
+ private class ServiceConnection extends ServiceConnector.Impl<IHotwordDetectionService> {
+ private final Object mLock = new Object();
+
+ private final Intent mIntent;
+ private final int mBindingFlags;
+ private final int mInstanceNumber;
+
+ private boolean mRespectServiceConnectionStatusChanged = true;
+ private boolean mIsBound = false;
+
+ ServiceConnection(@NonNull Context context,
+ @NonNull Intent intent, int bindingFlags, int userId,
+ @Nullable Function<IBinder, IHotwordDetectionService> binderAsInterface,
+ int instanceNumber) {
+ super(context, intent, bindingFlags, userId, binderAsInterface);
+ this.mIntent = intent;
+ this.mBindingFlags = bindingFlags;
+ this.mInstanceNumber = instanceNumber;
+ }
+
+ @Override // from ServiceConnector.Impl
+ protected void onServiceConnectionStatusChanged(IHotwordDetectionService service,
+ boolean connected) {
+ if (DEBUG) {
+ Slog.d(TAG, "onServiceConnectionStatusChanged connected = " + connected);
+ }
+ synchronized (mLock) {
+ if (!mRespectServiceConnectionStatusChanged) {
+ if (DEBUG) {
+ Slog.d(TAG, "Ignored onServiceConnectionStatusChanged event");
+ }
+ return;
+ }
+ mIsBound = connected;
+ }
+ }
+
+ @Override
+ protected long getAutoDisconnectTimeoutMs() {
+ return -1;
+ }
+
+ @Override
+ public void binderDied() {
+ super.binderDied();
+ synchronized (mLock) {
+ if (!mRespectServiceConnectionStatusChanged) {
+ if (DEBUG) {
+ Slog.d(TAG, "Ignored #binderDied event");
+ }
+ return;
+ }
+
+ Slog.w(TAG, "binderDied");
+ try {
+ mCallback.onError(-1);
+ } catch (RemoteException e) {
+ Slog.w(TAG, "Failed to report onError status: " + e);
+ }
+ }
+ }
+
+ @Override
+ protected boolean bindService(
+ @NonNull android.content.ServiceConnection serviceConnection) {
+ try {
+ return mContext.bindIsolatedService(
+ mIntent,
+ Context.BIND_AUTO_CREATE | mBindingFlags,
+ "hotword_detector_" + mInstanceNumber,
+ mExecutor,
+ serviceConnection);
+ } catch (IllegalArgumentException e) {
+ Slog.wtf(TAG, "Can't bind to the hotword detection service!", e);
+ return false;
+ }
+ }
+
+ boolean isBound() {
+ synchronized (mLock) {
+ return mIsBound;
+ }
+ }
+
+ void ignoreConnectionStatusEvents() {
+ synchronized (mLock) {
+ mRespectServiceConnectionStatusChanged = false;
+ }
+ }
+ }
+
+ private static Pair<ParcelFileDescriptor, ParcelFileDescriptor> createPipe() {
+ ParcelFileDescriptor[] fileDescriptors;
+ try {
+ fileDescriptors = ParcelFileDescriptor.createPipe();
+ } catch (IOException e) {
+ Slog.e(TAG, "Failed to create audio stream pipe", e);
+ return null;
+ }
+
+ return Pair.create(fileDescriptors[0], fileDescriptors[1]);
+ }
+
+ private static void updateAudioFlinger(ServiceConnection connection) {
+ // TODO: Consider using a proxy that limits the exposed API surface.
+ IBinder audioFlinger = ServiceManager.getService("media.audio_flinger");
+ if (audioFlinger == null) {
+ throw new IllegalStateException("Service media.audio_flinger wasn't found.");
+ }
+ connection.post(service -> service.updateAudioFlinger(audioFlinger));
+ }
+
+ private static void updateContentCaptureManager(ServiceConnection connection) {
+ IBinder b = ServiceManager
+ .getService(Context.CONTENT_CAPTURE_MANAGER_SERVICE);
+ IContentCaptureManager binderService = IContentCaptureManager.Stub.asInterface(b);
+ connection.post(
+ service -> service.updateContentCaptureManager(binderService,
+ new ContentCaptureOptions(null)));
+ }
+
private static void bestEffortClose(Closeable closeable) {
try {
closeable.close();
diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
index bc812c2ae4a7..162acba8002d 100644
--- a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
+++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
@@ -795,6 +795,10 @@ public class VoiceInteractionManagerService extends SystemService {
Settings.Secure.ASSISTANT, null, userHandle);
}
+ void forceRestartHotwordDetector() {
+ mImpl.forceRestartHotwordDetector();
+ }
+
@Override
public void showSession(Bundle args, int flags) {
synchronized (this) {
diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java
index ca30bc51e046..89c5a720ee7e 100644
--- a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java
+++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java
@@ -562,6 +562,14 @@ class VoiceInteractionManagerServiceImpl implements VoiceInteractionSessionConne
&& (serviceInfo.flags & ServiceInfo.FLAG_EXTERNAL_SERVICE) == 0;
}
+ void forceRestartHotwordDetector() {
+ if (mHotwordDetectionConnection == null) {
+ Slog.w(TAG, "Failed to force-restart hotword detection: no hotword detection active");
+ return;
+ }
+ mHotwordDetectionConnection.forceRestart();
+ }
+
public void dumpLocked(FileDescriptor fd, PrintWriter pw, String[] args) {
if (!mValid) {
pw.print(" NOT VALID: ");
diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceShellCommand.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceShellCommand.java
index 2e3ca0157a3b..cdd8f7b91d9d 100644
--- a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceShellCommand.java
+++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceShellCommand.java
@@ -54,6 +54,8 @@ final class VoiceInteractionManagerServiceShellCommand extends ShellCommand {
return requestHide(pw);
case "disable":
return requestDisable(pw);
+ case "restart-detection":
+ return requestRestartDetection(pw);
default:
return handleDefaultCommands(cmd);
}
@@ -74,6 +76,8 @@ final class VoiceInteractionManagerServiceShellCommand extends ShellCommand {
pw.println("");
pw.println(" disable [true|false]");
pw.println(" Temporarily disable (when true) service");
+ pw.println(" restart-detection");
+ pw.println(" Force a restart of a hotword detection service");
pw.println("");
}
}
@@ -143,6 +147,16 @@ final class VoiceInteractionManagerServiceShellCommand extends ShellCommand {
return 0;
}
+ private int requestRestartDetection(PrintWriter pw) {
+ Slog.i(TAG, "requestRestartDetection()");
+ try {
+ mService.forceRestartHotwordDetector();
+ } catch (Exception e) {
+ return handleError(pw, "requestRestartDetection()", e);
+ }
+ return 0;
+ }
+
private static int handleError(PrintWriter pw, String message, Exception e) {
Slog.e(TAG, "error calling " + message, e);
pw.printf("Error calling %s: %s\n", message, e);
diff --git a/telecomm/java/android/telecom/TelecomManager.java b/telecomm/java/android/telecom/TelecomManager.java
index 1953af4adee5..e000265f0a2c 100644
--- a/telecomm/java/android/telecom/TelecomManager.java
+++ b/telecomm/java/android/telecom/TelecomManager.java
@@ -1018,6 +1018,16 @@ public class TelecomManager {
// this magic number is a bug ID
public static final long ENABLE_GET_CALL_STATE_PERMISSION_PROTECTION = 157233955L;
+ /**
+ * Enable READ_PHONE_NUMBERS or READ_PRIVILEGED_PHONE_STATE protections on
+ * {@link TelecomManager#getPhoneAccount(PhoneAccountHandle)}.
+ * @hide
+ */
+ @ChangeId
+ @EnabledSince(targetSdkVersion = Build.VERSION_CODES.S)
+ // bug ID
+ public static final long ENABLE_GET_PHONE_ACCOUNT_PERMISSION_PROTECTION = 183407956L;
+
private static final String TAG = "TelecomManager";
@@ -1351,6 +1361,9 @@ public class TelecomManager {
* Return the {@link PhoneAccount} for a specified {@link PhoneAccountHandle}. Object includes
* resources which can be used in a user interface.
*
+ * Requires Permission:
+ * {@link android.Manifest.permission#READ_PHONE_NUMBERS} for applications targeting API
+ * level 31+.
* @param account The {@link PhoneAccountHandle}.
* @return The {@link PhoneAccount} object.
*/
@@ -1358,7 +1371,7 @@ public class TelecomManager {
ITelecomService service = getTelecomService();
if (service != null) {
try {
- return service.getPhoneAccount(account);
+ return service.getPhoneAccount(account, mContext.getPackageName());
} catch (RemoteException e) {
Log.e(TAG, "Error calling ITelecomService#getPhoneAccount", e);
}
diff --git a/telecomm/java/com/android/internal/telecom/ITelecomService.aidl b/telecomm/java/com/android/internal/telecom/ITelecomService.aidl
index 18afde742abb..6f286d9f3006 100644
--- a/telecomm/java/com/android/internal/telecom/ITelecomService.aidl
+++ b/telecomm/java/com/android/internal/telecom/ITelecomService.aidl
@@ -79,7 +79,7 @@ interface ITelecomService {
/**
* @see TelecomManager#getPhoneAccount
*/
- PhoneAccount getPhoneAccount(in PhoneAccountHandle account);
+ PhoneAccount getPhoneAccount(in PhoneAccountHandle account, String callingPackage);
/**
* @see TelecomManager#getAllPhoneAccountsCount