summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Android.bp15
-rw-r--r--api/current.txt25
-rw-r--r--api/system-current.txt26
-rw-r--r--api/test-current.txt24
-rw-r--r--cmds/bootanimation/BootAnimation.cpp69
-rw-r--r--cmds/bootanimation/BootAnimation.h4
-rw-r--r--cmds/bootanimation/bootanimation_main.cpp8
-rw-r--r--cmds/statsd/src/FieldValue.cpp19
-rw-r--r--cmds/statsd/src/FieldValue.h3
-rw-r--r--cmds/statsd/src/StatsService.cpp2
-rw-r--r--cmds/statsd/src/anomaly/AlarmTracker.cpp4
-rw-r--r--cmds/statsd/src/anomaly/AnomalyTracker.cpp14
-rw-r--r--cmds/statsd/src/anomaly/AnomalyTracker.h8
-rw-r--r--cmds/statsd/src/anomaly/DurationAnomalyTracker.cpp8
-rw-r--r--cmds/statsd/src/anomaly/subscriber_util.cpp13
-rw-r--r--cmds/statsd/src/anomaly/subscriber_util.h7
-rw-r--r--cmds/statsd/src/atoms.proto32
-rw-r--r--cmds/statsd/src/external/StatsPullerManager.cpp6
-rw-r--r--cmds/statsd/src/metrics/CountMetricProducer.cpp2
-rw-r--r--cmds/statsd/src/metrics/GaugeMetricProducer.cpp4
-rw-r--r--cmds/statsd/src/metrics/ValueMetricProducer.cpp4
-rw-r--r--cmds/statsd/src/metrics/duration_helper/DurationTracker.h4
-rw-r--r--cmds/statsd/src/packages/UidMap.cpp100
-rw-r--r--cmds/statsd/src/packages/UidMap.h15
-rw-r--r--cmds/statsd/src/stats_log.proto14
-rw-r--r--cmds/statsd/src/subscriber/IncidentdReporter.cpp72
-rw-r--r--cmds/statsd/src/subscriber/IncidentdReporter.h4
-rw-r--r--cmds/statsd/tests/anomaly/AnomalyTracker_test.cpp3
-rw-r--r--core/java/android/app/Activity.java5
-rw-r--r--core/java/android/app/AppOpsManager.java40
-rw-r--r--core/java/android/app/Service.java3
-rw-r--r--core/java/android/app/SystemServiceRegistry.java14
-rw-r--r--core/java/android/app/UiModeManager.java6
-rw-r--r--core/java/android/app/usage/UsageStats.java2
-rw-r--r--core/java/android/content/Context.java8
-rw-r--r--core/java/android/content/PermissionChecker.java6
-rw-r--r--core/java/android/content/pm/IPackageManager.aidl2
-rw-r--r--core/java/android/content/pm/PackageManager.java7
-rw-r--r--core/java/android/content/pm/ServiceInfo.java7
-rw-r--r--core/java/android/database/sqlite/SQLiteQueryBuilder.java42
-rw-r--r--core/java/android/net/ConnectivityManager.java5
-rw-r--r--core/java/android/net/IConnectivityManager.aidl2
-rw-r--r--core/java/android/net/INetworkMonitor.aidl1
-rw-r--r--core/java/android/net/INetworkMonitorCallbacks.aidl1
-rw-r--r--core/java/android/net/NetworkStack.java265
-rw-r--r--core/java/android/os/GraphicsEnvironment.java19
-rw-r--r--core/java/android/permission/PermissionControllerManager.java62
-rw-r--r--core/java/android/permission/PermissionManagerInternal.java62
-rw-r--r--core/java/android/provider/BaseColumns.java9
-rw-r--r--core/java/android/provider/Column.java50
-rw-r--r--core/java/android/provider/MediaStore.java311
-rw-r--r--core/java/android/service/contentcapture/ContentCaptureService.java31
-rw-r--r--core/java/android/service/notification/Adjustment.java9
-rw-r--r--core/java/android/service/notification/NotificationAssistantService.java14
-rw-r--r--core/java/android/service/notification/NotificationStats.java7
-rw-r--r--core/java/android/view/ContextThemeWrapper.java13
-rw-r--r--core/java/android/view/autofill/AutofillManager.java17
-rw-r--r--core/java/android/view/contentcapture/ContentCaptureHelper.java78
-rw-r--r--core/java/android/view/contentcapture/ContentCaptureManager.java128
-rw-r--r--core/java/android/view/contentcapture/ContentCaptureSession.java19
-rw-r--r--core/java/android/view/contentcapture/MainContentCaptureSession.java140
-rw-r--r--core/java/android/widget/ProgressBar.java41
-rw-r--r--core/java/android/widget/Toast.java12
-rw-r--r--core/java/com/android/internal/app/ChooserActivity.java75
-rw-r--r--core/java/com/android/internal/os/BackgroundThread.java12
-rw-r--r--core/java/com/android/server/backup/PermissionBackupHelper.java20
-rw-r--r--core/jni/Android.bp1
-rw-r--r--core/jni/android_media_AudioSystem.cpp2
-rw-r--r--core/jni/android_os_GraphicsEnvironment.cpp9
-rw-r--r--core/jni/com_android_internal_os_Zygote.cpp157
-rw-r--r--core/res/res/values-night/themes_device_defaults.xml3
-rw-r--r--core/res/res/values/attrs.xml15
-rw-r--r--core/res/res/values/config.xml17
-rw-r--r--core/res/res/values/public.xml2
-rw-r--r--core/res/res/values/strings.xml2
-rw-r--r--core/res/res/values/symbols.xml7
-rw-r--r--core/res/res/values/themes_device_defaults.xml5
-rw-r--r--graphics/java/android/graphics/Bitmap.java6
-rw-r--r--keystore/java/android/security/keystore/AndroidKeyStoreKeyGeneratorSpi.java8
-rw-r--r--libs/androidfw/include/androidfw/ResourceTypes.h4
-rw-r--r--libs/hwui/thread/ThreadBase.h2
-rw-r--r--libs/incident/proto/android/os/header.proto5
-rw-r--r--location/java/android/location/ILocationManager.aidl3
-rw-r--r--location/java/android/location/LocationManager.java12
-rw-r--r--media/java/android/media/AudioFocusInfo.java23
-rw-r--r--media/java/android/media/AudioFocusRequest.java6
-rw-r--r--media/java/android/media/AudioRecord.java17
-rw-r--r--media/java/android/media/MediaHTTPConnection.java32
-rw-r--r--media/java/android/media/MicrophoneDirection.java41
-rw-r--r--packages/CaptivePortalLogin/Android.bp2
-rw-r--r--packages/CaptivePortalLogin/AndroidManifest.xml2
-rw-r--r--packages/ExtServices/src/android/ext/services/notification/Assistant.java6
-rw-r--r--packages/NetworkStack/Android.bp3
-rw-r--r--packages/NetworkStack/AndroidManifest.xml2
-rw-r--r--packages/NetworkStack/jarjar-rules-shared.txt19
-rw-r--r--packages/NetworkStack/src/android/net/dhcp/DhcpPacketListener.java2
-rw-r--r--packages/NetworkStack/src/android/net/util/FdEventsReader.java (renamed from core/java/android/net/shared/FdEventsReader.java)3
-rw-r--r--packages/NetworkStack/src/android/net/util/PacketReader.java1
-rw-r--r--packages/NetworkStack/src/com/android/server/NetworkStackService.java6
-rw-r--r--packages/NetworkStack/src/com/android/server/connectivity/NetworkMonitor.java36
-rw-r--r--packages/NetworkStack/tests/Android.bp1
-rw-r--r--packages/NetworkStack/tests/src/android/net/apf/ApfTest.java42
-rw-r--r--packages/NetworkStack/tests/src/com/android/server/connectivity/NetworkMonitorTest.java29
-rw-r--r--packages/NetworkStackPermissionStub/Android.bp2
-rw-r--r--packages/SettingsLib/res/values-af/strings.xml7
-rw-r--r--packages/SettingsLib/res/values-am/strings.xml7
-rw-r--r--packages/SettingsLib/res/values-ar/strings.xml7
-rw-r--r--packages/SettingsLib/res/values-as/strings.xml31
-rw-r--r--packages/SettingsLib/res/values-az/strings.xml7
-rw-r--r--packages/SettingsLib/res/values-b+sr+Latn/strings.xml7
-rw-r--r--packages/SettingsLib/res/values-be/strings.xml7
-rw-r--r--packages/SettingsLib/res/values-bg/strings.xml7
-rw-r--r--packages/SettingsLib/res/values-bn/strings.xml29
-rw-r--r--packages/SettingsLib/res/values-bs/strings.xml7
-rw-r--r--packages/SettingsLib/res/values-ca/strings.xml7
-rw-r--r--packages/SettingsLib/res/values-cs/strings.xml7
-rw-r--r--packages/SettingsLib/res/values-da/strings.xml7
-rw-r--r--packages/SettingsLib/res/values-de/strings.xml7
-rw-r--r--packages/SettingsLib/res/values-el/strings.xml7
-rw-r--r--packages/SettingsLib/res/values-en-rAU/strings.xml7
-rw-r--r--packages/SettingsLib/res/values-en-rCA/strings.xml7
-rw-r--r--packages/SettingsLib/res/values-en-rGB/strings.xml7
-rw-r--r--packages/SettingsLib/res/values-en-rIN/strings.xml7
-rw-r--r--packages/SettingsLib/res/values-en-rXC/strings.xml7
-rw-r--r--packages/SettingsLib/res/values-es-rUS/strings.xml7
-rw-r--r--packages/SettingsLib/res/values-es/strings.xml7
-rw-r--r--packages/SettingsLib/res/values-et/strings.xml7
-rw-r--r--packages/SettingsLib/res/values-eu/strings.xml11
-rw-r--r--packages/SettingsLib/res/values-fa/strings.xml7
-rw-r--r--packages/SettingsLib/res/values-fi/strings.xml7
-rw-r--r--packages/SettingsLib/res/values-fr-rCA/strings.xml7
-rw-r--r--packages/SettingsLib/res/values-fr/strings.xml7
-rw-r--r--packages/SettingsLib/res/values-gl/strings.xml7
-rw-r--r--packages/SettingsLib/res/values-gu/strings.xml8
-rw-r--r--packages/SettingsLib/res/values-hi/strings.xml7
-rw-r--r--packages/SettingsLib/res/values-hr/strings.xml7
-rw-r--r--packages/SettingsLib/res/values-hu/strings.xml7
-rw-r--r--packages/SettingsLib/res/values-hy/strings.xml7
-rw-r--r--packages/SettingsLib/res/values-in/strings.xml7
-rw-r--r--packages/SettingsLib/res/values-is/strings.xml7
-rw-r--r--packages/SettingsLib/res/values-it/strings.xml7
-rw-r--r--packages/SettingsLib/res/values-iw/strings.xml8
-rw-r--r--packages/SettingsLib/res/values-ja/strings.xml7
-rw-r--r--packages/SettingsLib/res/values-ka/strings.xml7
-rw-r--r--packages/SettingsLib/res/values-kk/strings.xml7
-rw-r--r--packages/SettingsLib/res/values-km/strings.xml7
-rw-r--r--packages/SettingsLib/res/values-kn/strings.xml29
-rw-r--r--packages/SettingsLib/res/values-ko/strings.xml7
-rw-r--r--packages/SettingsLib/res/values-ky/strings.xml7
-rw-r--r--packages/SettingsLib/res/values-lo/strings.xml7
-rw-r--r--packages/SettingsLib/res/values-lt/strings.xml7
-rw-r--r--packages/SettingsLib/res/values-lv/strings.xml7
-rw-r--r--packages/SettingsLib/res/values-mk/strings.xml7
-rw-r--r--packages/SettingsLib/res/values-ml/strings.xml8
-rw-r--r--packages/SettingsLib/res/values-mn/strings.xml11
-rw-r--r--packages/SettingsLib/res/values-mr/strings.xml8
-rw-r--r--packages/SettingsLib/res/values-ms/strings.xml7
-rw-r--r--packages/SettingsLib/res/values-my/strings.xml7
-rw-r--r--packages/SettingsLib/res/values-nb/strings.xml7
-rw-r--r--packages/SettingsLib/res/values-ne/strings.xml29
-rw-r--r--packages/SettingsLib/res/values-nl/strings.xml7
-rw-r--r--packages/SettingsLib/res/values-or/strings.xml29
-rw-r--r--packages/SettingsLib/res/values-pa/strings.xml29
-rw-r--r--packages/SettingsLib/res/values-pl/strings.xml7
-rw-r--r--packages/SettingsLib/res/values-pt-rBR/strings.xml7
-rw-r--r--packages/SettingsLib/res/values-pt-rPT/strings.xml7
-rw-r--r--packages/SettingsLib/res/values-pt/strings.xml7
-rw-r--r--packages/SettingsLib/res/values-ro/strings.xml7
-rw-r--r--packages/SettingsLib/res/values-ru/strings.xml7
-rw-r--r--packages/SettingsLib/res/values-si/strings.xml7
-rw-r--r--packages/SettingsLib/res/values-sk/strings.xml7
-rw-r--r--packages/SettingsLib/res/values-sl/strings.xml7
-rw-r--r--packages/SettingsLib/res/values-sq/strings.xml7
-rw-r--r--packages/SettingsLib/res/values-sr/strings.xml7
-rw-r--r--packages/SettingsLib/res/values-sv/strings.xml7
-rw-r--r--packages/SettingsLib/res/values-sw/strings.xml7
-rw-r--r--packages/SettingsLib/res/values-ta/strings.xml39
-rw-r--r--packages/SettingsLib/res/values-te/strings.xml7
-rw-r--r--packages/SettingsLib/res/values-th/strings.xml7
-rw-r--r--packages/SettingsLib/res/values-tl/strings.xml7
-rw-r--r--packages/SettingsLib/res/values-tr/strings.xml7
-rw-r--r--packages/SettingsLib/res/values-uk/strings.xml7
-rw-r--r--packages/SettingsLib/res/values-ur/strings.xml29
-rw-r--r--packages/SettingsLib/res/values-uz/strings.xml7
-rw-r--r--packages/SettingsLib/res/values-vi/strings.xml7
-rw-r--r--packages/SettingsLib/res/values-zh-rCN/strings.xml7
-rw-r--r--packages/SettingsLib/res/values-zh-rHK/strings.xml19
-rw-r--r--packages/SettingsLib/res/values-zh-rTW/strings.xml7
-rw-r--r--packages/SettingsLib/res/values-zu/strings.xml7
-rw-r--r--packages/SettingsLib/src/com/android/settingslib/SliceBroadcastRelay.java33
-rw-r--r--packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java2
-rw-r--r--packages/SystemUI/AndroidManifest.xml5
-rw-r--r--packages/SystemUI/res/drawable/privacy_chip_bg.xml4
-rw-r--r--packages/SystemUI/res/layout/ongoing_privacy_chip.xml65
-rw-r--r--packages/SystemUI/res/raw/image_wallpaper_fragment_shader.glsl27
-rw-r--r--packages/SystemUI/res/raw/image_wallpaper_vertex_shader.glsl8
-rw-r--r--packages/SystemUI/res/values-land/dimens.xml1
-rw-r--r--packages/SystemUI/res/values/dimens.xml28
-rw-r--r--packages/SystemUI/res/values/strings.xml8
-rw-r--r--packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java1
-rw-r--r--packages/SystemUI/src/com/android/systemui/ImageWallpaper.java106
-rw-r--r--packages/SystemUI/src/com/android/systemui/SystemUIFactory.java3
-rw-r--r--packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java5
-rw-r--r--packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java72
-rw-r--r--packages/SystemUI/src/com/android/systemui/bubbles/BubbleTouchHandler.java168
-rw-r--r--packages/SystemUI/src/com/android/systemui/bubbles/BubbleView.java24
-rw-r--r--packages/SystemUI/src/com/android/systemui/bubbles/animation/ExpandedAnimationController.java160
-rw-r--r--packages/SystemUI/src/com/android/systemui/bubbles/animation/PhysicsAnimationLayout.java74
-rw-r--r--packages/SystemUI/src/com/android/systemui/glwallpaper/ImageGLProgram.java115
-rw-r--r--packages/SystemUI/src/com/android/systemui/glwallpaper/ImageGLWallpaper.java259
-rw-r--r--packages/SystemUI/src/com/android/systemui/glwallpaper/ImageProcessHelper.java144
-rw-r--r--packages/SystemUI/src/com/android/systemui/glwallpaper/ImageRevealHelper.java97
-rw-r--r--packages/SystemUI/src/com/android/systemui/glwallpaper/ImageWallpaperRenderer.java150
-rw-r--r--packages/SystemUI/src/com/android/systemui/privacy/OngoingPrivacyChip.kt11
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java24
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/AlertingNotificationManager.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/AmbientPulseManager.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/MediaArtworkProcessor.kt3
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationAlertingManager.java9
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryListener.java5
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java6
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationRowBinder.java10
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationEntry.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java16
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentInflater.java (renamed from packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationInflater.java)9
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationInlineImageCache.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationViewWrapper.java20
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/CollapsedStatusBarFragment.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarEdgePanel.java232
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java20
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationGroupAlertTransferHelper.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconAreaController.java21
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java25
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusIconContainer.java50
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManager.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/wallpaper/AodMaskView.java2
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/bubbles/animation/ExpandedAnimationControllerTest.java71
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/bubbles/animation/PhysicsAnimationLayoutTestCase.java5
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/AlertingNotificationManagerTest.java2
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationTestHelper.java6
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationEntryManagerTest.java4
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowTest.java6
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationContentInflaterTest.java (renamed from packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationInflaterTest.java)51
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationViewWrapperTest.java (renamed from packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationViewWrapperTest.java)32
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationIconAreaControllerTest.java5
-rw-r--r--services/contentcapture/java/com/android/server/contentcapture/ContentCaptureManagerService.java69
-rw-r--r--services/contentcapture/java/com/android/server/contentcapture/ContentCapturePerUserService.java79
-rw-r--r--services/contentcapture/java/com/android/server/contentcapture/ContentCaptureServerSession.java6
-rw-r--r--services/core/java/com/android/server/ConnectivityService.java119
-rw-r--r--services/core/java/com/android/server/ExtconUEventObserver.java5
-rw-r--r--services/core/java/com/android/server/FgThread.java12
-rw-r--r--services/core/java/com/android/server/IoThread.java12
-rw-r--r--services/core/java/com/android/server/LocationManagerService.java13
-rw-r--r--services/core/java/com/android/server/UiModeManagerService.java44
-rw-r--r--services/core/java/com/android/server/am/OomAdjuster.java3
-rw-r--r--services/core/java/com/android/server/appbinding/finders/CarrierMessagingClientServiceFinder.java6
-rw-r--r--services/core/java/com/android/server/attention/AttentionManagerService.java96
-rw-r--r--services/core/java/com/android/server/audio/AudioDeviceBroker.java4
-rw-r--r--services/core/java/com/android/server/audio/AudioService.java46
-rw-r--r--services/core/java/com/android/server/audio/FocusRequester.java27
-rw-r--r--services/core/java/com/android/server/audio/MediaFocusControl.java33
-rw-r--r--services/core/java/com/android/server/connectivity/Tethering.java2
-rw-r--r--services/core/java/com/android/server/connectivity/Vpn.java77
-rw-r--r--services/core/java/com/android/server/connectivity/tethering/TetheringDependencies.java4
-rw-r--r--services/core/java/com/android/server/display/ColorDisplayService.java479
-rw-r--r--services/core/java/com/android/server/display/DisplayPowerController.java2
-rw-r--r--services/core/java/com/android/server/display/whitebalance/DisplayWhiteBalanceController.java47
-rw-r--r--services/core/java/com/android/server/display/whitebalance/DisplayWhiteBalanceFactory.java10
-rw-r--r--services/core/java/com/android/server/display/whitebalance/DisplayWhiteBalanceThrottler.java2
-rw-r--r--services/core/java/com/android/server/location/GnssLocationProvider.java10
-rw-r--r--services/core/java/com/android/server/location/GnssVisibilityControl.java95
-rw-r--r--services/core/java/com/android/server/om/OverlayManagerService.java7
-rw-r--r--services/core/java/com/android/server/pm/OWNERS3
-rw-r--r--services/core/java/com/android/server/pm/PackageInstallerService.java6
-rw-r--r--services/core/java/com/android/server/pm/PackageManagerService.java157
-rw-r--r--services/core/java/com/android/server/pm/Settings.java246
-rw-r--r--services/core/java/com/android/server/pm/permission/PermissionManagerService.java339
-rw-r--r--services/core/java/com/android/server/pm/permission/PermissionManagerServiceInternal.java (renamed from services/core/java/com/android/server/pm/permission/PermissionManagerInternal.java)11
-rw-r--r--services/core/java/com/android/server/pm/permission/TEST_MAPPING3
-rw-r--r--services/core/java/com/android/server/policy/DisplayFoldController.java53
-rw-r--r--services/core/java/com/android/server/policy/PhoneWindowManager.java18
-rw-r--r--services/core/java/com/android/server/policy/WindowManagerPolicy.java15
-rw-r--r--services/core/java/com/android/server/role/RoleManagerService.java2
-rw-r--r--services/core/java/com/android/server/stats/StatsCompanionService.java45
-rw-r--r--services/core/java/com/android/server/telecom/TelecomLoaderService.java4
-rw-r--r--services/core/java/com/android/server/wallpaper/WallpaperManagerService.java7
-rw-r--r--services/core/java/com/android/server/wm/ActivityStarter.java23
-rw-r--r--services/core/java/com/android/server/wm/WindowManagerService.java90
-rw-r--r--services/core/java/com/android/server/wm/WindowManagerShellCommand.java38
-rw-r--r--services/core/java/com/android/server/wm/WindowTraceBuffer.java157
-rw-r--r--services/core/java/com/android/server/wm/WindowTraceQueueBuffer.java105
-rw-r--r--services/core/java/com/android/server/wm/WindowTraceRingBuffer.java70
-rw-r--r--services/core/java/com/android/server/wm/WindowTracing.java281
-rw-r--r--services/java/com/android/server/SystemServer.java5
-rw-r--r--services/net/Android.bp1
-rw-r--r--services/net/java/android/net/NetworkStackClient.java289
-rw-r--r--services/net/java/android/net/dhcp/DhcpServerCallbacks.java (renamed from core/java/android/net/dhcp/DhcpServerCallbacks.java)0
-rw-r--r--services/net/java/android/net/ip/IpClientCallbacks.java (renamed from core/java/android/net/ip/IpClientCallbacks.java)0
-rw-r--r--services/net/java/android/net/ip/IpClientUtil.java24
-rw-r--r--services/net/java/android/net/ip/IpServer.java9
-rw-r--r--services/tests/servicestests/src/com/android/server/backup/testutils/IPackageManagerStub.java10
-rw-r--r--services/tests/servicestests/src/com/android/server/display/ColorDisplayServiceTest.java118
-rw-r--r--services/tests/servicestests/src/com/android/server/pm/PackageManagerSettingsTests.java23
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/WindowTraceBufferTest.java146
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/WindowTracingTest.java9
-rw-r--r--services/usage/java/com/android/server/usage/IntervalStats.java22
-rw-r--r--services/usage/java/com/android/server/usage/UsageStatsService.java116
-rw-r--r--telecomm/java/android/telecom/Connection.java2
-rw-r--r--telephony/java/android/provider/Telephony.java5
-rw-r--r--telephony/java/android/telephony/SmsMessage.java9
-rw-r--r--telephony/java/android/telephony/SubscriptionManager.java17
-rw-r--r--telephony/java/android/telephony/ims/ImsCallProfile.java5
-rw-r--r--telephony/java/com/android/internal/telephony/SmsMessageBase.java16
-rw-r--r--telephony/java/com/android/internal/telephony/cdma/SmsMessage.java40
-rw-r--r--telephony/java/com/android/internal/telephony/gsm/SmsMessage.java3
-rw-r--r--test-mock/api/test-current.txt2
-rw-r--r--tests/net/java/com/android/server/ConnectivityServiceTest.java124
-rw-r--r--tests/net/java/com/android/server/connectivity/LingerMonitorTest.java5
-rw-r--r--tests/net/java/com/android/server/connectivity/TetheringTest.java6
-rw-r--r--tests/net/java/com/android/server/connectivity/VpnTest.java10
-rw-r--r--tools/aapt2/Debug.cpp2
-rw-r--r--tools/aapt2/ResourceParser.cpp16
-rw-r--r--tools/aapt2/ResourceParser_test.cpp48
-rw-r--r--tools/aapt2/ResourceTable.h3
-rw-r--r--tools/aapt2/ResourceUtils.cpp4
-rw-r--r--tools/aapt2/Resources.proto4
-rw-r--r--tools/aapt2/StringPool.cpp22
-rw-r--r--tools/aapt2/StringPool.h6
-rw-r--r--tools/aapt2/StringPool_test.cpp18
-rw-r--r--tools/aapt2/cmd/Convert.cpp17
-rw-r--r--tools/aapt2/cmd/Link.cpp3
-rw-r--r--tools/aapt2/format/binary/BinaryResourceParser.cpp7
-rw-r--r--tools/aapt2/format/binary/TableFlattener.cpp60
-rw-r--r--tools/aapt2/format/binary/TableFlattener.h3
-rw-r--r--tools/aapt2/format/binary/TableFlattener_test.cpp34
-rw-r--r--tools/aapt2/format/proto/ProtoDeserialize.cpp3
-rw-r--r--tools/aapt2/format/proto/ProtoSerialize.cpp3
-rw-r--r--tools/aapt2/format/proto/ProtoSerialize_test.cpp13
-rw-r--r--wifi/java/android/net/wifi/p2p/WifiP2pGroup.java4
339 files changed, 6401 insertions, 3489 deletions
diff --git a/Android.bp b/Android.bp
index 995fe3e2465e..1ee7405b42ab 100644
--- a/Android.bp
+++ b/Android.bp
@@ -209,6 +209,7 @@ java_defaults {
"core/java/android/hardware/soundtrigger/IRecognitionStatusCallback.aidl",
"core/java/android/hardware/usb/IUsbManager.aidl",
"core/java/android/hardware/usb/IUsbSerialReader.aidl",
+ "core/java/android/net/ICaptivePortal.aidl",
"core/java/android/net/IConnectivityManager.aidl",
"core/java/android/hardware/ISensorPrivacyListener.aidl",
"core/java/android/hardware/ISensorPrivacyManager.aidl",
@@ -772,7 +773,7 @@ java_defaults {
"android.hardware.vibrator-V1.2-java",
"android.hardware.vibrator-V1.3-java",
"android.hardware.wifi-V1.0-java-constants",
- "networkstack-aidl-interfaces-java",
+ "networkstack-aidl-framework-java",
"netd_aidl_parcelables-java",
"devicepolicyprotosnano",
],
@@ -893,10 +894,8 @@ aidl_interface {
srcs: [
"core/java/android/net/ApfCapabilitiesParcelable.aidl",
"core/java/android/net/DhcpResultsParcelable.aidl",
- "core/java/android/net/ICaptivePortal.aidl",
"core/java/android/net/INetworkMonitor.aidl",
"core/java/android/net/INetworkMonitorCallbacks.aidl",
- "core/java/android/net/IIpMemoryStore.aidl",
"core/java/android/net/INetworkStackConnector.aidl",
"core/java/android/net/INetworkStackStatusCallback.aidl",
"core/java/android/net/InitialConfigurationParcelable.aidl",
@@ -915,6 +914,16 @@ aidl_interface {
"core/java/android/net/dhcp/IDhcpServerCallbacks.aidl",
"core/java/android/net/ip/IIpClient.aidl",
"core/java/android/net/ip/IIpClientCallbacks.aidl",
+ ],
+ api_dir: "aidl/networkstack",
+}
+
+aidl_interface {
+ name: "networkstack-aidl-framework",
+ local_include_dir: "core/java",
+ srcs: [
+ "core/java/android/net/TcpKeepalivePacketDataParcelable.aidl",
+ "core/java/android/net/IIpMemoryStore.aidl",
"core/java/android/net/ipmemorystore/**/*.aidl",
],
api_dir: "aidl/networkstack",
diff --git a/api/current.txt b/api/current.txt
index 15c4fdfed178..fe86cbe48375 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -2222,6 +2222,7 @@ package android {
field public static final int TextAppearance_WindowTitle = 16973907; // 0x1030053
field public static final int Theme = 16973829; // 0x1030005
field public static final int ThemeOverlay = 16974407; // 0x1030247
+ field public static final int ThemeOverlay_DeviceDefault_Accent_DayNight = 16974564; // 0x10302e4
field public static final int ThemeOverlay_Material = 16974408; // 0x1030248
field public static final int ThemeOverlay_Material_ActionBar = 16974409; // 0x1030249
field public static final int ThemeOverlay_Material_Dark = 16974411; // 0x103024b
@@ -2233,6 +2234,7 @@ package android {
field public static final int Theme_Black_NoTitleBar = 16973833; // 0x1030009
field public static final int Theme_Black_NoTitleBar_Fullscreen = 16973834; // 0x103000a
field public static final int Theme_DeviceDefault = 16974120; // 0x1030128
+ field public static final int Theme_DeviceDefault_DayNight = 16974563; // 0x10302e3
field public static final int Theme_DeviceDefault_Dialog = 16974126; // 0x103012e
field public static final int Theme_DeviceDefault_DialogWhenLarge = 16974134; // 0x1030136
field public static final int Theme_DeviceDefault_DialogWhenLarge_NoActionBar = 16974135; // 0x1030137
@@ -13064,6 +13066,10 @@ package android.database.sqlite {
method public String buildUnionSubQuery(String, String[], java.util.Set<java.lang.String>, int, String, String, String, String);
method @Deprecated public String buildUnionSubQuery(String, String[], java.util.Set<java.lang.String>, int, String, String, String[], String, String);
method public int delete(@NonNull android.database.sqlite.SQLiteDatabase, @Nullable String, @Nullable String[]);
+ method public android.database.sqlite.SQLiteDatabase.CursorFactory getCursorFactory();
+ method public boolean getDistinct();
+ method public java.util.Map<java.lang.String,java.lang.String> getProjectionMap();
+ method public boolean getStrict();
method public String getTables();
method public android.database.Cursor query(android.database.sqlite.SQLiteDatabase, String[], String, String[], String, String, String);
method public android.database.Cursor query(android.database.sqlite.SQLiteDatabase, String[], String, String[], String, String, String, String);
@@ -23408,7 +23414,7 @@ package android.media {
method @NonNull public android.media.AudioPresentation.Builder setProgramId(int);
}
- public class AudioRecord implements android.media.AudioRecordingMonitor android.media.AudioRouting {
+ public class AudioRecord implements android.media.AudioRecordingMonitor android.media.AudioRouting android.media.MicrophoneDirection {
ctor public AudioRecord(int, int, int, int, int) throws java.lang.IllegalArgumentException;
method public void addOnRoutingChangedListener(android.media.AudioRouting.OnRoutingChangedListener, android.os.Handler);
method @Deprecated public void addOnRoutingChangedListener(android.media.AudioRecord.OnRoutingChangedListener, android.os.Handler);
@@ -23443,6 +23449,8 @@ package android.media {
method public void release();
method public void removeOnRoutingChangedListener(android.media.AudioRouting.OnRoutingChangedListener);
method @Deprecated public void removeOnRoutingChangedListener(android.media.AudioRecord.OnRoutingChangedListener);
+ method public boolean setMicrophoneDirection(int);
+ method public boolean setMicrophoneFieldDimension(@FloatRange(from=-1.0, to=1.0) float);
method public int setNotificationMarkerPosition(int);
method public int setPositionNotificationPeriod(int);
method public boolean setPreferredDevice(android.media.AudioDeviceInfo);
@@ -26092,6 +26100,15 @@ package android.media {
field public static final android.media.MediaTimestamp TIMESTAMP_UNKNOWN;
}
+ public interface MicrophoneDirection {
+ method public boolean setMicrophoneDirection(int);
+ method public boolean setMicrophoneFieldDimension(@FloatRange(from=-1.0, to=1.0) float);
+ field public static final int MIC_DIRECTION_BACK = 2; // 0x2
+ field public static final int MIC_DIRECTION_EXTERNAL = 3; // 0x3
+ field public static final int MIC_DIRECTION_FRONT = 1; // 0x1
+ field public static final int MIC_DIRECTION_UNSPECIFIED = 0; // 0x0
+ }
+
public final class MicrophoneInfo {
method @NonNull public String getAddress();
method public java.util.List<android.util.Pair<java.lang.Integer,java.lang.Integer>> getChannelMapping();
@@ -41588,6 +41605,7 @@ package android.service.notification {
field public static final android.os.Parcelable.Creator<android.service.notification.Adjustment> CREATOR;
field public static final String KEY_CONTEXTUAL_ACTIONS = "key_contextual_actions";
field public static final String KEY_IMPORTANCE = "key_importance";
+ field public static final String KEY_SNOOZE_CRITERIA = "key_snooze_criteria";
field public static final String KEY_TEXT_REPLIES = "key_text_replies";
field public static final String KEY_USER_SENTIMENT = "key_user_sentiment";
}
@@ -41645,12 +41663,14 @@ package android.service.notification {
method public void onActionInvoked(@NonNull String, @NonNull android.app.Notification.Action, int);
method public final android.os.IBinder onBind(android.content.Intent);
method public void onNotificationDirectReplied(@NonNull String);
- method public android.service.notification.Adjustment onNotificationEnqueued(android.service.notification.StatusBarNotification);
+ method public abstract android.service.notification.Adjustment onNotificationEnqueued(android.service.notification.StatusBarNotification);
method public android.service.notification.Adjustment onNotificationEnqueued(android.service.notification.StatusBarNotification, android.app.NotificationChannel);
method public void onNotificationExpansionChanged(@NonNull String, boolean, boolean);
method public void onNotificationRemoved(android.service.notification.StatusBarNotification, android.service.notification.NotificationListenerService.RankingMap, android.service.notification.NotificationStats, int);
+ method public abstract void onNotificationSnoozedUntilContext(android.service.notification.StatusBarNotification, String);
method public void onNotificationsSeen(java.util.List<java.lang.String>);
method public void onSuggestedReplySent(@NonNull String, @NonNull CharSequence, int);
+ method public final void unsnoozeNotification(String);
field public static final String SERVICE_INTERFACE = "android.service.notification.NotificationAssistantService";
field public static final int SOURCE_FROM_APP = 0; // 0x0
field public static final int SOURCE_FROM_ASSISTANT = 1; // 0x1
@@ -49247,6 +49267,7 @@ package android.view {
ctor public ContextThemeWrapper(android.content.Context, android.content.res.Resources.Theme);
method public void applyOverrideConfiguration(android.content.res.Configuration);
method protected void onApplyThemeResource(android.content.res.Resources.Theme, int, boolean);
+ method public void setTheme(@Nullable android.content.res.Resources.Theme);
}
public final class Display {
diff --git a/api/system-current.txt b/api/system-current.txt
index 357f6a4a3607..142068cdb48f 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -309,6 +309,7 @@ package android.app {
method @Deprecated @RequiresPermission(android.Manifest.permission.GET_APP_OPS_STATS) public java.util.List<android.app.AppOpsManager.PackageOps> getOpsForPackage(int, String, int[]);
method @NonNull @RequiresPermission(android.Manifest.permission.GET_APP_OPS_STATS) public java.util.List<android.app.AppOpsManager.PackageOps> getOpsForPackage(int, @NonNull String, @Nullable java.lang.String...);
method @NonNull @RequiresPermission(android.Manifest.permission.GET_APP_OPS_STATS) public java.util.List<android.app.AppOpsManager.PackageOps> getPackagesForOps(@Nullable String[]);
+ method public int noteProxyOpNoThrow(@NonNull String, @Nullable String, int);
method public static int opToDefaultMode(@NonNull String);
method @Nullable public static String opToPermission(@NonNull String);
method @RequiresPermission("android.permission.MANAGE_APP_OPS_MODES") public void setMode(String, int, String, int);
@@ -3409,13 +3410,13 @@ package android.media {
public final class AudioFocusInfo implements android.os.Parcelable {
method public int describeContents();
- method public android.media.AudioAttributes getAttributes();
- method public String getClientId();
+ method @NonNull public android.media.AudioAttributes getAttributes();
+ method @NonNull public String getClientId();
method public int getClientUid();
method public int getFlags();
method public int getGainRequest();
method public int getLossReceived();
- method public String getPackageName();
+ method @NonNull public String getPackageName();
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator<android.media.AudioFocusInfo> CREATOR;
}
@@ -3475,7 +3476,7 @@ package android.media {
field public static final int PLAYER_TYPE_UNKNOWN = -1; // 0xffffffff
}
- public class AudioRecord implements android.media.AudioRecordingMonitor android.media.AudioRouting {
+ public class AudioRecord implements android.media.AudioRecordingMonitor android.media.AudioRouting android.media.MicrophoneDirection {
ctor public AudioRecord(android.media.AudioAttributes, android.media.AudioFormat, int, int) throws java.lang.IllegalArgumentException;
}
@@ -3933,7 +3934,7 @@ package android.net {
method @RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED) public void getLatestTetheringEntitlementValue(int, boolean, @NonNull android.net.ConnectivityManager.TetheringEntitlementValueListener, @Nullable android.os.Handler);
method @RequiresPermission(anyOf={android.Manifest.permission.TETHER_PRIVILEGED, android.Manifest.permission.WRITE_SETTINGS}) public boolean isTetheringSupported();
method @RequiresPermission(anyOf={"android.permission.NETWORK_SETTINGS", android.Manifest.permission.NETWORK_SETUP_WIZARD, "android.permission.NETWORK_STACK"}) public void setAirplaneMode(boolean);
- method @RequiresPermission(android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK) public void startCaptivePortalApp(android.os.Bundle);
+ method @RequiresPermission(android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK) public void startCaptivePortalApp(android.net.Network, android.os.Bundle);
method @RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED) public void startTethering(int, boolean, android.net.ConnectivityManager.OnStartTetheringCallback);
method @RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED) public void startTethering(int, boolean, android.net.ConnectivityManager.OnStartTetheringCallback, android.os.Handler);
method @RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED) public void stopTethering(int);
@@ -6350,7 +6351,8 @@ package android.service.contentcapture {
method public void onDestroyContentCaptureSession(@NonNull android.view.contentcapture.ContentCaptureSessionId);
method public void onDisconnected();
method public void onUserDataRemovalRequest(@NonNull android.view.contentcapture.UserDataRemovalRequest);
- method public final void setContentCaptureWhitelist(@Nullable java.util.List<java.lang.String>, @Nullable java.util.List<android.content.ComponentName>);
+ method @Deprecated public final void setContentCaptureWhitelist(@Nullable java.util.List<java.lang.String>, @Nullable java.util.List<android.content.ComponentName>);
+ method public final void setContentCaptureWhitelist(@Nullable java.util.Set<java.lang.String>, @Nullable java.util.Set<android.content.ComponentName>);
field public static final String SERVICE_INTERFACE = "android.service.contentcapture.ContentCaptureService";
}
@@ -6521,6 +6523,15 @@ package android.service.euicc {
package android.service.notification {
+ public final class Adjustment implements android.os.Parcelable {
+ ctor protected Adjustment(android.os.Parcel);
+ field public static final String KEY_PEOPLE = "key_people";
+ }
+
+ public final class NotificationStats implements android.os.Parcelable {
+ ctor protected NotificationStats(android.os.Parcel);
+ }
+
public final class SnoozeCriterion implements android.os.Parcelable {
ctor public SnoozeCriterion(String, CharSequence, CharSequence);
ctor protected SnoozeCriterion(android.os.Parcel);
@@ -9307,7 +9318,8 @@ package android.view.accessibility {
package android.view.autofill {
public final class AutofillManager {
- method public void setAugmentedAutofillWhitelist(@Nullable java.util.List<java.lang.String>, @Nullable java.util.List<android.content.ComponentName>);
+ method @Deprecated public void setAugmentedAutofillWhitelist(@Nullable java.util.List<java.lang.String>, @Nullable java.util.List<android.content.ComponentName>);
+ method public void setAugmentedAutofillWhitelist(@Nullable java.util.Set<java.lang.String>, @Nullable java.util.Set<android.content.ComponentName>);
}
}
diff --git a/api/test-current.txt b/api/test-current.txt
index 47d38a7d2f3a..16098c1a80fa 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -516,13 +516,20 @@ package android.content.pm {
method @RequiresPermission("android.permission.INTERACT_ACROSS_USERS_FULL") public abstract java.util.List<android.content.pm.PackageInfo> getInstalledPackagesAsUser(int, int);
method @Nullable public abstract String[] getNamesForUids(int[]);
method public abstract String getPermissionControllerPackageName();
+ method @RequiresPermission(anyOf={"android.permission.GRANT_RUNTIME_PERMISSIONS", "android.permission.REVOKE_RUNTIME_PERMISSIONS"}) public abstract int getPermissionFlags(String, String, @NonNull android.os.UserHandle);
method @NonNull public abstract String getServicesSystemSharedLibraryPackageName();
method @NonNull public abstract String getSharedSystemSharedLibraryPackageName();
method public String getWellbeingPackageName();
method @RequiresPermission("android.permission.GRANT_RUNTIME_PERMISSIONS") public abstract void grantRuntimePermission(@NonNull String, @NonNull String, @NonNull android.os.UserHandle);
method @RequiresPermission("android.permission.REVOKE_RUNTIME_PERMISSIONS") public abstract void revokeRuntimePermission(@NonNull String, @NonNull String, @NonNull android.os.UserHandle);
+ method @RequiresPermission(anyOf={"android.permission.GRANT_RUNTIME_PERMISSIONS", "android.permission.REVOKE_RUNTIME_PERMISSIONS"}) public abstract void updatePermissionFlags(String, String, int, int, @NonNull android.os.UserHandle);
field public static final String FEATURE_ADOPTABLE_STORAGE = "android.software.adoptable_storage";
field public static final String FEATURE_FILE_BASED_ENCRYPTION = "android.software.file_based_encryption";
+ field public static final int FLAG_PERMISSION_REVIEW_REQUIRED = 64; // 0x40
+ field public static final int FLAG_PERMISSION_REVOKE_ON_UPGRADE = 8; // 0x8
+ field public static final int FLAG_PERMISSION_REVOKE_WHEN_REQUESTED = 128; // 0x80
+ field public static final int FLAG_PERMISSION_USER_FIXED = 2; // 0x2
+ field public static final int FLAG_PERMISSION_USER_SET = 1; // 0x1
field public static final int MATCH_FACTORY_ONLY = 2097152; // 0x200000
field public static final int MATCH_KNOWN_PACKAGES = 4202496; // 0x402000
field public static final String SYSTEM_SHARED_LIBRARY_SERVICES = "android.ext.services";
@@ -802,6 +809,7 @@ package android.location {
public class LocationManager {
method public String[] getBackgroundThrottlingWhitelist();
+ method public String[] getIgnoreSettingsWhitelist();
method @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public void requestLocationUpdates(android.location.LocationRequest, android.location.LocationListener, android.os.Looper);
method @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public void requestLocationUpdates(android.location.LocationRequest, android.app.PendingIntent);
method @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public void setLocationEnabledForUser(boolean, android.os.UserHandle);
@@ -936,7 +944,7 @@ package android.net {
}
public class ConnectivityManager {
- method @RequiresPermission(android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK) public void startCaptivePortalApp(android.os.Bundle);
+ method @RequiresPermission(android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK) public void startCaptivePortalApp(android.net.Network, android.os.Bundle);
field public static final String EXTRA_CAPTIVE_PORTAL_PROBE_SPEC = "android.net.extra.CAPTIVE_PORTAL_PROBE_SPEC";
field public static final String EXTRA_CAPTIVE_PORTAL_USER_AGENT = "android.net.extra.CAPTIVE_PORTAL_USER_AGENT";
}
@@ -2103,7 +2111,8 @@ package android.service.contentcapture {
method public void onDestroyContentCaptureSession(@NonNull android.view.contentcapture.ContentCaptureSessionId);
method public void onDisconnected();
method public void onUserDataRemovalRequest(@NonNull android.view.contentcapture.UserDataRemovalRequest);
- method public final void setContentCaptureWhitelist(@Nullable java.util.List<java.lang.String>, @Nullable java.util.List<android.content.ComponentName>);
+ method @Deprecated public final void setContentCaptureWhitelist(@Nullable java.util.List<java.lang.String>, @Nullable java.util.List<android.content.ComponentName>);
+ method public final void setContentCaptureWhitelist(@Nullable java.util.Set<java.lang.String>, @Nullable java.util.Set<android.content.ComponentName>);
field public static final String SERVICE_INTERFACE = "android.service.contentcapture.ContentCaptureService";
}
@@ -2692,7 +2701,8 @@ package android.view.autofill {
}
public final class AutofillManager {
- method public void setAugmentedAutofillWhitelist(@Nullable java.util.List<java.lang.String>, @Nullable java.util.List<android.content.ComponentName>);
+ method @Deprecated public void setAugmentedAutofillWhitelist(@Nullable java.util.List<java.lang.String>, @Nullable java.util.List<android.content.ComponentName>);
+ method public void setAugmentedAutofillWhitelist(@Nullable java.util.Set<java.lang.String>, @Nullable java.util.Set<android.content.ComponentName>);
field public static final String DEVICE_CONFIG_AUTOFILL_SMART_SUGGESTION_SUPPORTED_MODES = "smart_suggestion_supported_modes";
field public static final int FLAG_SMART_SUGGESTION_OFF = 0; // 0x0
field public static final int FLAG_SMART_SUGGESTION_SYSTEM = 1; // 0x1
@@ -2738,7 +2748,15 @@ package android.view.contentcapture {
public final class ContentCaptureManager {
method public boolean isContentCaptureFeatureEnabled();
method public void setContentCaptureFeatureEnabled(boolean);
+ field public static final String DEVICE_CONFIG_PROPERTY_IDLE_FLUSH_FREQUENCY = "idle_flush_frequency";
+ field public static final String DEVICE_CONFIG_PROPERTY_LOGGING_LEVEL = "logging_level";
+ field public static final String DEVICE_CONFIG_PROPERTY_LOG_HISTORY_SIZE = "log_history_size";
+ field public static final String DEVICE_CONFIG_PROPERTY_MAX_BUFFER_SIZE = "max_buffer_size";
field public static final String DEVICE_CONFIG_PROPERTY_SERVICE_EXPLICITLY_ENABLED = "service_explicitly_enabled";
+ field public static final String DEVICE_CONFIG_PROPERTY_TEXT_CHANGE_FLUSH_FREQUENCY = "text_change_flush_frequency";
+ field public static final int LOGGING_LEVEL_DEBUG = 1; // 0x1
+ field public static final int LOGGING_LEVEL_OFF = 0; // 0x0
+ field public static final int LOGGING_LEVEL_VERBOSE = 2; // 0x2
}
public final class ViewNode extends android.app.assist.AssistStructure.ViewNode {
diff --git a/cmds/bootanimation/BootAnimation.cpp b/cmds/bootanimation/BootAnimation.cpp
index 46917e4f6062..a6c7cae9bdb6 100644
--- a/cmds/bootanimation/BootAnimation.cpp
+++ b/cmds/bootanimation/BootAnimation.cpp
@@ -110,13 +110,30 @@ BootAnimation::BootAnimation(sp<Callbacks> callbacks)
} else {
mShuttingDown = true;
}
+ ALOGD("%sAnimationStartTiming start time: %" PRId64 "ms", mShuttingDown ? "Shutdown" : "Boot",
+ elapsedRealtime());
+}
+
+BootAnimation::~BootAnimation() {
+ if (mAnimation != nullptr) {
+ releaseAnimation(mAnimation);
+ mAnimation = nullptr;
+ }
+ ALOGD("%sAnimationStopTiming start time: %" PRId64 "ms", mShuttingDown ? "Shutdown" : "Boot",
+ elapsedRealtime());
}
void BootAnimation::onFirstRef() {
status_t err = mSession->linkToComposerDeath(this);
SLOGE_IF(err, "linkToComposerDeath failed (%s) ", strerror(-err));
if (err == NO_ERROR) {
- run("BootAnimation", PRIORITY_DISPLAY);
+ // Load the animation content -- this can be slow (eg 200ms)
+ // called before waitForSurfaceFlinger() in main() to avoid wait
+ ALOGD("%sAnimationPreloadTiming start time: %" PRId64 "ms",
+ mShuttingDown ? "Shutdown" : "Boot", elapsedRealtime());
+ preloadAnimation();
+ ALOGD("%sAnimationPreloadStopTiming start time: %" PRId64 "ms",
+ mShuttingDown ? "Shutdown" : "Boot", elapsedRealtime());
}
}
@@ -306,6 +323,20 @@ status_t BootAnimation::readyToRun() {
mFlingerSurface = s;
mTargetInset = -1;
+ return NO_ERROR;
+}
+
+bool BootAnimation::preloadAnimation() {
+ findBootAnimationFile();
+ if (!mZipFileName.isEmpty()) {
+ mAnimation = loadAnimation(mZipFileName);
+ return (mAnimation != nullptr);
+ }
+
+ return false;
+}
+
+void BootAnimation::findBootAnimationFile() {
// If the device has encryption turned on or is in process
// of being encrypted we show the encrypted boot animation.
char decrypt[PROPERTY_VALUE_MAX];
@@ -320,7 +351,7 @@ status_t BootAnimation::readyToRun() {
for (const char* f : encryptedBootFiles) {
if (access(f, R_OK) == 0) {
mZipFileName = f;
- return NO_ERROR;
+ return;
}
}
}
@@ -332,10 +363,9 @@ status_t BootAnimation::readyToRun() {
for (const char* f : (!mShuttingDown ? bootFiles : shutdownFiles)) {
if (access(f, R_OK) == 0) {
mZipFileName = f;
- return NO_ERROR;
+ return;
}
}
- return NO_ERROR;
}
bool BootAnimation::threadLoop()
@@ -790,8 +820,6 @@ bool BootAnimation::preloadZip(Animation& animation)
}
}
- mCallbacks->init(animation.parts);
-
zip->endIteration(cookie);
return true;
@@ -799,13 +827,25 @@ bool BootAnimation::preloadZip(Animation& animation)
bool BootAnimation::movie()
{
- Animation* animation = loadAnimation(mZipFileName);
- if (animation == NULL)
+ if (mAnimation == nullptr) {
+ mAnimation = loadAnimation(mZipFileName);
+ }
+
+ if (mAnimation == nullptr)
return false;
+ // mCallbacks->init() may get called recursively,
+ // this loop is needed to get the same results
+ for (const Animation::Part& part : mAnimation->parts) {
+ if (part.animation != nullptr) {
+ mCallbacks->init(part.animation->parts);
+ }
+ }
+ mCallbacks->init(mAnimation->parts);
+
bool anyPartHasClock = false;
- for (size_t i=0; i < animation->parts.size(); i++) {
- if(validClock(animation->parts[i])) {
+ for (size_t i=0; i < mAnimation->parts.size(); i++) {
+ if(validClock(mAnimation->parts[i])) {
anyPartHasClock = true;
break;
}
@@ -846,7 +886,7 @@ bool BootAnimation::movie()
bool clockFontInitialized = false;
if (mClockEnabled) {
clockFontInitialized =
- (initFont(&animation->clockFont, CLOCK_FONT_ASSET) == NO_ERROR);
+ (initFont(&mAnimation->clockFont, CLOCK_FONT_ASSET) == NO_ERROR);
mClockEnabled = clockFontInitialized;
}
@@ -855,7 +895,7 @@ bool BootAnimation::movie()
mTimeCheckThread->run("BootAnimation::TimeCheckThread", PRIORITY_NORMAL);
}
- playAnimation(*animation);
+ playAnimation(*mAnimation);
if (mTimeCheckThread != nullptr) {
mTimeCheckThread->requestExit();
@@ -863,10 +903,11 @@ bool BootAnimation::movie()
}
if (clockFontInitialized) {
- glDeleteTextures(1, &animation->clockFont.texture.name);
+ glDeleteTextures(1, &mAnimation->clockFont.texture.name);
}
- releaseAnimation(animation);
+ releaseAnimation(mAnimation);
+ mAnimation = nullptr;
return false;
}
diff --git a/cmds/bootanimation/BootAnimation.h b/cmds/bootanimation/BootAnimation.h
index 19616cb790c7..dc19fb09ef1d 100644
--- a/cmds/bootanimation/BootAnimation.h
+++ b/cmds/bootanimation/BootAnimation.h
@@ -115,6 +115,7 @@ public:
};
explicit BootAnimation(sp<Callbacks> callbacks);
+ virtual ~BootAnimation();
sp<SurfaceComposerClient> session() const;
@@ -155,6 +156,8 @@ private:
void releaseAnimation(Animation*) const;
bool parseAnimationDesc(Animation&);
bool preloadZip(Animation &animation);
+ void findBootAnimationFile();
+ bool preloadAnimation();
void checkExit();
@@ -182,6 +185,7 @@ private:
SortedVector<String8> mLoadedFiles;
sp<TimeCheckThread> mTimeCheckThread = nullptr;
sp<Callbacks> mCallbacks;
+ Animation* mAnimation = nullptr;
};
// ---------------------------------------------------------------------------
diff --git a/cmds/bootanimation/bootanimation_main.cpp b/cmds/bootanimation/bootanimation_main.cpp
index a52a5e92a840..6c7b3e51ff8d 100644
--- a/cmds/bootanimation/bootanimation_main.cpp
+++ b/cmds/bootanimation/bootanimation_main.cpp
@@ -44,14 +44,16 @@ int main()
sp<ProcessState> proc(ProcessState::self());
ProcessState::self()->startThreadPool();
+ // create the boot animation object (may take up to 200ms for 2MB zip)
+ sp<BootAnimation> boot = new BootAnimation(audioplay::createAnimationCallbacks());
+
waitForSurfaceFlinger();
- // create the boot animation object
- sp<BootAnimation> boot = new BootAnimation(audioplay::createAnimationCallbacks());
+ boot->run("BootAnimation", PRIORITY_DISPLAY);
+
ALOGV("Boot animation set up. Joining pool.");
IPCThreadState::self()->joinThreadPool();
}
- ALOGV("Boot animation exit");
return 0;
}
diff --git a/cmds/statsd/src/FieldValue.cpp b/cmds/statsd/src/FieldValue.cpp
index 80ed80776829..13f5c8ae5fd8 100644
--- a/cmds/statsd/src/FieldValue.cpp
+++ b/cmds/statsd/src/FieldValue.cpp
@@ -19,6 +19,7 @@
#include "FieldValue.h"
#include "HashableDimensionKey.h"
#include "math.h"
+#include "statslog.h"
namespace android {
namespace os {
@@ -122,6 +123,24 @@ bool isAttributionUidField(const FieldValue& value) {
return false;
}
+int32_t getUidIfExists(const FieldValue& value) {
+ bool isUid = false;
+ // the field is uid field if the field is the uid field in attribution node or marked as
+ // is_uid in atoms.proto
+ if (isAttributionUidField(value)) {
+ isUid = true;
+ } else {
+ auto it = android::util::AtomsInfo::kAtomsWithUidField.find(value.mField.getTag());
+ if (it != android::util::AtomsInfo::kAtomsWithUidField.end()) {
+ int uidField = it->second; // uidField is the field number in proto
+ isUid = value.mField.getDepth() == 0 && value.mField.getPosAtDepth(0) == uidField &&
+ value.mValue.getType() == INT;
+ }
+ }
+
+ return isUid ? value.mValue.int_value : -1;
+}
+
bool isAttributionUidField(const Field& field, const Value& value) {
int f = field.getField() & 0xff007f;
if (f == 0x10001 && value.getType() == INT) {
diff --git a/cmds/statsd/src/FieldValue.h b/cmds/statsd/src/FieldValue.h
index a5d00ac4e72b..6729e052b5ee 100644
--- a/cmds/statsd/src/FieldValue.h
+++ b/cmds/statsd/src/FieldValue.h
@@ -386,6 +386,9 @@ bool HasPositionALL(const FieldMatcher& matcher);
bool isAttributionUidField(const FieldValue& value);
+/* returns uid if the field is uid field, or -1 if the field is not a uid field */
+int getUidIfExists(const FieldValue& value);
+
void translateFieldMatcher(const FieldMatcher& matcher, std::vector<Matcher>* output);
bool isAttributionUidField(const Field& field, const Value& value);
diff --git a/cmds/statsd/src/StatsService.cpp b/cmds/statsd/src/StatsService.cpp
index fb603b9ce163..c542b6215c88 100644
--- a/cmds/statsd/src/StatsService.cpp
+++ b/cmds/statsd/src/StatsService.cpp
@@ -159,7 +159,7 @@ StatsService::StatsService(const sp<Looper>& handlerLooper)
}
})) {
- mUidMap = new UidMap();
+ mUidMap = UidMap::getInstance();
mPullerManager = new StatsPullerManager();
StatsPuller::SetUidMap(mUidMap);
mConfigManager = new ConfigManager();
diff --git a/cmds/statsd/src/anomaly/AlarmTracker.cpp b/cmds/statsd/src/anomaly/AlarmTracker.cpp
index 8d7369935ea4..019a9f7e5f9a 100644
--- a/cmds/statsd/src/anomaly/AlarmTracker.cpp
+++ b/cmds/statsd/src/anomaly/AlarmTracker.cpp
@@ -78,8 +78,8 @@ void AlarmTracker::informAlarmsFired(
}
if (!mSubscriptions.empty()) {
VLOG("AlarmTracker triggers the subscribers.");
- triggerSubscribers(mAlarmConfig.id(), DEFAULT_METRIC_DIMENSION_KEY, mConfigKey,
- mSubscriptions);
+ triggerSubscribers(mAlarmConfig.id(), 0 /*metricId N/A*/, DEFAULT_METRIC_DIMENSION_KEY,
+ 0 /* metricValue N/A */, mConfigKey, mSubscriptions);
}
firedAlarms.erase(mInternalAlarm);
mAlarmSec = findNextAlarmSec((timestampNs-1) / NS_PER_SEC + 1); // round up
diff --git a/cmds/statsd/src/anomaly/AnomalyTracker.cpp b/cmds/statsd/src/anomaly/AnomalyTracker.cpp
index ee111cddcfd7..d1dcb5df7838 100644
--- a/cmds/statsd/src/anomaly/AnomalyTracker.cpp
+++ b/cmds/statsd/src/anomaly/AnomalyTracker.cpp
@@ -207,7 +207,8 @@ bool AnomalyTracker::detectAnomaly(const int64_t& currentBucketNum,
getSumOverPastBuckets(key) + currentBucketValue > mAlert.trigger_if_sum_gt();
}
-void AnomalyTracker::declareAnomaly(const int64_t& timestampNs, const MetricDimensionKey& key) {
+void AnomalyTracker::declareAnomaly(const int64_t& timestampNs, int64_t metricId,
+ const MetricDimensionKey& key, int64_t metricValue) {
// TODO(b/110563466): Why receive timestamp? RefractoryPeriod should always be based on
// real time right now.
if (isInRefractoryPeriod(timestampNs, key)) {
@@ -225,7 +226,7 @@ void AnomalyTracker::declareAnomaly(const int64_t& timestampNs, const MetricDime
if (!mSubscriptions.empty()) {
ALOGI("An anomaly (%lld) %s has occurred! Informing subscribers.",
mAlert.id(), key.toString().c_str());
- informSubscribers(key);
+ informSubscribers(key, metricId, metricValue);
} else {
ALOGI("An anomaly has occurred! (But no subscriber for that alert.)");
}
@@ -238,11 +239,11 @@ void AnomalyTracker::declareAnomaly(const int64_t& timestampNs, const MetricDime
}
void AnomalyTracker::detectAndDeclareAnomaly(const int64_t& timestampNs,
- const int64_t& currBucketNum,
+ const int64_t& currBucketNum, int64_t metricId,
const MetricDimensionKey& key,
const int64_t& currentBucketValue) {
if (detectAnomaly(currBucketNum, key, currentBucketValue)) {
- declareAnomaly(timestampNs, key);
+ declareAnomaly(timestampNs, metricId, key, currentBucketValue);
}
}
@@ -255,8 +256,9 @@ bool AnomalyTracker::isInRefractoryPeriod(const int64_t& timestampNs,
return false;
}
-void AnomalyTracker::informSubscribers(const MetricDimensionKey& key) {
- triggerSubscribers(mAlert.id(), key, mConfigKey, mSubscriptions);
+void AnomalyTracker::informSubscribers(const MetricDimensionKey& key, int64_t metric_id,
+ int64_t metricValue) {
+ triggerSubscribers(mAlert.id(), metric_id, key, metricValue, mConfigKey, mSubscriptions);
}
} // namespace statsd
diff --git a/cmds/statsd/src/anomaly/AnomalyTracker.h b/cmds/statsd/src/anomaly/AnomalyTracker.h
index 927e2df1b53a..e9414735b82b 100644
--- a/cmds/statsd/src/anomaly/AnomalyTracker.h
+++ b/cmds/statsd/src/anomaly/AnomalyTracker.h
@@ -67,14 +67,16 @@ public:
const int64_t& currentBucketValue);
// Informs incidentd about the detected alert.
- void declareAnomaly(const int64_t& timestampNs, const MetricDimensionKey& key);
+ void declareAnomaly(const int64_t& timestampNs, int64_t metricId, const MetricDimensionKey& key,
+ int64_t metricValue);
// Detects if, based on past buckets plus the new currentBucketValue (which generally
// represents the partially-filled current bucket), an anomaly has happened, and if so,
// declares an anomaly and informs relevant subscribers.
// Also advances to currBucketNum-1.
void detectAndDeclareAnomaly(const int64_t& timestampNs, const int64_t& currBucketNum,
- const MetricDimensionKey& key, const int64_t& currentBucketValue);
+ int64_t metricId, const MetricDimensionKey& key,
+ const int64_t& currentBucketValue);
// Init the AlarmMonitor which is shared across anomaly trackers.
virtual void setAlarmMonitor(const sp<AlarmMonitor>& alarmMonitor) {
@@ -176,7 +178,7 @@ protected:
virtual void resetStorage();
// Informs the subscribers (incidentd, perfetto, broadcasts, etc) that an anomaly has occurred.
- void informSubscribers(const MetricDimensionKey& key);
+ void informSubscribers(const MetricDimensionKey& key, int64_t metricId, int64_t metricValue);
FRIEND_TEST(AnomalyTrackerTest, TestConsecutiveBuckets);
FRIEND_TEST(AnomalyTrackerTest, TestSparseBuckets);
diff --git a/cmds/statsd/src/anomaly/DurationAnomalyTracker.cpp b/cmds/statsd/src/anomaly/DurationAnomalyTracker.cpp
index 3acfd171848e..2b56810170e5 100644
--- a/cmds/statsd/src/anomaly/DurationAnomalyTracker.cpp
+++ b/cmds/statsd/src/anomaly/DurationAnomalyTracker.cpp
@@ -65,7 +65,9 @@ void DurationAnomalyTracker::stopAlarm(const MetricDimensionKey& dimensionKey,
// If the alarm is set in the past but hasn't fired yet (due to lag), catch it now.
if (itr->second != nullptr && timestampNs >= (int64_t)NS_PER_SEC * itr->second->timestampSec) {
- declareAnomaly(timestampNs, dimensionKey);
+ declareAnomaly(timestampNs, mAlert.metric_id(), dimensionKey,
+ mAlert.trigger_if_sum_gt() + (timestampNs / NS_PER_SEC) -
+ itr->second->timestampSec);
}
if (mAlarmMonitor != nullptr) {
mAlarmMonitor->remove(itr->second);
@@ -100,7 +102,9 @@ void DurationAnomalyTracker::informAlarmsFired(const int64_t& timestampNs,
// Now declare each of these alarms to have fired.
for (const auto& kv : matchedAlarms) {
- declareAnomaly(timestampNs, kv.first);
+ declareAnomaly(
+ timestampNs, mAlert.metric_id(), kv.first,
+ mAlert.trigger_if_sum_gt() + (timestampNs / NS_PER_SEC) - kv.second->timestampSec);
mAlarms.erase(kv.first);
firedAlarms.erase(kv.second); // No one else can also own it, so we're done with it.
}
diff --git a/cmds/statsd/src/anomaly/subscriber_util.cpp b/cmds/statsd/src/anomaly/subscriber_util.cpp
index 6b46b8b3b900..548a6869436d 100644
--- a/cmds/statsd/src/anomaly/subscriber_util.cpp
+++ b/cmds/statsd/src/anomaly/subscriber_util.cpp
@@ -30,9 +30,8 @@ namespace android {
namespace os {
namespace statsd {
-void triggerSubscribers(const int64_t rule_id,
- const MetricDimensionKey& dimensionKey,
- const ConfigKey& configKey,
+void triggerSubscribers(int64_t ruleId, int64_t metricId, const MetricDimensionKey& dimensionKey,
+ int64_t metricValue, const ConfigKey& configKey,
const std::vector<Subscription>& subscriptions) {
VLOG("informSubscribers called.");
if (subscriptions.empty()) {
@@ -50,13 +49,14 @@ void triggerSubscribers(const int64_t rule_id,
}
switch (subscription.subscriber_information_case()) {
case Subscription::SubscriberInformationCase::kIncidentdDetails:
- if (!GenerateIncidentReport(subscription.incidentd_details(), rule_id, configKey)) {
+ if (!GenerateIncidentReport(subscription.incidentd_details(), ruleId, metricId,
+ dimensionKey, metricValue, configKey)) {
ALOGW("Failed to generate incident report.");
}
break;
case Subscription::SubscriberInformationCase::kPerfettoDetails:
if (!CollectPerfettoTraceAndUploadToDropbox(subscription.perfetto_details(),
- subscription.id(), rule_id, configKey)) {
+ subscription.id(), ruleId, configKey)) {
ALOGW("Failed to generate perfetto traces.");
}
break;
@@ -66,7 +66,7 @@ void triggerSubscribers(const int64_t rule_id,
break;
case Subscription::SubscriberInformationCase::kPerfprofdDetails:
if (!CollectPerfprofdTraceAndUploadToDropbox(subscription.perfprofd_details(),
- rule_id, configKey)) {
+ ruleId, configKey)) {
ALOGW("Failed to generate perfprofd traces.");
}
break;
@@ -76,7 +76,6 @@ void triggerSubscribers(const int64_t rule_id,
}
}
-
} // namespace statsd
} // namespace os
} // namespace android
diff --git a/cmds/statsd/src/anomaly/subscriber_util.h b/cmds/statsd/src/anomaly/subscriber_util.h
index dba8981a72aa..1df3c8991f94 100644
--- a/cmds/statsd/src/anomaly/subscriber_util.h
+++ b/cmds/statsd/src/anomaly/subscriber_util.h
@@ -24,10 +24,9 @@ namespace android {
namespace os {
namespace statsd {
-void triggerSubscribers(const int64_t rule_id,
- const MetricDimensionKey& dimensionKey,
- const ConfigKey& configKey,
- const std::vector<Subscription>& subscriptions);
+void triggerSubscribers(const int64_t ruleId, const int64_t metricId,
+ const MetricDimensionKey& dimensionKey, int64_t metricValue,
+ const ConfigKey& configKey, const std::vector<Subscription>& subscriptions);
} // namespace statsd
} // namespace os
diff --git a/cmds/statsd/src/atoms.proto b/cmds/statsd/src/atoms.proto
index c707d8f4c35a..d7ab6e5f89bb 100644
--- a/cmds/statsd/src/atoms.proto
+++ b/cmds/statsd/src/atoms.proto
@@ -303,6 +303,8 @@ message Atom {
RoleHolder role_holder = 10049;
DangerousPermissionState dangerous_permission_state = 10050;
TrainInfo train_info = 10051;
+ TimeZoneDataInfo time_zone_data_info = 10052;
+ SDCardInfo sdcard_info = 10053;
}
// DO NOT USE field numbers above 100,000 in AOSP.
@@ -3262,6 +3264,28 @@ message BatteryCycleCount {
optional int32 cycle_count = 1;
}
+/**
+ * Logs that an SD card is mounted and information about it, its type (public or private) and the
+ * size in bytes.
+ * Pulled from:
+ * StatsCompanionService
+ */
+
+message SDCardInfo {
+
+ enum Type {
+ UNKNOWN = 0;
+ TYPE_PUBLIC = 1;
+ TYPE_PRIVATE = 2;
+ OTHERS = 3;
+ }
+
+ // Type of the SD card: TYPE_PUBLIC if portable and TYPE_PRIVATE if internal.
+ optional Type type = 1;
+ // Total size of the sd card in bytes.
+ optional int64 size_bytes = 2;
+}
+
/*
* Logs when a connection becomes available and lost.
* Logged in StatsCompanionService.java
@@ -5596,3 +5620,11 @@ message AssistGestureProgressReported {
// [0,100] progress for the assist gesture.
optional int32 progress = 1;
}
+
+/*
+ * Information about the time zone data on a device.
+ */
+message TimeZoneDataInfo {
+ // A version identifier for the data set on device. e.g. "2018i"
+ optional string tzdb_version = 1;
+}
diff --git a/cmds/statsd/src/external/StatsPullerManager.cpp b/cmds/statsd/src/external/StatsPullerManager.cpp
index 98f810fd9a2c..1513834b6724 100644
--- a/cmds/statsd/src/external/StatsPullerManager.cpp
+++ b/cmds/statsd/src/external/StatsPullerManager.cpp
@@ -234,6 +234,12 @@ std::map<int, PullAtomInfo> StatsPullerManager::kAllPullAtomInfo = {
{.puller = new StatsCompanionServicePuller(android::util::DANGEROUS_PERMISSION_STATE)}},
// TrainInfo.
{android::util::TRAIN_INFO, {.puller = new TrainInfoPuller()}},
+ // TimeZoneDataInfo.
+ {android::util::TIME_ZONE_DATA_INFO,
+ {.puller = new StatsCompanionServicePuller(android::util::TIME_ZONE_DATA_INFO)}},
+ // SDCardInfo
+ {android::util::SDCARD_INFO,
+ {.puller = new StatsCompanionServicePuller(android::util::SDCARD_INFO)}},
};
StatsPullerManager::StatsPullerManager() : mNextPullTimeNs(NO_ALARM_UPDATE) {
diff --git a/cmds/statsd/src/metrics/CountMetricProducer.cpp b/cmds/statsd/src/metrics/CountMetricProducer.cpp
index 5707de544648..e84f88d407d3 100644
--- a/cmds/statsd/src/metrics/CountMetricProducer.cpp
+++ b/cmds/statsd/src/metrics/CountMetricProducer.cpp
@@ -303,7 +303,7 @@ void CountMetricProducer::onMatchedLogEventInternalLocked(
if (prev != mCurrentFullCounters->end()) {
countWholeBucket += prev->second;
}
- tracker->detectAndDeclareAnomaly(eventTimeNs, mCurrentBucketNum, eventKey,
+ tracker->detectAndDeclareAnomaly(eventTimeNs, mCurrentBucketNum, mMetricId, eventKey,
countWholeBucket);
}
diff --git a/cmds/statsd/src/metrics/GaugeMetricProducer.cpp b/cmds/statsd/src/metrics/GaugeMetricProducer.cpp
index 837d532f7e09..63017936b1db 100644
--- a/cmds/statsd/src/metrics/GaugeMetricProducer.cpp
+++ b/cmds/statsd/src/metrics/GaugeMetricProducer.cpp
@@ -485,8 +485,8 @@ void GaugeMetricProducer::onMatchedLogEventInternalLocked(
gaugeVal = value.long_value;
}
for (auto& tracker : mAnomalyTrackers) {
- tracker->detectAndDeclareAnomaly(eventTimeNs, mCurrentBucketNum, eventKey,
- gaugeVal);
+ tracker->detectAndDeclareAnomaly(eventTimeNs, mCurrentBucketNum, mMetricId,
+ eventKey, gaugeVal);
}
}
}
diff --git a/cmds/statsd/src/metrics/ValueMetricProducer.cpp b/cmds/statsd/src/metrics/ValueMetricProducer.cpp
index bc7c8727284f..3cf378d7d7ce 100644
--- a/cmds/statsd/src/metrics/ValueMetricProducer.cpp
+++ b/cmds/statsd/src/metrics/ValueMetricProducer.cpp
@@ -697,8 +697,8 @@ void ValueMetricProducer::onMatchedLogEventInternalLocked(const size_t matcherIn
wholeBucketVal += prev->second;
}
for (auto& tracker : mAnomalyTrackers) {
- tracker->detectAndDeclareAnomaly(
- eventTimeNs, mCurrentBucketNum, eventKey, wholeBucketVal);
+ tracker->detectAndDeclareAnomaly(eventTimeNs, mCurrentBucketNum, mMetricId, eventKey,
+ wholeBucketVal);
}
}
}
diff --git a/cmds/statsd/src/metrics/duration_helper/DurationTracker.h b/cmds/statsd/src/metrics/duration_helper/DurationTracker.h
index ccb1d4359e89..081e61ed21fa 100644
--- a/cmds/statsd/src/metrics/duration_helper/DurationTracker.h
+++ b/cmds/statsd/src/metrics/duration_helper/DurationTracker.h
@@ -155,8 +155,8 @@ protected:
const int64_t& currentBucketValue) {
for (auto& anomalyTracker : mAnomalyTrackers) {
if (anomalyTracker != nullptr) {
- anomalyTracker->detectAndDeclareAnomaly(timestamp, currBucketNum, mEventKey,
- currentBucketValue);
+ anomalyTracker->detectAndDeclareAnomaly(timestamp, currBucketNum, mTrackerId,
+ mEventKey, currentBucketValue);
}
}
}
diff --git a/cmds/statsd/src/packages/UidMap.cpp b/cmds/statsd/src/packages/UidMap.cpp
index 5cf012638dce..d4b57dd68134 100644
--- a/cmds/statsd/src/packages/UidMap.cpp
+++ b/cmds/statsd/src/packages/UidMap.cpp
@@ -73,6 +73,11 @@ UidMap::UidMap() : mBytesUsed(0) {}
UidMap::~UidMap() {}
+sp<UidMap> UidMap::getInstance() {
+ static sp<UidMap> sInstance = new UidMap();
+ return sInstance;
+}
+
bool UidMap::hasApp(int uid, const string& packageName) const {
lock_guard<mutex> lock(mMutex);
@@ -336,6 +341,61 @@ size_t UidMap::getBytesUsed() const {
return mBytesUsed;
}
+void UidMap::writeUidMapSnapshot(int64_t timestamp, bool includeVersionStrings,
+ bool includeInstaller, const std::set<int32_t>& interestingUids,
+ std::set<string>* str_set, ProtoOutputStream* proto) {
+ lock_guard<mutex> lock(mMutex);
+
+ writeUidMapSnapshotLocked(timestamp, includeVersionStrings, includeInstaller, interestingUids,
+ str_set, proto);
+}
+
+void UidMap::writeUidMapSnapshotLocked(int64_t timestamp, bool includeVersionStrings,
+ bool includeInstaller,
+ const std::set<int32_t>& interestingUids,
+ std::set<string>* str_set, ProtoOutputStream* proto) {
+ proto->write(FIELD_TYPE_INT64 | FIELD_ID_SNAPSHOT_TIMESTAMP, (long long)timestamp);
+ for (const auto& kv : mMap) {
+ if (!interestingUids.empty() &&
+ interestingUids.find(kv.first.first) == interestingUids.end()) {
+ continue;
+ }
+ uint64_t token = proto->start(FIELD_TYPE_MESSAGE | FIELD_COUNT_REPEATED |
+ FIELD_ID_SNAPSHOT_PACKAGE_INFO);
+ if (str_set != nullptr) {
+ str_set->insert(kv.first.second);
+ proto->write(FIELD_TYPE_UINT64 | FIELD_ID_SNAPSHOT_PACKAGE_NAME_HASH,
+ (long long)Hash64(kv.first.second));
+ if (includeVersionStrings) {
+ str_set->insert(kv.second.versionString);
+ proto->write(FIELD_TYPE_UINT64 | FIELD_ID_SNAPSHOT_PACKAGE_VERSION_STRING_HASH,
+ (long long)Hash64(kv.second.versionString));
+ }
+ if (includeInstaller) {
+ str_set->insert(kv.second.installer);
+ proto->write(FIELD_TYPE_UINT64 | FIELD_ID_SNAPSHOT_PACKAGE_INSTALLER_HASH,
+ (long long)Hash64(kv.second.installer));
+ }
+ } else {
+ proto->write(FIELD_TYPE_STRING | FIELD_ID_SNAPSHOT_PACKAGE_NAME, kv.first.second);
+ if (includeVersionStrings) {
+ proto->write(FIELD_TYPE_STRING | FIELD_ID_SNAPSHOT_PACKAGE_VERSION_STRING,
+ kv.second.versionString);
+ }
+ if (includeInstaller) {
+ proto->write(FIELD_TYPE_STRING | FIELD_ID_SNAPSHOT_PACKAGE_INSTALLER,
+ kv.second.installer);
+ }
+ }
+
+ proto->write(FIELD_TYPE_INT64 | FIELD_ID_SNAPSHOT_PACKAGE_VERSION,
+ (long long)kv.second.versionCode);
+ proto->write(FIELD_TYPE_INT32 | FIELD_ID_SNAPSHOT_PACKAGE_UID, kv.first.first);
+ proto->write(FIELD_TYPE_BOOL | FIELD_ID_SNAPSHOT_PACKAGE_DELETED, kv.second.deleted);
+ proto->end(token);
+ }
+}
+
void UidMap::appendUidMap(const int64_t& timestamp, const ConfigKey& key, std::set<string>* str_set,
bool includeVersionStrings, bool includeInstaller,
ProtoOutputStream* proto) {
@@ -381,43 +441,9 @@ void UidMap::appendUidMap(const int64_t& timestamp, const ConfigKey& key, std::s
// Write snapshot from current uid map state.
uint64_t snapshotsToken =
proto->start(FIELD_TYPE_MESSAGE | FIELD_COUNT_REPEATED | FIELD_ID_SNAPSHOTS);
- proto->write(FIELD_TYPE_INT64 | FIELD_ID_SNAPSHOT_TIMESTAMP, (long long)timestamp);
- for (const auto& kv : mMap) {
- uint64_t token = proto->start(FIELD_TYPE_MESSAGE | FIELD_COUNT_REPEATED |
- FIELD_ID_SNAPSHOT_PACKAGE_INFO);
-
- if (str_set != nullptr) {
- str_set->insert(kv.first.second);
- proto->write(FIELD_TYPE_UINT64 | FIELD_ID_SNAPSHOT_PACKAGE_NAME_HASH,
- (long long)Hash64(kv.first.second));
- if (includeVersionStrings) {
- str_set->insert(kv.second.versionString);
- proto->write(FIELD_TYPE_UINT64 | FIELD_ID_SNAPSHOT_PACKAGE_VERSION_STRING_HASH,
- (long long)Hash64(kv.second.versionString));
- }
- if (includeInstaller) {
- str_set->insert(kv.second.installer);
- proto->write(FIELD_TYPE_UINT64 | FIELD_ID_SNAPSHOT_PACKAGE_INSTALLER_HASH,
- (long long)Hash64(kv.second.installer));
- }
- } else {
- proto->write(FIELD_TYPE_STRING | FIELD_ID_SNAPSHOT_PACKAGE_NAME, kv.first.second);
- if (includeVersionStrings) {
- proto->write(FIELD_TYPE_STRING | FIELD_ID_SNAPSHOT_PACKAGE_VERSION_STRING,
- kv.second.versionString);
- }
- if (includeInstaller) {
- proto->write(FIELD_TYPE_STRING | FIELD_ID_SNAPSHOT_PACKAGE_INSTALLER,
- kv.second.installer);
- }
- }
-
- proto->write(FIELD_TYPE_INT64 | FIELD_ID_SNAPSHOT_PACKAGE_VERSION,
- (long long)kv.second.versionCode);
- proto->write(FIELD_TYPE_INT32 | FIELD_ID_SNAPSHOT_PACKAGE_UID, kv.first.first);
- proto->write(FIELD_TYPE_BOOL | FIELD_ID_SNAPSHOT_PACKAGE_DELETED, kv.second.deleted);
- proto->end(token);
- }
+ writeUidMapSnapshotLocked(timestamp, includeVersionStrings, includeInstaller,
+ std::set<int32_t>() /*empty uid set means including every uid*/,
+ str_set, proto);
proto->end(snapshotsToken);
int64_t prevMin = getMinimumTimestampNs();
diff --git a/cmds/statsd/src/packages/UidMap.h b/cmds/statsd/src/packages/UidMap.h
index 75ff507ef09a..a7c5fb27375c 100644
--- a/cmds/statsd/src/packages/UidMap.h
+++ b/cmds/statsd/src/packages/UidMap.h
@@ -91,6 +91,8 @@ public:
UidMap();
~UidMap();
static const std::map<std::string, uint32_t> sAidToUidMapping;
+
+ static sp<UidMap> getInstance();
/*
* All three inputs must be the same size, and the jth element in each array refers to the same
* tuple, ie. uid[j] corresponds to packageName[j] with versionCode[j].
@@ -152,12 +154,25 @@ public:
std::set<int32_t> getAppUid(const string& package) const;
+ // Write current PackageInfoSnapshot to ProtoOutputStream.
+ // interestingUids: If not empty, only write the package info for these uids. If empty, write
+ // package info for all uids.
+ // str_set: if not null, add new string to the set and write str_hash to proto
+ // if null, write string to proto.
+ void writeUidMapSnapshot(int64_t timestamp, bool includeVersionStrings, bool includeInstaller,
+ const std::set<int32_t>& interestingUids, std::set<string>* str_set,
+ ProtoOutputStream* proto);
+
private:
std::set<string> getAppNamesFromUidLocked(const int32_t& uid, bool returnNormalized) const;
string normalizeAppName(const string& appName) const;
void getListenerListCopyLocked(std::vector<wp<PackageInfoListener>>* output);
+ void writeUidMapSnapshotLocked(int64_t timestamp, bool includeVersionStrings,
+ bool includeInstaller, const std::set<int32_t>& interestingUids,
+ std::set<string>* str_set, ProtoOutputStream* proto);
+
mutable mutex mMutex;
mutable mutex mIsolatedMutex;
diff --git a/cmds/statsd/src/stats_log.proto b/cmds/statsd/src/stats_log.proto
index 09b8fed60dcc..623d8bc06e38 100644
--- a/cmds/statsd/src/stats_log.proto
+++ b/cmds/statsd/src/stats_log.proto
@@ -457,3 +457,17 @@ message StatsdStatsReport {
}
repeated LogLossStats detected_log_loss = 16;
}
+
+message AlertTriggerDetails {
+ message MetricValue {
+ optional int64 metric_id = 1;
+ optional DimensionsValue dimension_in_what = 2;
+ optional DimensionsValue dimension_in_condition = 3;
+ optional int64 value = 4;
+ }
+ oneof value {
+ MetricValue trigger_metric = 1;
+ EventMetricData trigger_event = 2;
+ }
+ optional UidMapping.PackageInfoSnapshot package_info = 3;
+}
diff --git a/cmds/statsd/src/subscriber/IncidentdReporter.cpp b/cmds/statsd/src/subscriber/IncidentdReporter.cpp
index 42cac0cc4122..0ed2d75802da 100644
--- a/cmds/statsd/src/subscriber/IncidentdReporter.cpp
+++ b/cmds/statsd/src/subscriber/IncidentdReporter.cpp
@@ -16,7 +16,10 @@
#define DEBUG false
#include "Log.h"
+#include "FieldValue.h"
#include "IncidentdReporter.h"
+#include "packages/UidMap.h"
+#include "stats_log_util.h"
#include <android/os/IIncidentManager.h>
#include <android/os/IncidentReportArgs.h>
@@ -43,8 +46,18 @@ const int FIELD_ID_CONFIG_KEY = 3;
const int FIELD_ID_CONFIG_KEY_UID = 1;
const int FIELD_ID_CONFIG_KEY_ID = 2;
+const int FIELD_ID_TRIGGER_DETAILS = 4;
+const int FIELD_ID_TRIGGER_DETAILS_TRIGGER_METRIC = 1;
+const int FIELD_ID_METRIC_VALUE_METRIC_ID = 1;
+const int FIELD_ID_METRIC_VALUE_DIMENSION_IN_WHAT = 2;
+const int FIELD_ID_METRIC_VALUE_DIMENSION_IN_CONDITION = 3;
+const int FIELD_ID_METRIC_VALUE_VALUE = 4;
+
+const int FIELD_ID_PACKAGE_INFO = 3;
+
namespace {
-void getProtoData(const int64_t& rule_id, const ConfigKey& configKey, vector<uint8_t>* protoData) {
+void getProtoData(const int64_t& rule_id, int64_t metricId, const MetricDimensionKey& dimensionKey,
+ int64_t metricValue, const ConfigKey& configKey, vector<uint8_t>* protoData) {
ProtoOutputStream headerProto;
headerProto.write(FIELD_TYPE_INT64 | FIELD_ID_ALERT_ID, (long long)rule_id);
uint64_t token =
@@ -53,6 +66,58 @@ void getProtoData(const int64_t& rule_id, const ConfigKey& configKey, vector<uin
headerProto.write(FIELD_TYPE_INT64 | FIELD_ID_CONFIG_KEY_ID, (long long)configKey.GetId());
headerProto.end(token);
+ token = headerProto.start(FIELD_TYPE_MESSAGE | FIELD_ID_TRIGGER_DETAILS);
+
+ // MetricValue trigger_metric = 1;
+ uint64_t metricToken =
+ headerProto.start(FIELD_TYPE_MESSAGE | FIELD_ID_TRIGGER_DETAILS_TRIGGER_METRIC);
+ // message MetricValue {
+ // optional int64 metric_id = 1;
+ headerProto.write(FIELD_TYPE_INT64 | FIELD_ID_METRIC_VALUE_METRIC_ID, (long long)metricId);
+ // optional DimensionsValue dimension_in_what = 2;
+ uint64_t dimToken =
+ headerProto.start(FIELD_TYPE_MESSAGE | FIELD_ID_METRIC_VALUE_DIMENSION_IN_WHAT);
+ writeDimensionToProto(dimensionKey.getDimensionKeyInWhat(), nullptr, &headerProto);
+ headerProto.end(dimToken);
+
+ // optional DimensionsValue dimension_in_condition = 3;
+ dimToken = headerProto.start(FIELD_TYPE_MESSAGE | FIELD_ID_METRIC_VALUE_DIMENSION_IN_CONDITION);
+ writeDimensionToProto(dimensionKey.getDimensionKeyInCondition(), nullptr, &headerProto);
+ headerProto.end(dimToken);
+
+ // optional int64 value = 4;
+ headerProto.write(FIELD_TYPE_INT64 | FIELD_ID_METRIC_VALUE_VALUE, (long long)metricValue);
+
+ // }
+ headerProto.end(metricToken);
+
+ // write relevant uid package info
+ std::set<int32_t> uids;
+
+ for (const auto& dim : dimensionKey.getDimensionKeyInWhat().getValues()) {
+ int uid = getUidIfExists(dim);
+ // any uid <= 2000 are predefined AID_*
+ if (uid > 2000) {
+ uids.insert(uid);
+ }
+ }
+
+ for (const auto& dim : dimensionKey.getDimensionKeyInCondition().getValues()) {
+ int uid = getUidIfExists(dim);
+ if (uid > 2000) {
+ uids.insert(uid);
+ }
+ }
+
+ if (!uids.empty()) {
+ uint64_t token = headerProto.start(FIELD_TYPE_MESSAGE | FIELD_ID_PACKAGE_INFO);
+ UidMap::getInstance()->writeUidMapSnapshot(getElapsedRealtimeNs(), true, true, uids,
+ nullptr /*string set*/, &headerProto);
+ headerProto.end(token);
+ }
+
+ headerProto.end(token);
+
protoData->resize(headerProto.size());
size_t pos = 0;
auto iter = headerProto.data();
@@ -65,7 +130,8 @@ void getProtoData(const int64_t& rule_id, const ConfigKey& configKey, vector<uin
}
} // namespace
-bool GenerateIncidentReport(const IncidentdDetails& config, const int64_t& rule_id,
+bool GenerateIncidentReport(const IncidentdDetails& config, int64_t rule_id, int64_t metricId,
+ const MetricDimensionKey& dimensionKey, int64_t metricValue,
const ConfigKey& configKey) {
if (config.section_size() == 0) {
VLOG("The alert %lld contains zero section in config(%d,%lld)", (unsigned long long)rule_id,
@@ -76,7 +142,7 @@ bool GenerateIncidentReport(const IncidentdDetails& config, const int64_t& rule_
IncidentReportArgs incidentReport;
vector<uint8_t> protoData;
- getProtoData(rule_id, configKey, &protoData);
+ getProtoData(rule_id, metricId, dimensionKey, metricValue, configKey, &protoData);
incidentReport.addHeader(protoData);
for (int i = 0; i < config.section_size(); i++) {
diff --git a/cmds/statsd/src/subscriber/IncidentdReporter.h b/cmds/statsd/src/subscriber/IncidentdReporter.h
index 1b83fe23de8f..e78a4d98dcd8 100644
--- a/cmds/statsd/src/subscriber/IncidentdReporter.h
+++ b/cmds/statsd/src/subscriber/IncidentdReporter.h
@@ -16,6 +16,7 @@
#pragma once
+#include "HashableDimensionKey.h"
#include "config/ConfigKey.h"
#include "frameworks/base/cmds/statsd/src/statsd_config.pb.h" // Alert, IncidentdDetails
@@ -26,7 +27,8 @@ namespace statsd {
/**
* Calls incidentd to trigger an incident report and put in dropbox for uploading.
*/
-bool GenerateIncidentReport(const IncidentdDetails& config, const int64_t& rule_id,
+bool GenerateIncidentReport(const IncidentdDetails& config, int64_t rule_id, int64_t metricId,
+ const MetricDimensionKey& dimensionKey, int64_t metricValue,
const ConfigKey& configKey);
} // namespace statsd
diff --git a/cmds/statsd/tests/anomaly/AnomalyTracker_test.cpp b/cmds/statsd/tests/anomaly/AnomalyTracker_test.cpp
index 960fbdab1c15..c10703c36b98 100644
--- a/cmds/statsd/tests/anomaly/AnomalyTracker_test.cpp
+++ b/cmds/statsd/tests/anomaly/AnomalyTracker_test.cpp
@@ -90,7 +90,8 @@ void detectAndDeclareAnomalies(AnomalyTracker& tracker,
const std::shared_ptr<DimToValMap>& bucket,
const int64_t& eventTimestamp) {
for (const auto& kv : *bucket) {
- tracker.detectAndDeclareAnomaly(eventTimestamp, bucketNum, kv.first, kv.second);
+ tracker.detectAndDeclareAnomaly(eventTimestamp, bucketNum, 0 /*metric_id*/, kv.first,
+ kv.second);
}
}
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index 5f778da44a1c..e55c96443198 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -71,6 +71,7 @@ import android.os.IBinder;
import android.os.Looper;
import android.os.Parcelable;
import android.os.PersistableBundle;
+import android.os.Process;
import android.os.RemoteException;
import android.os.ServiceManager.ServiceNotFoundException;
import android.os.StrictMode;
@@ -2297,7 +2298,7 @@ public class Activity extends ContextThemeWrapper
public final void requestShowKeyboardShortcuts() {
Intent intent = new Intent(Intent.ACTION_SHOW_KEYBOARD_SHORTCUTS);
intent.setPackage(KEYBOARD_SHORTCUTS_RECEIVER_PKG_NAME);
- sendBroadcastAsUser(intent, UserHandle.SYSTEM);
+ sendBroadcastAsUser(intent, Process.myUserHandle());
}
/**
@@ -2306,7 +2307,7 @@ public class Activity extends ContextThemeWrapper
public final void dismissKeyboardShortcutsHelper() {
Intent intent = new Intent(Intent.ACTION_DISMISS_KEYBOARD_SHORTCUTS);
intent.setPackage(KEYBOARD_SHORTCUTS_RECEIVER_PKG_NAME);
- sendBroadcastAsUser(intent, UserHandle.SYSTEM);
+ sendBroadcastAsUser(intent, Process.myUserHandle());
}
@Override
diff --git a/core/java/android/app/AppOpsManager.java b/core/java/android/app/AppOpsManager.java
index f76f7b9a7fc7..13eec580ec14 100644
--- a/core/java/android/app/AppOpsManager.java
+++ b/core/java/android/app/AppOpsManager.java
@@ -4291,12 +4291,35 @@ public class AppOpsManager {
/**
* Like {@link #noteProxyOp(String, String)} but instead
* of throwing a {@link SecurityException} it returns {@link #MODE_ERRORED}.
+ *
+ * <p>This API requires the package with the {@code proxiedPackageName} to belongs to
+ * {@link Binder#getCallingUid()}.
*/
public int noteProxyOpNoThrow(String op, String proxiedPackageName) {
return noteProxyOpNoThrow(strOpToOp(op), proxiedPackageName);
}
/**
+ * Like {@link #noteProxyOp(String, String)} but instead
+ * of throwing a {@link SecurityException} it returns {@link #MODE_ERRORED}.
+ *
+ * <p>This API requires package with the {@code proxiedPackageName} to belong to
+ * {@code proxiedUid}.
+ *
+ * @param op The op to note
+ * @param proxiedPackageName The package to note the op for or {@code null} if the op should be
+ * noted for the "android" package
+ * @param proxiedUid The uid the package belongs to
+ *
+ * @hide
+ */
+ @SystemApi
+ public int noteProxyOpNoThrow(@NonNull String op, @Nullable String proxiedPackageName,
+ int proxiedUid) {
+ return noteProxyOpNoThrow(strOpToOp(op), proxiedPackageName, proxiedUid);
+ }
+
+ /**
* Report that an application has started executing a long-running operation. Note that you
* must pass in both the uid and name of the application to be checked; this function will
* verify that these two match, and if not, return {@link #MODE_IGNORED}. If this call
@@ -4495,17 +4518,30 @@ public class AppOpsManager {
* of throwing a {@link SecurityException} it returns {@link #MODE_ERRORED}.
* @hide
*/
- public int noteProxyOpNoThrow(int op, String proxiedPackageName) {
+ public int noteProxyOpNoThrow(int op, String proxiedPackageName, int proxiedUid) {
logOperationIfNeeded(op, mContext.getOpPackageName(), proxiedPackageName);
try {
return mService.noteProxyOperation(op, Process.myUid(), mContext.getOpPackageName(),
- Binder.getCallingUid(), proxiedPackageName);
+ proxiedUid, proxiedPackageName);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
/**
+ * Like {@link #noteProxyOp(int, String)} but instead
+ * of throwing a {@link SecurityException} it returns {@link #MODE_ERRORED}.
+ *
+ * <p>This API requires the package with {@code proxiedPackageName} to belongs to
+ * {@link Binder#getCallingUid()}.
+ *
+ * @hide
+ */
+ public int noteProxyOpNoThrow(int op, String proxiedPackageName) {
+ return noteProxyOpNoThrow(op, proxiedPackageName, Binder.getCallingUid());
+ }
+
+ /**
* Like {@link #noteOp} but instead of throwing a {@link SecurityException} it
* returns {@link #MODE_ERRORED}.
* @hide
diff --git a/core/java/android/app/Service.java b/core/java/android/app/Service.java
index 87bf5ed7db65..f116e133e338 100644
--- a/core/java/android/app/Service.java
+++ b/core/java/android/app/Service.java
@@ -27,6 +27,7 @@ import android.content.ComponentName;
import android.content.Context;
import android.content.ContextWrapper;
import android.content.Intent;
+import android.content.pm.ServiceInfo.ForegroundServiceType;
import android.content.res.Configuration;
import android.os.Build;
import android.os.IBinder;
@@ -735,7 +736,7 @@ public abstract class Service extends ContextWrapper implements ComponentCallbac
* @see {@link android.content.pm.ServiceInfo} for the set of FOREGROUND_SERVICE_TYPE flags.
*/
public final void startForeground(int id, @NonNull Notification notification,
- int foregroundServiceType) {
+ @ForegroundServiceType int foregroundServiceType) {
try {
mActivityManager.setServiceForeground(
new ComponentName(this, mClassName), mToken, id,
diff --git a/core/java/android/app/SystemServiceRegistry.java b/core/java/android/app/SystemServiceRegistry.java
index cca8bd00b646..c12a92f44fa2 100644
--- a/core/java/android/app/SystemServiceRegistry.java
+++ b/core/java/android/app/SystemServiceRegistry.java
@@ -106,7 +106,6 @@ import android.net.IpMemoryStore;
import android.net.IpSecManager;
import android.net.NetworkPolicyManager;
import android.net.NetworkScoreManager;
-import android.net.NetworkStack;
import android.net.NetworkWatchlistManager;
import android.net.lowpan.ILowpanManager;
import android.net.lowpan.LowpanManager;
@@ -336,13 +335,6 @@ final class SystemServiceRegistry {
}
});
- registerService(Context.NETWORK_STACK_SERVICE, NetworkStack.class,
- new StaticServiceFetcher<NetworkStack>() {
- @Override
- public NetworkStack createService() {
- return new NetworkStack();
- }});
-
registerService(Context.IP_MEMORY_STORE_SERVICE, IpMemoryStore.class,
new CachedServiceFetcher<IpMemoryStore>() {
@Override
@@ -1137,7 +1129,11 @@ final class SystemServiceRegistry {
IBinder b = ServiceManager
.getService(Context.CONTENT_CAPTURE_MANAGER_SERVICE);
IContentCaptureManager service = IContentCaptureManager.Stub.asInterface(b);
- return new ContentCaptureManager(outerContext, service);
+ if (service != null) {
+ // When feature is disabled, we return a null manager to apps so the
+ // performance impact is practically zero
+ return new ContentCaptureManager(outerContext, service);
+ }
}
return null;
}});
diff --git a/core/java/android/app/UiModeManager.java b/core/java/android/app/UiModeManager.java
index a554882123f1..46316e1a254b 100644
--- a/core/java/android/app/UiModeManager.java
+++ b/core/java/android/app/UiModeManager.java
@@ -229,7 +229,11 @@ public class UiModeManager {
* <strong>Note:</strong> On API 22 and below, changes to the night mode
* are only effective when the {@link Configuration#UI_MODE_TYPE_CAR car}
* or {@link Configuration#UI_MODE_TYPE_DESK desk} mode is enabled on a
- * device. Starting in API 23, changes to night mode are always effective.
+ * device. On API 23 through API 28, changes to night mode are always effective.
+ * <p>
+ * Starting in API 29, when the device is in car mode and this method is called, night mode
+ * will change, but the new setting is not persisted and the previously persisted setting
+ * will be restored when the device exits car mode.
* <p>
* Changes to night mode take effect globally and will result in a configuration change
* (and potentially an Activity lifecycle event) being applied to all running apps.
diff --git a/core/java/android/app/usage/UsageStats.java b/core/java/android/app/usage/UsageStats.java
index 94a2a3eaae7f..97efa01e982b 100644
--- a/core/java/android/app/usage/UsageStats.java
+++ b/core/java/android/app/usage/UsageStats.java
@@ -465,8 +465,6 @@ public final class UsageStats implements Parcelable {
mActivities.put(instanceId, eventType);
break;
case ACTIVITY_STOPPED:
- mActivities.put(instanceId, eventType);
- break;
case ACTIVITY_DESTROYED:
// remove activity from the map.
mActivities.delete(instanceId);
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index 957a48494892..25bfba26256f 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -49,7 +49,6 @@ import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteDatabase.CursorFactory;
import android.graphics.Bitmap;
import android.graphics.drawable.Drawable;
-import android.net.NetworkStack;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
@@ -3647,11 +3646,10 @@ public abstract class Context {
public static final String NETD_SERVICE = "netd";
/**
- * Use with {@link #getSystemService(String)} to retrieve a
- * {@link NetworkStack} for communicating with the network stack
+ * Use with {@link android.os.ServiceManager.getService()} to retrieve a
+ * {@link NetworkStackClient} IBinder for communicating with the network stack
* @hide
- * @see #getSystemService(String)
- * @see NetworkStack
+ * @see NetworkStackClient
*/
public static final String NETWORK_STACK_SERVICE = "network_stack";
diff --git a/core/java/android/content/PermissionChecker.java b/core/java/android/content/PermissionChecker.java
index 9f5c877e7081..6fe6e991fb1e 100644
--- a/core/java/android/content/PermissionChecker.java
+++ b/core/java/android/content/PermissionChecker.java
@@ -108,8 +108,7 @@ public final class PermissionChecker {
packageName = packageNames[0];
}
- if (appOpsManager.noteProxyOpNoThrow(op, packageName)
- != AppOpsManager.MODE_ALLOWED) {
+ if (appOpsManager.noteProxyOpNoThrow(op, packageName, uid) != AppOpsManager.MODE_ALLOWED) {
return PERMISSION_DENIED_APP_OP;
}
@@ -120,6 +119,9 @@ public final class PermissionChecker {
* Checks whether your app has a given permission and whether the app op
* that corresponds to this permission is allowed.
*
+ * <p>This API assumes the the {@link Binder#getCallingUid()} is the same as
+ * {@link Process#myUid()}.
+ *
* @param context Context for accessing resources.
* @param permission The permission to check.
* @return The permission check result which is either {@link #PERMISSION_GRANTED}
diff --git a/core/java/android/content/pm/IPackageManager.aidl b/core/java/android/content/pm/IPackageManager.aidl
index 36ffb0ea94d0..14e77258c65e 100644
--- a/core/java/android/content/pm/IPackageManager.aidl
+++ b/core/java/android/content/pm/IPackageManager.aidl
@@ -295,8 +295,6 @@ interface IPackageManager {
void restoreDefaultApps(in byte[] backup, int userId);
byte[] getIntentFilterVerificationBackup(int userId);
void restoreIntentFilterVerification(in byte[] backup, int userId);
- byte[] getPermissionGrantBackup(int userId);
- void restorePermissionGrants(in byte[] backup, int userId);
/**
* Report the set of 'Home' activity candidates, plus (if any) which of them
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index 3ea78df6ae39..00419212544a 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -2943,6 +2943,7 @@ public abstract class PackageManager {
* @hide
*/
@SystemApi
+ @TestApi
public static final int FLAG_PERMISSION_USER_SET = 1 << 0;
/**
@@ -2953,6 +2954,7 @@ public abstract class PackageManager {
* @hide
*/
@SystemApi
+ @TestApi
public static final int FLAG_PERMISSION_USER_FIXED = 1 << 1;
/**
@@ -2976,6 +2978,7 @@ public abstract class PackageManager {
* @hide
*/
@SystemApi
+ @TestApi
public static final int FLAG_PERMISSION_REVOKE_ON_UPGRADE = 1 << 3;
/**
@@ -3005,6 +3008,7 @@ public abstract class PackageManager {
* @hide
*/
@SystemApi
+ @TestApi
public static final int FLAG_PERMISSION_REVIEW_REQUIRED = 1 << 6;
/**
@@ -3014,6 +3018,7 @@ public abstract class PackageManager {
*
* @hide
*/
+ @TestApi
public static final int FLAG_PERMISSION_REVOKE_WHEN_REQUESTED = 1 << 7;
/**
@@ -3795,6 +3800,7 @@ public abstract class PackageManager {
* @hide
*/
@SystemApi
+ @TestApi
@RequiresPermission(anyOf = {
android.Manifest.permission.GRANT_RUNTIME_PERMISSIONS,
android.Manifest.permission.REVOKE_RUNTIME_PERMISSIONS
@@ -3815,6 +3821,7 @@ public abstract class PackageManager {
* @hide
*/
@SystemApi
+ @TestApi
@RequiresPermission(anyOf = {
android.Manifest.permission.GRANT_RUNTIME_PERMISSIONS,
android.Manifest.permission.REVOKE_RUNTIME_PERMISSIONS
diff --git a/core/java/android/content/pm/ServiceInfo.java b/core/java/android/content/pm/ServiceInfo.java
index 60475de351cf..4a2f800552f6 100644
--- a/core/java/android/content/pm/ServiceInfo.java
+++ b/core/java/android/content/pm/ServiceInfo.java
@@ -151,6 +151,7 @@ public class ServiceInfo extends ComponentInfo
* @hide
*/
@IntDef(flag = true, prefix = { "FOREGROUND_SERVICE_TYPE_" }, value = {
+ FOREGROUND_SERVICE_TYPE_MANIFEST,
FOREGROUND_SERVICE_TYPE_NONE,
FOREGROUND_SERVICE_TYPE_DATA_SYNC,
FOREGROUND_SERVICE_TYPE_MEDIA_PLAYBACK,
@@ -180,10 +181,10 @@ public class ServiceInfo extends ComponentInfo
}
/**
- * Return the current foreground service type.
- * @return the current foreground service type.
+ * Return foreground service type specified in the manifest..
+ * @return foreground service type specified in the manifest.
*/
- public int getForegroundServiceType() {
+ public @ForegroundServiceType int getForegroundServiceType() {
return mForegroundServiceType;
}
diff --git a/core/java/android/database/sqlite/SQLiteQueryBuilder.java b/core/java/android/database/sqlite/SQLiteQueryBuilder.java
index 5722e7b25fbf..ea489c456f3d 100644
--- a/core/java/android/database/sqlite/SQLiteQueryBuilder.java
+++ b/core/java/android/database/sqlite/SQLiteQueryBuilder.java
@@ -77,6 +77,14 @@ public class SQLiteQueryBuilder {
}
/**
+ * Get if the query is marked as DISTINCT, as last configured by
+ * {@link #setDistinct(boolean)}.
+ */
+ public boolean getDistinct() {
+ return mDistinct;
+ }
+
+ /**
* Returns the list of tables being queried
*
* @return the list of tables being queried
@@ -167,6 +175,14 @@ public class SQLiteQueryBuilder {
}
/**
+ * Gets the projection map for the query, as last configured by
+ * {@link #setProjectionMap(Map)}.
+ */
+ public Map<String, String> getProjectionMap() {
+ return mProjectionMap;
+ }
+
+ /**
* Sets a projection greylist of columns that will be allowed through, even
* when {@link #setStrict(boolean)} is enabled. This provides a way for
* abusive custom columns like {@code COUNT(*)} to continue working.
@@ -178,6 +194,16 @@ public class SQLiteQueryBuilder {
}
/**
+ * Gets the projection greylist for the query, as last configured by
+ * {@link #setProjectionGreylist(List)}.
+ *
+ * @hide
+ */
+ public List<Pattern> getProjectionGreylist() {
+ return mProjectionGreylist;
+ }
+
+ /**
* Sets the cursor factory to be used for the query. You can use
* one factory for all queries on a database but it is normally
* easier to specify the factory when doing this query.
@@ -189,6 +215,14 @@ public class SQLiteQueryBuilder {
}
/**
+ * Sets the cursor factory to be used for the query, as last configured by
+ * {@link #setCursorFactory(android.database.sqlite.SQLiteDatabase.CursorFactory)}.
+ */
+ public SQLiteDatabase.CursorFactory getCursorFactory() {
+ return mFactory;
+ }
+
+ /**
* When set, the selection is verified against malicious arguments.
* When using this class to create a statement using
* {@link #buildQueryString(boolean, String, String[], String, String, String, String, String)},
@@ -214,6 +248,14 @@ public class SQLiteQueryBuilder {
}
/**
+ * Get if the query is marked as strict, as last configured by
+ * {@link #setStrict(boolean)}.
+ */
+ public boolean getStrict() {
+ return mStrict;
+ }
+
+ /**
* Build an SQL query string from the given clauses.
*
* @param distinct true if you want each row to be unique, false otherwise.
diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java
index 68d36de19963..6d195ae47449 100644
--- a/core/java/android/net/ConnectivityManager.java
+++ b/core/java/android/net/ConnectivityManager.java
@@ -3936,15 +3936,16 @@ public class ConnectivityManager {
*
* <p>This endpoint is exclusively for use by the NetworkStack and is protected by the
* corresponding permission.
+ * @param network Network on which the captive portal was detected.
* @param appExtras Extras to include in the app start intent.
* @hide
*/
@SystemApi
@TestApi
@RequiresPermission(NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK)
- public void startCaptivePortalApp(Bundle appExtras) {
+ public void startCaptivePortalApp(Network network, Bundle appExtras) {
try {
- mService.startCaptivePortalAppInternal(appExtras);
+ mService.startCaptivePortalAppInternal(network, appExtras);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
diff --git a/core/java/android/net/IConnectivityManager.aidl b/core/java/android/net/IConnectivityManager.aidl
index 872671fa5697..87c62d2f10a7 100644
--- a/core/java/android/net/IConnectivityManager.aidl
+++ b/core/java/android/net/IConnectivityManager.aidl
@@ -168,7 +168,7 @@ interface IConnectivityManager
void setAcceptUnvalidated(in Network network, boolean accept, boolean always);
void setAvoidUnvalidated(in Network network);
void startCaptivePortalApp(in Network network);
- void startCaptivePortalAppInternal(in Bundle appExtras);
+ void startCaptivePortalAppInternal(in Network network, in Bundle appExtras);
boolean getAvoidBadWifi();
int getMultipathPreference(in Network Network);
diff --git a/core/java/android/net/INetworkMonitor.aidl b/core/java/android/net/INetworkMonitor.aidl
index 41f969acad6f..c94cdde15aa8 100644
--- a/core/java/android/net/INetworkMonitor.aidl
+++ b/core/java/android/net/INetworkMonitor.aidl
@@ -34,6 +34,7 @@ oneway interface INetworkMonitor {
void start();
void launchCaptivePortalApp();
+ void notifyCaptivePortalAppFinished(int response);
void forceReevaluation(int uid);
void notifyPrivateDnsChanged(in PrivateDnsConfigParcel config);
void notifyDnsResponse(int returnCode);
diff --git a/core/java/android/net/INetworkMonitorCallbacks.aidl b/core/java/android/net/INetworkMonitorCallbacks.aidl
index 514658549651..2c61511feb72 100644
--- a/core/java/android/net/INetworkMonitorCallbacks.aidl
+++ b/core/java/android/net/INetworkMonitorCallbacks.aidl
@@ -26,5 +26,4 @@ oneway interface INetworkMonitorCallbacks {
void notifyPrivateDnsConfigResolved(in PrivateDnsConfigParcel config);
void showProvisioningNotification(String action, String packageName);
void hideProvisioningNotification();
- void logCaptivePortalLoginEvent(int eventId, String packageName);
} \ No newline at end of file
diff --git a/core/java/android/net/NetworkStack.java b/core/java/android/net/NetworkStack.java
index ca49438390e9..dbb894f92f55 100644
--- a/core/java/android/net/NetworkStack.java
+++ b/core/java/android/net/NetworkStack.java
@@ -15,46 +15,17 @@
*/
package android.net;
-import static android.content.pm.PackageManager.PERMISSION_GRANTED;
-import static android.os.IServiceManager.DUMP_FLAG_PRIORITY_HIGH;
-import static android.os.IServiceManager.DUMP_FLAG_PRIORITY_NORMAL;
-
-import android.annotation.NonNull;
-import android.annotation.Nullable;
import android.annotation.SystemApi;
-import android.annotation.SystemService;
import android.annotation.TestApi;
-import android.content.ComponentName;
-import android.content.Context;
-import android.content.Intent;
-import android.content.ServiceConnection;
-import android.content.pm.PackageManager;
-import android.net.dhcp.DhcpServingParamsParcel;
-import android.net.dhcp.IDhcpServerCallbacks;
-import android.net.ip.IIpClientCallbacks;
-import android.os.Binder;
-import android.os.IBinder;
-import android.os.Process;
-import android.os.RemoteException;
-import android.os.ServiceManager;
-import android.os.UserHandle;
-import android.util.Slog;
-
-import com.android.internal.annotations.GuardedBy;
-
-import java.lang.reflect.InvocationTargetException;
-import java.util.ArrayList;
/**
- * Service used to communicate with the network stack, which is running in a separate module.
+ *
+ * Constants for client code communicating with the network stack service.
* @hide
*/
-@SystemService(Context.NETWORK_STACK_SERVICE)
@SystemApi
@TestApi
public class NetworkStack {
- private static final String TAG = NetworkStack.class.getSimpleName();
-
/**
* Permission granted only to the NetworkStack APK, defined in NetworkStackStub with signature
* protection level.
@@ -65,235 +36,5 @@ public class NetworkStack {
public static final String PERMISSION_MAINLINE_NETWORK_STACK =
"android.permission.MAINLINE_NETWORK_STACK";
- private static final int NETWORKSTACK_TIMEOUT_MS = 10_000;
-
- @NonNull
- @GuardedBy("mPendingNetStackRequests")
- private final ArrayList<NetworkStackCallback> mPendingNetStackRequests = new ArrayList<>();
- @Nullable
- @GuardedBy("mPendingNetStackRequests")
- private INetworkStackConnector mConnector;
-
- private volatile boolean mNetworkStackStartRequested = false;
-
- private interface NetworkStackCallback {
- void onNetworkStackConnected(INetworkStackConnector connector);
- }
-
- /** @hide */
- public NetworkStack() { }
-
- /**
- * Create a DHCP server according to the specified parameters.
- *
- * <p>The server will be returned asynchronously through the provided callbacks.
- * @hide
- */
- public void makeDhcpServer(final String ifName, final DhcpServingParamsParcel params,
- final IDhcpServerCallbacks cb) {
- requestConnector(connector -> {
- try {
- connector.makeDhcpServer(ifName, params, cb);
- } catch (RemoteException e) {
- e.rethrowFromSystemServer();
- }
- });
- }
-
- /**
- * Create an IpClient on the specified interface.
- *
- * <p>The IpClient will be returned asynchronously through the provided callbacks.
- * @hide
- */
- public void makeIpClient(String ifName, IIpClientCallbacks cb) {
- requestConnector(connector -> {
- try {
- connector.makeIpClient(ifName, cb);
- } catch (RemoteException e) {
- e.rethrowFromSystemServer();
- }
- });
- }
-
- /**
- * Create a NetworkMonitor.
- *
- * <p>The INetworkMonitor will be returned asynchronously through the provided callbacks.
- * @hide
- */
- public void makeNetworkMonitor(
- NetworkParcelable network, String name, INetworkMonitorCallbacks cb) {
- requestConnector(connector -> {
- try {
- connector.makeNetworkMonitor(network, name, cb);
- } catch (RemoteException e) {
- e.rethrowFromSystemServer();
- }
- });
- }
-
- private class NetworkStackConnection implements ServiceConnection {
- @Override
- public void onServiceConnected(ComponentName name, IBinder service) {
- registerNetworkStackService(service);
- }
-
- @Override
- public void onServiceDisconnected(ComponentName name) {
- // TODO: crash/reboot the system ?
- Slog.wtf(TAG, "Lost network stack connector");
- }
- };
-
- private void registerNetworkStackService(@NonNull IBinder service) {
- final INetworkStackConnector connector = INetworkStackConnector.Stub.asInterface(service);
-
- ServiceManager.addService(Context.NETWORK_STACK_SERVICE, service, false /* allowIsolated */,
- DUMP_FLAG_PRIORITY_HIGH | DUMP_FLAG_PRIORITY_NORMAL);
-
- final ArrayList<NetworkStackCallback> requests;
- synchronized (mPendingNetStackRequests) {
- requests = new ArrayList<>(mPendingNetStackRequests);
- mPendingNetStackRequests.clear();
- mConnector = connector;
- }
-
- for (NetworkStackCallback r : requests) {
- r.onNetworkStackConnected(connector);
- }
- }
-
- /**
- * Start the network stack. Should be called only once on device startup.
- *
- * <p>This method will start the network stack either in the network stack process, or inside
- * the system server on devices that do not support the network stack module. The network stack
- * connector will then be delivered asynchronously to clients that requested it before it was
- * started.
- * @hide
- */
- public void start(Context context) {
- mNetworkStackStartRequested = true;
- // Try to bind in-process if the library is available
- IBinder connector = null;
- try {
- final Class service = Class.forName(
- "com.android.server.NetworkStackService",
- true /* initialize */,
- context.getClassLoader());
- connector = (IBinder) service.getMethod("makeConnector", Context.class)
- .invoke(null, context);
- } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
- Slog.wtf(TAG, "Could not create network stack connector from NetworkStackService");
- // TODO: crash/reboot system here ?
- return;
- } catch (ClassNotFoundException e) {
- // Normal behavior if stack is provided by the app: fall through
- }
-
- // In-process network stack. Add the service to the service manager here.
- if (connector != null) {
- registerNetworkStackService(connector);
- return;
- }
- // Start the network stack process. The service will be added to the service manager in
- // NetworkStackConnection.onServiceConnected().
- final Intent intent = new Intent(INetworkStackConnector.class.getName());
- final ComponentName comp = intent.resolveSystemService(context.getPackageManager(), 0);
- intent.setComponent(comp);
-
- if (comp == null) {
- Slog.wtf(TAG, "Could not resolve the network stack with " + intent);
- // TODO: crash/reboot system server ?
- return;
- }
-
- final PackageManager pm = context.getPackageManager();
- int uid = -1;
- try {
- uid = pm.getPackageUid(comp.getPackageName(), UserHandle.USER_SYSTEM);
- } catch (PackageManager.NameNotFoundException e) {
- Slog.wtf("Network stack package not found", e);
- // Fall through
- }
-
- if (uid != Process.NETWORK_STACK_UID) {
- throw new SecurityException("Invalid network stack UID: " + uid);
- }
-
- final int hasPermission =
- pm.checkPermission(PERMISSION_MAINLINE_NETWORK_STACK, comp.getPackageName());
- if (hasPermission != PERMISSION_GRANTED) {
- throw new SecurityException(
- "Network stack does not have permission " + PERMISSION_MAINLINE_NETWORK_STACK);
- }
-
- if (!context.bindServiceAsUser(intent, new NetworkStackConnection(),
- Context.BIND_AUTO_CREATE | Context.BIND_IMPORTANT, UserHandle.SYSTEM)) {
- Slog.wtf(TAG,
- "Could not bind to network stack in-process, or in app with " + intent);
- // TODO: crash/reboot system server if no network stack after a timeout ?
- }
- }
-
- /**
- * For non-system server clients, get the connector registered by the system server.
- */
- private INetworkStackConnector getRemoteConnector() {
- // Block until the NetworkStack connector is registered in ServiceManager.
- // <p>This is only useful for non-system processes that do not have a way to be notified of
- // registration completion. Adding a callback system would be too heavy weight considering
- // that the connector is registered on boot, so it is unlikely that a client would request
- // it before it is registered.
- // TODO: consider blocking boot on registration and simplify much of the logic in this class
- IBinder connector;
- try {
- final long before = System.currentTimeMillis();
- while ((connector = ServiceManager.getService(Context.NETWORK_STACK_SERVICE)) == null) {
- Thread.sleep(20);
- if (System.currentTimeMillis() - before > NETWORKSTACK_TIMEOUT_MS) {
- Slog.e(TAG, "Timeout waiting for NetworkStack connector");
- return null;
- }
- }
- } catch (InterruptedException e) {
- Slog.e(TAG, "Error waiting for NetworkStack connector", e);
- return null;
- }
-
- return INetworkStackConnector.Stub.asInterface(connector);
- }
-
- private void requestConnector(@NonNull NetworkStackCallback request) {
- // TODO: PID check.
- final int caller = Binder.getCallingUid();
- if (caller != Process.SYSTEM_UID && !UserHandle.isSameApp(caller, Process.BLUETOOTH_UID)) {
- // Don't even attempt to obtain the connector and give a nice error message
- throw new SecurityException(
- "Only the system server should try to bind to the network stack.");
- }
-
- if (!mNetworkStackStartRequested) {
- // The network stack is not being started in this process, e.g. this process is not
- // the system server. Get a remote connector registered by the system server.
- final INetworkStackConnector connector = getRemoteConnector();
- synchronized (mPendingNetStackRequests) {
- mConnector = connector;
- }
- request.onNetworkStackConnected(connector);
- return;
- }
-
- final INetworkStackConnector connector;
- synchronized (mPendingNetStackRequests) {
- connector = mConnector;
- if (connector == null) {
- mPendingNetStackRequests.add(request);
- return;
- }
- }
-
- request.onNetworkStackConnected(connector);
- }
+ private NetworkStack() {}
}
diff --git a/core/java/android/os/GraphicsEnvironment.java b/core/java/android/os/GraphicsEnvironment.java
index cc241b3b7756..ec6da24dc2b1 100644
--- a/core/java/android/os/GraphicsEnvironment.java
+++ b/core/java/android/os/GraphicsEnvironment.java
@@ -61,6 +61,7 @@ public class GraphicsEnvironment {
private static final String SYSTEM_DRIVER_VERSION_NAME = "";
private static final long SYSTEM_DRIVER_VERSION_CODE = 0;
private static final String PROPERTY_GFX_DRIVER = "ro.gfx.driver.0";
+ private static final String PROPERTY_GFX_DRIVER_BUILD_DATE = "ro.gfx.driver.build_date";
private static final String ANGLE_RULES_FILE = "a4a_rules.json";
private static final String ANGLE_TEMP_RULES = "debug.angle.rules";
private static final String ACTION_ANGLE_FOR_ANDROID = "android.app.action.ANGLE_FOR_ANDROID";
@@ -79,8 +80,9 @@ public class GraphicsEnvironment {
setupGpuLayers(context, coreSettings, pm, packageName);
setupAngle(context, coreSettings, pm, packageName);
if (!chooseDriver(context, coreSettings, pm, packageName)) {
+ final String driverBuildDate = SystemProperties.get(PROPERTY_GFX_DRIVER_BUILD_DATE);
setGpuStats(SYSTEM_DRIVER_NAME, SYSTEM_DRIVER_VERSION_NAME, SYSTEM_DRIVER_VERSION_CODE,
- packageName);
+ driverBuildDate == null ? "" : driverBuildDate, packageName);
}
}
@@ -574,8 +576,8 @@ public class GraphicsEnvironment {
final PackageInfo driverPackageInfo;
try {
- driverPackageInfo =
- pm.getPackageInfo(driverPackageName, PackageManager.MATCH_SYSTEM_ONLY);
+ driverPackageInfo = pm.getPackageInfo(driverPackageName,
+ PackageManager.MATCH_SYSTEM_ONLY | PackageManager.GET_META_DATA);
} catch (PackageManager.NameNotFoundException e) {
Log.w(TAG, "driver package '" + driverPackageName + "' not installed");
return false;
@@ -655,9 +657,6 @@ public class GraphicsEnvironment {
return false;
}
- setGpuStats(driverPackageName, driverPackageInfo.versionName, driverAppInfo.longVersionCode,
- packageName);
-
final StringBuilder sb = new StringBuilder();
sb.append(driverAppInfo.nativeLibraryDir)
.append(File.pathSeparator);
@@ -669,6 +668,12 @@ public class GraphicsEnvironment {
if (DEBUG) Log.v(TAG, "gfx driver package libs: " + paths);
setDriverPath(paths);
+ final String driverBuildDate = driverAppInfo.metaData == null
+ ? ""
+ : driverAppInfo.metaData.getString("driver_build_date");
+ setGpuStats(driverPackageName, driverPackageInfo.versionName, driverAppInfo.longVersionCode,
+ driverBuildDate == null ? "" : driverBuildDate, packageName);
+
return true;
}
@@ -710,7 +715,7 @@ public class GraphicsEnvironment {
private static native void setDebugLayersGLES(String layers);
private static native void setDriverPath(String path);
private static native void setGpuStats(String driverPackageName, String driverVersionName,
- long driverVersionCode, String appPackageName);
+ long driverVersionCode, String driverBuildDate, String appPackageName);
private static native void setAngleInfo(String path, String appPackage, String devOptIn,
FileDescriptor rulesFd, long rulesOffset, long rulesLength);
private static native boolean getShouldUseAngle(String packageName);
diff --git a/core/java/android/permission/PermissionControllerManager.java b/core/java/android/permission/PermissionControllerManager.java
index 89967c325dd2..d62bc6c5a872 100644
--- a/core/java/android/permission/PermissionControllerManager.java
+++ b/core/java/android/permission/PermissionControllerManager.java
@@ -51,6 +51,7 @@ import android.os.RemoteException;
import android.os.UserHandle;
import android.util.ArrayMap;
import android.util.Log;
+import android.util.SparseArray;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.infra.AbstractMultiplePendingRequestsRemoteService;
@@ -85,9 +86,11 @@ public final class PermissionControllerManager {
private static final Object sLock = new Object();
- /** App global remote service used by all {@link PermissionControllerManager managers} */
+ /**
+ * Global remote services (per user) used by all {@link PermissionControllerManager managers}
+ */
@GuardedBy("sLock")
- private static RemoteService sRemoteService;
+ private static SparseArray<RemoteService> sRemoteServices = new SparseArray<>(1);
/**
* The key for retrieving the result from the returned bundle.
@@ -203,6 +206,7 @@ public final class PermissionControllerManager {
}
private final @NonNull Context mContext;
+ private final @NonNull RemoteService mRemoteService;
/**
* Create a new {@link PermissionControllerManager}.
@@ -213,14 +217,18 @@ public final class PermissionControllerManager {
*/
public PermissionControllerManager(@NonNull Context context) {
synchronized (sLock) {
- if (sRemoteService == null) {
+ RemoteService remoteService = sRemoteServices.get(context.getUserId(), null);
+ if (remoteService == null) {
Intent intent = new Intent(SERVICE_INTERFACE);
intent.setPackage(context.getPackageManager().getPermissionControllerPackageName());
ResolveInfo serviceInfo = context.getPackageManager().resolveService(intent, 0);
- sRemoteService = new RemoteService(context.getApplicationContext(),
- serviceInfo.getComponentInfo().getComponentName());
+ remoteService = new RemoteService(context.getApplicationContext(),
+ serviceInfo.getComponentInfo().getComponentName(), context.getUser());
+ sRemoteServices.put(context.getUserId(), remoteService);
}
+
+ mRemoteService = remoteService;
}
mContext = context;
@@ -255,7 +263,7 @@ public final class PermissionControllerManager {
+ " required");
}
- sRemoteService.scheduleRequest(new PendingRevokeRuntimePermissionRequest(sRemoteService,
+ mRemoteService.scheduleRequest(new PendingRevokeRuntimePermissionRequest(mRemoteService,
request, doDryRun, reason, mContext.getPackageName(), executor, callback));
}
@@ -276,7 +284,7 @@ public final class PermissionControllerManager {
checkNotNull(executor);
checkNotNull(callback);
- sRemoteService.scheduleRequest(new PendingGetRuntimePermissionBackup(sRemoteService,
+ mRemoteService.scheduleRequest(new PendingGetRuntimePermissionBackup(mRemoteService,
user, executor, callback));
}
@@ -294,8 +302,8 @@ public final class PermissionControllerManager {
checkNotNull(backup);
checkNotNull(user);
- sRemoteService.scheduleAsyncRequest(
- new PendingRestoreRuntimePermissionBackup(sRemoteService, backup, user));
+ mRemoteService.scheduleAsyncRequest(
+ new PendingRestoreRuntimePermissionBackup(mRemoteService, backup, user));
}
/**
@@ -318,8 +326,8 @@ public final class PermissionControllerManager {
checkNotNull(executor);
checkNotNull(callback);
- sRemoteService.scheduleRequest(
- new PendingRestoreDelayedRuntimePermissionBackup(sRemoteService, packageName,
+ mRemoteService.scheduleRequest(
+ new PendingRestoreDelayedRuntimePermissionBackup(mRemoteService, packageName,
user, executor, callback));
}
@@ -338,8 +346,8 @@ public final class PermissionControllerManager {
checkNotNull(packageName);
checkNotNull(callback);
- sRemoteService.scheduleRequest(new PendingGetAppPermissionRequest(sRemoteService,
- packageName, callback, handler == null ? sRemoteService.getHandler() : handler));
+ mRemoteService.scheduleRequest(new PendingGetAppPermissionRequest(mRemoteService,
+ packageName, callback, handler == null ? mRemoteService.getHandler() : handler));
}
/**
@@ -356,7 +364,7 @@ public final class PermissionControllerManager {
checkNotNull(packageName);
checkNotNull(permissionName);
- sRemoteService.scheduleAsyncRequest(new PendingRevokeAppPermissionRequest(packageName,
+ mRemoteService.scheduleAsyncRequest(new PendingRevokeAppPermissionRequest(packageName,
permissionName));
}
@@ -379,9 +387,9 @@ public final class PermissionControllerManager {
checkFlagsArgument(flags, COUNT_WHEN_SYSTEM | COUNT_ONLY_WHEN_GRANTED);
checkNotNull(callback);
- sRemoteService.scheduleRequest(new PendingCountPermissionAppsRequest(sRemoteService,
+ mRemoteService.scheduleRequest(new PendingCountPermissionAppsRequest(mRemoteService,
permissionNames, flags, callback,
- handler == null ? sRemoteService.getHandler() : handler));
+ handler == null ? mRemoteService.getHandler() : handler));
}
/**
@@ -402,7 +410,7 @@ public final class PermissionControllerManager {
checkNotNull(executor);
checkNotNull(callback);
- sRemoteService.scheduleRequest(new PendingGetPermissionUsagesRequest(sRemoteService,
+ mRemoteService.scheduleRequest(new PendingGetPermissionUsagesRequest(mRemoteService,
countSystem, numMillis, executor, callback));
}
@@ -424,8 +432,8 @@ public final class PermissionControllerManager {
checkNotNull(executor);
checkNotNull(callback);
- sRemoteService.scheduleRequest(new PendingIsApplicationQualifiedForRoleRequest(
- sRemoteService, roleName, packageName, executor, callback));
+ mRemoteService.scheduleRequest(new PendingIsApplicationQualifiedForRoleRequest(
+ mRemoteService, roleName, packageName, executor, callback));
}
/**
@@ -441,11 +449,12 @@ public final class PermissionControllerManager {
*
* @param context A context to use
* @param componentName The component of the service to connect to
+ * @param user User the remote service should be connected as
*/
- RemoteService(@NonNull Context context, @NonNull ComponentName componentName) {
- super(context, SERVICE_INTERFACE, componentName, UserHandle.myUserId(),
- service -> Log.e(TAG, "RuntimePermPresenterService " + service + " died"),
- false, false, 1);
+ RemoteService(@NonNull Context context, @NonNull ComponentName componentName,
+ @NonNull UserHandle user) {
+ super(context, SERVICE_INTERFACE, componentName, user.getIdentifier(),
+ service -> Log.e(TAG, "RemoteService " + service + " died"), false, false, 1);
}
/**
@@ -624,7 +633,7 @@ public final class PermissionControllerManager {
*
* <p>Needs to be called when canceling this task as it might be hung.
*/
- void interruptRead() {
+ void interruptWrite() {
IoUtils.closeQuietly(mLocalPipe);
}
@@ -806,18 +815,19 @@ public final class PermissionControllerManager {
@Override
public void run(@NonNull IPermissionController service) {
+ mBackupSender.execute(mBackup);
+
ParcelFileDescriptor remotePipe = mBackupSender.getRemotePipe();
try {
service.restoreRuntimePermissionBackup(mUser, remotePipe);
} catch (RemoteException e) {
Log.e(TAG, "Error sending runtime permission backup", e);
mBackupSender.cancel(false);
+ mBackupSender.interruptWrite();
} finally {
// Remote pipe end is duped by binder call. Local copy is not needed anymore
IoUtils.closeQuietly(remotePipe);
}
-
- mBackupSender.execute(mBackup);
}
}
diff --git a/core/java/android/permission/PermissionManagerInternal.java b/core/java/android/permission/PermissionManagerInternal.java
new file mode 100644
index 000000000000..92dbab33a2f0
--- /dev/null
+++ b/core/java/android/permission/PermissionManagerInternal.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.permission;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.os.UserHandle;
+
+/**
+ * Internal interfaces to be used by other components within the system server.
+ *
+ * <p>Only for use within the system server.
+ *
+ * @hide
+ */
+public abstract class PermissionManagerInternal {
+ /**
+ * Get the state of the runtime permissions as xml file.
+ *
+ * @param user The user the data should be extracted for
+ *
+ * @return The state as a xml file
+ */
+ public abstract @Nullable byte[] backupRuntimePermissions(@NonNull UserHandle user);
+
+ /**
+ * Restore a permission state previously backed up via {@link #backupRuntimePermissions}.
+ *
+ * <p>If not all state can be restored, the un-restoreable state will be delayed and can be
+ * re-tried via {@link #restoreDelayedRuntimePermissions}.
+ *
+ * @param backup The state as an xml file
+ * @param user The user the data should be restored for
+ */
+ public abstract void restoreRuntimePermissions(@NonNull byte[] backup,
+ @NonNull UserHandle user);
+
+ /**
+ * Try to apply permission backup of a package that was previously not applied.
+ *
+ * @param packageName The package that is newly installed
+ * @param user The user the package is installed for
+ *
+ * @see #restoreRuntimePermissions
+ */
+ public abstract void restoreDelayedRuntimePermissions(@NonNull String packageName,
+ @NonNull UserHandle user);
+}
diff --git a/core/java/android/provider/BaseColumns.java b/core/java/android/provider/BaseColumns.java
index f594c19d8eca..00c9e72df880 100644
--- a/core/java/android/provider/BaseColumns.java
+++ b/core/java/android/provider/BaseColumns.java
@@ -16,17 +16,18 @@
package android.provider;
-public interface BaseColumns
-{
+import android.database.Cursor;
+
+public interface BaseColumns {
/**
* The unique ID for a row.
- * <P>Type: INTEGER (long)</P>
*/
+ @Column(Cursor.FIELD_TYPE_INTEGER)
public static final String _ID = "_id";
/**
* The count of rows in a directory.
- * <P>Type: INTEGER</P>
*/
+ // @Column(Cursor.FIELD_TYPE_INTEGER)
public static final String _COUNT = "_count";
}
diff --git a/core/java/android/provider/Column.java b/core/java/android/provider/Column.java
new file mode 100644
index 000000000000..1364fb86cbd6
--- /dev/null
+++ b/core/java/android/provider/Column.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.provider;
+
+import static java.lang.annotation.ElementType.FIELD;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+import android.content.ContentProvider;
+import android.content.ContentValues;
+import android.database.Cursor;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+/**
+ * Denotes that a field is a {@link ContentProvider} column. It can be used as a
+ * key for {@link ContentValues} when inserting or updating data, or as a
+ * projection when querying.
+ *
+ * @hide
+ */
+@Documented
+@Retention(RUNTIME)
+@Target({FIELD})
+public @interface Column {
+ /**
+ * The {@link Cursor#getType(int)} of the data stored in this column.
+ */
+ int value();
+
+ /**
+ * This column is read-only and cannot be defined during insert or updates.
+ */
+ boolean readOnly() default false;
+}
diff --git a/core/java/android/provider/MediaStore.java b/core/java/android/provider/MediaStore.java
index 0b3842080a75..1b10bef76067 100644
--- a/core/java/android/provider/MediaStore.java
+++ b/core/java/android/provider/MediaStore.java
@@ -857,8 +857,6 @@ public final class MediaStore {
* this path. Instead of trying to open this path directly, apps should
* use {@link ContentResolver#openFileDescriptor(Uri, String)} to gain
* access.
- * <p>
- * Type: TEXT
*
* @deprecated Apps may not have filesystem permissions to directly
* access this path. Instead of trying to open this path
@@ -869,6 +867,7 @@ public final class MediaStore {
* {@link android.os.Build.VERSION_CODES#Q} or higher.
*/
@Deprecated
+ @Column(Cursor.FIELD_TYPE_STRING)
public static final String DATA = "_data";
/**
@@ -883,44 +882,44 @@ public final class MediaStore {
* If you require the hash of a specific item, you can call
* {@link ContentResolver#canonicalize(Uri)}, which will block until the
* hash is calculated.
- * <p>
- * Type: BLOB
+ *
* @removed
*/
@Deprecated
+ @Column(value = Cursor.FIELD_TYPE_BLOB, readOnly = true)
public static final String HASH = "_hash";
/**
* The size of the file in bytes
- * <P>Type: INTEGER (long)</P>
*/
+ @Column(value = Cursor.FIELD_TYPE_INTEGER, readOnly = true)
public static final String SIZE = "_size";
/**
* The display name of the file
- * <P>Type: TEXT</P>
*/
+ @Column(Cursor.FIELD_TYPE_STRING)
public static final String DISPLAY_NAME = "_display_name";
/**
* The title of the content
- * <P>Type: TEXT</P>
*/
+ @Column(value = Cursor.FIELD_TYPE_STRING, readOnly = true)
public static final String TITLE = "title";
/**
* The time the file was added to the media provider
* Units are seconds since 1970.
- * <P>Type: INTEGER (long)</P>
*/
+ @Column(value = Cursor.FIELD_TYPE_INTEGER, readOnly = true)
public static final String DATE_ADDED = "date_added";
/**
* The time the file was last modified
* Units are seconds since 1970.
* NOTE: This is for internal use by the media scanner. Do not modify this field.
- * <P>Type: INTEGER (long)</P>
*/
+ @Column(value = Cursor.FIELD_TYPE_INTEGER, readOnly = true)
public static final String DATE_MODIFIED = "date_modified";
/**
@@ -938,9 +937,8 @@ public final class MediaStore {
* {@code format} of {@code audio/ogg} would be ignored.
* <p>
* This is a read-only column that is automatically computed.
- * <p>
- * Type: TEXT
*/
+ @Column(Cursor.FIELD_TYPE_STRING)
public static final String MIME_TYPE = "mime_type";
/**
@@ -948,35 +946,34 @@ public final class MediaStore {
* Used to pass the new file's object handle through the media scanner
* from MTP to the media provider
* For internal use only by MTP, media scanner and media provider.
- * <P>Type: INTEGER</P>
* @hide
*/
+ @Deprecated
+ // @Column(Cursor.FIELD_TYPE_INTEGER)
public static final String MEDIA_SCANNER_NEW_OBJECT_ID = "media_scanner_new_object_id";
/**
* Non-zero if the media file is drm-protected
- * <P>Type: INTEGER (boolean)</P>
* @hide
*/
@UnsupportedAppUsage
+ @Deprecated
+ @Column(Cursor.FIELD_TYPE_INTEGER)
public static final String IS_DRM = "is_drm";
/**
* Flag indicating if a media item is pending, and still being inserted
* by its owner.
- * <p>
- * Type: BOOLEAN
*
* @see MediaColumns#IS_PENDING
* @see MediaStore#setIncludePending(Uri)
* @see MediaStore#createPending(Context, PendingParams)
*/
+ @Column(Cursor.FIELD_TYPE_INTEGER)
public static final String IS_PENDING = "is_pending";
/**
* Flag indicating if a media item is trashed.
- * <p>
- * Type: BOOLEAN
*
* @see MediaColumns#IS_TRASHED
* @see MediaStore#setIncludeTrashed(Uri)
@@ -985,57 +982,54 @@ public final class MediaStore {
* @removed
*/
@Deprecated
+ @Column(Cursor.FIELD_TYPE_INTEGER)
public static final String IS_TRASHED = "is_trashed";
/**
* The time the file should be considered expired. Units are seconds
* since 1970. Typically only meaningful in the context of
* {@link #IS_PENDING} or {@link #IS_TRASHED}.
- * <p>
- * Type: INTEGER
* @removed
*/
@Deprecated
+ @Column(Cursor.FIELD_TYPE_INTEGER)
public static final String DATE_EXPIRES = "date_expires";
/**
* The width of the image/video in pixels.
*/
+ @Column(value = Cursor.FIELD_TYPE_INTEGER, readOnly = true)
public static final String WIDTH = "width";
/**
* The height of the image/video in pixels.
*/
+ @Column(value = Cursor.FIELD_TYPE_INTEGER, readOnly = true)
public static final String HEIGHT = "height";
/**
* Package name that contributed this media. The value may be
* {@code NULL} if ownership cannot be reliably determined.
- * <p>
- * This is a read-only column that is automatically computed.
- * <p>
- * Type: TEXT
*/
+ @Column(value = Cursor.FIELD_TYPE_STRING, readOnly = true)
public static final String OWNER_PACKAGE_NAME = "owner_package_name";
/**
* The primary directory name this media exists under. The value may be
* {@code NULL} if the media doesn't have a primary directory name.
- * <p>
- * Type: TEXT
*
* @see PendingParams#setPrimaryDirectory(String)
*/
+ @Column(Cursor.FIELD_TYPE_STRING)
public static final String PRIMARY_DIRECTORY = "primary_directory";
/**
* The secondary directory name this media exists under. The value may
* be {@code NULL} if the media doesn't have a secondary directory name.
- * <p>
- * Type: TEXT
*
* @see PendingParams#setSecondaryDirectory(String)
*/
+ @Column(Cursor.FIELD_TYPE_STRING)
public static final String SECONDARY_DIRECTORY = "secondary_directory";
/**
@@ -1046,11 +1040,8 @@ public final class MediaStore {
* <p>
* Each "document ID" is created once for each new resource. Different
* renditions of that resource are expected to have different IDs.
- * <p>
- * This is a read-only column that is automatically computed.
- * <p>
- * Type: TEXT
*/
+ @Column(value = Cursor.FIELD_TYPE_STRING, readOnly = true)
public static final String DOCUMENT_ID = "document_id";
/**
@@ -1061,11 +1052,8 @@ public final class MediaStore {
* <p>
* This "instance ID" changes with each save operation of a specific
* "document ID".
- * <p>
- * This is a read-only column that is automatically computed.
- * <p>
- * Type: TEXT
*/
+ @Column(value = Cursor.FIELD_TYPE_STRING, readOnly = true)
public static final String INSTANCE_ID = "instance_id";
/**
@@ -1077,11 +1065,8 @@ public final class MediaStore {
* For example, when you save a PSD document as a JPEG, then convert the
* JPEG to GIF format, the "original document ID" of both the JPEG and
* GIF files is the "document ID" of the original PSD file.
- * <p>
- * This is a read-only column that is automatically computed.
- * <p>
- * Type: TEXT
*/
+ @Column(value = Cursor.FIELD_TYPE_STRING, readOnly = true)
public static final String ORIGINAL_DOCUMENT_ID = "original_document_id";
}
@@ -1172,43 +1157,46 @@ public final class MediaStore {
public interface FileColumns extends MediaColumns {
/**
* The MTP storage ID of the file
- * <P>Type: INTEGER</P>
* @hide
*/
@UnsupportedAppUsage
+ @Deprecated
+ // @Column(Cursor.FIELD_TYPE_INTEGER)
public static final String STORAGE_ID = "storage_id";
/**
* The MTP format code of the file
- * <P>Type: INTEGER</P>
* @hide
*/
@UnsupportedAppUsage
+ @Column(value = Cursor.FIELD_TYPE_INTEGER, readOnly = true)
public static final String FORMAT = "format";
/**
* The index of the parent directory of the file
- * <P>Type: INTEGER</P>
*/
+ @Column(value = Cursor.FIELD_TYPE_INTEGER, readOnly = true)
public static final String PARENT = "parent";
/**
* The MIME type of the file
* <P>Type: TEXT</P>
*/
+ @Column(Cursor.FIELD_TYPE_STRING)
public static final String MIME_TYPE = "mime_type";
/**
* The title of the content
* <P>Type: TEXT</P>
*/
+ @Column(value = Cursor.FIELD_TYPE_STRING, readOnly = true)
public static final String TITLE = "title";
/**
* The media type (audio, video, image or playlist)
* of the file, or 0 for not a media file
- * <P>Type: TEXT</P>
*/
+ @Column(Cursor.FIELD_TYPE_INTEGER)
public static final String MEDIA_TYPE = "media_type";
/**
@@ -1241,6 +1229,7 @@ public final class MediaStore {
* Column indicating if the file is part of Downloads collection.
* @hide
*/
+ @Column(value = Cursor.FIELD_TYPE_INTEGER, readOnly = true)
public static final String IS_DOWNLOAD = "is_download";
}
}
@@ -1260,23 +1249,20 @@ public final class MediaStore {
public interface DownloadColumns extends MediaColumns {
/**
* Uri indicating where the file has been downloaded from.
- * <p>
- * Type: TEXT
*/
+ @Column(Cursor.FIELD_TYPE_STRING)
String DOWNLOAD_URI = "download_uri";
/**
* Uri indicating HTTP referer of {@link #DOWNLOAD_URI}.
- * <p>
- * Type: TEXT
*/
+ @Column(Cursor.FIELD_TYPE_STRING)
String REFERER_URI = "referer_uri";
/**
* The description of the download.
- * <p>
- * Type: Text
*/
+ @Column(Cursor.FIELD_TYPE_STRING)
String DESCRIPTION = "description";
}
@@ -1442,29 +1428,28 @@ public final class MediaStore {
public interface ImageColumns extends MediaColumns {
/**
* The description of the image
- * <P>Type: TEXT</P>
*/
+ @Column(value = Cursor.FIELD_TYPE_STRING, readOnly = true)
public static final String DESCRIPTION = "description";
/**
* The picasa id of the image
- * <P>Type: TEXT</P>
*
* @deprecated this value was only relevant for images hosted on
* Picasa, which are no longer supported.
*/
@Deprecated
+ @Column(Cursor.FIELD_TYPE_STRING)
public static final String PICASA_ID = "picasa_id";
/**
* Whether the video should be published as public or private
- * <P>Type: INTEGER</P>
*/
+ @Column(Cursor.FIELD_TYPE_INTEGER)
public static final String IS_PRIVATE = "isprivate";
/**
* The latitude where the image was captured.
- * <P>Type: DOUBLE</P>
*
* @deprecated location details are no longer indexed for privacy
* reasons, and this value is now always {@code null}.
@@ -1472,11 +1457,11 @@ public final class MediaStore {
* {@link ExifInterface#getLatLong(float[])}.
*/
@Deprecated
+ @Column(value = Cursor.FIELD_TYPE_FLOAT, readOnly = true)
public static final String LATITUDE = "latitude";
/**
* The longitude where the image was captured.
- * <P>Type: DOUBLE</P>
*
* @deprecated location details are no longer indexed for privacy
* reasons, and this value is now always {@code null}.
@@ -1484,40 +1469,40 @@ public final class MediaStore {
* {@link ExifInterface#getLatLong(float[])}.
*/
@Deprecated
+ @Column(value = Cursor.FIELD_TYPE_FLOAT, readOnly = true)
public static final String LONGITUDE = "longitude";
/**
* The date & time that the image was taken in units
* of milliseconds since jan 1, 1970.
- * <P>Type: INTEGER</P>
*/
+ @Column(value = Cursor.FIELD_TYPE_INTEGER, readOnly = true)
public static final String DATE_TAKEN = "datetaken";
/**
* The orientation for the image expressed as degrees.
* Only degrees 0, 90, 180, 270 will work.
- * <P>Type: INTEGER</P>
*/
+ @Column(value = Cursor.FIELD_TYPE_INTEGER, readOnly = true)
public static final String ORIENTATION = "orientation";
/**
* The mini thumb id.
- * <P>Type: INTEGER</P>
*
* @deprecated all thumbnails should be obtained via
* {@link MediaStore.Images.Thumbnails#getThumbnail}, as this
* value is no longer supported.
*/
@Deprecated
+ @Column(Cursor.FIELD_TYPE_INTEGER)
public static final String MINI_THUMB_MAGIC = "mini_thumb_magic";
/**
* The primary bucket ID of this media item. This can be useful to
* present the user a first-level clustering of related media items.
* This is a read-only column that is automatically computed.
- * <p>
- * Type: INTEGER
*/
+ @Column(value = Cursor.FIELD_TYPE_INTEGER, readOnly = true)
public static final String BUCKET_ID = "bucket_id";
/**
@@ -1525,9 +1510,8 @@ public final class MediaStore {
* useful to present the user a first-level clustering of related
* media items. This is a read-only column that is automatically
* computed.
- * <p>
- * Type: TEXT
*/
+ @Column(value = Cursor.FIELD_TYPE_STRING, readOnly = true)
public static final String BUCKET_DISPLAY_NAME = "bucket_display_name";
/**
@@ -1541,9 +1525,8 @@ public final class MediaStore {
* {@code IMG1024.BURST001.JPG} and {@code IMG1024.BURST002.JPG}
* will have the same {@link #GROUP_ID} because the first portion of
* their filenames is identical.
- * <p>
- * Type: INTEGER
*/
+ @Column(value = Cursor.FIELD_TYPE_INTEGER, readOnly = true)
public static final String GROUP_ID = "group_id";
}
@@ -1848,8 +1831,6 @@ public final class MediaStore {
* apps should use
* {@link ContentResolver#openFileDescriptor(Uri, String)} to gain
* access.
- * <p>
- * Type: TEXT
*
* @deprecated Apps may not have filesystem permissions to directly
* access this path. Instead of trying to open this path
@@ -1860,39 +1841,45 @@ public final class MediaStore {
* {@link android.os.Build.VERSION_CODES#Q} or higher.
*/
@Deprecated
+ @Column(Cursor.FIELD_TYPE_STRING)
public static final String DATA = "_data";
/**
* The original image for the thumbnal
- * <P>Type: INTEGER (ID from Images table)</P>
*/
+ @Column(Cursor.FIELD_TYPE_INTEGER)
public static final String IMAGE_ID = "image_id";
/**
* The kind of the thumbnail
- * <P>Type: INTEGER (One of the values below)</P>
*/
+ @Column(Cursor.FIELD_TYPE_INTEGER)
public static final String KIND = "kind";
public static final int MINI_KIND = ThumbnailConstants.MINI_KIND;
public static final int FULL_SCREEN_KIND = ThumbnailConstants.FULL_SCREEN_KIND;
public static final int MICRO_KIND = ThumbnailConstants.MICRO_KIND;
+
/**
* The blob raw data of thumbnail
- * <P>Type: DATA STREAM</P>
+ *
+ * @deprecated this column never existed internally, and could never
+ * have returned valid data.
*/
+ @Deprecated
+ @Column(Cursor.FIELD_TYPE_BLOB)
public static final String THUMB_DATA = "thumb_data";
/**
* The width of the thumbnal
- * <P>Type: INTEGER (long)</P>
*/
+ @Column(value = Cursor.FIELD_TYPE_INTEGER, readOnly = true)
public static final String WIDTH = "width";
/**
* The height of the thumbnail
- * <P>Type: INTEGER (long)</P>
*/
+ @Column(value = Cursor.FIELD_TYPE_INTEGER, readOnly = true)
public static final String HEIGHT = "height";
}
}
@@ -1909,79 +1896,80 @@ public final class MediaStore {
/**
* A non human readable key calculated from the TITLE, used for
* searching, sorting and grouping
- * <P>Type: TEXT</P>
*/
+ @Column(value = Cursor.FIELD_TYPE_STRING, readOnly = true)
public static final String TITLE_KEY = "title_key";
/**
* The duration of the audio file, in ms
- * <P>Type: INTEGER (long)</P>
*/
+ @Column(value = Cursor.FIELD_TYPE_INTEGER, readOnly = true)
public static final String DURATION = "duration";
/**
* The position, in ms, playback was at when playback for this file
* was last stopped.
- * <P>Type: INTEGER (long)</P>
*/
+ @Column(Cursor.FIELD_TYPE_INTEGER)
public static final String BOOKMARK = "bookmark";
/**
* The id of the artist who created the audio file, if any
- * <P>Type: INTEGER (long)</P>
*/
+ @Column(value = Cursor.FIELD_TYPE_INTEGER, readOnly = true)
public static final String ARTIST_ID = "artist_id";
/**
* The artist who created the audio file, if any
- * <P>Type: TEXT</P>
*/
+ @Column(value = Cursor.FIELD_TYPE_STRING, readOnly = true)
public static final String ARTIST = "artist";
/**
* The artist credited for the album that contains the audio file
- * <P>Type: TEXT</P>
* @hide
*/
+ @Column(value = Cursor.FIELD_TYPE_STRING, readOnly = true)
public static final String ALBUM_ARTIST = "album_artist";
/**
* Whether the song is part of a compilation
- * <P>Type: TEXT</P>
* @hide
*/
+ @Deprecated
+ // @Column(Cursor.FIELD_TYPE_STRING)
public static final String COMPILATION = "compilation";
/**
* A non human readable key calculated from the ARTIST, used for
* searching, sorting and grouping
- * <P>Type: TEXT</P>
*/
+ @Column(value = Cursor.FIELD_TYPE_STRING, readOnly = true)
public static final String ARTIST_KEY = "artist_key";
/**
* The composer of the audio file, if any
- * <P>Type: TEXT</P>
*/
+ @Column(value = Cursor.FIELD_TYPE_STRING, readOnly = true)
public static final String COMPOSER = "composer";
/**
* The id of the album the audio file is from, if any
- * <P>Type: INTEGER (long)</P>
*/
+ @Column(value = Cursor.FIELD_TYPE_INTEGER, readOnly = true)
public static final String ALBUM_ID = "album_id";
/**
* The album the audio file is from, if any
- * <P>Type: TEXT</P>
*/
+ @Column(value = Cursor.FIELD_TYPE_STRING, readOnly = true)
public static final String ALBUM = "album";
/**
* A non human readable key calculated from the ALBUM, used for
* searching, sorting and grouping
- * <P>Type: TEXT</P>
*/
+ @Column(value = Cursor.FIELD_TYPE_STRING, readOnly = true)
public static final String ALBUM_KEY = "album_key";
/**
@@ -1990,63 +1978,63 @@ public final class MediaStore {
* disc number. For multi-disc sets, this number will
* be 1xxx for tracks on the first disc, 2xxx for tracks
* on the second disc, etc.
- * <P>Type: INTEGER</P>
*/
+ @Column(value = Cursor.FIELD_TYPE_INTEGER, readOnly = true)
public static final String TRACK = "track";
/**
* The year the audio file was recorded, if any
- * <P>Type: INTEGER</P>
*/
+ @Column(value = Cursor.FIELD_TYPE_INTEGER, readOnly = true)
public static final String YEAR = "year";
/**
* Non-zero if the audio file is music
- * <P>Type: INTEGER (boolean)</P>
*/
+ @Column(value = Cursor.FIELD_TYPE_INTEGER, readOnly = true)
public static final String IS_MUSIC = "is_music";
/**
* Non-zero if the audio file is a podcast
- * <P>Type: INTEGER (boolean)</P>
*/
+ @Column(value = Cursor.FIELD_TYPE_INTEGER, readOnly = true)
public static final String IS_PODCAST = "is_podcast";
/**
* Non-zero if the audio file may be a ringtone
- * <P>Type: INTEGER (boolean)</P>
*/
+ @Column(value = Cursor.FIELD_TYPE_INTEGER, readOnly = true)
public static final String IS_RINGTONE = "is_ringtone";
/**
* Non-zero if the audio file may be an alarm
- * <P>Type: INTEGER (boolean)</P>
*/
+ @Column(value = Cursor.FIELD_TYPE_INTEGER, readOnly = true)
public static final String IS_ALARM = "is_alarm";
/**
* Non-zero if the audio file may be a notification sound
- * <P>Type: INTEGER (boolean)</P>
*/
+ @Column(value = Cursor.FIELD_TYPE_INTEGER, readOnly = true)
public static final String IS_NOTIFICATION = "is_notification";
/**
* Non-zero if the audio file is an audiobook
- * <P>Type: INTEGER (boolean)</P>
*/
+ @Column(value = Cursor.FIELD_TYPE_INTEGER, readOnly = true)
public static final String IS_AUDIOBOOK = "is_audiobook";
/**
* The genre of the audio file, if any
- * <P>Type: TEXT</P>
* Does not exist in the database - only used by the media scanner for inserts.
* @hide
*/
+ @Deprecated
+ // @Column(Cursor.FIELD_TYPE_STRING)
public static final String GENRE = "genre";
/**
* The resource URI of a localized title, if any
- * <P>Type: TEXT</P>
* Conforms to this pattern:
* Scheme: {@link ContentResolver.SCHEME_ANDROID_RESOURCE}
* Authority: Package Name of ringtone title provider
@@ -2054,6 +2042,7 @@ public final class MediaStore {
* Second Path Segment: Resource ID of title
* @hide
*/
+ @Column(value = Cursor.FIELD_TYPE_STRING, readOnly = true)
public static final String TITLE_RESOURCE_URI = "title_resource_uri";
}
@@ -2142,6 +2131,7 @@ public final class MediaStore {
* @deprecated Apps may not have filesystem permissions to directly
* access this path.
*/
+ @Deprecated
public static @Nullable Uri getContentUriForPath(@NonNull String path) {
return getContentUri(getVolumeName(new File(path)));
}
@@ -2202,8 +2192,8 @@ public final class MediaStore {
public interface GenresColumns {
/**
* The name of the genre
- * <P>Type: TEXT</P>
*/
+ @Column(Cursor.FIELD_TYPE_STRING)
public static final String NAME = "name";
}
@@ -2287,14 +2277,14 @@ public final class MediaStore {
/**
* The ID of the audio file
- * <P>Type: INTEGER (long)</P>
*/
+ @Column(Cursor.FIELD_TYPE_INTEGER)
public static final String AUDIO_ID = "audio_id";
/**
* The ID of the genre
- * <P>Type: INTEGER (long)</P>
*/
+ @Column(Cursor.FIELD_TYPE_INTEGER)
public static final String GENRE_ID = "genre_id";
}
}
@@ -2305,8 +2295,8 @@ public final class MediaStore {
public interface PlaylistsColumns {
/**
* The name of the playlist
- * <P>Type: TEXT</P>
*/
+ @Column(Cursor.FIELD_TYPE_STRING)
public static final String NAME = "name";
/**
@@ -2317,8 +2307,6 @@ public final class MediaStore {
* apps should use
* {@link ContentResolver#openFileDescriptor(Uri, String)} to gain
* access.
- * <p>
- * Type: TEXT
*
* @deprecated Apps may not have filesystem permissions to directly
* access this path. Instead of trying to open this path
@@ -2329,21 +2317,22 @@ public final class MediaStore {
* {@link android.os.Build.VERSION_CODES#Q} or higher.
*/
@Deprecated
+ @Column(Cursor.FIELD_TYPE_STRING)
public static final String DATA = "_data";
/**
* The time the file was added to the media provider
* Units are seconds since 1970.
- * <P>Type: INTEGER (long)</P>
*/
+ @Column(value = Cursor.FIELD_TYPE_INTEGER, readOnly = true)
public static final String DATE_ADDED = "date_added";
/**
* The time the file was last modified
* Units are seconds since 1970.
* NOTE: This is for internal use by the media scanner. Do not modify this field.
- * <P>Type: INTEGER (long)</P>
*/
+ @Column(value = Cursor.FIELD_TYPE_INTEGER, readOnly = true)
public static final String DATE_MODIFIED = "date_modified";
}
@@ -2426,6 +2415,7 @@ public final class MediaStore {
/**
* The ID within the playlist.
*/
+ @Column(Cursor.FIELD_TYPE_INTEGER)
public static final String _ID = "_id";
/**
@@ -2436,20 +2426,20 @@ public final class MediaStore {
/**
* The ID of the audio file
- * <P>Type: INTEGER (long)</P>
*/
+ @Column(Cursor.FIELD_TYPE_INTEGER)
public static final String AUDIO_ID = "audio_id";
/**
* The ID of the playlist
- * <P>Type: INTEGER (long)</P>
*/
+ @Column(Cursor.FIELD_TYPE_INTEGER)
public static final String PLAYLIST_ID = "playlist_id";
/**
* The order of the songs in the playlist
- * <P>Type: INTEGER (long)></P>
*/
+ @Column(Cursor.FIELD_TYPE_INTEGER)
public static final String PLAY_ORDER = "play_order";
/**
@@ -2465,25 +2455,27 @@ public final class MediaStore {
public interface ArtistColumns {
/**
* The artist who created the audio file, if any
- * <P>Type: TEXT</P>
*/
+ @Column(value = Cursor.FIELD_TYPE_STRING, readOnly = true)
public static final String ARTIST = "artist";
/**
* A non human readable key calculated from the ARTIST, used for
* searching, sorting and grouping
- * <P>Type: TEXT</P>
*/
+ @Column(value = Cursor.FIELD_TYPE_STRING, readOnly = true)
public static final String ARTIST_KEY = "artist_key";
/**
* The number of albums in the database for this artist
*/
+ @Column(value = Cursor.FIELD_TYPE_INTEGER, readOnly = true)
public static final String NUMBER_OF_ALBUMS = "number_of_albums";
/**
* The number of albums in the database for this artist
*/
+ @Column(value = Cursor.FIELD_TYPE_INTEGER, readOnly = true)
public static final String NUMBER_OF_TRACKS = "number_of_tracks";
}
@@ -2551,34 +2543,34 @@ public final class MediaStore {
/**
* The id for the album
- * <P>Type: INTEGER</P>
*/
+ @Column(value = Cursor.FIELD_TYPE_INTEGER, readOnly = true)
public static final String ALBUM_ID = "album_id";
/**
* The album on which the audio file appears, if any
- * <P>Type: TEXT</P>
*/
+ @Column(value = Cursor.FIELD_TYPE_STRING, readOnly = true)
public static final String ALBUM = "album";
/**
* The artist whose songs appear on this album
- * <P>Type: TEXT</P>
*/
+ @Column(value = Cursor.FIELD_TYPE_STRING, readOnly = true)
public static final String ARTIST = "artist";
/**
* The number of songs on this album
- * <P>Type: INTEGER</P>
*/
+ @Column(value = Cursor.FIELD_TYPE_INTEGER, readOnly = true)
public static final String NUMBER_OF_SONGS = "numsongs";
/**
* This column is available when getting album info via artist,
* and indicates the number of songs on the album by the given
* artist.
- * <P>Type: INTEGER</P>
*/
+ @Column(value = Cursor.FIELD_TYPE_INTEGER, readOnly = true)
public static final String NUMBER_OF_SONGS_FOR_ARTIST = "numsongs_by_artist";
/**
@@ -2586,8 +2578,8 @@ public final class MediaStore {
* on this album were released. This will often
* be the same as {@link #LAST_YEAR}, but for compilation albums
* they might differ.
- * <P>Type: INTEGER</P>
*/
+ @Column(value = Cursor.FIELD_TYPE_INTEGER, readOnly = true)
public static final String FIRST_YEAR = "minyear";
/**
@@ -2595,20 +2587,19 @@ public final class MediaStore {
* on this album were released. This will often
* be the same as {@link #FIRST_YEAR}, but for compilation albums
* they might differ.
- * <P>Type: INTEGER</P>
*/
+ @Column(value = Cursor.FIELD_TYPE_INTEGER, readOnly = true)
public static final String LAST_YEAR = "maxyear";
/**
* A non human readable key calculated from the ALBUM, used for
* searching, sorting and grouping
- * <P>Type: TEXT</P>
*/
+ @Column(value = Cursor.FIELD_TYPE_STRING, readOnly = true)
public static final String ALBUM_KEY = "album_key";
/**
* Cached album art.
- * <P>Type: TEXT</P>
*
* @deprecated Apps may not have filesystem permissions to directly
* access this path. Instead of trying to open this path
@@ -2619,6 +2610,7 @@ public final class MediaStore {
* {@link android.os.Build.VERSION_CODES#Q} or higher.
*/
@Deprecated
+ @Column(Cursor.FIELD_TYPE_STRING)
public static final String ALBUM_ART = "album_art";
}
@@ -2676,6 +2668,43 @@ public final class MediaStore {
// Not instantiable.
private Radio() { }
}
+
+ /**
+ * This class provides utility methods to obtain thumbnails for various
+ * {@link Audio} items.
+ *
+ * @deprecated Callers should migrate to using
+ * {@link ContentResolver#loadThumbnail}, since it offers
+ * richer control over requested thumbnail sizes and
+ * cancellation behavior.
+ * @hide
+ */
+ @Deprecated
+ public static class Thumbnails implements BaseColumns {
+ /**
+ * Path to the thumbnail file on disk.
+ * <p>
+ * Note that apps may not have filesystem permissions to directly
+ * access this path. Instead of trying to open this path directly,
+ * apps should use
+ * {@link ContentResolver#openFileDescriptor(Uri, String)} to gain
+ * access.
+ *
+ * @deprecated Apps may not have filesystem permissions to directly
+ * access this path. Instead of trying to open this path
+ * directly, apps should use
+ * {@link ContentResolver#loadThumbnail}
+ * to gain access. This value will always be
+ * {@code NULL} for apps targeting
+ * {@link android.os.Build.VERSION_CODES#Q} or higher.
+ */
+ @Deprecated
+ @Column(Cursor.FIELD_TYPE_STRING)
+ public static final String DATA = "_data";
+
+ @Column(Cursor.FIELD_TYPE_INTEGER)
+ public static final String ALBUM_ID = "album_id";
+ }
}
public static final class Video {
@@ -2693,61 +2722,60 @@ public final class MediaStore {
/**
* The duration of the video file, in ms
- * <P>Type: INTEGER (long)</P>
*/
+ @Column(value = Cursor.FIELD_TYPE_INTEGER, readOnly = true)
public static final String DURATION = "duration";
/**
* The artist who created the video file, if any
- * <P>Type: TEXT</P>
*/
+ @Column(value = Cursor.FIELD_TYPE_STRING, readOnly = true)
public static final String ARTIST = "artist";
/**
* The album the video file is from, if any
- * <P>Type: TEXT</P>
*/
+ @Column(value = Cursor.FIELD_TYPE_STRING, readOnly = true)
public static final String ALBUM = "album";
/**
* The resolution of the video file, formatted as "XxY"
- * <P>Type: TEXT</P>
*/
+ @Column(value = Cursor.FIELD_TYPE_STRING, readOnly = true)
public static final String RESOLUTION = "resolution";
/**
* The description of the video recording
- * <P>Type: TEXT</P>
*/
+ @Column(value = Cursor.FIELD_TYPE_STRING, readOnly = true)
public static final String DESCRIPTION = "description";
/**
* Whether the video should be published as public or private
- * <P>Type: INTEGER</P>
*/
+ @Column(Cursor.FIELD_TYPE_INTEGER)
public static final String IS_PRIVATE = "isprivate";
/**
* The user-added tags associated with a video
- * <P>Type: TEXT</P>
*/
+ @Column(Cursor.FIELD_TYPE_STRING)
public static final String TAGS = "tags";
/**
* The YouTube category of the video
- * <P>Type: TEXT</P>
*/
+ @Column(Cursor.FIELD_TYPE_STRING)
public static final String CATEGORY = "category";
/**
* The language of the video
- * <P>Type: TEXT</P>
*/
+ @Column(Cursor.FIELD_TYPE_STRING)
public static final String LANGUAGE = "language";
/**
* The latitude where the video was captured.
- * <P>Type: DOUBLE</P>
*
* @deprecated location details are no longer indexed for privacy
* reasons, and this value is now always {@code null}.
@@ -2755,11 +2783,11 @@ public final class MediaStore {
* {@link ExifInterface#getLatLong(float[])}.
*/
@Deprecated
+ @Column(value = Cursor.FIELD_TYPE_FLOAT, readOnly = true)
public static final String LATITUDE = "latitude";
/**
* The longitude where the video was captured.
- * <P>Type: DOUBLE</P>
*
* @deprecated location details are no longer indexed for privacy
* reasons, and this value is now always {@code null}.
@@ -2767,33 +2795,33 @@ public final class MediaStore {
* {@link ExifInterface#getLatLong(float[])}.
*/
@Deprecated
+ @Column(value = Cursor.FIELD_TYPE_FLOAT, readOnly = true)
public static final String LONGITUDE = "longitude";
/**
* The date & time that the video was taken in units
* of milliseconds since jan 1, 1970.
- * <P>Type: INTEGER</P>
*/
+ @Column(value = Cursor.FIELD_TYPE_INTEGER, readOnly = true)
public static final String DATE_TAKEN = "datetaken";
/**
* The mini thumb id.
- * <P>Type: INTEGER</P>
*
* @deprecated all thumbnails should be obtained via
* {@link MediaStore.Images.Thumbnails#getThumbnail}, as this
* value is no longer supported.
*/
@Deprecated
+ @Column(Cursor.FIELD_TYPE_INTEGER)
public static final String MINI_THUMB_MAGIC = "mini_thumb_magic";
/**
* The primary bucket ID of this media item. This can be useful to
* present the user a first-level clustering of related media items.
* This is a read-only column that is automatically computed.
- * <p>
- * Type: INTEGER
*/
+ @Column(value = Cursor.FIELD_TYPE_INTEGER, readOnly = true)
public static final String BUCKET_ID = "bucket_id";
/**
@@ -2801,9 +2829,8 @@ public final class MediaStore {
* useful to present the user a first-level clustering of related
* media items. This is a read-only column that is automatically
* computed.
- * <p>
- * Type: TEXT
*/
+ @Column(value = Cursor.FIELD_TYPE_STRING, readOnly = true)
public static final String BUCKET_DISPLAY_NAME = "bucket_display_name";
/**
@@ -2817,9 +2844,8 @@ public final class MediaStore {
* {@code IMG1024.BURST001.JPG} and {@code IMG1024.BURST002.JPG}
* will have the same {@link #GROUP_ID} because the first portion of
* their filenames is identical.
- * <p>
- * Type: INTEGER
*/
+ @Column(value = Cursor.FIELD_TYPE_INTEGER, readOnly = true)
public static final String GROUP_ID = "group_id";
/**
@@ -2827,29 +2853,29 @@ public final class MediaStore {
* video should start playing at the next time it is opened. If the value is null or
* out of the range 0..DURATION-1 then the video should start playing from the
* beginning.
- * <P>Type: INTEGER</P>
*/
+ @Column(Cursor.FIELD_TYPE_INTEGER)
public static final String BOOKMARK = "bookmark";
/**
* The standard of color aspects
- * <P>Type: INTEGER</P>
* @hide
*/
+ @Column(value = Cursor.FIELD_TYPE_INTEGER, readOnly = true)
public static final String COLOR_STANDARD = "color_standard";
/**
* The transfer of color aspects
- * <P>Type: INTEGER</P>
* @hide
*/
+ @Column(value = Cursor.FIELD_TYPE_INTEGER, readOnly = true)
public static final String COLOR_TRANSFER = "color_transfer";
/**
* The range of color aspects
- * <P>Type: INTEGER</P>
* @hide
*/
+ @Column(value = Cursor.FIELD_TYPE_INTEGER, readOnly = true)
public static final String COLOR_RANGE = "color_range";
}
@@ -3016,8 +3042,6 @@ public final class MediaStore {
/**
* Path to the thumbnail file on disk.
- * <p>
- * Type: TEXT
*
* @deprecated Apps may not have filesystem permissions to directly
* access this path. Instead of trying to open this path
@@ -3028,18 +3052,19 @@ public final class MediaStore {
* {@link android.os.Build.VERSION_CODES#Q} or higher.
*/
@Deprecated
+ @Column(Cursor.FIELD_TYPE_STRING)
public static final String DATA = "_data";
/**
* The original image for the thumbnal
- * <P>Type: INTEGER (ID from Video table)</P>
*/
+ @Column(Cursor.FIELD_TYPE_INTEGER)
public static final String VIDEO_ID = "video_id";
/**
* The kind of the thumbnail
- * <P>Type: INTEGER (One of the values below)</P>
*/
+ @Column(Cursor.FIELD_TYPE_INTEGER)
public static final String KIND = "kind";
public static final int MINI_KIND = ThumbnailConstants.MINI_KIND;
@@ -3048,14 +3073,14 @@ public final class MediaStore {
/**
* The width of the thumbnal
- * <P>Type: INTEGER (long)</P>
*/
+ @Column(value = Cursor.FIELD_TYPE_INTEGER, readOnly = true)
public static final String WIDTH = "width";
/**
* The height of the thumbnail
- * <P>Type: INTEGER (long)</P>
*/
+ @Column(value = Cursor.FIELD_TYPE_INTEGER, readOnly = true)
public static final String HEIGHT = "height";
}
}
diff --git a/core/java/android/service/contentcapture/ContentCaptureService.java b/core/java/android/service/contentcapture/ContentCaptureService.java
index d2f98599e9a6..b60fbc593b1c 100644
--- a/core/java/android/service/contentcapture/ContentCaptureService.java
+++ b/core/java/android/service/contentcapture/ContentCaptureService.java
@@ -34,6 +34,7 @@ import android.os.Looper;
import android.os.RemoteException;
import android.service.autofill.AutofillService;
import android.util.ArrayMap;
+import android.util.ArraySet;
import android.util.Log;
import android.util.Slog;
import android.view.contentcapture.ContentCaptureContext;
@@ -49,7 +50,9 @@ import com.android.internal.os.IResultReceiver;
import java.io.FileDescriptor;
import java.io.PrintWriter;
+import java.util.ArrayList;
import java.util.List;
+import java.util.Set;
/**
* A service used to capture the content of the screen to provide contextual data in other areas of
@@ -164,6 +167,19 @@ public abstract class ContentCaptureService extends Service {
}
/**
+ * @deprecated use {@link #setContentCaptureWhitelist(Set, Set)} instead
+ */
+ @Deprecated
+ public final void setContentCaptureWhitelist(@Nullable List<String> packages,
+ @Nullable List<ComponentName> activities) {
+ setContentCaptureWhitelist(toSet(packages), toSet(activities));
+ }
+
+ private <T> ArraySet<T> toSet(@Nullable List<T> set) {
+ return set == null ? null : new ArraySet<T>(set);
+ }
+
+ /**
* Explicitly limits content capture to the given packages and activities.
*
* <p>To reset the whitelist, call it passing {@code null} to both arguments.
@@ -171,24 +187,29 @@ public abstract class ContentCaptureService extends Service {
* <p>Useful when the service wants to restrict content capture to a category of apps, like
* chat apps. For example, if the service wants to support view captures on all activities of
* app {@code ChatApp1} and just activities {@code act1} and {@code act2} of {@code ChatApp2},
- * it would call: {@code setContentCaptureWhitelist(Arrays.asList("ChatApp1"),
- * Arrays.asList(new ComponentName("ChatApp2", "act1"),
+ * it would call: {@code setContentCaptureWhitelist(Sets.newArraySet("ChatApp1"),
+ * Sets.newArraySet(new ComponentName("ChatApp2", "act1"),
* new ComponentName("ChatApp2", "act2")));}
*/
- public final void setContentCaptureWhitelist(@Nullable List<String> packages,
- @Nullable List<ComponentName> activities) {
+ public final void setContentCaptureWhitelist(@Nullable Set<String> packages,
+ @Nullable Set<ComponentName> activities) {
final IContentCaptureServiceCallback callback = mCallback;
if (callback == null) {
Log.w(TAG, "setContentCaptureWhitelist(): no server callback");
return;
}
+
try {
- callback.setContentCaptureWhitelist(packages, activities);
+ callback.setContentCaptureWhitelist(toList(packages), toList(activities));
} catch (RemoteException e) {
e.rethrowFromSystemServer();
}
}
+ private <T> ArrayList<T> toList(@Nullable Set<T> set) {
+ return set == null ? null : new ArrayList<T>(set);
+ }
+
/**
* Called when the Android system connects to service.
*
diff --git a/core/java/android/service/notification/Adjustment.java b/core/java/android/service/notification/Adjustment.java
index 93189b310485..2961426278dc 100644
--- a/core/java/android/service/notification/Adjustment.java
+++ b/core/java/android/service/notification/Adjustment.java
@@ -15,6 +15,7 @@
*/
package android.service.notification;
+import android.annotation.SystemApi;
import android.app.Notification;
import android.os.Bundle;
import android.os.Parcel;
@@ -36,13 +37,13 @@ public final class Adjustment implements Parcelable {
* See {@link android.app.Notification.Builder#addPerson(String)}.
* @hide
*/
+ @SystemApi
public static final String KEY_PEOPLE = "key_people";
/**
* Parcelable {@code ArrayList} of {@link SnoozeCriterion}. These criteria may be visible to
* users. If a user chooses to snooze a notification until one of these criterion, the
* assistant will be notified via
* {@link NotificationAssistantService#onNotificationSnoozedUntilContext}.
- * @hide
*/
public static final String KEY_SNOOZE_CRITERIA = "key_snooze_criteria";
/**
@@ -111,7 +112,11 @@ public final class Adjustment implements Parcelable {
mUser = user;
}
- private Adjustment(Parcel in) {
+ /**
+ * @hide
+ */
+ @SystemApi
+ protected Adjustment(Parcel in) {
if (in.readInt() == 1) {
mPackage = in.readString();
} else {
diff --git a/core/java/android/service/notification/NotificationAssistantService.java b/core/java/android/service/notification/NotificationAssistantService.java
index e93b1580bc66..a69724860634 100644
--- a/core/java/android/service/notification/NotificationAssistantService.java
+++ b/core/java/android/service/notification/NotificationAssistantService.java
@@ -21,6 +21,7 @@ import static java.lang.annotation.RetentionPolicy.SOURCE;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.SdkConstant;
+import android.annotation.SystemApi;
import android.app.Notification;
import android.app.NotificationChannel;
import android.app.admin.DevicePolicyManager;
@@ -103,7 +104,6 @@ public abstract class NotificationAssistantService extends NotificationListenerS
*
* @param sbn the notification to snooze
* @param snoozeCriterionId the {@link SnoozeCriterion#getId()} representing a device context.
- * @hide
*/
abstract public void onNotificationSnoozedUntilContext(StatusBarNotification sbn,
String snoozeCriterionId);
@@ -111,12 +111,13 @@ public abstract class NotificationAssistantService extends NotificationListenerS
/**
* A notification was posted by an app. Called before post.
*
+ * <p>Note: this method is only called if you don't override
+ * {@link #onNotificationEnqueued(StatusBarNotification, NotificationChannel)}.</p>
+ *
* @param sbn the new notification
* @return an adjustment or null to take no action, within 100ms.
*/
- public Adjustment onNotificationEnqueued(StatusBarNotification sbn) {
- return null;
- }
+ abstract public Adjustment onNotificationEnqueued(StatusBarNotification sbn);
/**
* A notification was posted by an app. Called before post.
@@ -240,12 +241,11 @@ public abstract class NotificationAssistantService extends NotificationListenerS
/**
* Inform the notification manager about un-snoozing a specific notification.
* <p>
- * This should only be used for notifications snoozed by this listener using
- * {@link #snoozeNotification(String, String)}. Once un-snoozed, you will get a
+ * This should only be used for notifications snoozed because of a contextual snooze suggestion
+ * you provided via {@link Adjustment#KEY_SNOOZE_CRITERIA}. Once un-snoozed, you will get a
* {@link #onNotificationPosted(StatusBarNotification, RankingMap)} callback for the
* notification.
* @param key The key of the notification to snooze
- * @hide
*/
public final void unsnoozeNotification(String key) {
if (!isBound()) return;
diff --git a/core/java/android/service/notification/NotificationStats.java b/core/java/android/service/notification/NotificationStats.java
index 814b4772a395..ebfabbfda326 100644
--- a/core/java/android/service/notification/NotificationStats.java
+++ b/core/java/android/service/notification/NotificationStats.java
@@ -16,6 +16,7 @@
package android.service.notification;
import android.annotation.IntDef;
+import android.annotation.SystemApi;
import android.app.RemoteInput;
import android.os.Parcel;
import android.os.Parcelable;
@@ -98,7 +99,11 @@ public final class NotificationStats implements Parcelable {
public NotificationStats() {
}
- private NotificationStats(Parcel in) {
+ /**
+ * @hide
+ */
+ @SystemApi
+ protected NotificationStats(Parcel in) {
mSeen = in.readByte() != 0;
mExpanded = in.readByte() != 0;
mDirectReplied = in.readByte() != 0;
diff --git a/core/java/android/view/ContextThemeWrapper.java b/core/java/android/view/ContextThemeWrapper.java
index c77500a9fd70..696e048ffed8 100644
--- a/core/java/android/view/ContextThemeWrapper.java
+++ b/core/java/android/view/ContextThemeWrapper.java
@@ -16,6 +16,7 @@
package android.view;
+import android.annotation.Nullable;
import android.annotation.StyleRes;
import android.annotation.UnsupportedAppUsage;
import android.content.Context;
@@ -23,6 +24,7 @@ import android.content.ContextWrapper;
import android.content.res.AssetManager;
import android.content.res.Configuration;
import android.content.res.Resources;
+import android.os.Build;
/**
* A context wrapper that allows you to modify or replace the theme of the
@@ -31,7 +33,7 @@ import android.content.res.Resources;
public class ContextThemeWrapper extends ContextWrapper {
@UnsupportedAppUsage
private int mThemeResource;
- @UnsupportedAppUsage
+ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 123768723)
private Resources.Theme mTheme;
@UnsupportedAppUsage
private LayoutInflater mInflater;
@@ -146,6 +148,15 @@ public class ContextThemeWrapper extends ContextWrapper {
}
}
+ /**
+ * Set the configure the current theme. If null is provided then the default Theme is returned
+ * on the next call to {@link #getTheme()}
+ * @param theme Theme to consume in the wrapper, a value of null resets the theme to the default
+ */
+ public void setTheme(@Nullable Resources.Theme theme) {
+ mTheme = theme;
+ }
+
/** @hide */
@Override
@UnsupportedAppUsage
diff --git a/core/java/android/view/autofill/AutofillManager.java b/core/java/android/view/autofill/AutofillManager.java
index f93ac4ce7d16..a6b40ed55ac5 100644
--- a/core/java/android/view/autofill/AutofillManager.java
+++ b/core/java/android/view/autofill/AutofillManager.java
@@ -78,6 +78,7 @@ import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
+import java.util.Set;
//TODO: use java.lang.ref.Cleaner once Android supports Java 9
import sun.misc.Cleaner;
@@ -1780,6 +1781,18 @@ public final class AutofillManager {
}
/**
+ * @deprecated use {@link #setAugmentedAutofillWhitelist(Set, Set)} instead.
+ * @hide
+ */
+ @SystemApi
+ @TestApi
+ @Deprecated
+ public void setAugmentedAutofillWhitelist(@Nullable List<String> packages,
+ @Nullable List<ComponentName> activities) {
+ // TODO(b/123100824): implement
+ }
+
+ /**
* Explicitly limits augmented autofill to the given packages and activities.
*
* <p>To reset the whitelist, call it passing {@code null} to both arguments.
@@ -1799,8 +1812,8 @@ public final class AutofillManager {
*/
@SystemApi
@TestApi
- public void setAugmentedAutofillWhitelist(@Nullable List<String> packages,
- @Nullable List<ComponentName> activities) {
+ public void setAugmentedAutofillWhitelist(@Nullable Set<String> packages,
+ @Nullable Set<ComponentName> activities) {
// TODO(b/123100824): implement
}
diff --git a/core/java/android/view/contentcapture/ContentCaptureHelper.java b/core/java/android/view/contentcapture/ContentCaptureHelper.java
index 508880feb3c3..1cf27fc56a8c 100644
--- a/core/java/android/view/contentcapture/ContentCaptureHelper.java
+++ b/core/java/android/view/contentcapture/ContentCaptureHelper.java
@@ -15,16 +15,29 @@
*/
package android.view.contentcapture;
+import static android.view.contentcapture.ContentCaptureManager.DEVICE_CONFIG_PROPERTY_LOGGING_LEVEL;
+import static android.view.contentcapture.ContentCaptureManager.LOGGING_LEVEL_DEBUG;
+import static android.view.contentcapture.ContentCaptureManager.LOGGING_LEVEL_OFF;
+import static android.view.contentcapture.ContentCaptureManager.LOGGING_LEVEL_VERBOSE;
+
+import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.os.Build;
+import android.provider.DeviceConfig;
+import android.util.Log;
+import android.view.contentcapture.ContentCaptureManager.LoggingLevel;
/**
- * Helpe class for this package.
+ * Helper class for this package and server's.
+ *
+ * @hide
*/
-final class ContentCaptureHelper {
+public final class ContentCaptureHelper {
- // TODO(b/121044306): define a way to dynamically set them(for example, using settings?)
- static final boolean VERBOSE = false;
- static final boolean DEBUG = true; // STOPSHIP if not set to false
+ private static final String TAG = ContentCaptureHelper.class.getSimpleName();
+
+ public static boolean sVerbose = false;
+ public static boolean sDebug = true;
/**
* Used to log text that could contain PII.
@@ -34,6 +47,61 @@ final class ContentCaptureHelper {
return text == null ? null : text.length() + "_chars";
}
+ /**
+ * Gets the value of a device config property from the Content Capture namespace.
+ */
+ public static int getIntDeviceConfigProperty(@NonNull String key, int defaultValue) {
+ final String value = DeviceConfig.getProperty(DeviceConfig.NAMESPACE_CONTENT_CAPTURE, key);
+ if (value == null) return defaultValue;
+
+ try {
+ return Integer.parseInt(value);
+ } catch (Exception e) {
+ Log.w(TAG, "error parsing value (" + value + ") of property " + key + ": " + e);
+ return defaultValue;
+ }
+ }
+
+ /**
+ * Sets the value of the static logging level constants based on device config.
+ */
+ public static void setLoggingLevel() {
+ final int defaultLevel = Build.IS_DEBUGGABLE ? LOGGING_LEVEL_DEBUG : LOGGING_LEVEL_OFF;
+ final int level = getIntDeviceConfigProperty(DEVICE_CONFIG_PROPERTY_LOGGING_LEVEL,
+ defaultLevel);
+ Log.i(TAG, "Setting logging level to " + getLoggingLevelAsString(level));
+ sVerbose = sDebug = false;
+ switch (level) {
+ case LOGGING_LEVEL_VERBOSE:
+ sVerbose = true;
+ // fall through
+ case LOGGING_LEVEL_DEBUG:
+ sDebug = true;
+ return;
+ case LOGGING_LEVEL_OFF:
+ // You log nothing, Jon Snow!
+ return;
+ default:
+ Log.w(TAG, "setLoggingLevel(): invalud level: " + level);
+ }
+ }
+
+ /**
+ * Gets a user-friendly value for a content capture logging level.
+ */
+ public static String getLoggingLevelAsString(@LoggingLevel int level) {
+ switch (level) {
+ case LOGGING_LEVEL_OFF:
+ return "OFF";
+ case LOGGING_LEVEL_DEBUG:
+ return "DEBUG";
+ case LOGGING_LEVEL_VERBOSE:
+ return "VERBOSE";
+ default:
+ return "UNKNOWN-" + level;
+ }
+ }
+
private ContentCaptureHelper() {
throw new UnsupportedOperationException("contains only static methods");
}
diff --git a/core/java/android/view/contentcapture/ContentCaptureManager.java b/core/java/android/view/contentcapture/ContentCaptureManager.java
index 634443d78b49..99063083e229 100644
--- a/core/java/android/view/contentcapture/ContentCaptureManager.java
+++ b/core/java/android/view/contentcapture/ContentCaptureManager.java
@@ -15,9 +15,10 @@
*/
package android.view.contentcapture;
-import static android.view.contentcapture.ContentCaptureHelper.DEBUG;
-import static android.view.contentcapture.ContentCaptureHelper.VERBOSE;
+import static android.view.contentcapture.ContentCaptureHelper.sDebug;
+import static android.view.contentcapture.ContentCaptureHelper.sVerbose;
+import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
@@ -38,16 +39,11 @@ import com.android.internal.util.Preconditions;
import com.android.internal.util.SyncResultReceiver;
import java.io.PrintWriter;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
-/*
- * NOTE: all methods in this class should return right away, or do the real work in a handler
- * thread.
- *
- * Hence, the only field that must be thread-safe is mEnabled, which is called at the beginning
- * of every method.
- */
/**
- * TODO(b/123577059): add javadocs / implement
+ * TODO(b/123577059): add javadocs / mention it can be null
*/
@SystemService(Context.CONTENT_CAPTURE_MANAGER_SERVICE)
public final class ContentCaptureManager {
@@ -85,12 +81,81 @@ public final class ContentCaptureManager {
public static final String DEVICE_CONFIG_PROPERTY_SERVICE_EXPLICITLY_ENABLED =
"service_explicitly_enabled";
+ /**
+ * Maximum number of events that are buffered before sent to the app.
+ *
+ * @hide
+ */
+ @TestApi
+ public static final String DEVICE_CONFIG_PROPERTY_MAX_BUFFER_SIZE = "max_buffer_size";
+
+ /**
+ * Frequency (in ms) of buffer flushes when no events are received.
+ *
+ * @hide
+ */
+ @TestApi
+ public static final String DEVICE_CONFIG_PROPERTY_IDLE_FLUSH_FREQUENCY = "idle_flush_frequency";
+
+ /**
+ * Frequency (in ms) of buffer flushes when no events are received and the last one was a
+ * text change event.
+ *
+ * @hide
+ */
+ @TestApi
+ public static final String DEVICE_CONFIG_PROPERTY_TEXT_CHANGE_FLUSH_FREQUENCY =
+ "text_change_flush_frequency";
+
+ /**
+ * Size of events that are logging on {@code dump}.
+ *
+ * <p>Set it to {@code 0} or less to disable history.
+ *
+ * @hide
+ */
+ @TestApi
+ public static final String DEVICE_CONFIG_PROPERTY_LOG_HISTORY_SIZE = "log_history_size";
+
+ /**
+ * Sets the logging level for {@code logcat} statements.
+ *
+ * <p>Valid values are: {@link #LOGGING_LEVEL_OFF}, {@value #LOGGING_LEVEL_DEBUG}, and
+ * {@link #LOGGING_LEVEL_VERBOSE}.
+ *
+ * @hide
+ */
+ @TestApi
+ public static final String DEVICE_CONFIG_PROPERTY_LOGGING_LEVEL = "logging_level";
+
+
+ /** @hide */
+ @TestApi
+ public static final int LOGGING_LEVEL_OFF = 0;
+
+ /** @hide */
+ @TestApi
+ public static final int LOGGING_LEVEL_DEBUG = 1;
+
+ /** @hide */
+ @TestApi
+ public static final int LOGGING_LEVEL_VERBOSE = 2;
+
+ /** @hide */
+ @IntDef(flag = false, value = {
+ LOGGING_LEVEL_OFF,
+ LOGGING_LEVEL_DEBUG,
+ LOGGING_LEVEL_VERBOSE
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface LoggingLevel {}
+
private final Object mLock = new Object();
@NonNull
private final Context mContext;
- @Nullable
+ @NonNull
private final IContentCaptureManager mService;
// Flags used for starting session.
@@ -107,11 +172,17 @@ public final class ContentCaptureManager {
/** @hide */
public ContentCaptureManager(@NonNull Context context,
- @Nullable IContentCaptureManager service) {
+ @NonNull IContentCaptureManager service) {
mContext = Preconditions.checkNotNull(context, "context cannot be null");
- if (VERBOSE) Log.v(TAG, "Constructor for " + context.getPackageName());
+ mService = Preconditions.checkNotNull(service, "service cannot be null");
+
+ // TODO(b/123096662): right now we're reading the device config values here, but ideally
+ // it should be read on ContentCaptureManagerService and passed back when the activity
+ // started.
+ ContentCaptureHelper.setLoggingLevel();
+
+ if (sVerbose) Log.v(TAG, "Constructor for " + context.getPackageName());
- mService = service;
// TODO(b/119220549): we might not even need a handler, as the IPCs are oneway. But if we
// do, then we should optimize it to run the tests after the Choreographer finishes the most
// important steps of the frame.
@@ -133,7 +204,7 @@ public final class ContentCaptureManager {
synchronized (mLock) {
if (mMainSession == null) {
mMainSession = new MainContentCaptureSession(mContext, this, mHandler, mService);
- if (VERBOSE) Log.v(TAG, "getMainContentCaptureSession(): created " + mMainSession);
+ if (sVerbose) Log.v(TAG, "getMainContentCaptureSession(): created " + mMainSession);
}
return mMainSession;
}
@@ -199,8 +270,6 @@ public final class ContentCaptureManager {
* </ul>
*/
public boolean isContentCaptureEnabled() {
- if (mService == null) return false;
-
final MainContentCaptureSession mainSession;
synchronized (mLock) {
mainSession = mMainSession;
@@ -219,7 +288,7 @@ public final class ContentCaptureManager {
* it on {@link android.app.Activity#onCreate(android.os.Bundle, android.os.PersistableBundle)}.
*/
public void setContentCaptureEnabled(boolean enabled) {
- if (DEBUG) {
+ if (sDebug) {
Log.d(TAG, "setContentCaptureEnabled(): setting to " + enabled + " for " + mContext);
}
@@ -242,8 +311,6 @@ public final class ContentCaptureManager {
@SystemApi
@TestApi
public boolean isContentCaptureFeatureEnabled() {
- if (mService == null) return false;
-
final SyncResultReceiver resultReceiver = new SyncResultReceiver(SYNC_CALLS_TIMEOUT_MS);
final int resultCode;
try {
@@ -275,7 +342,7 @@ public final class ContentCaptureManager {
@SystemApi
@TestApi
public void setContentCaptureFeatureEnabled(boolean enabled) {
- if (DEBUG) Log.d(TAG, "setContentCaptureFeatureEnabled(): setting to " + enabled);
+ if (sDebug) Log.d(TAG, "setContentCaptureFeatureEnabled(): setting to " + enabled);
final SyncResultReceiver resultReceiver = new SyncResultReceiver(SYNC_CALLS_TIMEOUT_MS);
final int resultCode;
@@ -314,22 +381,23 @@ public final class ContentCaptureManager {
/** @hide */
public void dump(String prefix, PrintWriter pw) {
+ pw.print(prefix); pw.println("ContentCaptureManager");
+ final String prefix2 = prefix + " ";
synchronized (mLock) {
- pw.print(prefix); pw.println("ContentCaptureManager");
- pw.print(prefix); pw.print("isContentCaptureEnabled(): ");
+ pw.print(prefix2); pw.print("isContentCaptureEnabled(): ");
pw.println(isContentCaptureEnabled());
+ pw.print(prefix); pw.print("Debug: "); pw.print(sDebug);
+ pw.print(" Verbose: "); pw.println(sVerbose);
pw.print(prefix); pw.print("Context: "); pw.println(mContext);
pw.print(prefix); pw.print("User: "); pw.println(mContext.getUserId());
- if (mService != null) {
- pw.print(prefix); pw.print("Service: "); pw.println(mService);
- }
+ pw.print(prefix); pw.print("Service: "); pw.println(mService);
pw.print(prefix); pw.print("Flags: "); pw.println(mFlags);
if (mMainSession != null) {
- final String prefix2 = prefix + " ";
- pw.print(prefix); pw.println("Main session:");
- mMainSession.dump(prefix2, pw);
+ final String prefix3 = prefix2 + " ";
+ pw.print(prefix2); pw.println("Main session:");
+ mMainSession.dump(prefix3, pw);
} else {
- pw.print(prefix); pw.println("No sessions");
+ pw.print(prefix2); pw.println("No sessions");
}
}
}
diff --git a/core/java/android/view/contentcapture/ContentCaptureSession.java b/core/java/android/view/contentcapture/ContentCaptureSession.java
index b8d3fa6f4404..1e051a43a42f 100644
--- a/core/java/android/view/contentcapture/ContentCaptureSession.java
+++ b/core/java/android/view/contentcapture/ContentCaptureSession.java
@@ -15,8 +15,8 @@
*/
package android.view.contentcapture;
-import static android.view.contentcapture.ContentCaptureHelper.DEBUG;
-import static android.view.contentcapture.ContentCaptureHelper.VERBOSE;
+import static android.view.contentcapture.ContentCaptureHelper.sDebug;
+import static android.view.contentcapture.ContentCaptureHelper.sVerbose;
import android.annotation.CallSuper;
import android.annotation.IntDef;
@@ -120,6 +120,13 @@ public abstract class ContentCaptureSession implements AutoCloseable {
*/
public static final int STATE_INTERNAL_ERROR = 0x100;
+ /**
+ * Session is disabled because service didn't whitelist package.
+ *
+ * @hide
+ */
+ public static final int STATE_PACKAGE_NOT_WHITELISTED = 0x200;
+
private static final int INITIAL_CHILDREN_CAPACITY = 5;
/** @hide */
@@ -233,7 +240,7 @@ public abstract class ContentCaptureSession implements AutoCloseable {
public final ContentCaptureSession createContentCaptureSession(
@NonNull ContentCaptureContext context) {
final ContentCaptureSession child = newChild(context);
- if (DEBUG) {
+ if (sDebug) {
Log.d(TAG, "createContentCaptureSession(" + context + ": parent=" + mId + ", child="
+ child.mId);
}
@@ -285,20 +292,20 @@ public abstract class ContentCaptureSession implements AutoCloseable {
public final void destroy() {
synchronized (mLock) {
if (mDestroyed) {
- if (DEBUG) Log.d(TAG, "destroy(" + mId + "): already destroyed");
+ if (sDebug) Log.d(TAG, "destroy(" + mId + "): already destroyed");
return;
}
mDestroyed = true;
// TODO(b/111276913): check state (for example, how to handle if it's waiting for remote
// id) and send it to the cache of batched commands
- if (VERBOSE) {
+ if (sVerbose) {
Log.v(TAG, "destroy(): state=" + getStateAsString(mState) + ", mId=" + mId);
}
// Finish children first
if (mChildren != null) {
final int numberChildren = mChildren.size();
- if (VERBOSE) Log.v(TAG, "Destroying " + numberChildren + " children first");
+ if (sVerbose) Log.v(TAG, "Destroying " + numberChildren + " children first");
for (int i = 0; i < numberChildren; i++) {
final ContentCaptureSession child = mChildren.get(i);
try {
diff --git a/core/java/android/view/contentcapture/MainContentCaptureSession.java b/core/java/android/view/contentcapture/MainContentCaptureSession.java
index d949f45ba5e6..f4021b11f317 100644
--- a/core/java/android/view/contentcapture/MainContentCaptureSession.java
+++ b/core/java/android/view/contentcapture/MainContentCaptureSession.java
@@ -23,9 +23,13 @@ import static android.view.contentcapture.ContentCaptureEvent.TYPE_SESSION_START
import static android.view.contentcapture.ContentCaptureEvent.TYPE_VIEW_APPEARED;
import static android.view.contentcapture.ContentCaptureEvent.TYPE_VIEW_DISAPPEARED;
import static android.view.contentcapture.ContentCaptureEvent.TYPE_VIEW_TEXT_CHANGED;
-import static android.view.contentcapture.ContentCaptureHelper.DEBUG;
-import static android.view.contentcapture.ContentCaptureHelper.VERBOSE;
+import static android.view.contentcapture.ContentCaptureHelper.getIntDeviceConfigProperty;
import static android.view.contentcapture.ContentCaptureHelper.getSanitizedString;
+import static android.view.contentcapture.ContentCaptureHelper.sDebug;
+import static android.view.contentcapture.ContentCaptureHelper.sVerbose;
+import static android.view.contentcapture.ContentCaptureManager.DEVICE_CONFIG_PROPERTY_IDLE_FLUSH_FREQUENCY;
+import static android.view.contentcapture.ContentCaptureManager.DEVICE_CONFIG_PROPERTY_LOG_HISTORY_SIZE;
+import static android.view.contentcapture.ContentCaptureManager.DEVICE_CONFIG_PROPERTY_MAX_BUFFER_SIZE;
import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -64,6 +68,7 @@ public final class MainContentCaptureSession extends ContentCaptureSession {
private static final String TAG = MainContentCaptureSession.class.getSimpleName();
+ // For readability purposes...
private static final boolean FORCE_FLUSH = true;
/**
@@ -71,17 +76,9 @@ public final class MainContentCaptureSession extends ContentCaptureSession {
*/
private static final int MSG_FLUSH = 1;
- /**
- * Maximum number of events that are buffered before sent to the app.
- */
- // TODO(b/121044064): use settings
- private static final int MAX_BUFFER_SIZE = 100;
-
- /**
- * Frequency the buffer is flushed if stale.
- */
- // TODO(b/121044064): use settings
- private static final int FLUSHING_FREQUENCY_MS = 5_000;
+ private static final int DEFAULT_MAX_BUFFER_SIZE = 100;
+ private static final int DEFAULT_FLUSHING_FREQUENCY_MS = 5_000;
+ private static final int DEFAULT_LOG_HISTORY_SIZE = 10;
/**
* Name of the {@link IResultReceiver} extra used to pass the binder interface to the service.
@@ -105,14 +102,14 @@ public final class MainContentCaptureSession extends ContentCaptureSession {
* Interface to the system_server binder object - it's only used to start the session (and
* notify when the session is finished).
*/
- @Nullable // TODO(b/122959591): shoul never be null, we should make main session null instead
+ @NonNull
private final IContentCaptureManager mSystemServerInterface;
/**
* Direct interface to the service binder object - it's used to send the events, including the
* last ones (when the session is finished)
*/
- @Nullable
+ @NonNull
private IContentCaptureDirectManager mDirectServiceInterface;
@Nullable
private DeathRecipient mDirectServiceVulture;
@@ -131,20 +128,42 @@ public final class MainContentCaptureSession extends ContentCaptureSession {
@Nullable
private ArrayList<ContentCaptureEvent> mEvents;
+ /**
+ * Maximum number of events that are buffered before sent to the app.
+ */
+ private final int mMaxBufferSize;
+
+ /**
+ * Frequency the buffer is flushed if idle.
+ */
+ private final int mIdleFlushingFrequencyMs;
+
// Used just for debugging purposes (on dump)
private long mNextFlush;
- // TODO(b/121044064): use settings to set size
- private final LocalLog mFlushHistory = new LocalLog(10);
+ @Nullable
+ private final LocalLog mFlushHistory;
/** @hide */
protected MainContentCaptureSession(@NonNull Context context,
@NonNull ContentCaptureManager manager, @NonNull Handler handler,
- @Nullable IContentCaptureManager systemServerInterface) {
+ @NonNull IContentCaptureManager systemServerInterface) {
mContext = context;
mManager = manager;
mHandler = handler;
mSystemServerInterface = systemServerInterface;
+
+ // TODO(b/123096662): right now we're reading the device config values here, but ideally
+ // it should be read on ContentCaptureManagerService and passed back when the activity
+ // started.
+ mMaxBufferSize = getIntDeviceConfigProperty(DEVICE_CONFIG_PROPERTY_MAX_BUFFER_SIZE,
+ DEFAULT_MAX_BUFFER_SIZE);
+ mIdleFlushingFrequencyMs = getIntDeviceConfigProperty(
+ DEVICE_CONFIG_PROPERTY_IDLE_FLUSH_FREQUENCY, DEFAULT_FLUSHING_FREQUENCY_MS);
+ final int logHistorySize = getIntDeviceConfigProperty(
+ DEVICE_CONFIG_PROPERTY_LOG_HISTORY_SIZE, DEFAULT_LOG_HISTORY_SIZE);
+
+ mFlushHistory = logHistorySize > 0 ? new LocalLog(logHistorySize) : null;
}
@Override
@@ -169,14 +188,14 @@ public final class MainContentCaptureSession extends ContentCaptureSession {
int flags) {
if (!isContentCaptureEnabled()) return;
- if (VERBOSE) {
+ if (sVerbose) {
Log.v(TAG, "start(): token=" + token + ", comp="
+ ComponentName.flattenToShortString(component));
}
if (hasStarted()) {
// TODO(b/122959591): make sure this is expected (and when), or use Log.w
- if (DEBUG) {
+ if (sDebug) {
Log.d(TAG, "ignoring handleStartSession(" + token + "/"
+ ComponentName.flattenToShortString(component) + " while on state "
+ getStateAsString(mState));
@@ -187,14 +206,12 @@ public final class MainContentCaptureSession extends ContentCaptureSession {
mApplicationToken = token;
mComponentName = component;
- if (VERBOSE) {
+ if (sVerbose) {
Log.v(TAG, "handleStartSession(): token=" + token + ", act="
+ getDebugState() + ", id=" + mId);
}
try {
- if (mSystemServerInterface == null) return;
-
mSystemServerInterface.startSession(mApplicationToken, component, mId, flags,
new IResultReceiver.Stub() {
@Override
@@ -254,7 +271,7 @@ public final class MainContentCaptureSession extends ContentCaptureSession {
mState = resultCode;
mDisabled.set(false);
}
- if (VERBOSE) {
+ if (sVerbose) {
Log.v(TAG, "handleSessionStarted() result: id=" + mId + " resultCode=" + resultCode
+ ", state=" + getStateAsString(mState) + ", disabled=" + mDisabled.get()
+ ", binder=" + binder + ", events=" + (mEvents == null ? 0 : mEvents.size()));
@@ -269,7 +286,7 @@ public final class MainContentCaptureSession extends ContentCaptureSession {
@UiThread
private void sendEvent(@NonNull ContentCaptureEvent event, boolean forceFlush) {
final int eventType = event.getType();
- if (VERBOSE) Log.v(TAG, "handleSendEvent(" + getDebugState() + "): " + event);
+ if (sVerbose) Log.v(TAG, "handleSendEvent(" + getDebugState() + "): " + event);
if (!hasStarted() && eventType != ContentCaptureEvent.TYPE_SESSION_STARTED
&& eventType != ContentCaptureEvent.TYPE_CONTEXT_UPDATED) {
// TODO(b/120494182): comment when this could happen (dialogs?)
@@ -282,14 +299,14 @@ public final class MainContentCaptureSession extends ContentCaptureSession {
// This happens when the event was queued in the handler before the sesison was ready,
// then handleSessionStarted() returned and set it as disabled - we need to drop it,
// otherwise it will keep triggering handleScheduleFlush()
- if (VERBOSE) Log.v(TAG, "handleSendEvent(): ignoring when disabled");
+ if (sVerbose) Log.v(TAG, "handleSendEvent(): ignoring when disabled");
return;
}
if (mEvents == null) {
- if (VERBOSE) {
- Log.v(TAG, "handleSendEvent(): creating buffer for " + MAX_BUFFER_SIZE + " events");
+ if (sVerbose) {
+ Log.v(TAG, "handleSendEvent(): creating buffer for " + mMaxBufferSize + " events");
}
- mEvents = new ArrayList<>(MAX_BUFFER_SIZE);
+ mEvents = new ArrayList<>(mMaxBufferSize);
}
// Some type of events can be merged together
@@ -301,7 +318,7 @@ public final class MainContentCaptureSession extends ContentCaptureSession {
// TODO(b/121045053): check if flags match
if (lastEvent.getType() == TYPE_VIEW_TEXT_CHANGED
&& lastEvent.getId().equals(event.getId())) {
- if (VERBOSE) {
+ if (sVerbose) {
Log.v(TAG, "Buffering VIEW_TEXT_CHANGED event, updated text="
+ getSanitizedString(event.getText()));
}
@@ -315,7 +332,7 @@ public final class MainContentCaptureSession extends ContentCaptureSession {
final ContentCaptureEvent lastEvent = mEvents.get(mEvents.size() - 1);
if (lastEvent.getType() == TYPE_VIEW_DISAPPEARED
&& event.getSessionId().equals(lastEvent.getSessionId())) {
- if (VERBOSE) {
+ if (sVerbose) {
Log.v(TAG, "Buffering TYPE_VIEW_DISAPPEARED events for session "
+ lastEvent.getSessionId());
}
@@ -330,20 +347,20 @@ public final class MainContentCaptureSession extends ContentCaptureSession {
final int numberEvents = mEvents.size();
- final boolean bufferEvent = numberEvents < MAX_BUFFER_SIZE;
+ final boolean bufferEvent = numberEvents < mMaxBufferSize;
if (bufferEvent && !forceFlush) {
scheduleFlush(FLUSH_REASON_IDLE_TIMEOUT, /* checkExisting= */ true);
return;
}
- if (mState != STATE_ACTIVE && numberEvents >= MAX_BUFFER_SIZE) {
+ if (mState != STATE_ACTIVE && numberEvents >= mMaxBufferSize) {
// Callback from startSession hasn't been called yet - typically happens on system
// apps that are started before the system service
// TODO(b/122959591): try to ignore session while system is not ready / boot
// not complete instead. Similarly, the manager service should return right away
// when the user does not have a service set
- if (DEBUG) {
+ if (sDebug) {
Log.d(TAG, "Closing session for " + getDebugState()
+ " after " + numberEvents + " delayed events");
}
@@ -398,12 +415,12 @@ public final class MainContentCaptureSession extends ContentCaptureSession {
@UiThread
private void scheduleFlush(@FlushReason int reason, boolean checkExisting) {
- if (VERBOSE) {
+ if (sVerbose) {
Log.v(TAG, "handleScheduleFlush(" + getDebugState(reason)
+ ", checkExisting=" + checkExisting);
}
if (!hasStarted()) {
- if (VERBOSE) Log.v(TAG, "handleScheduleFlush(): session not started yet");
+ if (sVerbose) Log.v(TAG, "handleScheduleFlush(): session not started yet");
return;
}
@@ -418,19 +435,19 @@ public final class MainContentCaptureSession extends ContentCaptureSession {
// "Renew" the flush message by removing the previous one
mHandler.removeMessages(MSG_FLUSH);
}
- mNextFlush = System.currentTimeMillis() + FLUSHING_FREQUENCY_MS;
- if (VERBOSE) {
+ mNextFlush = System.currentTimeMillis() + mIdleFlushingFrequencyMs;
+ if (sVerbose) {
Log.v(TAG, "handleScheduleFlush(): scheduled to flush in "
- + FLUSHING_FREQUENCY_MS + "ms: " + TimeUtils.logTimeOfDay(mNextFlush));
+ + mIdleFlushingFrequencyMs + "ms: " + TimeUtils.logTimeOfDay(mNextFlush));
}
// Post using a Runnable directly to trim a few μs from PooledLambda.obtainMessage()
- mHandler.postDelayed(() -> flushIfNeeded(reason), MSG_FLUSH, FLUSHING_FREQUENCY_MS);
+ mHandler.postDelayed(() -> flushIfNeeded(reason), MSG_FLUSH, mIdleFlushingFrequencyMs);
}
@UiThread
private void flushIfNeeded(@FlushReason int reason) {
if (mEvents == null || mEvents.isEmpty()) {
- if (VERBOSE) Log.v(TAG, "Nothing to flush");
+ if (sVerbose) Log.v(TAG, "Nothing to flush");
return;
}
flush(reason);
@@ -448,7 +465,7 @@ public final class MainContentCaptureSession extends ContentCaptureSession {
}
if (mDirectServiceInterface == null) {
- if (VERBOSE) {
+ if (sVerbose) {
Log.v(TAG, "handleForceFlush(" + getDebugState(reason) + "): hold your horses, "
+ "client not ready: " + mEvents);
}
@@ -460,14 +477,16 @@ public final class MainContentCaptureSession extends ContentCaptureSession {
final int numberEvents = mEvents.size();
final String reasonString = getflushReasonAsString(reason);
- if (DEBUG) {
+ if (sDebug) {
Log.d(TAG, "Flushing " + numberEvents + " event(s) for " + getDebugState(reason));
}
- // Logs reason, size, max size, idle timeout
- final String logRecord = "r=" + reasonString + " s=" + numberEvents
- + " m=" + MAX_BUFFER_SIZE + " i=" + FLUSHING_FREQUENCY_MS;
- try {
+ if (mFlushHistory != null) {
+ // Logs reason, size, max size, idle timeout
+ final String logRecord = "r=" + reasonString + " s=" + numberEvents
+ + " m=" + mMaxBufferSize + " i=" + mIdleFlushingFrequencyMs;
mFlushHistory.log(logRecord);
+ }
+ try {
mHandler.removeMessages(MSG_FLUSH);
final ParceledListSlice<ContentCaptureEvent> events = clearEvents();
@@ -500,15 +519,13 @@ public final class MainContentCaptureSession extends ContentCaptureSession {
@UiThread
private void destroySession() {
- if (DEBUG) {
+ if (sDebug) {
Log.d(TAG, "Destroying session (ctx=" + mContext + ", id=" + mId + ") with "
+ (mEvents == null ? 0 : mEvents.size()) + " event(s) for "
+ getDebugState());
}
try {
- if (mSystemServerInterface == null) return;
-
mSystemServerInterface.finishSession(mId);
} catch (RemoteException e) {
Log.e(TAG, "Error destroying system-service session " + mId + " for "
@@ -520,7 +537,7 @@ public final class MainContentCaptureSession extends ContentCaptureSession {
// clearings out.
@UiThread
private void resetSession(int newState) {
- if (VERBOSE) {
+ if (sVerbose) {
Log.v(TAG, "handleResetSession(" + getActivityName() + "): from "
+ getStateAsString(mState) + " to " + getStateAsString(newState));
}
@@ -628,12 +645,11 @@ public final class MainContentCaptureSession extends ContentCaptureSession {
@Override
void dump(@NonNull String prefix, @NonNull PrintWriter pw) {
+ super.dump(prefix, pw);
+
pw.print(prefix); pw.print("mContext: "); pw.println(mContext);
pw.print(prefix); pw.print("user: "); pw.println(mContext.getUserId());
- if (mSystemServerInterface != null) {
- pw.print(prefix); pw.print("mSystemServerInterface: ");
- pw.println(mSystemServerInterface);
- }
+ pw.print(prefix); pw.print("mSystemServerInterface: ");
if (mDirectServiceInterface != null) {
pw.print(prefix); pw.print("mDirectServiceInterface: ");
pw.println(mDirectServiceInterface);
@@ -651,8 +667,8 @@ public final class MainContentCaptureSession extends ContentCaptureSession {
if (mEvents != null && !mEvents.isEmpty()) {
final int numberEvents = mEvents.size();
pw.print(prefix); pw.print("buffered events: "); pw.print(numberEvents);
- pw.print('/'); pw.println(MAX_BUFFER_SIZE);
- if (VERBOSE && numberEvents > 0) {
+ pw.print('/'); pw.println(mMaxBufferSize);
+ if (sVerbose && numberEvents > 0) {
final String prefix3 = prefix + " ";
for (int i = 0; i < numberEvents; i++) {
final ContentCaptureEvent event = mEvents.get(i);
@@ -660,13 +676,17 @@ public final class MainContentCaptureSession extends ContentCaptureSession {
pw.println();
}
}
- pw.print(prefix); pw.print("flush frequency: "); pw.println(FLUSHING_FREQUENCY_MS);
+ pw.print(prefix); pw.print("flush frequency: "); pw.println(mIdleFlushingFrequencyMs);
pw.print(prefix); pw.print("next flush: ");
TimeUtils.formatDuration(mNextFlush - System.currentTimeMillis(), pw);
pw.print(" ("); pw.print(TimeUtils.logTimeOfDay(mNextFlush)); pw.println(")");
}
- pw.print(prefix); pw.println("flush history:");
- mFlushHistory.reverseDump(/* fd= */ null, pw, /* args= */ null); pw.println();
+ if (mFlushHistory != null) {
+ pw.print(prefix); pw.println("flush history:");
+ mFlushHistory.reverseDump(/* fd= */ null, pw, /* args= */ null); pw.println();
+ } else {
+ pw.print(prefix); pw.println("not logging flush history");
+ }
super.dump(prefix, pw);
}
diff --git a/core/java/android/widget/ProgressBar.java b/core/java/android/widget/ProgressBar.java
index 29f070ed5a65..8113b40eaee0 100644
--- a/core/java/android/widget/ProgressBar.java
+++ b/core/java/android/widget/ProgressBar.java
@@ -199,7 +199,9 @@ public class ProgressBar extends View {
private boolean mMaxInitialized;
private int mBehavior;
- @UnsupportedAppUsage
+ // Better to define a Drawable that implements Animatable if you want to modify animation
+ // characteristics programatically.
+ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 124052713)
private int mDuration;
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
private boolean mIndeterminate;
@@ -284,7 +286,6 @@ public class ProgressBar extends View {
}
}
-
mDuration = a.getInt(R.styleable.ProgressBar_indeterminateDuration, mDuration);
mMinWidth = a.getDimensionPixelSize(R.styleable.ProgressBar_minWidth, mMinWidth);
@@ -709,7 +710,17 @@ public class ProgressBar extends View {
/**
* Define the drawable used to draw the progress bar in indeterminate mode.
*
+ * <p>For the Drawable to animate, it must implement {@link Animatable}, or override
+ * {@link Drawable#onLevelChange(int)}. A Drawable that implements Animatable will be animated
+ * via that interface and therefore provides the greatest amount of customization. A Drawable
+ * that only overrides onLevelChange(int) is animated directly by ProgressBar and only the
+ * animation {@link android.R.styleable#ProgressBar_indeterminateDuration duration},
+ * {@link android.R.styleable#ProgressBar_indeterminateBehavior repeating behavior}, and
+ * {@link #setInterpolator(Interpolator) interpolator} can be modified, and only before the
+ * indeterminate animation begins.
+ *
* @param d the new drawable
+ * @attr ref android.R.styleable#ProgressBar_indeterminateDrawable
* @see #getIndeterminateDrawable()
* @see #setIndeterminate(boolean)
*/
@@ -1774,10 +1785,21 @@ public class ProgressBar extends View {
/**
* Sets the acceleration curve for the indeterminate animation.
- * The interpolator is loaded as a resource from the specified context.
+ *
+ * <p>The interpolator is loaded as a resource from the specified context. Defaults to a linear
+ * interpolation.
+ *
+ * <p>The interpolator only affects the indeterminate animation if the
+ * {@link #setIndeterminateDrawable(Drawable) supplied indeterminate drawable} does not
+ * implement {@link Animatable}.
+ *
+ * <p>This call must be made before the indeterminate animation starts for it to have an affect.
*
* @param context The application environment
* @param resID The resource identifier of the interpolator to load
+ * @attr ref android.R.styleable#ProgressBar_interpolator
+ * @see #setInterpolator(Interpolator)
+ * @see #getInterpolator()
*/
public void setInterpolator(Context context, @InterpolatorRes int resID) {
setInterpolator(AnimationUtils.loadInterpolator(context, resID));
@@ -1787,7 +1809,17 @@ public class ProgressBar extends View {
* Sets the acceleration curve for the indeterminate animation.
* Defaults to a linear interpolation.
*
+ * <p>The interpolator only affects the indeterminate animation if the
+ * {@link #setIndeterminateDrawable(Drawable) supplied indeterminate drawable} does not
+ * implement {@link Animatable}.
+ *
+ * <p>This call must be made before the indeterminate animation starts for it to have
+ * an affect.
+ *
* @param interpolator The interpolator which defines the acceleration curve
+ * @attr ref android.R.styleable#ProgressBar_interpolator
+ * @see #setInterpolator(Context, int)
+ * @see #getInterpolator()
*/
public void setInterpolator(Interpolator interpolator) {
mInterpolator = interpolator;
@@ -1797,6 +1829,9 @@ public class ProgressBar extends View {
* Gets the acceleration curve type for the indeterminate animation.
*
* @return the {@link Interpolator} associated to this animation
+ * @attr ref android.R.styleable#ProgressBar_interpolator
+ * @see #setInterpolator(Context, int)
+ * @see #setInterpolator(Interpolator)
*/
@InspectableProperty
public Interpolator getInterpolator() {
diff --git a/core/java/android/widget/Toast.java b/core/java/android/widget/Toast.java
index eef40e1f6e2e..d037337d4546 100644
--- a/core/java/android/widget/Toast.java
+++ b/core/java/android/widget/Toast.java
@@ -95,7 +95,7 @@ public class Toast {
public static final int LENGTH_LONG = 1;
final Context mContext;
- @UnsupportedAppUsage
+ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
final TN mTN;
@UnsupportedAppUsage
int mDuration;
@@ -354,7 +354,7 @@ public class Toast {
}
private static class TN extends ITransientNotification.Stub {
- @UnsupportedAppUsage
+ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
private final WindowManager.LayoutParams mParams = new WindowManager.LayoutParams();
private static final int SHOW = 0;
@@ -362,18 +362,18 @@ public class Toast {
private static final int CANCEL = 2;
final Handler mHandler;
- @UnsupportedAppUsage
+ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
int mGravity;
int mX;
- @UnsupportedAppUsage
+ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
int mY;
float mHorizontalMargin;
float mVerticalMargin;
- @UnsupportedAppUsage
+ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
View mView;
- @UnsupportedAppUsage
+ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
View mNextView;
int mDuration;
diff --git a/core/java/com/android/internal/app/ChooserActivity.java b/core/java/com/android/internal/app/ChooserActivity.java
index fbf80914e2f1..2009fd50137a 100644
--- a/core/java/com/android/internal/app/ChooserActivity.java
+++ b/core/java/com/android/internal/app/ChooserActivity.java
@@ -623,7 +623,14 @@ public class ChooserActivity extends ResolverActivity {
private FileInfo extractFileInfo(Uri uri, ContentResolver resolver) {
String fileName = null;
boolean hasThumbnail = false;
- Cursor cursor = resolver.query(uri, null, null, null, null);
+ Cursor cursor = null;
+
+ try {
+ cursor = resolver.query(uri, null, null, null, null);
+ } catch (SecurityException e) {
+ Log.w(TAG, "Error loading file preview", e);
+ }
+
if (cursor != null && cursor.getCount() > 0) {
int nameIndex = cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME);
int flagsIndex = cursor.getColumnIndex(DocumentsContract.Document.COLUMN_FLAGS);
@@ -655,46 +662,50 @@ public class ChooserActivity extends ResolverActivity {
// due to permissions issues
findViewById(R.id.file_copy_button).setVisibility(View.GONE);
- try {
- ContentResolver resolver = getContentResolver();
- TextView fileNameView = findViewById(R.id.content_preview_filename);
- String action = targetIntent.getAction();
- if (Intent.ACTION_SEND.equals(action)) {
- Uri uri = targetIntent.getParcelableExtra(Intent.EXTRA_STREAM);
-
- FileInfo fileInfo = extractFileInfo(uri, resolver);
- fileNameView.setText(fileInfo.name);
+ String action = targetIntent.getAction();
+ if (Intent.ACTION_SEND.equals(action)) {
+ Uri uri = targetIntent.getParcelableExtra(Intent.EXTRA_STREAM);
+ loadFileUriIntoView(uri);
+ } else {
+ List<Uri> uris = targetIntent.getParcelableArrayListExtra(Intent.EXTRA_STREAM);
+ int uriCount = uris.size();
- if (fileInfo.hasThumbnail) {
- loadUriIntoView(R.id.content_preview_file_thumbnail, uri);
- } else {
- ImageView fileIconView = findViewById(R.id.content_preview_file_icon);
- fileIconView.setVisibility(View.VISIBLE);
- fileIconView.setImageResource(R.drawable.ic_doc_generic);
- }
+ if (uriCount == 0) {
+ contentPreviewLayout.setVisibility(View.GONE);
+ Log.i(TAG,
+ "Appears to be no uris available in EXTRA_STREAM, removing "
+ + "preview area");
+ return;
+ } else if (uriCount == 1) {
+ loadFileUriIntoView(uris.get(0));
} else {
- List<Uri> uris = targetIntent.getParcelableArrayListExtra(Intent.EXTRA_STREAM);
- if (uris.size() == 0) {
- contentPreviewLayout.setVisibility(View.GONE);
- Log.i(TAG,
- "Appears to be no uris available in EXTRA_STREAM, removing preview "
- + "area");
- return;
- }
-
- FileInfo fileInfo = extractFileInfo(uris.get(0), resolver);
- int remFileCount = uris.size() - 1;
+ FileInfo fileInfo = extractFileInfo(uris.get(0), getContentResolver());
+ int remUriCount = uriCount - 1;
String fileName = getResources().getQuantityString(R.plurals.file_count,
- remFileCount, fileInfo.name, remFileCount);
+ remUriCount, fileInfo.name, remUriCount);
+ TextView fileNameView = findViewById(R.id.content_preview_filename);
fileNameView.setText(fileName);
+
ImageView fileIconView = findViewById(R.id.content_preview_file_icon);
fileIconView.setVisibility(View.VISIBLE);
fileIconView.setImageResource(R.drawable.ic_file_copy);
}
- } catch (SecurityException e) {
- Log.w(TAG, "Error loading file preview", e);
- contentPreviewLayout.setVisibility(View.GONE);
+ }
+ }
+
+ private void loadFileUriIntoView(Uri uri) {
+ FileInfo fileInfo = extractFileInfo(uri, getContentResolver());
+
+ TextView fileNameView = findViewById(R.id.content_preview_filename);
+ fileNameView.setText(fileInfo.name);
+
+ if (fileInfo.hasThumbnail) {
+ loadUriIntoView(R.id.content_preview_file_thumbnail, uri);
+ } else {
+ ImageView fileIconView = findViewById(R.id.content_preview_file_icon);
+ fileIconView.setVisibility(View.VISIBLE);
+ fileIconView.setImageResource(R.drawable.ic_doc_generic);
}
}
diff --git a/core/java/com/android/internal/os/BackgroundThread.java b/core/java/com/android/internal/os/BackgroundThread.java
index eada142dd3c6..22c832e0689c 100644
--- a/core/java/com/android/internal/os/BackgroundThread.java
+++ b/core/java/com/android/internal/os/BackgroundThread.java
@@ -17,10 +17,13 @@
package com.android.internal.os;
import android.os.Handler;
+import android.os.HandlerExecutor;
import android.os.HandlerThread;
import android.os.Looper;
import android.os.Trace;
+import java.util.concurrent.Executor;
+
/**
* Shared singleton background thread for each process.
*/
@@ -29,6 +32,7 @@ public final class BackgroundThread extends HandlerThread {
private static final long SLOW_DELIVERY_THRESHOLD_MS = 30_000;
private static BackgroundThread sInstance;
private static Handler sHandler;
+ private static HandlerExecutor sHandlerExecutor;
private BackgroundThread() {
super("android.bg", android.os.Process.THREAD_PRIORITY_BACKGROUND);
@@ -43,6 +47,7 @@ public final class BackgroundThread extends HandlerThread {
looper.setSlowLogThresholdMs(
SLOW_DISPATCH_THRESHOLD_MS, SLOW_DELIVERY_THRESHOLD_MS);
sHandler = new Handler(sInstance.getLooper());
+ sHandlerExecutor = new HandlerExecutor(sHandler);
}
}
@@ -59,4 +64,11 @@ public final class BackgroundThread extends HandlerThread {
return sHandler;
}
}
+
+ public static Executor getExecutor() {
+ synchronized (BackgroundThread.class) {
+ ensureThreadLocked();
+ return sHandlerExecutor;
+ }
+ }
}
diff --git a/core/java/com/android/server/backup/PermissionBackupHelper.java b/core/java/com/android/server/backup/PermissionBackupHelper.java
index c0ba18159639..c7c423b82cf1 100644
--- a/core/java/com/android/server/backup/PermissionBackupHelper.java
+++ b/core/java/com/android/server/backup/PermissionBackupHelper.java
@@ -16,11 +16,14 @@
package com.android.server.backup;
-import android.app.AppGlobals;
+import android.annotation.NonNull;
import android.app.backup.BlobBackupHelper;
-import android.content.pm.IPackageManager;
+import android.os.UserHandle;
+import android.permission.PermissionManagerInternal;
import android.util.Slog;
+import com.android.server.LocalServices;
+
public class PermissionBackupHelper extends BlobBackupHelper {
private static final String TAG = "PermissionBackup";
private static final boolean DEBUG = false;
@@ -31,24 +34,26 @@ public class PermissionBackupHelper extends BlobBackupHelper {
// key under which the permission-grant state blob is committed to backup
private static final String KEY_PERMISSIONS = "permissions";
- private final int mUserId;
+ private final @NonNull UserHandle mUser;
+
+ private final @NonNull PermissionManagerInternal mPermissionManager;
public PermissionBackupHelper(int userId) {
super(STATE_VERSION, KEY_PERMISSIONS);
- mUserId = userId;
+ mUser = UserHandle.of(userId);
+ mPermissionManager = LocalServices.getService(PermissionManagerInternal.class);
}
@Override
protected byte[] getBackupPayload(String key) {
- IPackageManager pm = AppGlobals.getPackageManager();
if (DEBUG) {
Slog.d(TAG, "Handling backup of " + key);
}
try {
switch (key) {
case KEY_PERMISSIONS:
- return pm.getPermissionGrantBackup(mUserId);
+ return mPermissionManager.backupRuntimePermissions(mUser);
default:
Slog.w(TAG, "Unexpected backup key " + key);
@@ -61,14 +66,13 @@ public class PermissionBackupHelper extends BlobBackupHelper {
@Override
protected void applyRestoredPayload(String key, byte[] payload) {
- IPackageManager pm = AppGlobals.getPackageManager();
if (DEBUG) {
Slog.d(TAG, "Handling restore of " + key);
}
try {
switch (key) {
case KEY_PERMISSIONS:
- pm.restorePermissionGrants(payload, mUserId);
+ mPermissionManager.restoreRuntimePermissions(payload, mUser);
break;
default:
diff --git a/core/jni/Android.bp b/core/jni/Android.bp
index af0b7c307ef6..74061367804e 100644
--- a/core/jni/Android.bp
+++ b/core/jni/Android.bp
@@ -230,6 +230,7 @@ cc_library_shared {
],
static_libs: [
+ "libasync_safe",
"libgif",
"libseccomp_policy",
"libgrallocusage",
diff --git a/core/jni/android_media_AudioSystem.cpp b/core/jni/android_media_AudioSystem.cpp
index a2ed7d3391ed..bd998999ce63 100644
--- a/core/jni/android_media_AudioSystem.cpp
+++ b/core/jni/android_media_AudioSystem.cpp
@@ -1918,7 +1918,6 @@ static jint android_media_AudioSystem_setUidDeviceAffinities(JNIEnv *env, jobjec
for (jint i = 0; i < nb; i++) {
deviceTypesVector.push_back((audio_devices_t) typesPtr[i]);
}
- env->ReleaseIntArrayElements(deviceTypes, typesPtr, 0);
// check each address is a string and add device type/address to list for device affinity
Vector<AudioDeviceTypeAddr> deviceVector;
@@ -1932,6 +1931,7 @@ static jint android_media_AudioSystem_setUidDeviceAffinities(JNIEnv *env, jobjec
AudioDeviceTypeAddr dev = AudioDeviceTypeAddr(typesPtr[i], address);
deviceVector.add(dev);
}
+ env->ReleaseIntArrayElements(deviceTypes, typesPtr, 0);
status_t status = AudioSystem::setUidDeviceAffinities((uid_t) uid, deviceVector);
return (jint) nativeToJavaStatus(status);
diff --git a/core/jni/android_os_GraphicsEnvironment.cpp b/core/jni/android_os_GraphicsEnvironment.cpp
index 95f99b760382..0ccc327f6d97 100644
--- a/core/jni/android_os_GraphicsEnvironment.cpp
+++ b/core/jni/android_os_GraphicsEnvironment.cpp
@@ -34,13 +34,16 @@ void setDriverPath(JNIEnv* env, jobject clazz, jstring path) {
void setGpuStats_native(JNIEnv* env, jobject clazz, jstring driverPackageName,
jstring driverVersionName, jlong driverVersionCode,
- jstring appPackageName) {
+ jstring driverBuildDate, jstring appPackageName) {
ScopedUtfChars driverPackageNameChars(env, driverPackageName);
ScopedUtfChars driverVersionNameChars(env, driverVersionName);
+ ScopedUtfChars driverBuildDateChars(env, driverBuildDate);
ScopedUtfChars appPackageNameChars(env, appPackageName);
android::GraphicsEnv::getInstance().setGpuStats(driverPackageNameChars.c_str(),
driverVersionNameChars.c_str(),
- driverVersionCode, appPackageNameChars.c_str());
+ driverVersionCode,
+ driverBuildDateChars.c_str(),
+ appPackageNameChars.c_str());
}
void setAngleInfo_native(JNIEnv* env, jobject clazz, jstring path, jstring appName, jstring devOptIn,
@@ -84,7 +87,7 @@ void setDebugLayersGLES_native(JNIEnv* env, jobject clazz, jstring layers) {
const JNINativeMethod g_methods[] = {
{ "getCanLoadSystemLibraries", "()I", reinterpret_cast<void*>(getCanLoadSystemLibraries_native) },
{ "setDriverPath", "(Ljava/lang/String;)V", reinterpret_cast<void*>(setDriverPath) },
- { "setGpuStats", "(Ljava/lang/String;Ljava/lang/String;JLjava/lang/String;)V", reinterpret_cast<void*>(setGpuStats_native) },
+ { "setGpuStats", "(Ljava/lang/String;Ljava/lang/String;JLjava/lang/String;Ljava/lang/String;)V", reinterpret_cast<void*>(setGpuStats_native) },
{ "setAngleInfo", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/io/FileDescriptor;JJ)V", reinterpret_cast<void*>(setAngleInfo_native) },
{ "getShouldUseAngle", "(Ljava/lang/String;)Z", reinterpret_cast<void*>(shouldUseAngle_native) },
{ "setLayerPaths", "(Ljava/lang/ClassLoader;Ljava/lang/String;)V", reinterpret_cast<void*>(setLayerPaths_native) },
diff --git a/core/jni/com_android_internal_os_Zygote.cpp b/core/jni/com_android_internal_os_Zygote.cpp
index 5cecf66a593c..7b4e4ea43415 100644
--- a/core/jni/com_android_internal_os_Zygote.cpp
+++ b/core/jni/com_android_internal_os_Zygote.cpp
@@ -25,6 +25,8 @@
#define LOG_TAG "Zygote"
+#include <async_safe/log.h>
+
// sys/mount.h has to come before linux/fs.h due to redefinition of MS_RDONLY, MS_BIND, etc
#include <sys/mount.h>
#include <linux/fs.h>
@@ -303,27 +305,23 @@ static void SigChldHandler(int /*signal_number*/) {
int saved_errno = errno;
while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {
- // Log process-death status that we care about. In general it is
- // not safe to call LOG(...) from a signal handler because of
- // possible reentrancy. However, we know a priori that the
- // current implementation of LOG() is safe to call from a SIGCHLD
- // handler in the zygote process. If the LOG() implementation
- // changes its locking strategy or its use of syscalls within the
- // lazy-init critical section, its use here may become unsafe.
+ // Log process-death status that we care about.
if (WIFEXITED(status)) {
- ALOGI("Process %d exited cleanly (%d)", pid, WEXITSTATUS(status));
+ async_safe_format_log(ANDROID_LOG_INFO, LOG_TAG,
+ "Process %d exited cleanly (%d)", pid, WEXITSTATUS(status));
} else if (WIFSIGNALED(status)) {
- ALOGI("Process %d exited due to signal (%d)", pid, WTERMSIG(status));
- if (WCOREDUMP(status)) {
- ALOGI("Process %d dumped core.", pid);
- }
+ async_safe_format_log(ANDROID_LOG_INFO, LOG_TAG,
+ "Process %d exited due to signal %d (%s)%s", pid,
+ WTERMSIG(status), strsignal(WTERMSIG(status)),
+ WCOREDUMP(status) ? "; core dumped" : "");
}
// If the just-crashed process is the system_server, bring down zygote
// so that it is restarted by init and system server will be restarted
// from there.
if (pid == gSystemServerPid) {
- ALOGE("Exit zygote because system server (%d) has terminated", pid);
+ async_safe_format_log(ANDROID_LOG_ERROR, LOG_TAG,
+ "Exit zygote because system server (pid %d) has terminated", pid);
kill(getpid(), SIGKILL);
}
@@ -336,14 +334,17 @@ static void SigChldHandler(int /*signal_number*/) {
// Note that we shouldn't consider ECHILD an error because
// the secondary zygote might have no children left to wait for.
if (pid < 0 && errno != ECHILD) {
- ALOGW("Zygote SIGCHLD error in waitpid: %s", strerror(errno));
+ async_safe_format_log(ANDROID_LOG_WARN, LOG_TAG,
+ "Zygote SIGCHLD error in waitpid: %s", strerror(errno));
}
if (blastulas_removed > 0) {
if (write(gBlastulaPoolEventFD, &blastulas_removed, sizeof(blastulas_removed)) == -1) {
// If this write fails something went terribly wrong. We will now kill
// the zygote and let the system bring it back up.
- ALOGE("Zygote failed to write to blastula pool event FD: %s", strerror(errno));
+ async_safe_format_log(ANDROID_LOG_ERROR, LOG_TAG,
+ "Zygote failed to write to blastula pool event FD: %s",
+ strerror(errno));
kill(getpid(), SIGKILL);
}
}
@@ -612,7 +613,7 @@ static void CreateDir(const std::string& dir,
}
}
-static void CreatePkgSandbox(uid_t uid, const std::string& package_name, fail_fn_t fail_fn) {
+static void CreatePkgSandboxTarget(uid_t uid, const std::string& package_name, fail_fn_t fail_fn) {
// Create /mnt/user/0/package/<package-name>
userid_t user_id = multiuser_get_user_id(uid);
std::string pkg_sandbox_dir = StringPrintf("/mnt/user/%d", user_id);
@@ -622,7 +623,7 @@ static void CreatePkgSandbox(uid_t uid, const std::string& package_name, fail_fn
CreateDir(pkg_sandbox_dir, 0700, AID_ROOT, AID_ROOT, fail_fn);
StringAppendF(&pkg_sandbox_dir, "/%s", package_name.c_str());
- CreateDir(pkg_sandbox_dir, 0700, AID_ROOT, AID_ROOT, fail_fn);
+ CreateDir(pkg_sandbox_dir, 0755, uid, uid, fail_fn);
}
static void BindMount(const std::string& sourceDir, const std::string& targetDir,
@@ -642,29 +643,98 @@ static void MountPkgSpecificDir(const std::string& mntSourceRoot,
fail_fn_t fail_fn) {
std::string mntSourceDir = StringPrintf("%s/Android/%s/%s",
mntSourceRoot.c_str(), dirName, packageName.c_str());
- CreateDir(mntSourceDir, 0755, uid, uid, fail_fn);
std::string mntTargetDir = StringPrintf("%s/Android/%s/%s",
mntTargetRoot.c_str(), dirName, packageName.c_str());
- CreateDir(mntTargetDir, 0755, uid, uid, fail_fn);
BindMount(mntSourceDir, mntTargetDir, fail_fn);
}
+static void CreateSubDirs(int dirfd, const std::string& parentDirPath,
+ const std::vector<std::string>& subDirs,
+ fail_fn_t fail_fn) {
+ for (auto& dirName : subDirs) {
+ struct stat sb;
+ if (TEMP_FAILURE_RETRY(fstatat(dirfd, dirName.c_str(), &sb, 0)) == 0) {
+ if (S_ISDIR(sb.st_mode)) {
+ continue;
+ } else if (TEMP_FAILURE_RETRY(unlinkat(dirfd, dirName.c_str(), 0)) == -1) {
+ fail_fn(CREATE_ERROR("Failed to unlinkat on %s/%s: %s",
+ parentDirPath.c_str(), dirName.c_str(), strerror(errno)));
+ }
+ } else if (errno != ENOENT) {
+ fail_fn(CREATE_ERROR("Failed to fstatat on %s/%s: %s",
+ parentDirPath.c_str(), dirName.c_str(), strerror(errno)));
+ }
+ if (TEMP_FAILURE_RETRY(mkdirat(dirfd, dirName.c_str(), 0700)) == -1) {
+ fail_fn(CREATE_ERROR("Failed to mkdirat on %s/%s: %s",
+ parentDirPath.c_str(), dirName.c_str(), strerror(errno)));
+ }
+ }
+}
+
+static void EnsurePkgSpecificDirs(const std::string& path,
+ const std::vector<std::string>& packageNames,
+ bool createSandboxDir,
+ fail_fn_t fail_fn) {
+ std::string androidDir = StringPrintf("%s/Android", path.c_str());
+ android::base::unique_fd androidFd(
+ open(androidDir.c_str(), O_RDONLY | O_DIRECTORY | O_CLOEXEC));
+ if (androidFd.get() < 0) {
+ if (errno == ENOENT || errno == ENOTDIR) {
+ if (errno == ENOTDIR && TEMP_FAILURE_RETRY(unlink(androidDir.c_str())) == -1) {
+ fail_fn(CREATE_ERROR("Failed to unlink %s: %s",
+ androidDir.c_str(), strerror(errno)));
+ }
+ if (TEMP_FAILURE_RETRY(mkdir(androidDir.c_str(), 0700)) == -1) {
+ fail_fn(CREATE_ERROR("Failed to mkdir %s: %s",
+ androidDir.c_str(), strerror(errno)));
+ }
+ androidFd.reset(open(androidDir.c_str(), O_RDONLY | O_DIRECTORY | O_CLOEXEC));
+ }
-static void createPkgSpecificDirRoots(const std::string& parentDir,
- bool createSandbox,
- mode_t mode, uid_t uid, gid_t gid,
- fail_fn_t fail_fn) {
- std::string androidDir = StringPrintf("%s/Android", parentDir.c_str());
- CreateDir(androidDir, mode, uid, gid, fail_fn);
- std::vector<std::string> dirs = {"data", "media", "obb"};
- if (createSandbox) {
- dirs.push_back("sandbox");
+ if (androidFd.get() < 0) {
+ fail_fn(CREATE_ERROR("Failed to open %s: %s", androidDir.c_str(), strerror(errno)));
+ }
+ }
+
+ std::vector<std::string> dataMediaObbDirs = {"data", "media", "obb"};
+ if (createSandboxDir) {
+ dataMediaObbDirs.push_back("sandbox");
+ }
+ CreateSubDirs(androidFd.get(), androidDir, dataMediaObbDirs, fail_fn);
+ if (createSandboxDir) {
+ dataMediaObbDirs.pop_back();
+ }
+ for (auto& dirName : dataMediaObbDirs) {
+ std::string dataDir = StringPrintf("%s/%s", androidDir.c_str(), dirName.c_str());
+ android::base::unique_fd dataFd(
+ openat(androidFd, dirName.c_str(), O_RDONLY | O_DIRECTORY | O_CLOEXEC));
+ if (dataFd.get() < 0) {
+ fail_fn(CREATE_ERROR("Failed to openat %s/%s: %s",
+ androidDir.c_str(), dirName.c_str(), strerror(errno)));
+ }
+ CreateSubDirs(dataFd.get(), dataDir, packageNames, fail_fn);
+ }
+}
+
+static void CreatePkgSandboxSource(const std::string& sandboxSource, fail_fn_t fail_fn) {
+
+ struct stat sb;
+ if (TEMP_FAILURE_RETRY(stat(sandboxSource.c_str(), &sb)) == 0) {
+ if (S_ISDIR(sb.st_mode)) {
+ return;
+ } else if (TEMP_FAILURE_RETRY(unlink(sandboxSource.c_str())) == -1) {
+ fail_fn(CREATE_ERROR("Failed to unlink %s: %s",
+ sandboxSource.c_str(), strerror(errno)));
+ }
+ } else if (errno != ENOENT) {
+ fail_fn(CREATE_ERROR("Failed to stat %s: %s",
+ sandboxSource.c_str(), strerror(errno)));
}
- for (auto& dir : dirs) {
- std::string path = StringPrintf("%s/%s", androidDir.c_str(), dir.c_str());
- CreateDir(path, mode, uid, gid, fail_fn);
+ if (TEMP_FAILURE_RETRY(mkdir(sandboxSource.c_str(), 0700)) == -1) {
+ fail_fn(CREATE_ERROR("Failed to mkdir %s: %s",
+ sandboxSource.c_str(), strerror(errno)));
}
}
@@ -680,21 +750,21 @@ static void PreparePkgSpecificDirs(const std::vector<std::string>& packageNames,
StringAppendF(&mntTarget, "/%d", userId);
}
- if (TEMP_FAILURE_RETRY(access(mntSource.c_str(), F_OK)) < 0) {
+ if (TEMP_FAILURE_RETRY(access(mntSource.c_str(), F_OK)) == -1) {
ALOGE("Can't access %s: %s", mntSource.c_str(), strerror(errno));
continue;
}
- // Create /mnt/runtime/write/emulated/0/Android/{data,media,obb,sandbox}
- createPkgSpecificDirRoots(mntSource, true, 0700, AID_ROOT, AID_ROOT, fail_fn);
+ // Ensure /mnt/runtime/write/emulated/0/Android/{data,media,obb}
+ EnsurePkgSpecificDirs(mntSource, packageNames, true, fail_fn);
std::string sandboxSource = StringPrintf("%s/Android/sandbox/%s",
mntSource.c_str(), sandboxId.c_str());
- CreateDir(sandboxSource, 0755, uid, uid, fail_fn);
+ CreatePkgSandboxSource(sandboxSource, fail_fn);
BindMount(sandboxSource, mntTarget, fail_fn);
- // Create /storage/emulated/0/Android/{data,media,obb}
- createPkgSpecificDirRoots(mntTarget, false, 0755, uid, uid, fail_fn);
+ // Ensure /storage/emulated/0/Android/{data,media,obb}
+ EnsurePkgSpecificDirs(mntTarget, packageNames, false, fail_fn);
for (auto& package : packageNames) {
MountPkgSpecificDir(mntSource, mntTarget, package, uid, "data", fail_fn);
MountPkgSpecificDir(mntSource, mntTarget, package, uid, "media", fail_fn);
@@ -775,15 +845,14 @@ static void MountEmulatedStorage(uid_t uid, jint mount_mode,
userid_t user_id = multiuser_get_user_id(uid);
std::string pkgSandboxDir =
StringPrintf("/mnt/user/%d/package/%s", user_id, package_name.c_str());
- struct stat sb;
bool sandboxAlreadyCreated = true;
- if (TEMP_FAILURE_RETRY(lstat(pkgSandboxDir.c_str(), &sb)) == -1) {
+ if (TEMP_FAILURE_RETRY(access(pkgSandboxDir.c_str(), F_OK)) == -1) {
if (errno == ENOENT) {
ALOGD("Sandbox not yet created for %s", pkgSandboxDir.c_str());
sandboxAlreadyCreated = false;
- CreatePkgSandbox(uid, package_name, fail_fn);
+ CreatePkgSandboxTarget(uid, package_name, fail_fn);
} else {
- fail_fn(CREATE_ERROR("Failed to lstat %s: %s",
+ fail_fn(CREATE_ERROR("Failed to access %s: %s",
pkgSandboxDir.c_str(), strerror(errno)));
}
}
@@ -794,7 +863,7 @@ static void MountEmulatedStorage(uid_t uid, jint mount_mode,
pkgSandboxDir.c_str(), strerror(errno)));
}
- if (access("/storage/obb_mount", F_OK) == 0) {
+ if (TEMP_FAILURE_RETRY(access("/storage/obb_mount", F_OK)) == 0) {
if (mount_mode != MOUNT_EXTERNAL_INSTALLER) {
remove("/storage/obb_mount");
}
@@ -1384,8 +1453,8 @@ static jlong CalculateCapabilities(JNIEnv* env, jint uid, jint gid, jintArray gi
RuntimeAbort(env, __LINE__, "Bad gids array");
}
- for (int gid_index = gids_num; --gids_num >= 0;) {
- if (native_gid_proxy[gid_index] == AID_WAKELOCK) {
+ for (int gids_index = 0; gids_index < gids_num; ++gids_index) {
+ if (native_gid_proxy[gids_index] == AID_WAKELOCK) {
gid_wakelock_found = true;
break;
}
diff --git a/core/res/res/values-night/themes_device_defaults.xml b/core/res/res/values-night/themes_device_defaults.xml
index 949c12e7d1da..0721f6fb3802 100644
--- a/core/res/res/values-night/themes_device_defaults.xml
+++ b/core/res/res/values-night/themes_device_defaults.xml
@@ -65,4 +65,7 @@ easier.
<style name="Theme.DeviceDefault.Dialog.AppError" parent="Theme.DeviceDefault.Dialog.Alert" />
<style name="Theme.DeviceDefault.DayNight" parent="Theme.DeviceDefault" />
+
+ <style name="ThemeOverlay.DeviceDefault.Accent.DayNight"
+ parent="@style/ThemeOverlay.DeviceDefault.Accent" />
</resources> \ No newline at end of file
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index 46e14b41960c..224f54c64b63 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -4349,14 +4349,18 @@
<attr name="indeterminate" format="boolean" />
<!-- Restricts to ONLY indeterminate mode (state-keeping progress mode will not work). -->
<attr name="indeterminateOnly" format="boolean" />
- <!-- Drawable used for the indeterminate mode. -->
+ <!-- Drawable used for the indeterminate mode. One that implements Animatable offers more
+ control over the animation.-->
<attr name="indeterminateDrawable" format="reference" />
<!-- Drawable used for the progress mode. -->
<attr name="progressDrawable" format="reference" />
- <!-- Duration of the indeterminate animation. -->
+ <!-- Duration of the indeterminate animation. Only affects the indeterminate animation
+ if the indeterminate Drawable does not implement
+ android.graphics.drawable.Animatable. -->
<attr name="indeterminateDuration" format="integer" min="1" />
- <!-- Defines how the indeterminate mode should behave when the progress
- reaches max. -->
+ <!-- Defines how the indeterminate mode should behave when the progress reaches max. Only
+ affects the indeterminate animation if the indeterminate Drawable does not implement
+ android.graphics.drawable.Animatable. -->
<attr name="indeterminateBehavior">
<!-- Progress starts over from 0. -->
<enum name="repeat" value="1" />
@@ -4367,6 +4371,9 @@
<attr name="maxWidth" />
<attr name="minHeight" format="dimension" />
<attr name="maxHeight" />
+ <!-- Sets the acceleration curve for the indeterminate animation. Defaults to a linear
+ interpolation. Only affects the indeterminate animation if the indeterminate Drawable
+ does not implement android.graphics.drawable.Animatable.-->
<attr name="interpolator" format="reference" />
<!-- Timeout between frames of animation in milliseconds.
{@deprecated Not used by the framework}. -->
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index dae2692c7722..e65e7da57e58 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -46,6 +46,8 @@
<item><xliff:g id="id">@string/status_bar_cast</xliff:g></item>
<item><xliff:g id="id">@string/status_bar_vpn</xliff:g></item>
<item><xliff:g id="id">@string/status_bar_bluetooth</xliff:g></item>
+ <item><xliff:g id="id">@string/status_bar_camera</xliff:g></item>
+ <item><xliff:g id="id">@string/status_bar_microphone</xliff:g></item>
<item><xliff:g id="id">@string/status_bar_location</xliff:g></item>
<item><xliff:g id="id">@string/status_bar_mute</xliff:g></item>
<item><xliff:g id="id">@string/status_bar_volume</xliff:g></item>
@@ -55,8 +57,6 @@
<item><xliff:g id="id">@string/status_bar_hotspot</xliff:g></item>
<item><xliff:g id="id">@string/status_bar_mobile</xliff:g></item>
<item><xliff:g id="id">@string/status_bar_airplane</xliff:g></item>
- <item><xliff:g id="id">@string/status_bar_microphone</xliff:g></item>
- <item><xliff:g id="id">@string/status_bar_camera</xliff:g></item>
<item><xliff:g id="id">@string/status_bar_battery</xliff:g></item>
</string-array>
@@ -869,6 +869,9 @@
which means to get a larger screen. -->
<bool name="config_lidControlsDisplayFold">false</bool>
+ <!-- Indicate the display area rect for foldable devices in folded state. -->
+ <string name="config_foldedArea"></string>
+
<!-- Desk dock behavior -->
<!-- The number of degrees to rotate the display when the device is in a desk dock.
@@ -3911,19 +3914,19 @@
<!-- See DisplayWhiteBalanceController.
A float array containing a list of ambient color temperatures, in Kelvin. This array,
- together with config_displayWhiteBalanceDisplayTemperatureValues, is used to generate a
+ together with config_displayWhiteBalanceDisplayColorTemperatures, is used to generate a
lookup table used in DisplayWhiteBalanceController. This lookup table is used to map
ambient color temperature readings to a target color temperature for the display.
This table is optional. If used, this array must,
1) Contain at least two entries
- 2) Be the same length as config_displayWhiteBalanceDisplayTemperatureValues. -->
- <array name="config_displayWhiteBalanceAmbientTemperatureValues">
+ 2) Be the same length as config_displayWhiteBalanceDisplayColorTemperatures. -->
+ <array name="config_displayWhiteBalanceAmbientColorTemperatures">
</array>
<!-- See DisplayWhiteBalanceController.
An array containing a list of display color temperatures, in Kelvin. See
- config_displayWhiteBalanceAmbientTemperatureValues for additional details.
+ config_displayWhiteBalanceAmbientColorTemperatures for additional details.
The same restrictions apply to this array. -->
- <array name="config_displayWhiteBalanceDisplayTemperatureValues">
+ <array name="config_displayWhiteBalanceDisplayColorTemperatures">
</array>
</resources>
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index 5e65605a4c65..3580dd475ab9 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -2951,6 +2951,8 @@
<public-group type="style" first-id="0x010302e2">
<!-- @hide @SystemApi -->
<public name="Theme.DeviceDefault.DocumentsUI" />
+ <public name="Theme.DeviceDefault.DayNight" />
+ <public name="ThemeOverlay.DeviceDefault.Accent.DayNight" />
</public-group>
<public-group type="id" first-id="0x01020046">
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 0cdf38849d8b..5948f2988bc4 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -3712,7 +3712,7 @@
<string name="ext_media_browse_action">Explore</string>
<!-- Notification action to transfer media [CHAR LIMIT=40] -->
- <string name="ext_media_seamless_action">Seamless transfer</string>
+ <string name="ext_media_seamless_action">Switch output</string>
<!-- Notification title when external media is missing [CHAR LIMIT=30] -->
<string name="ext_media_missing_title"><xliff:g id="name" example="SD card">%s</xliff:g> missing</string>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 08fc36db928e..7ef5e022c1c4 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -3586,7 +3586,10 @@
<java-symbol type="integer" name="config_defaultRingVibrationIntensity" />
<java-symbol type="bool" name="config_maskMainBuiltInDisplayCutout" />
+
+ <!-- For Foldables -->
<java-symbol type="bool" name="config_lidControlsDisplayFold" />
+ <java-symbol type="string" name="config_foldedArea" />
<java-symbol type="array" name="config_disableApksUnlessMatchedSku_apk_list" />
<java-symbol type="array" name="config_disableApkUnlessMatchedSku_skus_list" />
@@ -3653,7 +3656,7 @@
<java-symbol type="array" name="config_displayWhiteBalanceDecreaseThresholds" />
<java-symbol type="dimen" name="config_displayWhiteBalanceLowLightAmbientBrightnessThreshold" />
<java-symbol type="dimen" name="config_displayWhiteBalanceLowLightAmbientColorTemperature" />
- <java-symbol type="array" name="config_displayWhiteBalanceAmbientTemperatureValues" />
- <java-symbol type="array" name="config_displayWhiteBalanceDisplayTemperatureValues" />
+ <java-symbol type="array" name="config_displayWhiteBalanceAmbientColorTemperatures" />
+ <java-symbol type="array" name="config_displayWhiteBalanceDisplayColorTemperatures" />
<java-symbol type="drawable" name="ic_action_open" />
</resources>
diff --git a/core/res/res/values/themes_device_defaults.xml b/core/res/res/values/themes_device_defaults.xml
index 160350878349..194c86c2fb81 100644
--- a/core/res/res/values/themes_device_defaults.xml
+++ b/core/res/res/values/themes_device_defaults.xml
@@ -1652,6 +1652,7 @@ easier.
<style name="Theme.DeviceDefault.Settings.Dialog.NoActionBar" parent="Theme.DeviceDefault.Light.Dialog.NoActionBar" />
+ <!-- DeviceDefault theme for day/night activities. -->
<style name="Theme.DeviceDefault.DayNight" parent="Theme.DeviceDefault.Light" />
<!-- Theme used for the intent picker activity. -->
@@ -1697,6 +1698,10 @@ easier.
<item name="colorAccent">@color/accent_device_default_light</item>
</style>
+ <!-- Theme overlay that replaces colorAccent with the colorAccent from {@link #Theme_DeviceDefault_DayNight}. -->
+ <style name="ThemeOverlay.DeviceDefault.Accent.DayNight"
+ parent="@style/ThemeOverlay.DeviceDefault.Accent.Light" />
+
<style name="ThemeOverlay.DeviceDefault.Dark.ActionBar.Accent" parent="ThemeOverlay.Material.Dark.ActionBar">
<item name="colorAccent">@color/accent_device_default_dark</item>
</style>
diff --git a/graphics/java/android/graphics/Bitmap.java b/graphics/java/android/graphics/Bitmap.java
index bdb63643f615..81356710cce6 100644
--- a/graphics/java/android/graphics/Bitmap.java
+++ b/graphics/java/android/graphics/Bitmap.java
@@ -1509,6 +1509,9 @@ public final class Bitmap implements Parcelable {
* Convenience method that returns the width of this bitmap divided
* by the density scale factor.
*
+ * Returns the bitmap's width multiplied by the ratio of the target density to the bitmap's
+ * source density
+ *
* @param targetDensity The density of the target canvas of the bitmap.
* @return The scaled width of this bitmap, according to the density scale factor.
*/
@@ -1520,6 +1523,9 @@ public final class Bitmap implements Parcelable {
* Convenience method that returns the height of this bitmap divided
* by the density scale factor.
*
+ * Returns the bitmap's height multiplied by the ratio of the target density to the bitmap's
+ * source density
+ *
* @param targetDensity The density of the target canvas of the bitmap.
* @return The scaled height of this bitmap, according to the density scale factor.
*/
diff --git a/keystore/java/android/security/keystore/AndroidKeyStoreKeyGeneratorSpi.java b/keystore/java/android/security/keystore/AndroidKeyStoreKeyGeneratorSpi.java
index aa2917484a05..3dc884eb38ad 100644
--- a/keystore/java/android/security/keystore/AndroidKeyStoreKeyGeneratorSpi.java
+++ b/keystore/java/android/security/keystore/AndroidKeyStoreKeyGeneratorSpi.java
@@ -17,7 +17,6 @@
package android.security.keystore;
import android.security.Credentials;
-import android.security.GateKeeper;
import android.security.KeyStore;
import android.security.keymaster.KeyCharacteristics;
import android.security.keymaster.KeymasterArguments;
@@ -204,7 +203,12 @@ public abstract class AndroidKeyStoreKeyGeneratorSpi extends KeyGeneratorSpi {
}
}
}
-
+ if (mKeymasterAlgorithm == KeymasterDefs.KM_ALGORITHM_3DES) {
+ if (mKeySizeBits != 168) {
+ throw new InvalidAlgorithmParameterException(
+ "3DES key size must be 168 bits.");
+ }
+ }
if (mKeymasterAlgorithm == KeymasterDefs.KM_ALGORITHM_HMAC) {
if (mKeySizeBits < 64) {
throw new InvalidAlgorithmParameterException(
diff --git a/libs/androidfw/include/androidfw/ResourceTypes.h b/libs/androidfw/include/androidfw/ResourceTypes.h
index 742813e58129..875b90b7ac65 100644
--- a/libs/androidfw/include/androidfw/ResourceTypes.h
+++ b/libs/androidfw/include/androidfw/ResourceTypes.h
@@ -1647,6 +1647,10 @@ struct ResTable_overlayable_policy_header
// The overlay must reside of the product partition or must have existed on the product
// partition before an upgrade to overlay these resources.
POLICY_PRODUCT_PARTITION = 0x00000008,
+
+ // The overlay must be signed with the same signature as the actor of the target resource,
+ // which can be separate or the same as the target package with the resource.
+ POLICY_SIGNATURE = 0x00000010,
};
uint32_t policy_flags;
diff --git a/libs/hwui/thread/ThreadBase.h b/libs/hwui/thread/ThreadBase.h
index 8cdcc46b97fb..0289d3fd2ef7 100644
--- a/libs/hwui/thread/ThreadBase.h
+++ b/libs/hwui/thread/ThreadBase.h
@@ -68,10 +68,12 @@ protected:
void processQueue() { mQueue.process(); }
virtual bool threadLoop() override {
+ Looper::setForThread(mLooper);
while (!exitPending()) {
waitForWork();
processQueue();
}
+ Looper::setForThread(nullptr);
return false;
}
diff --git a/libs/incident/proto/android/os/header.proto b/libs/incident/proto/android/os/header.proto
index a84dc48b8b34..d463f87055b3 100644
--- a/libs/incident/proto/android/os/header.proto
+++ b/libs/incident/proto/android/os/header.proto
@@ -37,4 +37,9 @@ message IncidentHeaderProto {
optional int64 id = 2; // The unique id of the statsd config.
}
optional StatsdConfigKey config_key = 3;
+
+ // Details about the trigger. com.android.os.AlertTriggerDetails
+ // Only use bytes type here to avoid indirect dependency on atoms.proto
+ // And this header passes through incidentd without incidentd parsing it.
+ optional bytes trigger_details = 4;
}
diff --git a/location/java/android/location/ILocationManager.aidl b/location/java/android/location/ILocationManager.aidl
index 1aeefb84129f..57a0a725fb41 100644
--- a/location/java/android/location/ILocationManager.aidl
+++ b/location/java/android/location/ILocationManager.aidl
@@ -114,6 +114,7 @@ interface ILocationManager
// for reporting callback completion
void locationCallbackFinished(ILocationListener listener);
- // used by gts tests to verify throttling whitelist
+ // used by gts tests to verify whitelists
String[] getBackgroundThrottlingWhitelist();
+ String[] getIgnoreSettingsWhitelist();
}
diff --git a/location/java/android/location/LocationManager.java b/location/java/android/location/LocationManager.java
index c027fd499033..586ee2a43683 100644
--- a/location/java/android/location/LocationManager.java
+++ b/location/java/android/location/LocationManager.java
@@ -414,6 +414,18 @@ public class LocationManager {
}
/**
+ * @hide
+ */
+ @TestApi
+ public String[] getIgnoreSettingsWhitelist() {
+ try {
+ return mService.getIgnoreSettingsWhitelist();
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
* @hide - hide this constructor because it has a parameter
* of type ILocationManager, which is a system private class. The
* right way to create an instance of this class is using the
diff --git a/media/java/android/media/AudioFocusInfo.java b/media/java/android/media/AudioFocusInfo.java
index 0a9ca025e2b0..3594ee7f6a91 100644
--- a/media/java/android/media/AudioFocusInfo.java
+++ b/media/java/android/media/AudioFocusInfo.java
@@ -16,6 +16,7 @@
package android.media;
+import android.annotation.NonNull;
import android.annotation.SystemApi;
import android.os.Parcel;
import android.os.Parcelable;
@@ -29,10 +30,10 @@ import java.util.Objects;
@SystemApi
public final class AudioFocusInfo implements Parcelable {
- private final AudioAttributes mAttributes;
+ private final @NonNull AudioAttributes mAttributes;
private final int mClientUid;
- private final String mClientId;
- private final String mPackageName;
+ private final @NonNull String mClientId;
+ private final @NonNull String mPackageName;
private final int mSdkTarget;
private int mGainRequest;
private int mLossReceived;
@@ -80,13 +81,21 @@ public final class AudioFocusInfo implements Parcelable {
* The audio attributes for the audio focus request.
* @return non-null {@link AudioAttributes}.
*/
- public AudioAttributes getAttributes() { return mAttributes; }
+ public @NonNull AudioAttributes getAttributes() {
+ return mAttributes;
+ }
- public int getClientUid() { return mClientUid; }
+ public int getClientUid() {
+ return mClientUid;
+ }
- public String getClientId() { return mClientId; }
+ public @NonNull String getClientId() {
+ return mClientId;
+ }
- public String getPackageName() { return mPackageName; }
+ public @NonNull String getPackageName() {
+ return mPackageName;
+ }
/**
* The type of audio focus gain request.
diff --git a/media/java/android/media/AudioFocusRequest.java b/media/java/android/media/AudioFocusRequest.java
index b9731d111aa3..4e7050129058 100644
--- a/media/java/android/media/AudioFocusRequest.java
+++ b/media/java/android/media/AudioFocusRequest.java
@@ -225,9 +225,9 @@ public final class AudioFocusRequest {
/** @hide */
public static final String KEY_ACCESSIBILITY_FORCE_FOCUS_DUCKING = "a11y_force_ducking";
- private final OnAudioFocusChangeListener mFocusListener; // may be null
- private final Handler mListenerHandler; // may be null
- private final AudioAttributes mAttr; // never null
+ private final @Nullable OnAudioFocusChangeListener mFocusListener;
+ private final @Nullable Handler mListenerHandler;
+ private final @NonNull AudioAttributes mAttr;
private final int mFocusGain;
private final int mFlags;
diff --git a/media/java/android/media/AudioRecord.java b/media/java/android/media/AudioRecord.java
index 92afe7ede8f2..24a3a9b32f77 100644
--- a/media/java/android/media/AudioRecord.java
+++ b/media/java/android/media/AudioRecord.java
@@ -17,6 +17,7 @@
package android.media;
import android.annotation.CallbackExecutor;
+import android.annotation.FloatRange;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -1713,12 +1714,11 @@ public class AudioRecord implements AudioRouting, MicrophoneDirection,
/**
* Specifies the logical microphone (for processing).
*
- * @param direction Direction constant (MicrophoneDirection.MIC_DIRECTION_*)
- * @return retval OK if the call is successful, an error code otherwise.
- * @hide
+ * @param direction Direction constant.
+ * @return true if sucessful.
*/
- public int setMicrophoneDirection(int direction) {
- return native_set_microphone_direction(direction);
+ public boolean setMicrophoneDirection(int direction) {
+ return native_set_microphone_direction(direction) == 0;
}
/**
@@ -1727,11 +1727,10 @@ public class AudioRecord implements AudioRouting, MicrophoneDirection,
*
* @param zoom the desired field dimension of microphone capture. Range is from -1 (wide angle),
* though 0 (no zoom) to 1 (maximum zoom).
- * @return retval OK if the call is successful, an error code otherwise.
- * @hide
+ * @return true if sucessful.
*/
- public int setMicrophoneFieldDimension(float zoom) {
- return native_set_microphone_field_dimension(zoom);
+ public boolean setMicrophoneFieldDimension(@FloatRange(from = -1.0, to = 1.0) float zoom) {
+ return native_set_microphone_field_dimension(zoom) == 0;
}
//---------------------------------------------------------
diff --git a/media/java/android/media/MediaHTTPConnection.java b/media/java/android/media/MediaHTTPConnection.java
index ad25a06fabe2..5f324f7f97ed 100644
--- a/media/java/android/media/MediaHTTPConnection.java
+++ b/media/java/android/media/MediaHTTPConnection.java
@@ -16,6 +16,8 @@
package android.media;
+import static android.media.MediaPlayer.MEDIA_ERROR_UNSUPPORTED;
+
import android.annotation.UnsupportedAppUsage;
import android.net.NetworkUtils;
import android.os.IBinder;
@@ -23,21 +25,19 @@ import android.os.StrictMode;
import android.util.Log;
import java.io.BufferedInputStream;
-import java.io.InputStream;
import java.io.IOException;
+import java.io.InputStream;
import java.net.CookieHandler;
-import java.net.CookieManager;
-import java.net.Proxy;
-import java.net.URL;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.NoRouteToHostException;
import java.net.ProtocolException;
+import java.net.Proxy;
+import java.net.URL;
import java.net.UnknownServiceException;
import java.util.HashMap;
import java.util.Map;
-
-import static android.media.MediaPlayer.MEDIA_ERROR_UNSUPPORTED;
+import java.util.concurrent.atomic.AtomicBoolean;
/** @hide */
public class MediaHTTPConnection extends IMediaHTTPConnection.Stub {
@@ -67,6 +67,7 @@ public class MediaHTTPConnection extends IMediaHTTPConnection.Stub {
// from com.squareup.okhttp.internal.http
private final static int HTTP_TEMP_REDIRECT = 307;
private final static int MAX_REDIRECTS = 20;
+ private AtomicBoolean mIsConnected = new AtomicBoolean(false);
@UnsupportedAppUsage
public MediaHTTPConnection() {
@@ -90,6 +91,7 @@ public class MediaHTTPConnection extends IMediaHTTPConnection.Stub {
mAllowCrossDomainRedirect = true;
mURL = new URL(uri);
mHeaders = convertHeaderStringToMap(headers);
+ mIsConnected.set(true);
} catch (MalformedURLException e) {
return null;
}
@@ -140,7 +142,14 @@ public class MediaHTTPConnection extends IMediaHTTPConnection.Stub {
@Override
@UnsupportedAppUsage
public void disconnect() {
- teardownConnection();
+ if (mIsConnected.getAndSet(false)) {
+ (new Thread() {
+ @Override
+ public void run() {
+ teardownConnection();
+ }
+ }).start();
+ }
mHeaders = null;
mURL = null;
}
@@ -325,7 +334,14 @@ public class MediaHTTPConnection extends IMediaHTTPConnection.Stub {
@Override
@UnsupportedAppUsage
public int readAt(long offset, int size) {
- return native_readAt(offset, size);
+ if (!mIsConnected.get()) {
+ return -1;
+ }
+ int result = native_readAt(offset, size);
+ if (!mIsConnected.get()) {
+ return -1;
+ }
+ return result;
}
private int readAt(long offset, byte[] data, int size) {
diff --git a/media/java/android/media/MicrophoneDirection.java b/media/java/android/media/MicrophoneDirection.java
index 99201c0279bf..489e2683259e 100644
--- a/media/java/android/media/MicrophoneDirection.java
+++ b/media/java/android/media/MicrophoneDirection.java
@@ -16,38 +16,46 @@
package android.media;
-/**
- * @hide
- */
+import android.annotation.FloatRange;
+import android.annotation.IntDef;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
public interface MicrophoneDirection {
/**
- * @hide
+ * Don't do any directionality processing of the activated microphone(s).
*/
int MIC_DIRECTION_UNSPECIFIED = 0;
-
/**
- * @hide
+ * Optimize capture for audio coming from the screen-side of the device.
*/
int MIC_DIRECTION_FRONT = 1;
-
/**
- * @hide
+ * Optimize capture for audio coming from the side of the device opposite the screen.
*/
int MIC_DIRECTION_BACK = 2;
-
/**
- * @hide
+ * Optimize capture for audio coming from an off-device microphone.
*/
int MIC_DIRECTION_EXTERNAL = 3;
+ /** @hide */
+ @IntDef({
+ MIC_DIRECTION_UNSPECIFIED,
+ MIC_DIRECTION_FRONT,
+ MIC_DIRECTION_BACK,
+ MIC_DIRECTION_EXTERNAL
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface Directionmode{};
/**
* Specifies the logical microphone (for processing).
*
- * @param direction Direction constant (MicrophoneDirection.MIC_DIRECTION_*)
- * @return retval OK if the call is successful, an error code otherwise.
- * @hide
+ * @param direction Direction constant.
+ * @return true if sucessful.
*/
- int setMicrophoneDirection(int direction);
+ boolean setMicrophoneDirection(@Directionmode int direction);
/**
* Specifies the zoom factor (i.e. the field dimension) for the selected microphone
@@ -55,8 +63,7 @@ public interface MicrophoneDirection {
*
* @param zoom the desired field dimension of microphone capture. Range is from -1 (wide angle),
* though 0 (no zoom) to 1 (maximum zoom).
- * @return retval OK if the call is successful, an error code otherwise.
- * @hide
+ * @return true if sucessful.
*/
- int setMicrophoneFieldDimension(float zoom);
+ boolean setMicrophoneFieldDimension(@FloatRange(from = -1.0, to = 1.0) float zoom);
}
diff --git a/packages/CaptivePortalLogin/Android.bp b/packages/CaptivePortalLogin/Android.bp
index 7acdfa1fd4a8..a71977f8cc6c 100644
--- a/packages/CaptivePortalLogin/Android.bp
+++ b/packages/CaptivePortalLogin/Android.bp
@@ -18,7 +18,7 @@ android_app {
name: "CaptivePortalLogin",
srcs: ["src/**/*.java"],
sdk_version: "system_current",
- certificate: "platform",
+ certificate: "networkstack",
static_libs: [
"androidx.legacy_legacy-support-v4",
"metrics-constants-protos",
diff --git a/packages/CaptivePortalLogin/AndroidManifest.xml b/packages/CaptivePortalLogin/AndroidManifest.xml
index e15dca046006..0894ee576a2d 100644
--- a/packages/CaptivePortalLogin/AndroidManifest.xml
+++ b/packages/CaptivePortalLogin/AndroidManifest.xml
@@ -23,8 +23,8 @@
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
- <uses-permission android:name="android.permission.NETWORK_SETTINGS" />
<uses-permission android:name="android.permission.NETWORK_BYPASS_PRIVATE_DNS" />
+ <uses-permission android:name="android.permission.MAINLINE_NETWORK_STACK" />
<application android:label="@string/app_name"
android:usesCleartextTraffic="true"
diff --git a/packages/ExtServices/src/android/ext/services/notification/Assistant.java b/packages/ExtServices/src/android/ext/services/notification/Assistant.java
index c5e598d8ce46..31a3ff4a9b8f 100644
--- a/packages/ExtServices/src/android/ext/services/notification/Assistant.java
+++ b/packages/ExtServices/src/android/ext/services/notification/Assistant.java
@@ -221,6 +221,12 @@ public class Assistant extends NotificationAssistantService {
}
@Override
+ public Adjustment onNotificationEnqueued(StatusBarNotification sbn) {
+ // we use the version with channel, so this is never called.
+ return null;
+ }
+
+ @Override
public Adjustment onNotificationEnqueued(StatusBarNotification sbn,
NotificationChannel channel) {
if (DEBUG) Log.i(TAG, "ENQUEUED " + sbn.getKey() + " on " + channel.getId());
diff --git a/packages/NetworkStack/Android.bp b/packages/NetworkStack/Android.bp
index d6565936c860..b700bf324817 100644
--- a/packages/NetworkStack/Android.bp
+++ b/packages/NetworkStack/Android.bp
@@ -35,11 +35,12 @@ java_library {
android_app {
name: "NetworkStack",
sdk_version: "system_current",
- certificate: "platform",
+ certificate: "networkstack",
privileged: true,
static_libs: [
"NetworkStackLib"
],
+ jarjar_rules: "jarjar-rules-shared.txt",
manifest: "AndroidManifest.xml",
required: ["NetworkStackPermissionStub"],
} \ No newline at end of file
diff --git a/packages/NetworkStack/AndroidManifest.xml b/packages/NetworkStack/AndroidManifest.xml
index 860ebfbf6da7..047671281fcc 100644
--- a/packages/NetworkStack/AndroidManifest.xml
+++ b/packages/NetworkStack/AndroidManifest.xml
@@ -24,12 +24,10 @@
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.CONNECTIVITY_INTERNAL" />
- <uses-permission android:name="android.permission.NETWORK_SETTINGS" />
<!-- Signature permission defined in NetworkStackStub -->
<uses-permission android:name="android.permission.MAINLINE_NETWORK_STACK" />
<!-- Send latency broadcast as current user -->
<uses-permission android:name="android.permission.INTERACT_ACROSS_USERS" />
- <uses-permission android:name="android.permission.NETWORK_STACK" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.READ_PRIVILEGED_PHONE_STATE" />
<application
diff --git a/packages/NetworkStack/jarjar-rules-shared.txt b/packages/NetworkStack/jarjar-rules-shared.txt
new file mode 100644
index 000000000000..a8c712a3336d
--- /dev/null
+++ b/packages/NetworkStack/jarjar-rules-shared.txt
@@ -0,0 +1,19 @@
+rule com.android.internal.util.** android.net.networkstack.util.@1
+
+rule android.net.shared.Inet4AddressUtils* android.net.networkstack.shared.Inet4AddressUtils@1
+rule android.net.shared.InetAddressUtils* android.net.networkstack.shared.InetAddressUtils@1
+
+# Ignore DhcpResultsParcelable, but jarjar DhcpResults
+# TODO: move DhcpResults into services.net and delete from here
+rule android.net.DhcpResultsParcelable* @0
+rule android.net.DhcpResults* android.net.networkstack.DhcpResults@1
+rule android.net.LocalLog* android.net.networkstack.LocalLog@1
+
+# TODO: remove from framework dependencies, then remove here
+rule android.net.InterfaceConfigurationParcel* android.net.networkstack.InterfaceConfigurationParcel@1
+rule android.net.TetherStatsParcel* android.net.networkstack.TetherStatsParcel@1
+
+# Used by UidRange, which is used by framework classes such as NetworkCapabilities.
+rule android.net.UidRangeParcel* android.net.networkstack.UidRangeParcel@1
+# TODO: move TcpKeepalivePacketData to services.net and delete
+rule android.net.TcpKeepalivePacketDataParcelable* android.net.networkstack.TcpKeepalivePacketDataParcelable@1 \ No newline at end of file
diff --git a/packages/NetworkStack/src/android/net/dhcp/DhcpPacketListener.java b/packages/NetworkStack/src/android/net/dhcp/DhcpPacketListener.java
index 96d1a287ef09..97d26c7c9c1f 100644
--- a/packages/NetworkStack/src/android/net/dhcp/DhcpPacketListener.java
+++ b/packages/NetworkStack/src/android/net/dhcp/DhcpPacketListener.java
@@ -18,7 +18,7 @@ package android.net.dhcp;
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.net.shared.FdEventsReader;
+import android.net.util.FdEventsReader;
import android.os.Handler;
import android.system.Os;
diff --git a/core/java/android/net/shared/FdEventsReader.java b/packages/NetworkStack/src/android/net/util/FdEventsReader.java
index bffbfb115886..1380ea720d40 100644
--- a/core/java/android/net/shared/FdEventsReader.java
+++ b/packages/NetworkStack/src/android/net/util/FdEventsReader.java
@@ -14,14 +14,13 @@
* limitations under the License.
*/
-package android.net.shared;
+package android.net.util;
import static android.os.MessageQueue.OnFileDescriptorEventListener.EVENT_ERROR;
import static android.os.MessageQueue.OnFileDescriptorEventListener.EVENT_INPUT;
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.net.util.SocketUtils;
import android.os.Handler;
import android.os.Looper;
import android.os.MessageQueue;
diff --git a/packages/NetworkStack/src/android/net/util/PacketReader.java b/packages/NetworkStack/src/android/net/util/PacketReader.java
index 94b1e9f2e14e..4aec6b6753a6 100644
--- a/packages/NetworkStack/src/android/net/util/PacketReader.java
+++ b/packages/NetworkStack/src/android/net/util/PacketReader.java
@@ -18,7 +18,6 @@ package android.net.util;
import static java.lang.Math.max;
-import android.net.shared.FdEventsReader;
import android.os.Handler;
import android.system.Os;
diff --git a/packages/NetworkStack/src/com/android/server/NetworkStackService.java b/packages/NetworkStack/src/com/android/server/NetworkStackService.java
index c6a207f26577..90db207c9902 100644
--- a/packages/NetworkStack/src/com/android/server/NetworkStackService.java
+++ b/packages/NetworkStack/src/com/android/server/NetworkStackService.java
@@ -247,6 +247,12 @@ public class NetworkStackService extends Service {
}
@Override
+ public void notifyCaptivePortalAppFinished(int response) {
+ checkNetworkStackCallingPermission();
+ mNm.notifyCaptivePortalAppFinished(response);
+ }
+
+ @Override
public void forceReevaluation(int uid) {
checkNetworkStackCallingPermission();
mNm.forceReevaluation(uid);
diff --git a/packages/NetworkStack/src/com/android/server/connectivity/NetworkMonitor.java b/packages/NetworkStack/src/com/android/server/connectivity/NetworkMonitor.java
index b9e901b5c5e3..ec4a47930fad 100644
--- a/packages/NetworkStack/src/com/android/server/connectivity/NetworkMonitor.java
+++ b/packages/NetworkStack/src/com/android/server/connectivity/NetworkMonitor.java
@@ -39,9 +39,7 @@ import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
-import android.net.CaptivePortal;
import android.net.ConnectivityManager;
-import android.net.ICaptivePortal;
import android.net.INetworkMonitor;
import android.net.INetworkMonitorCallbacks;
import android.net.LinkProperties;
@@ -460,6 +458,13 @@ public class NetworkMonitor extends StateMachine {
sendMessage(CMD_LAUNCH_CAPTIVE_PORTAL_APP);
}
+ /**
+ * Notify that the captive portal app was closed with the provided response code.
+ */
+ public void notifyCaptivePortalAppFinished(int response) {
+ sendMessage(CMD_CAPTIVE_PORTAL_APP_FINISHED, response);
+ }
+
@Override
protected void log(String s) {
if (DBG) Log.d(TAG + "/" + mNetwork.toString(), s);
@@ -671,29 +676,8 @@ public class NetworkMonitor extends StateMachine {
case CMD_LAUNCH_CAPTIVE_PORTAL_APP:
final Bundle appExtras = new Bundle();
// OneAddressPerFamilyNetwork is not parcelable across processes.
- appExtras.putParcelable(
- ConnectivityManager.EXTRA_NETWORK, new Network(mNetwork));
- appExtras.putParcelable(ConnectivityManager.EXTRA_CAPTIVE_PORTAL,
- new CaptivePortal(new ICaptivePortal.Stub() {
- @Override
- public void appResponse(int response) {
- if (response == APP_RETURN_WANTED_AS_IS) {
- mContext.enforceCallingPermission(
- PERMISSION_NETWORK_SETTINGS,
- "CaptivePortal");
- }
- sendMessage(CMD_CAPTIVE_PORTAL_APP_FINISHED, response);
- }
-
- @Override
- public void logEvent(int eventId, String packageName)
- throws RemoteException {
- mContext.enforceCallingPermission(
- PERMISSION_NETWORK_SETTINGS,
- "CaptivePortal");
- mCallback.logCaptivePortalLoginEvent(eventId, packageName);
- }
- }));
+ final Network network = new Network(mNetwork);
+ appExtras.putParcelable(ConnectivityManager.EXTRA_NETWORK, network);
final CaptivePortalProbeResult probeRes = mLastPortalProbeResult;
appExtras.putString(EXTRA_CAPTIVE_PORTAL_URL, probeRes.detectUrl);
if (probeRes.probeSpec != null) {
@@ -702,7 +686,7 @@ public class NetworkMonitor extends StateMachine {
}
appExtras.putString(ConnectivityManager.EXTRA_CAPTIVE_PORTAL_USER_AGENT,
mCaptivePortalUserAgent);
- mCm.startCaptivePortalApp(appExtras);
+ mCm.startCaptivePortalApp(network, appExtras);
return HANDLED;
default:
return NOT_HANDLED;
diff --git a/packages/NetworkStack/tests/Android.bp b/packages/NetworkStack/tests/Android.bp
index 4a09b3e205a6..5c7b514834cb 100644
--- a/packages/NetworkStack/tests/Android.bp
+++ b/packages/NetworkStack/tests/Android.bp
@@ -18,6 +18,7 @@ android_test {
name: "NetworkStackTests",
certificate: "platform",
srcs: ["src/**/*.java"],
+ test_suites: ["device-tests"],
resource_dirs: ["res"],
static_libs: [
"android-support-test",
diff --git a/packages/NetworkStack/tests/src/android/net/apf/ApfTest.java b/packages/NetworkStack/tests/src/android/net/apf/ApfTest.java
index a4a100000d12..af71ac534bf7 100644
--- a/packages/NetworkStack/tests/src/android/net/apf/ApfTest.java
+++ b/packages/NetworkStack/tests/src/android/net/apf/ApfTest.java
@@ -22,6 +22,7 @@ import static android.system.OsConstants.ETH_P_ARP;
import static android.system.OsConstants.ETH_P_IP;
import static android.system.OsConstants.ETH_P_IPV6;
import static android.system.OsConstants.IPPROTO_ICMPV6;
+import static android.system.OsConstants.IPPROTO_TCP;
import static android.system.OsConstants.IPPROTO_UDP;
import static android.system.OsConstants.SOCK_STREAM;
@@ -1017,6 +1018,7 @@ public class ApfTest {
private static final int IPV4_TCP_SEQ_NUM_OFFSET = IPV4_TCP_HEADER_OFFSET + 4;
private static final int IPV4_TCP_ACK_NUM_OFFSET = IPV4_TCP_HEADER_OFFSET + 8;
private static final int IPV4_TCP_HEADER_LENGTH_OFFSET = IPV4_TCP_HEADER_OFFSET + 12;
+ private static final int IPV4_TCP_HEADER_FLAG_OFFSET = IPV4_TCP_HEADER_OFFSET + 13;
private static final byte[] IPV4_BROADCAST_ADDRESS =
{(byte) 255, (byte) 255, (byte) 255, (byte) 255};
@@ -1568,7 +1570,7 @@ public class ApfTest {
// Verify IPv4 packet from another address is passed
assertPass(program,
ipv4Packet(IPV4_ANOTHER_ADDR, IPV4_KEEPALIVE_SRC_ADDR, anotherSrcPort,
- anotherDstPort, anotherSeqNum, anotherAckNum));
+ anotherDstPort, anotherSeqNum, anotherAckNum, 0 /* dataLength */));
// Remove IPv4 keepalive filter
apfFilter.removeKeepalivePacketFilter(slot1);
@@ -1613,15 +1615,15 @@ public class ApfTest {
// dst: 10.0.0.5, port: 12345
assertDrop(program,
ipv4Packet(IPV4_KEEPALIVE_DST_ADDR, IPV4_KEEPALIVE_SRC_ADDR,
- dstPort, srcPort, ackNum, seqNum + 1));
+ dstPort, srcPort, ackNum, seqNum + 1, 0 /* dataLength */));
// Verify IPv4 non-keepalive ack packet from the same source address is passed
assertPass(program,
ipv4Packet(IPV4_KEEPALIVE_DST_ADDR, IPV4_KEEPALIVE_SRC_ADDR,
- dstPort, srcPort, ackNum + 100, seqNum));
+ dstPort, srcPort, ackNum + 100, seqNum, 0 /* dataLength */));
// Verify IPv4 packet from another address is passed
assertPass(program,
ipv4Packet(IPV4_ANOTHER_ADDR, IPV4_KEEPALIVE_SRC_ADDR, anotherSrcPort,
- anotherDstPort, anotherSeqNum, anotherAckNum));
+ anotherDstPort, anotherSeqNum, anotherAckNum, 0 /* dataLength */));
// Verify IPv6 keepalive ack packet is dropped
// src: 2404:0:0:0:0:0:faf2, port: 54321
@@ -1650,13 +1652,13 @@ public class ApfTest {
// Verify IPv4, IPv6 packets are passed
assertPass(program,
ipv4Packet(IPV4_KEEPALIVE_DST_ADDR, IPV4_KEEPALIVE_SRC_ADDR,
- dstPort, srcPort, ackNum, seqNum + 1));
+ dstPort, srcPort, ackNum, seqNum + 1, 0 /* dataLength */));
assertPass(program,
ipv6Packet(IPV6_KEEPALIVE_DST_ADDR, IPV6_KEEPALIVE_SRC_ADDR,
dstPort, srcPort, ackNum, seqNum + 1));
assertPass(program,
ipv4Packet(IPV4_ANOTHER_ADDR, IPV4_KEEPALIVE_SRC_ADDR, srcPort,
- dstPort, anotherSeqNum, anotherAckNum));
+ dstPort, anotherSeqNum, anotherAckNum, 0 /* dataLength */));
assertPass(program,
ipv6Packet(IPV6_ANOTHER_ADDR, IPV6_KEEPALIVE_SRC_ADDR, srcPort,
dstPort, anotherSeqNum, anotherAckNum));
@@ -1664,28 +1666,30 @@ public class ApfTest {
apfFilter.shutdown();
}
- private static byte[] ipv4Packet(byte[] sip, byte[] tip, int sport,
- int dport, int seq, int ack) {
- ByteBuffer packet = ByteBuffer.wrap(new byte[100]);
+ private static byte[] ipv4Packet(byte[] sip, byte[] dip, int sport,
+ int dport, int seq, int ack, int dataLength) {
+ final int totalLength = dataLength + IPV4_HEADER_LEN + IPV4_TCP_HEADER_LEN;
+
+ ByteBuffer packet = ByteBuffer.wrap(new byte[totalLength + ETH_HEADER_LEN]);
+
+ // ether type
packet.putShort(ETH_ETHERTYPE_OFFSET, (short) ETH_P_IP);
+
+ // IPv4 header
packet.put(IPV4_VERSION_IHL_OFFSET, (byte) 0x45);
+ packet.putShort(IPV4_TOTAL_LENGTH_OFFSET, (short) totalLength);
+ packet.put(IPV4_PROTOCOL_OFFSET, (byte) IPPROTO_TCP);
put(packet, IPV4_SRC_ADDR_OFFSET, sip);
- put(packet, IPV4_DEST_ADDR_OFFSET, tip);
+ put(packet, IPV4_DEST_ADDR_OFFSET, dip);
packet.putShort(IPV4_TCP_SRC_PORT_OFFSET, (short) sport);
packet.putShort(IPV4_TCP_DEST_PORT_OFFSET, (short) dport);
packet.putInt(IPV4_TCP_SEQ_NUM_OFFSET, seq);
packet.putInt(IPV4_TCP_ACK_NUM_OFFSET, ack);
- return packet.array();
- }
- private static byte[] ipv4Packet(byte[] sip, byte[] tip, int sport,
- int dport, int seq, int ack, int dataLength) {
- final int totalLength = dataLength + IPV4_HEADER_LEN + IPV4_TCP_HEADER_LEN;
-
- ByteBuffer packet = ByteBuffer.wrap(ipv4Packet(sip, tip, sport, dport, seq, ack));
- packet.putShort(IPV4_TOTAL_LENGTH_OFFSET, (short) totalLength);
- // TCP header length 5, reserved 3 bits, NS=0
+ // TCP header length 5(20 bytes), reserved 3 bits, NS=0
packet.put(IPV4_TCP_HEADER_LENGTH_OFFSET, (byte) 0x50);
+ // TCP flags: ACK set
+ packet.put(IPV4_TCP_HEADER_FLAG_OFFSET, (byte) 0x10);
return packet.array();
}
diff --git a/packages/NetworkStack/tests/src/com/android/server/connectivity/NetworkMonitorTest.java b/packages/NetworkStack/tests/src/com/android/server/connectivity/NetworkMonitorTest.java
index b98b0f798fe3..9a16bb77182e 100644
--- a/packages/NetworkStack/tests/src/com/android/server/connectivity/NetworkMonitorTest.java
+++ b/packages/NetworkStack/tests/src/com/android/server/connectivity/NetworkMonitorTest.java
@@ -16,8 +16,7 @@
package com.android.server.connectivity;
-import static android.net.ConnectivityManager.ACTION_CAPTIVE_PORTAL_SIGN_IN;
-import static android.net.ConnectivityManager.EXTRA_CAPTIVE_PORTAL;
+import static android.net.CaptivePortal.APP_RETURN_DISMISSED;
import static android.net.INetworkMonitor.NETWORK_TEST_RESULT_INVALID;
import static android.net.INetworkMonitor.NETWORK_TEST_RESULT_VALID;
import static android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET;
@@ -41,8 +40,6 @@ import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.content.Context;
-import android.content.Intent;
-import android.net.CaptivePortal;
import android.net.ConnectivityManager;
import android.net.INetworkMonitorCallbacks;
import android.net.InetAddresses;
@@ -54,10 +51,10 @@ import android.net.captiveportal.CaptivePortalProbeResult;
import android.net.metrics.IpConnectivityLog;
import android.net.util.SharedLog;
import android.net.wifi.WifiManager;
+import android.os.Bundle;
import android.os.ConditionVariable;
import android.os.Handler;
import android.os.SystemClock;
-import android.os.UserHandle;
import android.provider.Settings;
import android.support.test.filters.SmallTest;
import android.support.test.runner.AndroidJUnit4;
@@ -487,19 +484,23 @@ public class NetworkMonitorTest {
// Check that startCaptivePortalApp sends the expected intent.
nm.launchCaptivePortalApp();
- final ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class);
- verify(mContext, timeout(HANDLER_TIMEOUT_MS).times(1))
- .startActivityAsUser(intentCaptor.capture(), eq(UserHandle.CURRENT));
- final Intent intent = intentCaptor.getValue();
- assertEquals(ACTION_CAPTIVE_PORTAL_SIGN_IN, intent.getAction());
- final Network network = intent.getParcelableExtra(ConnectivityManager.EXTRA_NETWORK);
- assertEquals(TEST_NETID, network.netId);
+ final ArgumentCaptor<Bundle> bundleCaptor = ArgumentCaptor.forClass(Bundle.class);
+ final ArgumentCaptor<Network> networkCaptor = ArgumentCaptor.forClass(Network.class);
+ verify(mCm, timeout(HANDLER_TIMEOUT_MS).times(1))
+ .startCaptivePortalApp(networkCaptor.capture(), bundleCaptor.capture());
+ final Bundle bundle = bundleCaptor.getValue();
+ final Network bundleNetwork = bundle.getParcelable(ConnectivityManager.EXTRA_NETWORK);
+ assertEquals(TEST_NETID, bundleNetwork.netId);
+ // network is passed both in bundle and as parameter, as the bundle is opaque to the
+ // framework and only intended for the captive portal app, but the framework needs
+ // the network to identify the right NetworkMonitor.
+ assertEquals(TEST_NETID, networkCaptor.getValue().netId);
// Have the app report that the captive portal is dismissed, and check that we revalidate.
setStatus(mHttpsConnection, 204);
setStatus(mHttpConnection, 204);
- final CaptivePortal captivePortal = intent.getParcelableExtra(EXTRA_CAPTIVE_PORTAL);
- captivePortal.reportCaptivePortalDismissed();
+
+ nm.notifyCaptivePortalAppFinished(APP_RETURN_DISMISSED);
verify(mCallbacks, timeout(HANDLER_TIMEOUT_MS).times(1))
.notifyNetworkTested(NETWORK_TEST_RESULT_VALID, null);
}
diff --git a/packages/NetworkStackPermissionStub/Android.bp b/packages/NetworkStackPermissionStub/Android.bp
index 94870c919dfa..dd70cf56b51b 100644
--- a/packages/NetworkStackPermissionStub/Android.bp
+++ b/packages/NetworkStackPermissionStub/Android.bp
@@ -21,7 +21,7 @@ android_app {
// a classes.dex.
srcs: ["src/**/*.java"],
platform_apis: true,
- certificate: "platform",
+ certificate: "networkstack",
privileged: true,
manifest: "AndroidManifest.xml",
}
diff --git a/packages/SettingsLib/res/values-af/strings.xml b/packages/SettingsLib/res/values-af/strings.xml
index 0988cab78a49..cfc76b70275f 100644
--- a/packages/SettingsLib/res/values-af/strings.xml
+++ b/packages/SettingsLib/res/values-af/strings.xml
@@ -87,8 +87,8 @@
<string name="bluetooth_profile_sap" msgid="5764222021851283125">"SIM-toegang"</string>
<string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"HD-oudio: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
<string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"HD oudio"</string>
- <string name="bluetooth_profile_hearing_aid" msgid="7999237886427812595">"Gehoortoestel"</string>
- <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="7188282786730266159">"Gekoppel aan gehoortoestel"</string>
+ <string name="bluetooth_profile_hearing_aid" msgid="6680721080542444257">"Gehoortoestelle"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="3051944447369418317">"Gekoppel aan gehoortoestelle"</string>
<string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"Gekoppel aan media-oudio"</string>
<string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"Gekoppel aan foonoudio"</string>
<string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"Gekoppel aan lêeroordragbediener"</string>
@@ -105,7 +105,7 @@
<string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"Gebruik vir foonoudio"</string>
<string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"Gebruik vir lêeroordrag"</string>
<string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"Gebruik vir invoer"</string>
- <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="908775281788309484">"Gebruik vir gehoortoestel"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="8843499209204010224">"Gebruik vir gehoortoestelle"</string>
<string name="bluetooth_pairing_accept" msgid="6163520056536604875">"Bind saam"</string>
<string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"BIND SAAM"</string>
<string name="bluetooth_pairing_decline" msgid="4185420413578948140">"Kanselleer"</string>
@@ -136,6 +136,7 @@
<string name="process_kernel_label" msgid="3916858646836739323">"Android-bedryfstelsel"</string>
<string name="data_usage_uninstalled_apps" msgid="614263770923231598">"Verwyderde programme"</string>
<string name="data_usage_uninstalled_apps_users" msgid="7986294489899813194">"Verwyderde programme en gebruikers"</string>
+ <string name="data_usage_ota" msgid="5377889154805560860">"Stelselopdaterings"</string>
<string name="tether_settings_title_usb" msgid="6688416425801386511">"USB-verbinding"</string>
<string name="tether_settings_title_wifi" msgid="3277144155960302049">"Wi-Fi-warmkol"</string>
<string name="tether_settings_title_bluetooth" msgid="355855408317564420">"Bluetooth-verbinding"</string>
diff --git a/packages/SettingsLib/res/values-am/strings.xml b/packages/SettingsLib/res/values-am/strings.xml
index 301d6099a6a7..6e6d58fb4470 100644
--- a/packages/SettingsLib/res/values-am/strings.xml
+++ b/packages/SettingsLib/res/values-am/strings.xml
@@ -87,8 +87,8 @@
<string name="bluetooth_profile_sap" msgid="5764222021851283125">"የሲም መዳረሻ"</string>
<string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"ኤችዲ ኦዲዮ፦ <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
<string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"ኤችዲ ኦዲዮ"</string>
- <string name="bluetooth_profile_hearing_aid" msgid="7999237886427812595">"መስሚያ አጋዥ መሣሪያ"</string>
- <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="7188282786730266159">"ከመስሚያ አጋዥ መሣሪያ ጋር ተገናኝቷል"</string>
+ <string name="bluetooth_profile_hearing_aid" msgid="6680721080542444257">"አጋዥ መስሚያዎች"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="3051944447369418317">"ከአጋዥ መስሚያዎች ጋር ተገናኝቷል"</string>
<string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"ወደ ማህደረ መረጃ አውዲዮ ተያይዟል"</string>
<string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"ወደ ስልክ አውዲዮ ተያይዟል"</string>
<string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"ወደ ፋይል ዝውውር አገልጋይ ተያይዟል"</string>
@@ -105,7 +105,7 @@
<string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"ለስልክ ድምፅ ተጠቀም"</string>
<string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"ለፋይል ዝውውር ተጠቀም"</string>
<string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"ለውፅአት ተጠቀም"</string>
- <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="908775281788309484">"ለመስሚያ አጋዥ መሣሪያ ተጠቀም"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="8843499209204010224">"ለአጋዥ መስሚያዎች ይጠቀሙ"</string>
<string name="bluetooth_pairing_accept" msgid="6163520056536604875">"አጣምር"</string>
<string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"አጣምር"</string>
<string name="bluetooth_pairing_decline" msgid="4185420413578948140">"ይቅር"</string>
@@ -136,6 +136,7 @@
<string name="process_kernel_label" msgid="3916858646836739323">"Android ስርዓተ ክወና"</string>
<string name="data_usage_uninstalled_apps" msgid="614263770923231598">"የተወገዱ መተግበሪያዎች"</string>
<string name="data_usage_uninstalled_apps_users" msgid="7986294489899813194">"የተወገዱ መተግበሪያዎች እና ተጠቃሚዎች"</string>
+ <string name="data_usage_ota" msgid="5377889154805560860">"የሥርዓት ዝማኔዎች"</string>
<string name="tether_settings_title_usb" msgid="6688416425801386511">"USB መሰካት"</string>
<string name="tether_settings_title_wifi" msgid="3277144155960302049">"ተጓጓዥ ድረስ ነጥቦች"</string>
<string name="tether_settings_title_bluetooth" msgid="355855408317564420">"ብሉቱዝ ማያያዝ"</string>
diff --git a/packages/SettingsLib/res/values-ar/strings.xml b/packages/SettingsLib/res/values-ar/strings.xml
index 91de9e3f693c..18d47ace8608 100644
--- a/packages/SettingsLib/res/values-ar/strings.xml
+++ b/packages/SettingsLib/res/values-ar/strings.xml
@@ -87,8 +87,8 @@
<string name="bluetooth_profile_sap" msgid="5764222021851283125">"‏الوصول إلى شريحة SIM"</string>
<string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"صوت عالي الدقة: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
<string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"صوت عالي الدقة"</string>
- <string name="bluetooth_profile_hearing_aid" msgid="7999237886427812595">"سماعة الأذن الطبية"</string>
- <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="7188282786730266159">"تم توصيل سماعة الأذن الطبية"</string>
+ <string name="bluetooth_profile_hearing_aid" msgid="6680721080542444257">"سماعات الأذن الطبية"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="3051944447369418317">"تمّ التوصيل بسماعات الأذن الطبية"</string>
<string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"متصل بالإعدادات الصوتية للوسائط"</string>
<string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"متصل بالإعدادات الصوتية للهاتف"</string>
<string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"متصل بخادم نقل الملف"</string>
@@ -105,7 +105,7 @@
<string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"الاستخدام لإعدادات الهاتف الصوتية"</string>
<string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"استخدامه لنقل الملفات"</string>
<string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"استخدام للإدخال"</string>
- <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="908775281788309484">"استخدام سماعة الأذن الطبية"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="8843499209204010224">"استخدام سماعات الأذن الطبية"</string>
<string name="bluetooth_pairing_accept" msgid="6163520056536604875">"إقران"</string>
<string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"إقران"</string>
<string name="bluetooth_pairing_decline" msgid="4185420413578948140">"إلغاء"</string>
@@ -136,6 +136,7 @@
<string name="process_kernel_label" msgid="3916858646836739323">"‏نظام التشغيل Android"</string>
<string name="data_usage_uninstalled_apps" msgid="614263770923231598">"التطبيقات المزالة"</string>
<string name="data_usage_uninstalled_apps_users" msgid="7986294489899813194">"التطبيقات والمستخدمون الذين تمت إزالتهم"</string>
+ <string name="data_usage_ota" msgid="5377889154805560860">"تحديثات النظام"</string>
<string name="tether_settings_title_usb" msgid="6688416425801386511">"‏ربط USB"</string>
<string name="tether_settings_title_wifi" msgid="3277144155960302049">"نقطة اتصال محمولة"</string>
<string name="tether_settings_title_bluetooth" msgid="355855408317564420">"ربط البلوتوث"</string>
diff --git a/packages/SettingsLib/res/values-as/strings.xml b/packages/SettingsLib/res/values-as/strings.xml
index e726ae46e3a2..f865563200e1 100644
--- a/packages/SettingsLib/res/values-as/strings.xml
+++ b/packages/SettingsLib/res/values-as/strings.xml
@@ -38,27 +38,20 @@
<string name="connected_via_network_scorer" msgid="5713793306870815341">"%1$s মাধ্যমেদি স্বয়ংক্ৰিয়ভাৱে সংযোগ কৰা হৈছে"</string>
<string name="connected_via_network_scorer_default" msgid="7867260222020343104">"নেটৱৰ্ক ৰেটিং প্ৰদানকাৰীৰ জৰিয়তে স্বয়ং সংয়োগ কৰা হ’ল"</string>
<string name="connected_via_passpoint" msgid="2826205693803088747">"%1$s-ৰ মাধ্যমেদি সংযোগ কৰা হৈছে"</string>
- <!-- no translation found for connected_via_app (5571999941988929520) -->
- <skip />
+ <string name="connected_via_app" msgid="5571999941988929520">"<xliff:g id="NAME">%1$s</xliff:g>ৰ জৰিয়তে সংযুক্ত"</string>
<string name="available_via_passpoint" msgid="1617440946846329613">"%1$sৰ মাধ্যমেৰে উপলব্ধ"</string>
- <!-- no translation found for tap_to_sign_up (6449724763052579434) -->
- <skip />
+ <string name="tap_to_sign_up" msgid="6449724763052579434">"ছাইন আপ কৰিবলৈ টিপক"</string>
<string name="wifi_connected_no_internet" msgid="8202906332837777829">"সংযোজিত, ইণ্টাৰনেট নাই"</string>
<string name="wifi_status_no_internet" msgid="5784710974669608361">"ইণ্টাৰনেট সংযোগ নাই"</string>
<string name="wifi_status_sign_in_required" msgid="123517180404752756">"ছাইন ইন কৰা দৰকাৰী"</string>
<string name="wifi_ap_unable_to_handle_new_sta" msgid="5348824313514404541">"একচেছ পইণ্ট কিছু সময়ৰ বাবে পূৰ্ণ হৈ আছে"</string>
<string name="connected_via_carrier" msgid="7583780074526041912">"%1$sৰ যোগেৰে সংযোজিত"</string>
<string name="available_via_carrier" msgid="1469036129740799053">"%1$sৰ মাধ্যমেৰে উপলব্ধ"</string>
- <!-- no translation found for osu_opening_provider (5488997661548640424) -->
- <skip />
- <!-- no translation found for osu_connect_failed (2187750899158158934) -->
- <skip />
- <!-- no translation found for osu_completing_sign_up (9037638564719197082) -->
- <skip />
- <!-- no translation found for osu_sign_up_failed (7296159750352873260) -->
- <skip />
- <!-- no translation found for osu_sign_up_complete (8207626049093289203) -->
- <skip />
+ <string name="osu_opening_provider" msgid="5488997661548640424">"<xliff:g id="PASSPOINTPROVIDER">%1$s</xliff:g> খুলি থকা হৈছে"</string>
+ <string name="osu_connect_failed" msgid="2187750899158158934">"সংযোগ কৰিব পৰা নগ’ল"</string>
+ <string name="osu_completing_sign_up" msgid="9037638564719197082">"ছাইন আপ সম্পূৰ্ণ কৰি থকা হৈছে…"</string>
+ <string name="osu_sign_up_failed" msgid="7296159750352873260">"ছাইন আপ সম্পূৰ্ণ কৰিব পৰা নগ’ল। আকৌ চেষ্টা কৰিবলৈ টিপক।"</string>
+ <string name="osu_sign_up_complete" msgid="8207626049093289203">"ছাইন আপ সম্পূৰ্ণ হৈছে সংযোগ কৰি থকা হৈছে…"</string>
<string name="speed_label_very_slow" msgid="1867055264243608530">"অতি লেহেম"</string>
<string name="speed_label_slow" msgid="813109590815810235">"লেহেমীয়া"</string>
<string name="speed_label_okay" msgid="2331665440671174858">"ঠিক"</string>
@@ -94,8 +87,8 @@
<string name="bluetooth_profile_sap" msgid="5764222021851283125">"ছিম প্ৰৱেশ"</string>
<string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"এইচ্ছডি অডি\'অ: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
<string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"এইচ্ছডি অডিঅ’"</string>
- <string name="bluetooth_profile_hearing_aid" msgid="7999237886427812595">"শ্ৰৱণ যন্ত্ৰ"</string>
- <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="7188282786730266159">"শ্ৰৱণ যন্ত্ৰৰ লগত সংযোগ কৰা হ’ল"</string>
+ <string name="bluetooth_profile_hearing_aid" msgid="6680721080542444257">"শ্ৰৱণ যন্ত্ৰ"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="3051944447369418317">"শ্ৰৱণ যন্ত্ৰলৈ সংযোগ কৰা হৈছে"</string>
<string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"মিডিয়া অডিঅ’লৈ সংযোগ হৈছে"</string>
<string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"ফ’ন অডিঅ\'ৰ লগত সংযোগ কৰা হ’ল"</string>
<string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"ফাইল ট্ৰান্সফাৰ ছাৰ্ভাৰৰ সৈতে সংযোজিত হৈ আছে"</string>
@@ -112,7 +105,7 @@
<string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"ফ\'ন অডিঅ\'ৰ বাবে ব্যৱহাৰ কৰক"</string>
<string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"ফাইল স্থানান্তৰ কৰিবলৈ ব্যৱহাৰ কৰক"</string>
<string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"ইনপুটৰ বাবে ব্যৱহাৰ কৰক"</string>
- <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="908775281788309484">"শ্ৰৱণ যন্ত্ৰৰ বাবে ব্যৱহাৰ কৰক"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="8843499209204010224">"শ্ৰৱণ যন্ত্ৰৰ বাবে ব্যৱহাৰ কৰক"</string>
<string name="bluetooth_pairing_accept" msgid="6163520056536604875">"যোৰা লগাওক"</string>
<string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"যোৰা লগাওক"</string>
<string name="bluetooth_pairing_decline" msgid="4185420413578948140">"বাতিল কৰক"</string>
@@ -143,8 +136,10 @@
<string name="process_kernel_label" msgid="3916858646836739323">"Android OS"</string>
<string name="data_usage_uninstalled_apps" msgid="614263770923231598">"আঁতৰোৱা এপ্‌সমূহ"</string>
<string name="data_usage_uninstalled_apps_users" msgid="7986294489899813194">"আঁতৰোৱা এপ্‌ আৰু ব্যৱহাৰকাৰীসমূহ"</string>
+ <!-- no translation found for data_usage_ota (5377889154805560860) -->
+ <skip />
<string name="tether_settings_title_usb" msgid="6688416425801386511">"ইউএছবি টেডাৰিং"</string>
- <string name="tether_settings_title_wifi" msgid="3277144155960302049">"প\'ৰ্টেবল হ\'টস্প\'ট"</string>
+ <string name="tether_settings_title_wifi" msgid="3277144155960302049">"প\'ৰ্টেবল হটস্পট"</string>
<string name="tether_settings_title_bluetooth" msgid="355855408317564420">"ব্লুটুথ টেডাৰিং"</string>
<string name="tether_settings_title_usb_bluetooth" msgid="5355828977109785001">"টেডাৰ কৰি থকা হৈছে"</string>
<string name="tether_settings_title_all" msgid="8356136101061143841">"টেডাৰিং আৰু প\'ৰ্টেবল হটস্পট"</string>
diff --git a/packages/SettingsLib/res/values-az/strings.xml b/packages/SettingsLib/res/values-az/strings.xml
index 4dd4817cee8a..8e6e07d17d09 100644
--- a/packages/SettingsLib/res/values-az/strings.xml
+++ b/packages/SettingsLib/res/values-az/strings.xml
@@ -87,8 +87,8 @@
<string name="bluetooth_profile_sap" msgid="5764222021851283125">"SIM Girişi"</string>
<string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"HD audio: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
<string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"HD audio"</string>
- <string name="bluetooth_profile_hearing_aid" msgid="7999237886427812595">"Qulaqlıq"</string>
- <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="7188282786730266159">"Qulaqlığa qoşuldunuz"</string>
+ <string name="bluetooth_profile_hearing_aid" msgid="6680721080542444257">"Eşitmə Aparatı"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="3051944447369418317">"Eşitmə Aparatlarına qoşuldu"</string>
<string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"Media audioya birləşdirilib"</string>
<string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"Telefon audiosuna qoşulu"</string>
<string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"Fayl transfer serverinə qoşulu"</string>
@@ -105,7 +105,7 @@
<string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"Telefon audiosu istifadə edin"</string>
<string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"Fayl transferi üçün istifadə edin"</string>
<string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"Daxiletmə üçün istifadə edin"</string>
- <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="908775281788309484">"Qulaqlıq üçün istifadə edin"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="8843499209204010224">"Eşitmə Aparatları üçün istifadə edin"</string>
<string name="bluetooth_pairing_accept" msgid="6163520056536604875">"Birləşdir"</string>
<string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"CÜTLƏNDİR"</string>
<string name="bluetooth_pairing_decline" msgid="4185420413578948140">"Ləğv et"</string>
@@ -136,6 +136,7 @@
<string name="process_kernel_label" msgid="3916858646836739323">"Android OS"</string>
<string name="data_usage_uninstalled_apps" msgid="614263770923231598">"Silinmiş tətbiqlər"</string>
<string name="data_usage_uninstalled_apps_users" msgid="7986294489899813194">"Tətbiqləri və istifadəçiləri silin"</string>
+ <string name="data_usage_ota" msgid="5377889154805560860">"Sistem güncəllənməsi"</string>
<string name="tether_settings_title_usb" msgid="6688416425801386511">"USB Birləşmə"</string>
<string name="tether_settings_title_wifi" msgid="3277144155960302049">"Portativ hotspot"</string>
<string name="tether_settings_title_bluetooth" msgid="355855408317564420">"Bluetooth birləşmə"</string>
diff --git a/packages/SettingsLib/res/values-b+sr+Latn/strings.xml b/packages/SettingsLib/res/values-b+sr+Latn/strings.xml
index dc5430114ba7..1cdd1fd30984 100644
--- a/packages/SettingsLib/res/values-b+sr+Latn/strings.xml
+++ b/packages/SettingsLib/res/values-b+sr+Latn/strings.xml
@@ -87,8 +87,8 @@
<string name="bluetooth_profile_sap" msgid="5764222021851283125">"Pristup SIM kartici"</string>
<string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"HD zvuk: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
<string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"HD zvuk"</string>
- <string name="bluetooth_profile_hearing_aid" msgid="7999237886427812595">"Slušni aparat"</string>
- <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="7188282786730266159">"Povezano sa slušnim aparatom"</string>
+ <string name="bluetooth_profile_hearing_aid" msgid="6680721080542444257">"Slušni aparati"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="3051944447369418317">"Povezano sa slušnim aparatima"</string>
<string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"Povezano sa zvukom medija"</string>
<string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"Povezano sa zvukom telefona"</string>
<string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"Povezano sa serverom za prenos datoteka"</string>
@@ -105,7 +105,7 @@
<string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"Korišćenje za audio telefona"</string>
<string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"Korišćenje za prenos datoteka"</string>
<string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"Koristi za ulaz"</string>
- <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="908775281788309484">"Koristi za slušni aparat"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="8843499209204010224">"Koristi za slušne aparate"</string>
<string name="bluetooth_pairing_accept" msgid="6163520056536604875">"Upari"</string>
<string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"UPARI"</string>
<string name="bluetooth_pairing_decline" msgid="4185420413578948140">"Otkaži"</string>
@@ -136,6 +136,7 @@
<string name="process_kernel_label" msgid="3916858646836739323">"Android OS"</string>
<string name="data_usage_uninstalled_apps" msgid="614263770923231598">"Uklonjene aplikacije"</string>
<string name="data_usage_uninstalled_apps_users" msgid="7986294489899813194">"Uklonjene aplikacije i korisnici"</string>
+ <string name="data_usage_ota" msgid="5377889154805560860">"Ažuriranja sistema"</string>
<string name="tether_settings_title_usb" msgid="6688416425801386511">"USB Internet povezivanje"</string>
<string name="tether_settings_title_wifi" msgid="3277144155960302049">"Prenosni hotspot"</string>
<string name="tether_settings_title_bluetooth" msgid="355855408317564420">"Bluetooth privezivanje"</string>
diff --git a/packages/SettingsLib/res/values-be/strings.xml b/packages/SettingsLib/res/values-be/strings.xml
index 2fa2692a3bbf..1a60c3d1a531 100644
--- a/packages/SettingsLib/res/values-be/strings.xml
+++ b/packages/SettingsLib/res/values-be/strings.xml
@@ -87,8 +87,8 @@
<string name="bluetooth_profile_sap" msgid="5764222021851283125">"Доступ да SIM-карты"</string>
<string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"Аўдыя ў HD: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
<string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"Аўдыя ў HD"</string>
- <string name="bluetooth_profile_hearing_aid" msgid="7999237886427812595">"Слыхавы апарат"</string>
- <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="7188282786730266159">"Падключана да слыхавога апарата"</string>
+ <string name="bluetooth_profile_hearing_aid" msgid="6680721080542444257">"Слыхавыя апараты"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="3051944447369418317">"Падключана да слыхавых апаратаў"</string>
<string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"Падключана да аўдыё медыа"</string>
<string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"Падключана да аўдыё тэлефона"</string>
<string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"Падключаны да серверу перадачы файлаў"</string>
@@ -105,7 +105,7 @@
<string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"Выкарыстоўваць для аўдыё тэлефона"</string>
<string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"Выкарыстоўваць для перадачы файлаў"</string>
<string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"Выкарыстоўваць для ўводу"</string>
- <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="908775281788309484">"Выкарыстоўваць для слыхавога апарата"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="8843499209204010224">"Выкарыстоўваць для слыхавых апаратаў"</string>
<string name="bluetooth_pairing_accept" msgid="6163520056536604875">"Падлучыць"</string>
<string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"СПАЛУЧЫЦЬ"</string>
<string name="bluetooth_pairing_decline" msgid="4185420413578948140">"Скасаваць"</string>
@@ -136,6 +136,7 @@
<string name="process_kernel_label" msgid="3916858646836739323">"АС Android"</string>
<string name="data_usage_uninstalled_apps" msgid="614263770923231598">"Выдаленыя прыкладанні"</string>
<string name="data_usage_uninstalled_apps_users" msgid="7986294489899813194">"Выдаленыя прыкладанні і карыстальнiкi"</string>
+ <string name="data_usage_ota" msgid="5377889154805560860">"Абнаўленні сістэмы"</string>
<string name="tether_settings_title_usb" msgid="6688416425801386511">"USB-мадэм"</string>
<string name="tether_settings_title_wifi" msgid="3277144155960302049">"Партатыўная кропка доступу"</string>
<string name="tether_settings_title_bluetooth" msgid="355855408317564420">"Bluetooth-мадэм"</string>
diff --git a/packages/SettingsLib/res/values-bg/strings.xml b/packages/SettingsLib/res/values-bg/strings.xml
index 1454118c46c0..aaedce4bf1a2 100644
--- a/packages/SettingsLib/res/values-bg/strings.xml
+++ b/packages/SettingsLib/res/values-bg/strings.xml
@@ -87,8 +87,8 @@
<string name="bluetooth_profile_sap" msgid="5764222021851283125">"Достъп до SIM картата"</string>
<string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"Висококачествено аудио: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
<string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"Висококачествено аудио"</string>
- <string name="bluetooth_profile_hearing_aid" msgid="7999237886427812595">"Слухов апарат"</string>
- <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="7188282786730266159">"Има връзка със слуховия апарат"</string>
+ <string name="bluetooth_profile_hearing_aid" msgid="6680721080542444257">"Слухови апарати"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="3051944447369418317">"Установена е връзка със слухов апарат"</string>
<string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"Установена е връзка с медийно аудио"</string>
<string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"Връзка със звука на телефона"</string>
<string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"Установена е връзка със сървър за трансфер на файлове"</string>
@@ -105,7 +105,7 @@
<string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"Използване на телефон за аудио"</string>
<string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"Използване на за пренос на файлове"</string>
<string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"Да се използва за въвеждане"</string>
- <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="908775281788309484">"Използване за слухов апарат"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="8843499209204010224">"Използване за слухови апарати"</string>
<string name="bluetooth_pairing_accept" msgid="6163520056536604875">"Сдвояване"</string>
<string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"СДВОЯВАНЕ"</string>
<string name="bluetooth_pairing_decline" msgid="4185420413578948140">"Отказ"</string>
@@ -136,6 +136,7 @@
<string name="process_kernel_label" msgid="3916858646836739323">"Android (ОС)"</string>
<string name="data_usage_uninstalled_apps" msgid="614263770923231598">"Премахнати приложения"</string>
<string name="data_usage_uninstalled_apps_users" msgid="7986294489899813194">"Премахнати приложения и потребители"</string>
+ <string name="data_usage_ota" msgid="5377889154805560860">"Системни актуализации"</string>
<string name="tether_settings_title_usb" msgid="6688416425801386511">"Тетъринг през USB"</string>
<string name="tether_settings_title_wifi" msgid="3277144155960302049">"Преносима точка за достъп"</string>
<string name="tether_settings_title_bluetooth" msgid="355855408317564420">"Тетъринг през Bluetooth"</string>
diff --git a/packages/SettingsLib/res/values-bn/strings.xml b/packages/SettingsLib/res/values-bn/strings.xml
index dbf397f10c2a..ef8dd3de56a9 100644
--- a/packages/SettingsLib/res/values-bn/strings.xml
+++ b/packages/SettingsLib/res/values-bn/strings.xml
@@ -38,27 +38,20 @@
<string name="connected_via_network_scorer" msgid="5713793306870815341">"স্বয়ংক্রিয়ভাবে %1$s এর মাধ্যমে কানেক্ট হয়েছে"</string>
<string name="connected_via_network_scorer_default" msgid="7867260222020343104">"নেটওয়ার্কের রেটিং প্রদানকারীর মাধ্যমে অটোমেটিক কানেক্ট"</string>
<string name="connected_via_passpoint" msgid="2826205693803088747">"%1$s মাধ্যমে কানেক্ট হয়েছে"</string>
- <!-- no translation found for connected_via_app (5571999941988929520) -->
- <skip />
+ <string name="connected_via_app" msgid="5571999941988929520">"<xliff:g id="NAME">%1$s</xliff:g>-এর মাধ্যমে কানেক্ট করা আছে"</string>
<string name="available_via_passpoint" msgid="1617440946846329613">"%1$s এর মাধ্যমে উপলব্ধ"</string>
- <!-- no translation found for tap_to_sign_up (6449724763052579434) -->
- <skip />
+ <string name="tap_to_sign_up" msgid="6449724763052579434">"সাইন-আপ করতে ট্যাপ করুন"</string>
<string name="wifi_connected_no_internet" msgid="8202906332837777829">"কানেক্ট, ইন্টারনেট নেই"</string>
<string name="wifi_status_no_internet" msgid="5784710974669608361">"ইন্টারনেট কানেকশন নেই"</string>
<string name="wifi_status_sign_in_required" msgid="123517180404752756">"সাইন-ইন করা দরকার"</string>
<string name="wifi_ap_unable_to_handle_new_sta" msgid="5348824313514404541">"এই মুহূর্তে অ্যাক্সেস পয়েন্টের কোনও কানেকশন ফাঁকা নেই"</string>
<string name="connected_via_carrier" msgid="7583780074526041912">"%1$s এর মাধ্যমে কানেক্ট হয়েছে"</string>
<string name="available_via_carrier" msgid="1469036129740799053">"%1$s এর মাধ্যমে পাওয়া যাচ্ছে"</string>
- <!-- no translation found for osu_opening_provider (5488997661548640424) -->
- <skip />
- <!-- no translation found for osu_connect_failed (2187750899158158934) -->
- <skip />
- <!-- no translation found for osu_completing_sign_up (9037638564719197082) -->
- <skip />
- <!-- no translation found for osu_sign_up_failed (7296159750352873260) -->
- <skip />
- <!-- no translation found for osu_sign_up_complete (8207626049093289203) -->
- <skip />
+ <string name="osu_opening_provider" msgid="5488997661548640424">"<xliff:g id="PASSPOINTPROVIDER">%1$s</xliff:g> খোলা হচ্ছে"</string>
+ <string name="osu_connect_failed" msgid="2187750899158158934">"কানেক্ট করা যায়নি"</string>
+ <string name="osu_completing_sign_up" msgid="9037638564719197082">"সাইন-আপ সম্পূর্ণ করা হচ্ছে…"</string>
+ <string name="osu_sign_up_failed" msgid="7296159750352873260">"সাইন-আপ করা যায়নি। আবার চেষ্টা করতে ট্যাপ করুন।"</string>
+ <string name="osu_sign_up_complete" msgid="8207626049093289203">"সাইন-আপ করা হয়ে গেছে। কানেক্ট করা হচ্ছে…"</string>
<string name="speed_label_very_slow" msgid="1867055264243608530">"খুব ধীরে"</string>
<string name="speed_label_slow" msgid="813109590815810235">"ধীরে"</string>
<string name="speed_label_okay" msgid="2331665440671174858">"ঠিক আছে"</string>
@@ -94,8 +87,8 @@
<string name="bluetooth_profile_sap" msgid="5764222021851283125">"সিম -এর অ্যাক্সেস"</string>
<string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"HD অডিও: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
<string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"HD অডিও"</string>
- <string name="bluetooth_profile_hearing_aid" msgid="7999237886427812595">"হিয়ারিং এড"</string>
- <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="7188282786730266159">"শ্রবণ যন্ত্রের সাথে কানেক্ট রয়েছে"</string>
+ <string name="bluetooth_profile_hearing_aid" msgid="6680721080542444257">"হিয়ারিং এড"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="3051944447369418317">"হিয়ারিং এডের সাথে কানেক্ট করা হয়েছে"</string>
<string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"মিডিয়া অডিওতে কানেক্ট রয়েছে"</string>
<string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"ফোন অডিওতে কানেক্ট"</string>
<string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"ফাইল স্থানান্তর সার্ভারের সঙ্গে কানেক্ট"</string>
@@ -112,7 +105,7 @@
<string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"ফোন অডিওয়ের জন্য ব্যবহার করুন"</string>
<string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"ফাইল স্থানান্তরের জন্য ব্যবহার করুন"</string>
<string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"ইনপুটের জন্য ব্যবহার করুন"</string>
- <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="908775281788309484">"শ্রবণ যন্ত্রের জন্য ব্যবহার করুন"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="8843499209204010224">"হিয়ারিং এডের জন্য ব্যবহার করুন"</string>
<string name="bluetooth_pairing_accept" msgid="6163520056536604875">"যুক্ত করুন"</string>
<string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"যুক্ত করুন"</string>
<string name="bluetooth_pairing_decline" msgid="4185420413578948140">"বাতিল করুন"</string>
@@ -143,6 +136,8 @@
<string name="process_kernel_label" msgid="3916858646836739323">"Android OS"</string>
<string name="data_usage_uninstalled_apps" msgid="614263770923231598">"সরানো অ্যাপ্লিকেশানগুলি"</string>
<string name="data_usage_uninstalled_apps_users" msgid="7986294489899813194">"সরানো অ্যাপ্লিকেশানগুলি এবং ব্যবহারকারীগণ"</string>
+ <!-- no translation found for data_usage_ota (5377889154805560860) -->
+ <skip />
<string name="tether_settings_title_usb" msgid="6688416425801386511">"USB টিথারিং"</string>
<string name="tether_settings_title_wifi" msgid="3277144155960302049">"পোর্টেবল হটস্পট"</string>
<string name="tether_settings_title_bluetooth" msgid="355855408317564420">"ব্লুটুথ টিথারিং"</string>
diff --git a/packages/SettingsLib/res/values-bs/strings.xml b/packages/SettingsLib/res/values-bs/strings.xml
index 272e7971e5bf..4193d5250570 100644
--- a/packages/SettingsLib/res/values-bs/strings.xml
+++ b/packages/SettingsLib/res/values-bs/strings.xml
@@ -87,8 +87,8 @@
<string name="bluetooth_profile_sap" msgid="5764222021851283125">"Pristup SIM-u"</string>
<string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"HD audio: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
<string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"HD audio"</string>
- <string name="bluetooth_profile_hearing_aid" msgid="7999237886427812595">"Slušni aparat"</string>
- <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="7188282786730266159">"Povezano na slušni aparat"</string>
+ <string name="bluetooth_profile_hearing_aid" msgid="6680721080542444257">"Slušni aparat"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="3051944447369418317">"Povezan na slušne aparate"</string>
<string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"Povezano sa zvukom medija"</string>
<string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"Povezano na zvuk telefona"</string>
<string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"Povezano sa serverom za prijenos podataka"</string>
@@ -105,7 +105,7 @@
<string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"Koristi za zvuk telefona"</string>
<string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"Koristi za prijenos fajlova"</string>
<string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"Koristi kao ulaz"</string>
- <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="908775281788309484">"Koristi za slušni aparat"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="8843499209204010224">"Korištenje za slušne aparate"</string>
<string name="bluetooth_pairing_accept" msgid="6163520056536604875">"Upari"</string>
<string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"UPARI"</string>
<string name="bluetooth_pairing_decline" msgid="4185420413578948140">"Otkaži"</string>
@@ -136,6 +136,7 @@
<string name="process_kernel_label" msgid="3916858646836739323">"Android OS"</string>
<string name="data_usage_uninstalled_apps" msgid="614263770923231598">"Uklonjene aplikacije"</string>
<string name="data_usage_uninstalled_apps_users" msgid="7986294489899813194">"Uklonjene aplikacije i korisnici"</string>
+ <string name="data_usage_ota" msgid="5377889154805560860">"Ažuriranja sistema"</string>
<string name="tether_settings_title_usb" msgid="6688416425801386511">"Povezivanje mobitela USB-om"</string>
<string name="tether_settings_title_wifi" msgid="3277144155960302049">"Prijenosna pristupna tačka"</string>
<string name="tether_settings_title_bluetooth" msgid="355855408317564420">"Dijeljenje Bluetooth veze"</string>
diff --git a/packages/SettingsLib/res/values-ca/strings.xml b/packages/SettingsLib/res/values-ca/strings.xml
index 5d2dd65f9824..9c3e4d94cf26 100644
--- a/packages/SettingsLib/res/values-ca/strings.xml
+++ b/packages/SettingsLib/res/values-ca/strings.xml
@@ -87,8 +87,8 @@
<string name="bluetooth_profile_sap" msgid="5764222021851283125">"Accés a la SIM"</string>
<string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"Àudio HD: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
<string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"Àudio HD"</string>
- <string name="bluetooth_profile_hearing_aid" msgid="7999237886427812595">"Audiòfon"</string>
- <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="7188282786730266159">"S\'ha connectat a l\'audiòfon"</string>
+ <string name="bluetooth_profile_hearing_aid" msgid="6680721080542444257">"Audiòfons"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="3051944447369418317">"S\'ha connectat als audiòfons"</string>
<string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"Connectat a l\'àudio del mitjà"</string>
<string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"Connectat a àudio del telèfon"</string>
<string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"Connectat al servidor de transferència de fitxers"</string>
@@ -105,7 +105,7 @@
<string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"Utilitza-ho per a l\'àudio del telèfon"</string>
<string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"Utilitza per a la transferència de fitxers"</string>
<string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"Utilitza per a entrada"</string>
- <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="908775281788309484">"Utilitza per a l\'audiòfon"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="8843499209204010224">"Utilitza per als audiòfons"</string>
<string name="bluetooth_pairing_accept" msgid="6163520056536604875">"Vincula"</string>
<string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"VINCULA"</string>
<string name="bluetooth_pairing_decline" msgid="4185420413578948140">"Cancel·la"</string>
@@ -136,6 +136,7 @@
<string name="process_kernel_label" msgid="3916858646836739323">"Android OS"</string>
<string name="data_usage_uninstalled_apps" msgid="614263770923231598">"Aplicacions eliminades"</string>
<string name="data_usage_uninstalled_apps_users" msgid="7986294489899813194">"Aplicacions i usuaris eliminats"</string>
+ <string name="data_usage_ota" msgid="5377889154805560860">"Actualitzacions del sistema"</string>
<string name="tether_settings_title_usb" msgid="6688416425801386511">"Compartició de xarxa per USB"</string>
<string name="tether_settings_title_wifi" msgid="3277144155960302049">"Punt d\'accés Wi-Fi"</string>
<string name="tether_settings_title_bluetooth" msgid="355855408317564420">"Compartició de xarxa per Bluetooth"</string>
diff --git a/packages/SettingsLib/res/values-cs/strings.xml b/packages/SettingsLib/res/values-cs/strings.xml
index 19a042ed2f6d..b6507bccce1d 100644
--- a/packages/SettingsLib/res/values-cs/strings.xml
+++ b/packages/SettingsLib/res/values-cs/strings.xml
@@ -87,8 +87,8 @@
<string name="bluetooth_profile_sap" msgid="5764222021851283125">"Přístup k SIM kartě"</string>
<string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"HD zvuk: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
<string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"HD zvuk"</string>
- <string name="bluetooth_profile_hearing_aid" msgid="7999237886427812595">"Naslouchátko"</string>
- <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="7188282786730266159">"Připojeno k naslouchátku"</string>
+ <string name="bluetooth_profile_hearing_aid" msgid="6680721080542444257">"Naslouchátka"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="3051944447369418317">"Připojeno k naslouchátkům"</string>
<string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"Připojeno ke zvukovému médiu"</string>
<string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"Připojeno k náhlavní soupravě"</string>
<string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"Připojeno k serveru pro přenos dat"</string>
@@ -105,7 +105,7 @@
<string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"Umožňuje připojení náhlavní soupravy"</string>
<string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"Použít pro přenos souborů"</string>
<string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"Použít pro vstup"</string>
- <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="908775281788309484">"Použít pro naslouchátko"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="8843499209204010224">"Použít pro naslouchátka"</string>
<string name="bluetooth_pairing_accept" msgid="6163520056536604875">"Párovat"</string>
<string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"PÁROVAT"</string>
<string name="bluetooth_pairing_decline" msgid="4185420413578948140">"Zrušit"</string>
@@ -136,6 +136,7 @@
<string name="process_kernel_label" msgid="3916858646836739323">"OS Android"</string>
<string name="data_usage_uninstalled_apps" msgid="614263770923231598">"Odebrané aplikace"</string>
<string name="data_usage_uninstalled_apps_users" msgid="7986294489899813194">"Odebrané aplikace a odebraní uživatelé"</string>
+ <string name="data_usage_ota" msgid="5377889154805560860">"Aktualizace systému"</string>
<string name="tether_settings_title_usb" msgid="6688416425801386511">"Připojení přes USB"</string>
<string name="tether_settings_title_wifi" msgid="3277144155960302049">"Přenosný hotspot"</string>
<string name="tether_settings_title_bluetooth" msgid="355855408317564420">"Připojení přes Bluetooth"</string>
diff --git a/packages/SettingsLib/res/values-da/strings.xml b/packages/SettingsLib/res/values-da/strings.xml
index bde67fde480f..a870cf883590 100644
--- a/packages/SettingsLib/res/values-da/strings.xml
+++ b/packages/SettingsLib/res/values-da/strings.xml
@@ -87,8 +87,8 @@
<string name="bluetooth_profile_sap" msgid="5764222021851283125">"SIM-adgang"</string>
<string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"HD-lyd: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
<string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"HD-lyd"</string>
- <string name="bluetooth_profile_hearing_aid" msgid="7999237886427812595">"Høreapparat"</string>
- <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="7188282786730266159">"Der er oprettet forbindelse til høreapparat"</string>
+ <string name="bluetooth_profile_hearing_aid" msgid="6680721080542444257">"Høreapparater"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="3051944447369418317">"Forbundet til høreapparater"</string>
<string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"Forbundet til medielyd"</string>
<string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"Forbundet til telefonlyd"</string>
<string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"Forbundet til filoverførselsserver"</string>
@@ -105,7 +105,7 @@
<string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"Brug til telefonlyd"</string>
<string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"Brug til filoverførsel"</string>
<string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"Brug til input"</string>
- <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="908775281788309484">"Anvend til høreapparat"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="8843499209204010224">"Brug til høreapparater"</string>
<string name="bluetooth_pairing_accept" msgid="6163520056536604875">"Par"</string>
<string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"ACCEPTÉR PARRING"</string>
<string name="bluetooth_pairing_decline" msgid="4185420413578948140">"Annuller"</string>
@@ -136,6 +136,7 @@
<string name="process_kernel_label" msgid="3916858646836739323">"Android OS"</string>
<string name="data_usage_uninstalled_apps" msgid="614263770923231598">"Fjernede apps"</string>
<string name="data_usage_uninstalled_apps_users" msgid="7986294489899813194">"Fjernede apps og brugere"</string>
+ <string name="data_usage_ota" msgid="5377889154805560860">"Systemopdateringer"</string>
<string name="tether_settings_title_usb" msgid="6688416425801386511">"Netdeling via USB"</string>
<string name="tether_settings_title_wifi" msgid="3277144155960302049">"Hotspot"</string>
<string name="tether_settings_title_bluetooth" msgid="355855408317564420">"Netdeling via Bluetooth"</string>
diff --git a/packages/SettingsLib/res/values-de/strings.xml b/packages/SettingsLib/res/values-de/strings.xml
index 543e8f86ee71..c1d502e30717 100644
--- a/packages/SettingsLib/res/values-de/strings.xml
+++ b/packages/SettingsLib/res/values-de/strings.xml
@@ -87,8 +87,8 @@
<string name="bluetooth_profile_sap" msgid="5764222021851283125">"Zugriff auf SIM"</string>
<string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"HD-Audio: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
<string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"HD-Audio"</string>
- <string name="bluetooth_profile_hearing_aid" msgid="7999237886427812595">"Hörhilfe"</string>
- <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="7188282786730266159">"Mit Hörhilfe verbunden"</string>
+ <string name="bluetooth_profile_hearing_aid" msgid="6680721080542444257">"Hörhilfen"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="3051944447369418317">"Mit Hörhilfen verbunden"</string>
<string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"Verbunden mit Medien-Audio"</string>
<string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"Verbunden mit Telefon-Audio"</string>
<string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"Mit Dateiübertragungsserver verbunden"</string>
@@ -105,7 +105,7 @@
<string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"Für Telefon-Audio verwenden"</string>
<string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"Für Dateiübertragung verwenden"</string>
<string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"Für Eingabe verwenden"</string>
- <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="908775281788309484">"Für Hörhilfe verwenden"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="8843499209204010224">"Für Hörhilfen verwenden"</string>
<string name="bluetooth_pairing_accept" msgid="6163520056536604875">"Koppeln"</string>
<string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"KOPPELN"</string>
<string name="bluetooth_pairing_decline" msgid="4185420413578948140">"Abbrechen"</string>
@@ -136,6 +136,7 @@
<string name="process_kernel_label" msgid="3916858646836739323">"Android OS"</string>
<string name="data_usage_uninstalled_apps" msgid="614263770923231598">"Entfernte Apps"</string>
<string name="data_usage_uninstalled_apps_users" msgid="7986294489899813194">"Entfernte Apps und Nutzer"</string>
+ <string name="data_usage_ota" msgid="5377889154805560860">"Systemupdates"</string>
<string name="tether_settings_title_usb" msgid="6688416425801386511">"USB-Tethering"</string>
<string name="tether_settings_title_wifi" msgid="3277144155960302049">"Mobiler Hotspot"</string>
<string name="tether_settings_title_bluetooth" msgid="355855408317564420">"Bluetooth-Tethering"</string>
diff --git a/packages/SettingsLib/res/values-el/strings.xml b/packages/SettingsLib/res/values-el/strings.xml
index f7ec12be8651..22c1b26dc2fa 100644
--- a/packages/SettingsLib/res/values-el/strings.xml
+++ b/packages/SettingsLib/res/values-el/strings.xml
@@ -87,8 +87,8 @@
<string name="bluetooth_profile_sap" msgid="5764222021851283125">"Πρόσβαση SIM"</string>
<string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"Ήχος HD: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
<string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"Ήχος HD"</string>
- <string name="bluetooth_profile_hearing_aid" msgid="7999237886427812595">"Βοήθημα ακοής"</string>
- <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="7188282786730266159">"Συνδέθηκε σε βοήθημα ακοής"</string>
+ <string name="bluetooth_profile_hearing_aid" msgid="6680721080542444257">"Βοηθήματα ακοής"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="3051944447369418317">"Έγινε σύνδεση σε βοηθήματα ακοής"</string>
<string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"Συνδέθηκε σε ήχο πολυμέσων"</string>
<string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"Συνδεδεμένο στον ήχο τηλεφώνου"</string>
<string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"Συνδεδεμένο σε διακομιστή μεταφοράς αρχείων"</string>
@@ -105,7 +105,7 @@
<string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"Χρήση για ήχο τηλεφώνου"</string>
<string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"Χρήση για τη μεταφορά αρχείων"</string>
<string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"Χρήση για είσοδο"</string>
- <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="908775281788309484">"Χρήση για βοήθημα ακοής"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="8843499209204010224">"Χρήση για βοηθήματα ακοής"</string>
<string name="bluetooth_pairing_accept" msgid="6163520056536604875">"Σύζευξη"</string>
<string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"ΣΥΖΕΥΞΗ"</string>
<string name="bluetooth_pairing_decline" msgid="4185420413578948140">"Ακύρωση"</string>
@@ -136,6 +136,7 @@
<string name="process_kernel_label" msgid="3916858646836739323">"Λειτουργικό σύστημα Android"</string>
<string name="data_usage_uninstalled_apps" msgid="614263770923231598">"Εφαρμογές που καταργήθηκαν"</string>
<string name="data_usage_uninstalled_apps_users" msgid="7986294489899813194">"Εφαρμογές και χρήστες που έχουν καταργηθεί"</string>
+ <string name="data_usage_ota" msgid="5377889154805560860">"Ενημερώσεις συστήματος"</string>
<string name="tether_settings_title_usb" msgid="6688416425801386511">"Πρόσδεση USB"</string>
<string name="tether_settings_title_wifi" msgid="3277144155960302049">"Φορητό σημείο πρόσβασης"</string>
<string name="tether_settings_title_bluetooth" msgid="355855408317564420">"Πρόσδεση Bluetooth"</string>
diff --git a/packages/SettingsLib/res/values-en-rAU/strings.xml b/packages/SettingsLib/res/values-en-rAU/strings.xml
index b9d309398d67..d4f4e5e1104a 100644
--- a/packages/SettingsLib/res/values-en-rAU/strings.xml
+++ b/packages/SettingsLib/res/values-en-rAU/strings.xml
@@ -87,8 +87,8 @@
<string name="bluetooth_profile_sap" msgid="5764222021851283125">"SIM Access"</string>
<string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"HD audio: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
<string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"HD audio"</string>
- <string name="bluetooth_profile_hearing_aid" msgid="7999237886427812595">"Hearing Aid"</string>
- <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="7188282786730266159">"Connected to Hearing Aid"</string>
+ <string name="bluetooth_profile_hearing_aid" msgid="6680721080542444257">"Hearing Aids"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="3051944447369418317">"Connected to Hearing Aids"</string>
<string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"Connected to media audio"</string>
<string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"Connected to phone audio"</string>
<string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"Connected to file-transfer server"</string>
@@ -105,7 +105,7 @@
<string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"Use for phone audio"</string>
<string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"Use for file transfer"</string>
<string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"Use for input"</string>
- <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="908775281788309484">"Use for Hearing Aid"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="8843499209204010224">"Use for Hearing Aids"</string>
<string name="bluetooth_pairing_accept" msgid="6163520056536604875">"Pair"</string>
<string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"PAIR"</string>
<string name="bluetooth_pairing_decline" msgid="4185420413578948140">"Cancel"</string>
@@ -136,6 +136,7 @@
<string name="process_kernel_label" msgid="3916858646836739323">"Android OS"</string>
<string name="data_usage_uninstalled_apps" msgid="614263770923231598">"Removed apps"</string>
<string name="data_usage_uninstalled_apps_users" msgid="7986294489899813194">"Removed apps and users"</string>
+ <string name="data_usage_ota" msgid="5377889154805560860">"System updates"</string>
<string name="tether_settings_title_usb" msgid="6688416425801386511">"USB tethering"</string>
<string name="tether_settings_title_wifi" msgid="3277144155960302049">"Portable hotspot"</string>
<string name="tether_settings_title_bluetooth" msgid="355855408317564420">"Bluetooth tethering"</string>
diff --git a/packages/SettingsLib/res/values-en-rCA/strings.xml b/packages/SettingsLib/res/values-en-rCA/strings.xml
index b9d309398d67..d4f4e5e1104a 100644
--- a/packages/SettingsLib/res/values-en-rCA/strings.xml
+++ b/packages/SettingsLib/res/values-en-rCA/strings.xml
@@ -87,8 +87,8 @@
<string name="bluetooth_profile_sap" msgid="5764222021851283125">"SIM Access"</string>
<string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"HD audio: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
<string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"HD audio"</string>
- <string name="bluetooth_profile_hearing_aid" msgid="7999237886427812595">"Hearing Aid"</string>
- <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="7188282786730266159">"Connected to Hearing Aid"</string>
+ <string name="bluetooth_profile_hearing_aid" msgid="6680721080542444257">"Hearing Aids"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="3051944447369418317">"Connected to Hearing Aids"</string>
<string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"Connected to media audio"</string>
<string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"Connected to phone audio"</string>
<string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"Connected to file-transfer server"</string>
@@ -105,7 +105,7 @@
<string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"Use for phone audio"</string>
<string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"Use for file transfer"</string>
<string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"Use for input"</string>
- <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="908775281788309484">"Use for Hearing Aid"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="8843499209204010224">"Use for Hearing Aids"</string>
<string name="bluetooth_pairing_accept" msgid="6163520056536604875">"Pair"</string>
<string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"PAIR"</string>
<string name="bluetooth_pairing_decline" msgid="4185420413578948140">"Cancel"</string>
@@ -136,6 +136,7 @@
<string name="process_kernel_label" msgid="3916858646836739323">"Android OS"</string>
<string name="data_usage_uninstalled_apps" msgid="614263770923231598">"Removed apps"</string>
<string name="data_usage_uninstalled_apps_users" msgid="7986294489899813194">"Removed apps and users"</string>
+ <string name="data_usage_ota" msgid="5377889154805560860">"System updates"</string>
<string name="tether_settings_title_usb" msgid="6688416425801386511">"USB tethering"</string>
<string name="tether_settings_title_wifi" msgid="3277144155960302049">"Portable hotspot"</string>
<string name="tether_settings_title_bluetooth" msgid="355855408317564420">"Bluetooth tethering"</string>
diff --git a/packages/SettingsLib/res/values-en-rGB/strings.xml b/packages/SettingsLib/res/values-en-rGB/strings.xml
index b9d309398d67..d4f4e5e1104a 100644
--- a/packages/SettingsLib/res/values-en-rGB/strings.xml
+++ b/packages/SettingsLib/res/values-en-rGB/strings.xml
@@ -87,8 +87,8 @@
<string name="bluetooth_profile_sap" msgid="5764222021851283125">"SIM Access"</string>
<string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"HD audio: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
<string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"HD audio"</string>
- <string name="bluetooth_profile_hearing_aid" msgid="7999237886427812595">"Hearing Aid"</string>
- <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="7188282786730266159">"Connected to Hearing Aid"</string>
+ <string name="bluetooth_profile_hearing_aid" msgid="6680721080542444257">"Hearing Aids"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="3051944447369418317">"Connected to Hearing Aids"</string>
<string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"Connected to media audio"</string>
<string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"Connected to phone audio"</string>
<string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"Connected to file-transfer server"</string>
@@ -105,7 +105,7 @@
<string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"Use for phone audio"</string>
<string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"Use for file transfer"</string>
<string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"Use for input"</string>
- <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="908775281788309484">"Use for Hearing Aid"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="8843499209204010224">"Use for Hearing Aids"</string>
<string name="bluetooth_pairing_accept" msgid="6163520056536604875">"Pair"</string>
<string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"PAIR"</string>
<string name="bluetooth_pairing_decline" msgid="4185420413578948140">"Cancel"</string>
@@ -136,6 +136,7 @@
<string name="process_kernel_label" msgid="3916858646836739323">"Android OS"</string>
<string name="data_usage_uninstalled_apps" msgid="614263770923231598">"Removed apps"</string>
<string name="data_usage_uninstalled_apps_users" msgid="7986294489899813194">"Removed apps and users"</string>
+ <string name="data_usage_ota" msgid="5377889154805560860">"System updates"</string>
<string name="tether_settings_title_usb" msgid="6688416425801386511">"USB tethering"</string>
<string name="tether_settings_title_wifi" msgid="3277144155960302049">"Portable hotspot"</string>
<string name="tether_settings_title_bluetooth" msgid="355855408317564420">"Bluetooth tethering"</string>
diff --git a/packages/SettingsLib/res/values-en-rIN/strings.xml b/packages/SettingsLib/res/values-en-rIN/strings.xml
index b9d309398d67..d4f4e5e1104a 100644
--- a/packages/SettingsLib/res/values-en-rIN/strings.xml
+++ b/packages/SettingsLib/res/values-en-rIN/strings.xml
@@ -87,8 +87,8 @@
<string name="bluetooth_profile_sap" msgid="5764222021851283125">"SIM Access"</string>
<string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"HD audio: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
<string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"HD audio"</string>
- <string name="bluetooth_profile_hearing_aid" msgid="7999237886427812595">"Hearing Aid"</string>
- <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="7188282786730266159">"Connected to Hearing Aid"</string>
+ <string name="bluetooth_profile_hearing_aid" msgid="6680721080542444257">"Hearing Aids"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="3051944447369418317">"Connected to Hearing Aids"</string>
<string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"Connected to media audio"</string>
<string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"Connected to phone audio"</string>
<string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"Connected to file-transfer server"</string>
@@ -105,7 +105,7 @@
<string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"Use for phone audio"</string>
<string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"Use for file transfer"</string>
<string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"Use for input"</string>
- <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="908775281788309484">"Use for Hearing Aid"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="8843499209204010224">"Use for Hearing Aids"</string>
<string name="bluetooth_pairing_accept" msgid="6163520056536604875">"Pair"</string>
<string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"PAIR"</string>
<string name="bluetooth_pairing_decline" msgid="4185420413578948140">"Cancel"</string>
@@ -136,6 +136,7 @@
<string name="process_kernel_label" msgid="3916858646836739323">"Android OS"</string>
<string name="data_usage_uninstalled_apps" msgid="614263770923231598">"Removed apps"</string>
<string name="data_usage_uninstalled_apps_users" msgid="7986294489899813194">"Removed apps and users"</string>
+ <string name="data_usage_ota" msgid="5377889154805560860">"System updates"</string>
<string name="tether_settings_title_usb" msgid="6688416425801386511">"USB tethering"</string>
<string name="tether_settings_title_wifi" msgid="3277144155960302049">"Portable hotspot"</string>
<string name="tether_settings_title_bluetooth" msgid="355855408317564420">"Bluetooth tethering"</string>
diff --git a/packages/SettingsLib/res/values-en-rXC/strings.xml b/packages/SettingsLib/res/values-en-rXC/strings.xml
index 2d3e8301cb1e..98b63eec19dc 100644
--- a/packages/SettingsLib/res/values-en-rXC/strings.xml
+++ b/packages/SettingsLib/res/values-en-rXC/strings.xml
@@ -87,8 +87,8 @@
<string name="bluetooth_profile_sap" msgid="5764222021851283125">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‎‎‏‏‏‏‏‏‏‏‏‏‏‎‏‎‏‎‎‎‎‏‎‏‏‎‎‎‏‏‏‎‎‎‎‎‏‎‏‏‏‎‏‏‎‏‏‏‏‏‏‏‏‎‏‎‏‏‎‏‎‏‎SIM Access‎‏‎‎‏‎"</string>
<string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‎‎‏‎‏‏‏‎‎‎‏‏‏‎‏‏‎‏‎‎‎‎‎‎‎‏‏‎‎‎‎‎‎‏‏‎‏‎‎‎‎‏‎‏‎‎‎‎‎‎‎‎‏‏‎‏‎‏‎‏‏‏‎HD audio: ‎‏‎‎‏‏‎<xliff:g id="CODEC_NAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
<string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‏‏‎‏‏‎‎‎‎‏‏‎‏‏‏‎‏‎‏‏‏‎‏‎‏‏‏‏‏‎‎‎‎‏‏‏‎‏‏‏‏‎‎‏‏‏‏‏‏‎‎‎‎‎‎‎‏‎‎‏‏‏‎HD audio‎‏‎‎‏‎"</string>
- <string name="bluetooth_profile_hearing_aid" msgid="7999237886427812595">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‏‎‏‏‏‏‎‎‎‎‎‎‏‏‎‎‎‎‎‎‎‎‎‏‏‏‏‎‎‏‏‏‎‏‎‏‏‎‎‏‏‎‎‎‎‎‎‏‎‏‎‎‏‎‏‏‏‏‎‎‏‏‎Hearing Aid‎‏‎‎‏‎"</string>
- <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="7188282786730266159">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‏‎‎‎‏‏‏‏‎‎‎‎‎‏‏‏‏‎‏‎‎‏‎‎‎‏‏‏‎‎‎‎‎‎‎‎‎‎‎‎‎‏‏‏‎‎‏‏‎‎‏‏‏‎‎‎‏‎‏‏‏‏‎Connected to Hearing Aid‎‏‎‎‏‎"</string>
+ <string name="bluetooth_profile_hearing_aid" msgid="6680721080542444257">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‎‏‏‏‎‎‏‎‏‏‎‏‏‎‏‎‏‏‎‎‎‎‎‏‏‎‏‏‎‏‎‏‎‎‎‎‎‏‎‎‏‏‎‎‏‎‎‎‏‏‏‎‏‎‏‏‏‎‎‎‎‏‎Hearing Aids‎‏‎‎‏‎"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="3051944447369418317">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‎‏‎‏‎‏‎‎‏‎‏‏‎‏‎‏‎‏‎‏‏‏‏‎‏‎‎‏‏‏‎‎‎‎‏‎‎‏‏‏‎‏‎‏‏‏‎‎‎‎‏‎‏‏‎‎‏‎‎‏‏‎‏‎Connected to Hearing Aids‎‏‎‎‏‎"</string>
<string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‎‎‏‏‎‏‎‏‎‏‏‏‏‎‏‎‎‏‏‎‎‏‎‏‏‏‎‎‎‏‎‎‎‏‏‎‎‏‏‏‎‏‎‏‏‎‏‎‏‏‏‎‎‏‎‏‏‏‏‏‏‎‎Connected to media audio‎‏‎‎‏‎"</string>
<string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‏‎‏‎‏‎‎‏‎‏‎‎‎‏‏‎‎‏‎‏‏‎‏‏‎‎‎‎‏‏‎‏‎‎‏‏‏‎‏‎‎‏‏‎‏‏‎‏‏‎‎‏‏‎‏‎‎‏‏‏‏‏‎Connected to phone audio‎‏‎‎‏‎"</string>
<string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‎‎‎‏‎‏‏‏‏‏‎‎‎‏‏‎‏‏‏‏‎‎‏‏‏‏‎‏‎‏‎‏‏‏‏‏‎‏‎‎‏‎‏‎‎Connected to file transfer server‎‏‎‎‏‎"</string>
@@ -105,7 +105,7 @@
<string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‏‏‏‎‎‎‏‏‎‏‎‎‎‏‎‎‎‎‏‏‎‎‏‏‎‎‏‎‏‏‎‏‏‎‎‏‏‏‏‏‎‏‎‏‏‎‎‎‏‎‏‎‏‎‎‏‏‎‎‎‏‏‎Use for phone audio‎‏‎‎‏‎"</string>
<string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‎‏‏‎‎‎‏‎‏‏‎‏‏‎‏‎‎‎‎‏‏‎‏‎‏‎‏‏‎‎‏‎‎‎‎‏‎‎‎‎‎‎‏‎‎‎‎‎‏‎‎‎‎‎‎‏‏‎‏‏‏‎‎‎Use for file transfer‎‏‎‎‏‎"</string>
<string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‎‏‎‏‏‎‎‏‏‏‎‏‎‏‏‎‏‎‎‎‎‎‎‎‎‎‎‏‎‏‎‎‏‏‏‏‏‏‏‎‏‏‏‏‎‎‎‎‏‎‎‏‏‎‏‎‏‎‎‏‏‎Use for input‎‏‎‎‏‎"</string>
- <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="908775281788309484">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‎‎‏‏‎‎‏‎‎‏‏‏‎‎‏‎‎‏‏‏‏‎‎‏‎‎‏‏‎‏‏‏‎‎‏‎‏‏‏‎‏‎‎‏‎‏‏‏‎‎‏‏‏‏‏‏‏‎‏‏‎‎‎Use for Hearing Aid‎‏‎‎‏‎"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="8843499209204010224">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‏‏‏‎‏‎‏‎‏‏‏‎‏‎‎‏‏‎‏‎‏‏‏‎‏‎‏‏‎‏‎‎‎‎‏‎‎‎‎‎‎‎‏‏‎‏‏‎‎‎‏‏‎‎‏‏‏‏‎‎‎‎‎Use for Hearing Aids‎‏‎‎‏‎"</string>
<string name="bluetooth_pairing_accept" msgid="6163520056536604875">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‎‏‎‏‎‏‏‎‎‎‏‎‎‏‎‎‏‏‏‎‎‎‏‏‎‏‎‏‎‏‏‏‏‎‏‏‏‏‏‏‎‏‏‏‎‎‎‎‏‎‎‎‎‎‏‏‎‎‏‎‏‏‎Pair‎‏‎‎‏‎"</string>
<string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‎‏‎‏‎‎‎‎‎‏‏‏‏‏‎‏‏‏‏‎‏‏‎‏‎‏‏‏‎‏‏‎‎‎‏‏‏‎‏‎‏‏‏‎‏‏‎‏‎‎‎‎‏‏‏‎‎‏‏‏‎‏‎PAIR‎‏‎‎‏‎"</string>
<string name="bluetooth_pairing_decline" msgid="4185420413578948140">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‎‏‏‏‎‏‎‎‎‎‏‎‏‎‏‏‎‎‏‏‎‎‏‏‎‏‏‎‎‎‎‏‏‎‏‏‎‏‏‎‎‎‎‏‎‏‎‏‎‏‎‏‏‏‎‎‎‏‎‏‏‎‎‎Cancel‎‏‎‎‏‎"</string>
@@ -136,6 +136,7 @@
<string name="process_kernel_label" msgid="3916858646836739323">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‎‏‏‎‏‏‎‎‏‎‏‏‎‏‏‎‏‏‏‏‎‏‎‎‎‏‎‏‏‏‏‏‏‎‏‏‎‎‎‎‎‎‏‏‏‏‎‏‏‏‏‏‏‎‎‏‏‏‏‏‎‏‏‎Android OS‎‏‎‎‏‎"</string>
<string name="data_usage_uninstalled_apps" msgid="614263770923231598">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‎‎‏‎‎‎‏‎‎‎‎‏‏‎‎‏‎‎‏‏‎‏‏‎‏‎‎‏‎‏‎‎‏‎‏‎‎‎‎‏‎‎‎‏‎‏‎‏‏‎‏‎‎‏‎‏‏‎‏‏‏‎‎Removed apps‎‏‎‎‏‎"</string>
<string name="data_usage_uninstalled_apps_users" msgid="7986294489899813194">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‏‎‏‏‏‎‏‏‎‏‎‏‎‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‎‎‏‏‏‏‏‏‎‎‎‏‎‎‎‏‏‎‏‎‎‏‎‎‏‎‏‎‎‏‎‏‎‎Removed apps and users‎‏‎‎‏‎"</string>
+ <string name="data_usage_ota" msgid="5377889154805560860">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‎‎‏‎‏‎‏‎‏‎‎‎‏‎‎‎‎‏‏‎‎‏‏‎‏‏‎‎‎‏‎‏‏‎‏‎‎‏‏‎‎‏‏‏‎‎‎‏‏‏‎‏‏‎‎‎‎‏‏‏‎‎‎System updates‎‏‎‎‏‎"</string>
<string name="tether_settings_title_usb" msgid="6688416425801386511">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‎‏‏‏‎‎‏‏‎‏‎‎‏‎‎‎‎‎‎‏‏‏‎‏‎‎‏‏‎‏‎‏‏‏‎‎‎‏‏‏‎‎‎‏‏‏‏‎‎‎‏‎‏‎‎‎‎‎‏‏‏‏‎USB tethering‎‏‎‎‏‎"</string>
<string name="tether_settings_title_wifi" msgid="3277144155960302049">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‎‏‎‏‏‎‏‎‏‏‏‏‎‏‎‏‏‎‎‎‎‎‏‎‎‏‏‏‏‏‏‎‎‏‎‏‏‎‏‏‏‎‎‎‎‏‎‏‏‎‏‏‎‎‏‏‏‏‎‎‎‎‏‎Portable hotspot‎‏‎‎‏‎"</string>
<string name="tether_settings_title_bluetooth" msgid="355855408317564420">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‎‏‏‏‎‎‏‏‏‏‎‎‎‎‎‏‎‎‎‎‎‎‏‎‎‏‏‎‏‏‏‏‎‎‎‏‎‎‎‎‏‎‏‎‏‏‏‎‎‎‎‏‏‎‎‎‎‎‎‏‎‎‎Bluetooth tethering‎‏‎‎‏‎"</string>
diff --git a/packages/SettingsLib/res/values-es-rUS/strings.xml b/packages/SettingsLib/res/values-es-rUS/strings.xml
index 00f85e665112..e803abdac612 100644
--- a/packages/SettingsLib/res/values-es-rUS/strings.xml
+++ b/packages/SettingsLib/res/values-es-rUS/strings.xml
@@ -87,8 +87,8 @@
<string name="bluetooth_profile_sap" msgid="5764222021851283125">"Acceso SIM"</string>
<string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"Audio en HD: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
<string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"Audio en HD"</string>
- <string name="bluetooth_profile_hearing_aid" msgid="7999237886427812595">"Audífonos"</string>
- <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="7188282786730266159">"Conectado a un audífono"</string>
+ <string name="bluetooth_profile_hearing_aid" msgid="6680721080542444257">"Audífonos"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="3051944447369418317">"Conectado a audífonos"</string>
<string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"Conectado al audio multimedia"</string>
<string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"Conectado al audio del dispositivo"</string>
<string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"Conectado al servidor de transferencia de archivo"</string>
@@ -105,7 +105,7 @@
<string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"Utilizar para el audio del dispositivo"</string>
<string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"Utilizar para la transferencia de archivos"</string>
<string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"Utilizar para entrada"</string>
- <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="908775281788309484">"Usar con audífonos"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="8843499209204010224">"Usar para audífonos"</string>
<string name="bluetooth_pairing_accept" msgid="6163520056536604875">"Vincular"</string>
<string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"SINCRONIZAR"</string>
<string name="bluetooth_pairing_decline" msgid="4185420413578948140">"Cancelar"</string>
@@ -136,6 +136,7 @@
<string name="process_kernel_label" msgid="3916858646836739323">"SO Android"</string>
<string name="data_usage_uninstalled_apps" msgid="614263770923231598">"Aplicaciones eliminadas"</string>
<string name="data_usage_uninstalled_apps_users" msgid="7986294489899813194">"Aplicaciones y usuarios eliminados"</string>
+ <string name="data_usage_ota" msgid="5377889154805560860">"Actualizaciones del sistema"</string>
<string name="tether_settings_title_usb" msgid="6688416425801386511">"Conexión mediante USB"</string>
<string name="tether_settings_title_wifi" msgid="3277144155960302049">"Hotspot portátil"</string>
<string name="tether_settings_title_bluetooth" msgid="355855408317564420">"Conexión mediante Bluetooth"</string>
diff --git a/packages/SettingsLib/res/values-es/strings.xml b/packages/SettingsLib/res/values-es/strings.xml
index b21b7d1ead5f..293eff121b2a 100644
--- a/packages/SettingsLib/res/values-es/strings.xml
+++ b/packages/SettingsLib/res/values-es/strings.xml
@@ -87,8 +87,8 @@
<string name="bluetooth_profile_sap" msgid="5764222021851283125">"Acceso a tarjeta SIM"</string>
<string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"Audio HD: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
<string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"Audio HD"</string>
- <string name="bluetooth_profile_hearing_aid" msgid="7999237886427812595">"Audífonos"</string>
- <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="7188282786730266159">"Conectado a audífono"</string>
+ <string name="bluetooth_profile_hearing_aid" msgid="6680721080542444257">"Audífonos"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="3051944447369418317">"Conectado a audífonos"</string>
<string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"Conectado al audio del medio"</string>
<string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"Conectado al audio del teléfono"</string>
<string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"Conectado con el servidor de transferencia de archivos"</string>
@@ -105,7 +105,7 @@
<string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"Utilizar para audio del teléfono"</string>
<string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"Uso de la transferencia de archivos"</string>
<string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"Usar para entrada"</string>
- <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="908775281788309484">"Usar con audífonos"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="8843499209204010224">"Usar con audífonos"</string>
<string name="bluetooth_pairing_accept" msgid="6163520056536604875">"Vincular"</string>
<string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"VINCULAR"</string>
<string name="bluetooth_pairing_decline" msgid="4185420413578948140">"Cancelar"</string>
@@ -136,6 +136,7 @@
<string name="process_kernel_label" msgid="3916858646836739323">"SO Android"</string>
<string name="data_usage_uninstalled_apps" msgid="614263770923231598">"Aplicaciones eliminadas"</string>
<string name="data_usage_uninstalled_apps_users" msgid="7986294489899813194">"Usuarios y aplicaciones eliminados"</string>
+ <string name="data_usage_ota" msgid="5377889154805560860">"Actualizaciones del sistema"</string>
<string name="tether_settings_title_usb" msgid="6688416425801386511">"Compartir conexión por USB"</string>
<string name="tether_settings_title_wifi" msgid="3277144155960302049">"Zona Wi-Fi portátil"</string>
<string name="tether_settings_title_bluetooth" msgid="355855408317564420">"Compartir conexión por Bluetooth"</string>
diff --git a/packages/SettingsLib/res/values-et/strings.xml b/packages/SettingsLib/res/values-et/strings.xml
index fab137519725..14ac8272432f 100644
--- a/packages/SettingsLib/res/values-et/strings.xml
+++ b/packages/SettingsLib/res/values-et/strings.xml
@@ -87,8 +87,8 @@
<string name="bluetooth_profile_sap" msgid="5764222021851283125">"SIM-kaardi juurdepääs"</string>
<string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"HD-heli: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
<string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"HD-heli"</string>
- <string name="bluetooth_profile_hearing_aid" msgid="7999237886427812595">"Kuuldeaparaat"</string>
- <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="7188282786730266159">"Kuuldeaparaadiga ühendatud"</string>
+ <string name="bluetooth_profile_hearing_aid" msgid="6680721080542444257">"Kuuldeaparaadid"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="3051944447369418317">"Kuuldeaparaatidega ühendatud"</string>
<string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"Ühendatud meediumiheliga"</string>
<string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"Ühendatud telefoniheliga"</string>
<string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"Ühendatud failiedastuse serveriga"</string>
@@ -105,7 +105,7 @@
<string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"Kasuta telefoniheli jaoks"</string>
<string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"Kasutage failide edastamiseks"</string>
<string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"Kasutage sisendi jaoks"</string>
- <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="908775281788309484">"Kuuldeaparaadiga kasutamiseks"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="8843499209204010224">"Kasuta kuulmisaparaatide puhul"</string>
<string name="bluetooth_pairing_accept" msgid="6163520056536604875">"Seo"</string>
<string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"SEO"</string>
<string name="bluetooth_pairing_decline" msgid="4185420413578948140">"Tühista"</string>
@@ -136,6 +136,7 @@
<string name="process_kernel_label" msgid="3916858646836739323">"Android OS"</string>
<string name="data_usage_uninstalled_apps" msgid="614263770923231598">"Eemaldatud rakendused"</string>
<string name="data_usage_uninstalled_apps_users" msgid="7986294489899813194">"Eemaldatud rakendused ja kasutajad"</string>
+ <string name="data_usage_ota" msgid="5377889154805560860">"Süsteemivärskendused"</string>
<string name="tether_settings_title_usb" msgid="6688416425801386511">"USB jagamine"</string>
<string name="tether_settings_title_wifi" msgid="3277144155960302049">"Mobiilne kuumkoht"</string>
<string name="tether_settings_title_bluetooth" msgid="355855408317564420">"Jagamine Bluetoothiga"</string>
diff --git a/packages/SettingsLib/res/values-eu/strings.xml b/packages/SettingsLib/res/values-eu/strings.xml
index 7d3e1f3049da..04710c7bb0cb 100644
--- a/packages/SettingsLib/res/values-eu/strings.xml
+++ b/packages/SettingsLib/res/values-eu/strings.xml
@@ -87,8 +87,8 @@
<string name="bluetooth_profile_sap" msgid="5764222021851283125">"SIM txartelerako sarbidea"</string>
<string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"Kalitate handiko audioa: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
<string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"Kalitate handiko audioa"</string>
- <string name="bluetooth_profile_hearing_aid" msgid="7999237886427812595">"Audiofonoa"</string>
- <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="7188282786730266159">"Audiofonora konektatuta"</string>
+ <string name="bluetooth_profile_hearing_aid" msgid="6680721080542444257">"Audifonoak"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="3051944447369418317">"Audifonoetara konektatuta"</string>
<string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"Euskarriaren audiora konektatuta"</string>
<string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"Telefonoaren audiora konektatuta"</string>
<string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"Fitxategi-transferentziako zerbitzarira konektatuta"</string>
@@ -105,7 +105,7 @@
<string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"Erabili telefonoaren audiorako"</string>
<string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"Erabili fitxategi-transferentziarako"</string>
<string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"Erabili idazketarako"</string>
- <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="908775281788309484">"Erabili audiofonorako"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="8843499209204010224">"Erabili audifonoak"</string>
<string name="bluetooth_pairing_accept" msgid="6163520056536604875">"Parekatu"</string>
<string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"PAREKATU"</string>
<string name="bluetooth_pairing_decline" msgid="4185420413578948140">"Utzi"</string>
@@ -121,8 +121,8 @@
<string name="bluetooth_talkback_headphone" msgid="26580326066627664">"Aurikularra"</string>
<string name="bluetooth_talkback_input_peripheral" msgid="5165842622743212268">"Idazteko gailua"</string>
<string name="bluetooth_talkback_bluetooth" msgid="5615463912185280812">"Bluetooth gailua"</string>
- <string name="bluetooth_hearingaid_left_pairing_message" msgid="7378813500862148102">"Ezkerreko audiofonoa parekatzen…"</string>
- <string name="bluetooth_hearingaid_right_pairing_message" msgid="1550373802309160891">"Eskuineko audiofonoa parekatzen…"</string>
+ <string name="bluetooth_hearingaid_left_pairing_message" msgid="7378813500862148102">"Ezkerreko audifonoa parekatzen…"</string>
+ <string name="bluetooth_hearingaid_right_pairing_message" msgid="1550373802309160891">"Eskuineko audifonoa parekatzen…"</string>
<string name="bluetooth_hearingaid_left_battery_level" msgid="8797811465352097562">"Ezkerrekoa. Bateria: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="bluetooth_hearingaid_right_battery_level" msgid="7309476148173459677">"Eskuinekoa. Bateria: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="accessibility_wifi_off" msgid="1166761729660614716">"Desaktibatuta dago Wi-Fi konexioa."</string>
@@ -136,6 +136,7 @@
<string name="process_kernel_label" msgid="3916858646836739323">"Android sistema eragilea"</string>
<string name="data_usage_uninstalled_apps" msgid="614263770923231598">"Kendutako aplikazioak"</string>
<string name="data_usage_uninstalled_apps_users" msgid="7986294489899813194">"Kendutako aplikazioak eta erabiltzaileak"</string>
+ <string name="data_usage_ota" msgid="5377889154805560860">"Sistemaren eguneratzeak"</string>
<string name="tether_settings_title_usb" msgid="6688416425801386511">"Konexioa partekatzea (USB)"</string>
<string name="tether_settings_title_wifi" msgid="3277144155960302049">"Sare publiko eramangarria"</string>
<string name="tether_settings_title_bluetooth" msgid="355855408317564420">"Konexioa partekatzea (Bluetooth)"</string>
diff --git a/packages/SettingsLib/res/values-fa/strings.xml b/packages/SettingsLib/res/values-fa/strings.xml
index 293c463334fd..8f5509255f51 100644
--- a/packages/SettingsLib/res/values-fa/strings.xml
+++ b/packages/SettingsLib/res/values-fa/strings.xml
@@ -87,8 +87,8 @@
<string name="bluetooth_profile_sap" msgid="5764222021851283125">"دسترسی سیم‌کارت"</string>
<string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"‏صدای HD: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
<string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"‏صدای HD"</string>
- <string name="bluetooth_profile_hearing_aid" msgid="7999237886427812595">"سمعک"</string>
- <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="7188282786730266159">"متصل به سمعک"</string>
+ <string name="bluetooth_profile_hearing_aid" msgid="6680721080542444257">"سمعک‌ها"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="3051944447369418317">"متصل به سمعک‌ها"</string>
<string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"به رسانه صوتی متصل شد"</string>
<string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"به تلفن صوتی متصل شد"</string>
<string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"به سرور انتقال فایل متصل شد"</string>
@@ -105,7 +105,7 @@
<string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"استفاده برای تلفن صوتی"</string>
<string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"استفاده برای انتقال فایل"</string>
<string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"استفاده برای چاپ"</string>
- <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="908775281788309484">"استفاده برای سمعک"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="8843499209204010224">"استفاده برای سمعک‌ها"</string>
<string name="bluetooth_pairing_accept" msgid="6163520056536604875">"مرتبط‌سازی"</string>
<string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"مرتبط‌سازی"</string>
<string name="bluetooth_pairing_decline" msgid="4185420413578948140">"لغو"</string>
@@ -136,6 +136,7 @@
<string name="process_kernel_label" msgid="3916858646836739323">"‏سیستم عامل Android"</string>
<string name="data_usage_uninstalled_apps" msgid="614263770923231598">"برنامه‌های حذف شده"</string>
<string name="data_usage_uninstalled_apps_users" msgid="7986294489899813194">"برنامه‌ها و کاربران حذف شده"</string>
+ <string name="data_usage_ota" msgid="5377889154805560860">"به‌روزرسانی‌های سیستم"</string>
<string name="tether_settings_title_usb" msgid="6688416425801386511">"‏اتصال داده با سیم USB"</string>
<string name="tether_settings_title_wifi" msgid="3277144155960302049">"نقطه اتصال قابل حمل"</string>
<string name="tether_settings_title_bluetooth" msgid="355855408317564420">"اتصال اینترنت با تلفن همراه بلوتوث"</string>
diff --git a/packages/SettingsLib/res/values-fi/strings.xml b/packages/SettingsLib/res/values-fi/strings.xml
index f335eb930c1c..5802a03f1070 100644
--- a/packages/SettingsLib/res/values-fi/strings.xml
+++ b/packages/SettingsLib/res/values-fi/strings.xml
@@ -87,8 +87,8 @@
<string name="bluetooth_profile_sap" msgid="5764222021851283125">"SIM-kortin käyttö"</string>
<string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"HD-ääni: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
<string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"HD-ääni"</string>
- <string name="bluetooth_profile_hearing_aid" msgid="7999237886427812595">"Kuulolaite"</string>
- <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="7188282786730266159">"Kuulolaite yhdistetty"</string>
+ <string name="bluetooth_profile_hearing_aid" msgid="6680721080542444257">"Kuulolaitteet"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="3051944447369418317">"Yhdistetty kuulolaitteisiin"</string>
<string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"Yhdistetty median ääneen"</string>
<string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"Yhdistetty puhelimen ääneen"</string>
<string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"Yhdistetty tiedostonsiirtopalvelimeen"</string>
@@ -105,7 +105,7 @@
<string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"Käytä puhelimen äänille"</string>
<string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"Käytä tiedostojen siirtoon"</string>
<string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"Käytä syöttöön"</string>
- <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="908775281788309484">"Käytä kuulolaitteen kanssa"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="8843499209204010224">"Käytä kuulolaitteilla"</string>
<string name="bluetooth_pairing_accept" msgid="6163520056536604875">"Muodosta laitepari"</string>
<string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"MUODOSTA LAITEPARI"</string>
<string name="bluetooth_pairing_decline" msgid="4185420413578948140">"Peruuta"</string>
@@ -136,6 +136,7 @@
<string name="process_kernel_label" msgid="3916858646836739323">"Android-käyttöjärjestelmä"</string>
<string name="data_usage_uninstalled_apps" msgid="614263770923231598">"Poistetut sovellukset"</string>
<string name="data_usage_uninstalled_apps_users" msgid="7986294489899813194">"Poistetut sovellukset ja käyttäjät"</string>
+ <string name="data_usage_ota" msgid="5377889154805560860">"Järjestelmäpäivitykset"</string>
<string name="tether_settings_title_usb" msgid="6688416425801386511">"Jaettu yhteys USB:n kautta"</string>
<string name="tether_settings_title_wifi" msgid="3277144155960302049">"Kannettava yhteyspiste"</string>
<string name="tether_settings_title_bluetooth" msgid="355855408317564420">"Jaettu Bluetooth-yhteys"</string>
diff --git a/packages/SettingsLib/res/values-fr-rCA/strings.xml b/packages/SettingsLib/res/values-fr-rCA/strings.xml
index 49591039178c..ec8d6b086418 100644
--- a/packages/SettingsLib/res/values-fr-rCA/strings.xml
+++ b/packages/SettingsLib/res/values-fr-rCA/strings.xml
@@ -87,8 +87,8 @@
<string name="bluetooth_profile_sap" msgid="5764222021851283125">"Accès à la carte SIM"</string>
<string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"Audio HD : <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
<string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"Audio HD"</string>
- <string name="bluetooth_profile_hearing_aid" msgid="7999237886427812595">"Prothèse auditive"</string>
- <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="7188282786730266159">"Connecté à la prothèse auditive"</string>
+ <string name="bluetooth_profile_hearing_aid" msgid="6680721080542444257">"Prothèses auditives"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="3051944447369418317">"Connecté aux prothèses auditives"</string>
<string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"Connecté aux paramètres audio du média"</string>
<string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"Connecté à l\'audio du téléphone"</string>
<string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"Connexion au serveur de transfert de fichiers"</string>
@@ -105,7 +105,7 @@
<string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"Utiliser pour les paramètres audio du téléphone"</string>
<string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"Utiliser pour le transfert de fichiers"</string>
<string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"Utiliser comme entrée"</string>
- <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="908775281788309484">"Utiliser avec la prothèse auditive"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="8843499209204010224">"Utiliser avec les prothèses auditives"</string>
<string name="bluetooth_pairing_accept" msgid="6163520056536604875">"Associer"</string>
<string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"ASSOCIER"</string>
<string name="bluetooth_pairing_decline" msgid="4185420413578948140">"Annuler"</string>
@@ -136,6 +136,7 @@
<string name="process_kernel_label" msgid="3916858646836739323">"Système d\'exploitation Android"</string>
<string name="data_usage_uninstalled_apps" msgid="614263770923231598">"Applications supprimées"</string>
<string name="data_usage_uninstalled_apps_users" msgid="7986294489899813194">"Applications et utilisateurs supprimés"</string>
+ <string name="data_usage_ota" msgid="5377889154805560860">"Mises à jour système"</string>
<string name="tether_settings_title_usb" msgid="6688416425801386511">"Partage de connexion par USB"</string>
<string name="tether_settings_title_wifi" msgid="3277144155960302049">"Point d\'accès Wi-Fi mobile"</string>
<string name="tether_settings_title_bluetooth" msgid="355855408317564420">"Partage connexion Bluetooth"</string>
diff --git a/packages/SettingsLib/res/values-fr/strings.xml b/packages/SettingsLib/res/values-fr/strings.xml
index 1f071de1ac6b..0b620d80cbb2 100644
--- a/packages/SettingsLib/res/values-fr/strings.xml
+++ b/packages/SettingsLib/res/values-fr/strings.xml
@@ -87,8 +87,8 @@
<string name="bluetooth_profile_sap" msgid="5764222021851283125">"Accès à la carte SIM"</string>
<string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"Audio HD : <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
<string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"Audio HD"</string>
- <string name="bluetooth_profile_hearing_aid" msgid="7999237886427812595">"Assistance auditive"</string>
- <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="7188282786730266159">"Connecté à la prothèse auditive"</string>
+ <string name="bluetooth_profile_hearing_aid" msgid="6680721080542444257">"Appareils auditifs"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="3051944447369418317">"Connexion établie avec les appareils auditifs"</string>
<string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"Connecté aux paramètres audio du média"</string>
<string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"Connecté aux paramètres audio du téléphone"</string>
<string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"Connexion au serveur de transfert de fichiers"</string>
@@ -105,7 +105,7 @@
<string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"Utiliser pour les paramètres audio du téléphone"</string>
<string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"Utiliser pour le transfert de fichiers"</string>
<string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"Utiliser comme entrée"</string>
- <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="908775281788309484">"Utiliser pour l\'assistance auditive"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="8843499209204010224">"Utiliser pour les appareils auditifs"</string>
<string name="bluetooth_pairing_accept" msgid="6163520056536604875">"Associer"</string>
<string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"ASSOCIER"</string>
<string name="bluetooth_pairing_decline" msgid="4185420413578948140">"Annuler"</string>
@@ -136,6 +136,7 @@
<string name="process_kernel_label" msgid="3916858646836739323">"Plate-forme Android"</string>
<string name="data_usage_uninstalled_apps" msgid="614263770923231598">"Applications supprimées"</string>
<string name="data_usage_uninstalled_apps_users" msgid="7986294489899813194">"Applications et utilisateurs supprimés"</string>
+ <string name="data_usage_ota" msgid="5377889154805560860">"Mises à jour du système"</string>
<string name="tether_settings_title_usb" msgid="6688416425801386511">"Partage connexion Bluetooth par USB"</string>
<string name="tether_settings_title_wifi" msgid="3277144155960302049">"Point d\'accès Wi-Fi mobile"</string>
<string name="tether_settings_title_bluetooth" msgid="355855408317564420">"Partage connexion Bluetooth"</string>
diff --git a/packages/SettingsLib/res/values-gl/strings.xml b/packages/SettingsLib/res/values-gl/strings.xml
index 06faf00036dd..b4d7fcb9270f 100644
--- a/packages/SettingsLib/res/values-gl/strings.xml
+++ b/packages/SettingsLib/res/values-gl/strings.xml
@@ -87,8 +87,8 @@
<string name="bluetooth_profile_sap" msgid="5764222021851283125">"Acceso á SIM"</string>
<string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"Audio en HD: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
<string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"Audio en HD"</string>
- <string name="bluetooth_profile_hearing_aid" msgid="7999237886427812595">"Audiófonos"</string>
- <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="7188282786730266159">"Conectouse ao audiófono"</string>
+ <string name="bluetooth_profile_hearing_aid" msgid="6680721080542444257">"Audiófonos"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="3051944447369418317">"Conectado a audiófonos"</string>
<string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"Conectado ao audio multimedia"</string>
<string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"Conectado ao audio do teléfono"</string>
<string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"Conectado ao servidor de transferencia de ficheiros"</string>
@@ -105,7 +105,7 @@
<string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"Utilízase para o audio do teléfono"</string>
<string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"Utilízase para a transferencia de ficheiros"</string>
<string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"Utilízase para a entrada"</string>
- <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="908775281788309484">"Usar con audiófonos"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="8843499209204010224">"Utilizar para audiófonos"</string>
<string name="bluetooth_pairing_accept" msgid="6163520056536604875">"Sincronizar"</string>
<string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"SINCRONIZAR"</string>
<string name="bluetooth_pairing_decline" msgid="4185420413578948140">"Cancelar"</string>
@@ -136,6 +136,7 @@
<string name="process_kernel_label" msgid="3916858646836739323">"SO Android"</string>
<string name="data_usage_uninstalled_apps" msgid="614263770923231598">"Aplicacións eliminadas"</string>
<string name="data_usage_uninstalled_apps_users" msgid="7986294489899813194">"Aplicacións e usuarios eliminados"</string>
+ <string name="data_usage_ota" msgid="5377889154805560860">"Actualizacións do sistema"</string>
<string name="tether_settings_title_usb" msgid="6688416425801386511">"Conexión compart. por USB"</string>
<string name="tether_settings_title_wifi" msgid="3277144155960302049">"Zona wifi portátil"</string>
<string name="tether_settings_title_bluetooth" msgid="355855408317564420">"Conexión por Bluetooth"</string>
diff --git a/packages/SettingsLib/res/values-gu/strings.xml b/packages/SettingsLib/res/values-gu/strings.xml
index 232dea9e1f1a..97b9036157a3 100644
--- a/packages/SettingsLib/res/values-gu/strings.xml
+++ b/packages/SettingsLib/res/values-gu/strings.xml
@@ -87,8 +87,8 @@
<string name="bluetooth_profile_sap" msgid="5764222021851283125">"સિમ ઍક્સેસ"</string>
<string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"HD ઑડિઓ: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
<string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"HD ઑડિઓ"</string>
- <string name="bluetooth_profile_hearing_aid" msgid="7999237886427812595">"સાંભળવામાં સહાય આપતું યંત્ર"</string>
- <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="7188282786730266159">"સાંભળવામાં સહાય આપતા યંત્ર સાથે કનેક્ટ કરેલ"</string>
+ <string name="bluetooth_profile_hearing_aid" msgid="6680721080542444257">"શ્રવણ યંત્રો"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="3051944447369418317">"શ્રવણ યંત્રો સાથે કનેક્ટ કરેલું છે"</string>
<string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"મીડિયા ઑડિઓ સાથે કનેક્ટ કર્યુ"</string>
<string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"ફોન ઑડિઓ સાથે કનેક્ટ થયાં"</string>
<string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"ફાઇલ સ્થાનાંતરણ સેવાથી કનેક્ટ થયાં"</string>
@@ -105,7 +105,7 @@
<string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"ફોન ઑડિઓ માટે ઉપયોગ કરો"</string>
<string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"ફાઇલ સ્થાનાંતર માટે ઉપયોગ કરો"</string>
<string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"ઇનપુટ માટે ઉપયોગ કરો"</string>
- <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="908775281788309484">"સાંભળવામાં સહાય આપતા યંત્ર માટે ઉપયોગ કરો"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="8843499209204010224">"શ્રવણ યંત્રો માટે ઉપયોગ કરો"</string>
<string name="bluetooth_pairing_accept" msgid="6163520056536604875">"જોડી"</string>
<string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"જોડાણ બનાવો"</string>
<string name="bluetooth_pairing_decline" msgid="4185420413578948140">"રદ કરો"</string>
@@ -136,6 +136,8 @@
<string name="process_kernel_label" msgid="3916858646836739323">"Android OS"</string>
<string name="data_usage_uninstalled_apps" msgid="614263770923231598">"દૂર કરેલી ઍપ્લિકેશનો"</string>
<string name="data_usage_uninstalled_apps_users" msgid="7986294489899813194">"દૂર કરેલી ઍપ્લિકેશનો અને વપરાશકર્તાઓ"</string>
+ <!-- no translation found for data_usage_ota (5377889154805560860) -->
+ <skip />
<string name="tether_settings_title_usb" msgid="6688416425801386511">"USB ટિથરિંગ"</string>
<string name="tether_settings_title_wifi" msgid="3277144155960302049">"પોર્ટેબલ હૉટસ્પૉટ"</string>
<string name="tether_settings_title_bluetooth" msgid="355855408317564420">"બ્લૂટૂથ ટિથરિંગ"</string>
diff --git a/packages/SettingsLib/res/values-hi/strings.xml b/packages/SettingsLib/res/values-hi/strings.xml
index 2f03eb1b9c3a..8b1ca93d9acd 100644
--- a/packages/SettingsLib/res/values-hi/strings.xml
+++ b/packages/SettingsLib/res/values-hi/strings.xml
@@ -87,8 +87,8 @@
<string name="bluetooth_profile_sap" msgid="5764222021851283125">"सिम ऐक्सेस"</string>
<string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"HD ऑडियो: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
<string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"HD ऑडियो"</string>
- <string name="bluetooth_profile_hearing_aid" msgid="7999237886427812595">"सुनने में मददगार डिवाइस"</string>
- <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="7188282786730266159">"सुनने में मददगार डिवाइस से जाेड़ा गया"</string>
+ <string name="bluetooth_profile_hearing_aid" msgid="6680721080542444257">"सुनने में मदद करने वाले डिवाइस"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="3051944447369418317">"सुनने में मदद करने वाले डिवाइस से कनेक्ट है"</string>
<string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"मीडिया ऑडियो से कनेक्‍ट किया गया"</string>
<string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"फ़ोन ऑडियो से कनेक्‍ट किया गया"</string>
<string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"फ़ाइल स्‍थानांतरण सर्वर से कनेक्‍ट किया गया"</string>
@@ -105,7 +105,7 @@
<string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"फ़ोन ऑडियो के लिए उपयोग करें"</string>
<string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"फ़ाइल स्‍थानांतरण के लिए उपयोग करें"</string>
<string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"इनपुट के लिए उपयोग करें"</string>
- <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="908775281788309484">"सुनने में मददगार डिवाइस के लिए इस्तेमाल करें"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="8843499209204010224">"सुनने में मदद करने वाले डिवाइस के लिए इस्तेमाल करें"</string>
<string name="bluetooth_pairing_accept" msgid="6163520056536604875">"जोड़ें"</string>
<string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"जोड़ें"</string>
<string name="bluetooth_pairing_decline" msgid="4185420413578948140">"रद्द करें"</string>
@@ -136,6 +136,7 @@
<string name="process_kernel_label" msgid="3916858646836739323">"Android OS"</string>
<string name="data_usage_uninstalled_apps" msgid="614263770923231598">"निकाले गए ऐप्स"</string>
<string name="data_usage_uninstalled_apps_users" msgid="7986294489899813194">"ऐप्स और उपयोगकर्ताओं को निकालें"</string>
+ <string name="data_usage_ota" msgid="5377889154805560860">"सिस्टम अपडेट"</string>
<string name="tether_settings_title_usb" msgid="6688416425801386511">"यूएसबी से टेदरिंग"</string>
<string name="tether_settings_title_wifi" msgid="3277144155960302049">"पोर्टेबल हॉटस्‍पॉट"</string>
<string name="tether_settings_title_bluetooth" msgid="355855408317564420">"ब्लूटूथ टेदरिंग"</string>
diff --git a/packages/SettingsLib/res/values-hr/strings.xml b/packages/SettingsLib/res/values-hr/strings.xml
index bb14b066276b..b4cbbdbf3af9 100644
--- a/packages/SettingsLib/res/values-hr/strings.xml
+++ b/packages/SettingsLib/res/values-hr/strings.xml
@@ -87,8 +87,8 @@
<string name="bluetooth_profile_sap" msgid="5764222021851283125">"Pristup SIM-u"</string>
<string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"HD audio: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
<string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"HD audio"</string>
- <string name="bluetooth_profile_hearing_aid" msgid="7999237886427812595">"Slušni aparat"</string>
- <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="7188282786730266159">"Povezano sa slušnim aparatom"</string>
+ <string name="bluetooth_profile_hearing_aid" msgid="6680721080542444257">"Slušni aparati"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="3051944447369418317">"Povezano sa Slušnim aparatima"</string>
<string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"Povezano s medijskim zvukom"</string>
<string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"Povezano sa telefonskim zvukom"</string>
<string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"Povezano s poslužiteljem za prijenos datoteka"</string>
@@ -105,7 +105,7 @@
<string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"Koristi za telefonski zvuk"</string>
<string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"Koristi za prijenos datoteke"</string>
<string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"Upotrijebi za ulaz"</string>
- <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="908775281788309484">"Upotrebljavaj za slušni aparat"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="8843499209204010224">"Upotrijebi za Slušne aparate"</string>
<string name="bluetooth_pairing_accept" msgid="6163520056536604875">"Upari"</string>
<string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"UPARI"</string>
<string name="bluetooth_pairing_decline" msgid="4185420413578948140">"Odustani"</string>
@@ -136,6 +136,7 @@
<string name="process_kernel_label" msgid="3916858646836739323">"Android OS"</string>
<string name="data_usage_uninstalled_apps" msgid="614263770923231598">"Uklonjene aplikacije"</string>
<string name="data_usage_uninstalled_apps_users" msgid="7986294489899813194">"Uklonjene aplikacije i korisnici"</string>
+ <string name="data_usage_ota" msgid="5377889154805560860">"Ažuriranja sustava"</string>
<string name="tether_settings_title_usb" msgid="6688416425801386511">"USB dijeljenje veze"</string>
<string name="tether_settings_title_wifi" msgid="3277144155960302049">"Prijen. pristupna točka"</string>
<string name="tether_settings_title_bluetooth" msgid="355855408317564420">"Dijeljenje Bluetoothom veze"</string>
diff --git a/packages/SettingsLib/res/values-hu/strings.xml b/packages/SettingsLib/res/values-hu/strings.xml
index 14d8c78ed6b8..589eb59d4299 100644
--- a/packages/SettingsLib/res/values-hu/strings.xml
+++ b/packages/SettingsLib/res/values-hu/strings.xml
@@ -87,8 +87,8 @@
<string name="bluetooth_profile_sap" msgid="5764222021851283125">"SIM-elérés"</string>
<string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"HD audio: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
<string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"HD audio"</string>
- <string name="bluetooth_profile_hearing_aid" msgid="7999237886427812595">"Hallókészülék"</string>
- <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="7188282786730266159">"Csatlakoztatva a hallókészülékhez"</string>
+ <string name="bluetooth_profile_hearing_aid" msgid="6680721080542444257">"Hallókészülékek"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="3051944447369418317">"Hallókészülékhez csatlakoztatva"</string>
<string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"Csatlakoztatva az eszköz hangjához"</string>
<string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"Csatlakoztatva a telefon hangjához"</string>
<string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"Csatlakozva a fájlküldő szerverhez"</string>
@@ -105,7 +105,7 @@
<string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"Felhasználás a telefon hangjához"</string>
<string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"Felhasználás fájlátvitelre"</string>
<string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"Használat beviteli eszközként"</string>
- <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="908775281788309484">"Használat hallókészülékhez"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="8843499209204010224">"Hallókészülékkel való használat"</string>
<string name="bluetooth_pairing_accept" msgid="6163520056536604875">"Párosítás"</string>
<string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"PÁROSÍTÁS"</string>
<string name="bluetooth_pairing_decline" msgid="4185420413578948140">"Mégse"</string>
@@ -136,6 +136,7 @@
<string name="process_kernel_label" msgid="3916858646836739323">"Android OS"</string>
<string name="data_usage_uninstalled_apps" msgid="614263770923231598">"Eltávolított alkalmazások"</string>
<string name="data_usage_uninstalled_apps_users" msgid="7986294489899813194">"Eltávolított alkalmazások és felhasználók"</string>
+ <string name="data_usage_ota" msgid="5377889154805560860">"Rendszerfrissítések"</string>
<string name="tether_settings_title_usb" msgid="6688416425801386511">"USB-megosztás"</string>
<string name="tether_settings_title_wifi" msgid="3277144155960302049">"Hordozható hotspot"</string>
<string name="tether_settings_title_bluetooth" msgid="355855408317564420">"Bluetooth megosztása"</string>
diff --git a/packages/SettingsLib/res/values-hy/strings.xml b/packages/SettingsLib/res/values-hy/strings.xml
index 28ebe4febea9..736b4c3d88c9 100644
--- a/packages/SettingsLib/res/values-hy/strings.xml
+++ b/packages/SettingsLib/res/values-hy/strings.xml
@@ -87,8 +87,8 @@
<string name="bluetooth_profile_sap" msgid="5764222021851283125">"SIM քարտի հասանելիություն"</string>
<string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"HD աուդիո՝ <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
<string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"HD աուդիո"</string>
- <string name="bluetooth_profile_hearing_aid" msgid="7999237886427812595">"Լսողական ապարատ"</string>
- <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="7188282786730266159">"Միացված է լսողական ապարատին"</string>
+ <string name="bluetooth_profile_hearing_aid" msgid="6680721080542444257">"Լսողական ապարատ"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="3051944447369418317">"Լսողական ապարատը միացված է"</string>
<string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"Միացված է մեդիա աուդիոյին"</string>
<string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"Միացված է հեռախոսի ձայնային տվյալներին"</string>
<string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"Միացված է ֆայլերի փոխանցման սերվերին"</string>
@@ -105,7 +105,7 @@
<string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"Օգտագործել հեռախոսի աուդիոյի համար"</string>
<string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"Օգտագործել ֆայլի փոխանցման համար"</string>
<string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"Օգտագործել ներմուծման համար"</string>
- <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="908775281788309484">"Օգտագործել լսողական ապարատի համար"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="8843499209204010224">"Օգտագործել լսողական ապարատի համար"</string>
<string name="bluetooth_pairing_accept" msgid="6163520056536604875">"Զուգավորել"</string>
<string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"Զուգավորել"</string>
<string name="bluetooth_pairing_decline" msgid="4185420413578948140">"Չեղարկել"</string>
@@ -136,6 +136,7 @@
<string name="process_kernel_label" msgid="3916858646836739323">"Android OS"</string>
<string name="data_usage_uninstalled_apps" msgid="614263770923231598">"Հեռացված ծրագրեր"</string>
<string name="data_usage_uninstalled_apps_users" msgid="7986294489899813194">"Հեռացված հավելվածներն ու օգտատերերը"</string>
+ <string name="data_usage_ota" msgid="5377889154805560860">"Համակարգի թարմացումներ"</string>
<string name="tether_settings_title_usb" msgid="6688416425801386511">"USB մոդեմ"</string>
<string name="tether_settings_title_wifi" msgid="3277144155960302049">"Դյուրակիր թեժ կետ"</string>
<string name="tether_settings_title_bluetooth" msgid="355855408317564420">"Bluetooth մոդեմ"</string>
diff --git a/packages/SettingsLib/res/values-in/strings.xml b/packages/SettingsLib/res/values-in/strings.xml
index 182e52338891..c5d8f30d332f 100644
--- a/packages/SettingsLib/res/values-in/strings.xml
+++ b/packages/SettingsLib/res/values-in/strings.xml
@@ -87,8 +87,8 @@
<string name="bluetooth_profile_sap" msgid="5764222021851283125">"Akses SIM"</string>
<string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"Audio HD: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
<string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"Audio HD"</string>
- <string name="bluetooth_profile_hearing_aid" msgid="7999237886427812595">"Alat Bantu Dengar"</string>
- <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="7188282786730266159">"Terhubung ke Alat Bantu Dengar"</string>
+ <string name="bluetooth_profile_hearing_aid" msgid="6680721080542444257">"Alat Bantu Dengar"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="3051944447369418317">"Terhubung ke Alat Bantu Dengar"</string>
<string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"Tersambung ke media audio"</string>
<string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"Tersambung ke audio ponsel"</string>
<string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"Sambungkan ke server transfer file"</string>
@@ -105,7 +105,7 @@
<string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"Gunakan untuk audio ponsel"</string>
<string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"Gunakan untuk transfer file"</string>
<string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"Gunakan untuk masukan"</string>
- <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="908775281788309484">"Gunakan untuk Alat Bantu Dengar"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="8843499209204010224">"Gunakan untuk Alat Bantu Dengar"</string>
<string name="bluetooth_pairing_accept" msgid="6163520056536604875">"Sandingkan"</string>
<string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"SANDINGKAN"</string>
<string name="bluetooth_pairing_decline" msgid="4185420413578948140">"Batal"</string>
@@ -136,6 +136,7 @@
<string name="process_kernel_label" msgid="3916858646836739323">"OS Android"</string>
<string name="data_usage_uninstalled_apps" msgid="614263770923231598">"Aplikasi dihapus"</string>
<string name="data_usage_uninstalled_apps_users" msgid="7986294489899813194">"Aplikasi dan pengguna yang dihapus"</string>
+ <string name="data_usage_ota" msgid="5377889154805560860">"Update sistem"</string>
<string name="tether_settings_title_usb" msgid="6688416425801386511">"Tethering USB"</string>
<string name="tether_settings_title_wifi" msgid="3277144155960302049">"Hotspot portabel"</string>
<string name="tether_settings_title_bluetooth" msgid="355855408317564420">"Tethering bluetooth"</string>
diff --git a/packages/SettingsLib/res/values-is/strings.xml b/packages/SettingsLib/res/values-is/strings.xml
index 577b7ae4dadb..58505f55e6e5 100644
--- a/packages/SettingsLib/res/values-is/strings.xml
+++ b/packages/SettingsLib/res/values-is/strings.xml
@@ -87,8 +87,8 @@
<string name="bluetooth_profile_sap" msgid="5764222021851283125">"Aðgangur að SIM-korti"</string>
<string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"HD-hljóð: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
<string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"HD-hljóð"</string>
- <string name="bluetooth_profile_hearing_aid" msgid="7999237886427812595">"Heyrnatæki"</string>
- <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="7188282786730266159">"Tengt við heyrnartæki"</string>
+ <string name="bluetooth_profile_hearing_aid" msgid="6680721080542444257">"Heyrnartæki"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="3051944447369418317">"Tengt við heyrnartæki"</string>
<string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"Tengt við hljóðspilun efnis"</string>
<string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"Tengt við hljóð símans"</string>
<string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"Tengt við skráaflutningsþjón"</string>
@@ -105,7 +105,7 @@
<string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"Nota fyrir hljóð símans"</string>
<string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"Nota við skráaflutning"</string>
<string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"Nota fyrir inntak"</string>
- <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="908775281788309484">"Nota fyrir heyrnartæki"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="8843499209204010224">"Nota fyrir heyrnartæki"</string>
<string name="bluetooth_pairing_accept" msgid="6163520056536604875">"Para"</string>
<string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"PARA"</string>
<string name="bluetooth_pairing_decline" msgid="4185420413578948140">"Hætta við"</string>
@@ -136,6 +136,7 @@
<string name="process_kernel_label" msgid="3916858646836739323">"Android stýrikerfið"</string>
<string name="data_usage_uninstalled_apps" msgid="614263770923231598">"Fjarlægð forrit"</string>
<string name="data_usage_uninstalled_apps_users" msgid="7986294489899813194">"Fjarlægð forrit og notendur"</string>
+ <string name="data_usage_ota" msgid="5377889154805560860">"Kerfisuppfærslur"</string>
<string name="tether_settings_title_usb" msgid="6688416425801386511">"USB-tjóðrun"</string>
<string name="tether_settings_title_wifi" msgid="3277144155960302049">"Heitur reitur"</string>
<string name="tether_settings_title_bluetooth" msgid="355855408317564420">"Bluetooth-tjóðrun"</string>
diff --git a/packages/SettingsLib/res/values-it/strings.xml b/packages/SettingsLib/res/values-it/strings.xml
index 9fc32949db38..6d863aa2a982 100644
--- a/packages/SettingsLib/res/values-it/strings.xml
+++ b/packages/SettingsLib/res/values-it/strings.xml
@@ -87,8 +87,8 @@
<string name="bluetooth_profile_sap" msgid="5764222021851283125">"Accesso alla SIM"</string>
<string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"Audio HD: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
<string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"Audio HD"</string>
- <string name="bluetooth_profile_hearing_aid" msgid="7999237886427812595">"Apparecchio acustico"</string>
- <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="7188282786730266159">"Connesso all\'apparecchio acustico"</string>
+ <string name="bluetooth_profile_hearing_aid" msgid="6680721080542444257">"Apparecchi acustici"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="3051944447369418317">"Connessione con gli apparecchi acustici stabilita"</string>
<string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"Collegato ad audio media"</string>
<string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"Collegato ad audio telefono"</string>
<string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"Collegato al server di trasferimento file"</string>
@@ -105,7 +105,7 @@
<string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"Usa per audio telefono"</string>
<string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"Usa per trasferimento file"</string>
<string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"Utilizza per l\'input"</string>
- <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="908775281788309484">"Usa per l\'apparecchio acustico"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="8843499209204010224">"Utilizza per gli apparecchi acustici"</string>
<string name="bluetooth_pairing_accept" msgid="6163520056536604875">"Accoppia"</string>
<string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"ACCOPPIA"</string>
<string name="bluetooth_pairing_decline" msgid="4185420413578948140">"Annulla"</string>
@@ -136,6 +136,7 @@
<string name="process_kernel_label" msgid="3916858646836739323">"Sistema operativo Android"</string>
<string name="data_usage_uninstalled_apps" msgid="614263770923231598">"Applicazioni rimosse"</string>
<string name="data_usage_uninstalled_apps_users" msgid="7986294489899813194">"App e utenti rimossi"</string>
+ <string name="data_usage_ota" msgid="5377889154805560860">"Aggiornamenti di sistema"</string>
<string name="tether_settings_title_usb" msgid="6688416425801386511">"Tethering USB"</string>
<string name="tether_settings_title_wifi" msgid="3277144155960302049">"Hotspot portatile"</string>
<string name="tether_settings_title_bluetooth" msgid="355855408317564420">"Tethering Bluetooth"</string>
diff --git a/packages/SettingsLib/res/values-iw/strings.xml b/packages/SettingsLib/res/values-iw/strings.xml
index 8ee11e4b2069..6e37c9a6eeda 100644
--- a/packages/SettingsLib/res/values-iw/strings.xml
+++ b/packages/SettingsLib/res/values-iw/strings.xml
@@ -87,8 +87,8 @@
<string name="bluetooth_profile_sap" msgid="5764222021851283125">"‏גישה ל-SIM"</string>
<string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"‏אודיו באיכות HD: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
<string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"‏אודיו באיכות HD"</string>
- <string name="bluetooth_profile_hearing_aid" msgid="7999237886427812595">"מכשיר שמיעה"</string>
- <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="7188282786730266159">"מחובר למכשיר שמיעה"</string>
+ <string name="bluetooth_profile_hearing_aid" msgid="6680721080542444257">"מכשירי שמיעה"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="3051944447369418317">"מחובר אל מכשירי שמיעה"</string>
<string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"מחובר לאודיו של מדיה"</string>
<string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"מחובר לאודיו של הטלפון"</string>
<string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"מחובר לשרת העברת קבצים"</string>
@@ -105,7 +105,7 @@
<string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"השתמש עבור האודיו של הטלפון"</string>
<string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"השתמש להעברת קבצים"</string>
<string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"השתמש לקלט"</string>
- <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="908775281788309484">"יש להשתמש עבור מכשיר שמיעה"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="8843499209204010224">"שימוש בשביל מכשירי שמיעה"</string>
<string name="bluetooth_pairing_accept" msgid="6163520056536604875">"התאם"</string>
<string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"התאם"</string>
<string name="bluetooth_pairing_decline" msgid="4185420413578948140">"ביטול"</string>
@@ -136,6 +136,8 @@
<string name="process_kernel_label" msgid="3916858646836739323">"Android OS"</string>
<string name="data_usage_uninstalled_apps" msgid="614263770923231598">"אפליקציות שהוסרו"</string>
<string name="data_usage_uninstalled_apps_users" msgid="7986294489899813194">"אפליקציות ומשתמשים שהוסרו"</string>
+ <!-- no translation found for data_usage_ota (5377889154805560860) -->
+ <skip />
<string name="tether_settings_title_usb" msgid="6688416425801386511">"‏שיתוף אינטרנט דרך USB"</string>
<string name="tether_settings_title_wifi" msgid="3277144155960302049">"נקודה לשיתוף אינטרנט"</string>
<string name="tether_settings_title_bluetooth" msgid="355855408317564420">"‏שיתוף אינטרנט דרך Bluetooth"</string>
diff --git a/packages/SettingsLib/res/values-ja/strings.xml b/packages/SettingsLib/res/values-ja/strings.xml
index 4efd61b37383..233e8e80b646 100644
--- a/packages/SettingsLib/res/values-ja/strings.xml
+++ b/packages/SettingsLib/res/values-ja/strings.xml
@@ -87,8 +87,8 @@
<string name="bluetooth_profile_sap" msgid="5764222021851283125">"SIMアクセス"</string>
<string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"HD オーディオ: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
<string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"HD オーディオ"</string>
- <string name="bluetooth_profile_hearing_aid" msgid="7999237886427812595">"補聴器"</string>
- <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="7188282786730266159">"補聴器に接続済み"</string>
+ <string name="bluetooth_profile_hearing_aid" msgid="6680721080542444257">"補聴器"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="3051944447369418317">"補聴器に接続"</string>
<string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"メディアの音声に接続"</string>
<string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"携帯電話の音声に接続"</string>
<string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"ファイル転送サーバーに接続"</string>
@@ -105,7 +105,7 @@
<string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"携帯電話の音声に使用"</string>
<string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"ファイル転送に使用"</string>
<string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"入力に使用"</string>
- <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="908775281788309484">"補聴器に使用"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="8843499209204010224">"補聴器に使用"</string>
<string name="bluetooth_pairing_accept" msgid="6163520056536604875">"ペア設定する"</string>
<string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"ペア設定する"</string>
<string name="bluetooth_pairing_decline" msgid="4185420413578948140">"キャンセル"</string>
@@ -136,6 +136,7 @@
<string name="process_kernel_label" msgid="3916858646836739323">"Android OS"</string>
<string name="data_usage_uninstalled_apps" msgid="614263770923231598">"削除したアプリケーション"</string>
<string name="data_usage_uninstalled_apps_users" msgid="7986294489899813194">"削除されたアプリとユーザー"</string>
+ <string name="data_usage_ota" msgid="5377889154805560860">"システム アップデート"</string>
<string name="tether_settings_title_usb" msgid="6688416425801386511">"USB テザリング"</string>
<string name="tether_settings_title_wifi" msgid="3277144155960302049">"ポータブルアクセスポイント"</string>
<string name="tether_settings_title_bluetooth" msgid="355855408317564420">"Bluetooth テザリング"</string>
diff --git a/packages/SettingsLib/res/values-ka/strings.xml b/packages/SettingsLib/res/values-ka/strings.xml
index c613a06b2544..09bea2a0795f 100644
--- a/packages/SettingsLib/res/values-ka/strings.xml
+++ b/packages/SettingsLib/res/values-ka/strings.xml
@@ -87,8 +87,8 @@
<string name="bluetooth_profile_sap" msgid="5764222021851283125">"SIM წვდომა"</string>
<string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"HD აუდიო: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
<string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"HD აუდიო"</string>
- <string name="bluetooth_profile_hearing_aid" msgid="7999237886427812595">"სმენის აპარატი"</string>
- <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="7188282786730266159">"დაკავშირებულია სმენის აპარატთან"</string>
+ <string name="bluetooth_profile_hearing_aid" msgid="6680721080542444257">"სმენის მოწყობილობები"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="3051944447369418317">"დაკავშირებულია სმენის მოწყობილობებთან"</string>
<string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"დაკავშირებულია აუდიო მულტიმედიურ სისტემასთან"</string>
<string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"დაკავშირებულია ტელეფონის აუდიო მოწყობილობასთან"</string>
<string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"დაკავშირებულია ფაილების გადაცემის სერვერთან"</string>
@@ -105,7 +105,7 @@
<string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"გამოიყენეთ ტელეფონის აუდიომოწყობილობაში"</string>
<string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"ფაილების ტრანსფერისათვის გამოყენება"</string>
<string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"შეტანისთვის გამოყენება"</string>
- <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="908775281788309484">"სმენის აპარატის გამოყენება"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="8843499209204010224">"გამოყენება სმენის მოწყობილობებისთვის"</string>
<string name="bluetooth_pairing_accept" msgid="6163520056536604875">"დაწყვილება"</string>
<string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"დაწყვილება"</string>
<string name="bluetooth_pairing_decline" msgid="4185420413578948140">"გაუქმება"</string>
@@ -136,6 +136,7 @@
<string name="process_kernel_label" msgid="3916858646836739323">"Android OS"</string>
<string name="data_usage_uninstalled_apps" msgid="614263770923231598">"აპების წაშლა"</string>
<string name="data_usage_uninstalled_apps_users" msgid="7986294489899813194">"წაშლილი აპები და მომხმარებლები"</string>
+ <string name="data_usage_ota" msgid="5377889154805560860">"სისტემის განახლებები"</string>
<string name="tether_settings_title_usb" msgid="6688416425801386511">"USB ტეტერინგი"</string>
<string name="tether_settings_title_wifi" msgid="3277144155960302049">"პორტატული უსადენო ქსელი"</string>
<string name="tether_settings_title_bluetooth" msgid="355855408317564420">"Bluetooth ტეტერინგი"</string>
diff --git a/packages/SettingsLib/res/values-kk/strings.xml b/packages/SettingsLib/res/values-kk/strings.xml
index 8d6d76ecd30d..8670ec96012e 100644
--- a/packages/SettingsLib/res/values-kk/strings.xml
+++ b/packages/SettingsLib/res/values-kk/strings.xml
@@ -87,8 +87,8 @@
<string name="bluetooth_profile_sap" msgid="5764222021851283125">"SIM картасына кіру"</string>
<string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"HD форматты аудиомазмұн: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
<string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"HD форматты аудиомазмұн"</string>
- <string name="bluetooth_profile_hearing_aid" msgid="7999237886427812595">"Есту аппараты"</string>
- <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="7188282786730266159">"Есту аппаратына жалғанған"</string>
+ <string name="bluetooth_profile_hearing_aid" msgid="6680721080542444257">"Есту аппараттары"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="3051944447369418317">"Есту аппараттарына жалғанған"</string>
<string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"Медиа аудиосына жалғанған"</string>
<string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"Телефон аудиосына қосылған"</string>
<string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"Файл жіберу серверіне жалғанған"</string>
@@ -105,7 +105,7 @@
<string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"Телефон аудиосы үшін қолдану"</string>
<string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"Файлды жіберу үшін қолдану"</string>
<string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"Кіріс үшін қолдану"</string>
- <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="908775281788309484">"Есту аппаратына пайдалану"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="8843499209204010224">"Есту аппараттары үшін пайдалану"</string>
<string name="bluetooth_pairing_accept" msgid="6163520056536604875">"Жұптау"</string>
<string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"ЖҰПТАУ"</string>
<string name="bluetooth_pairing_decline" msgid="4185420413578948140">"Бас тарту"</string>
@@ -136,6 +136,7 @@
<string name="process_kernel_label" msgid="3916858646836739323">"Android операциялық жүйесі"</string>
<string name="data_usage_uninstalled_apps" msgid="614263770923231598">"Алынған қолданбалар"</string>
<string name="data_usage_uninstalled_apps_users" msgid="7986294489899813194">"Алынған қолданбалар және пайдаланушылар"</string>
+ <string name="data_usage_ota" msgid="5377889154805560860">"Жүйелік жаңарту"</string>
<string name="tether_settings_title_usb" msgid="6688416425801386511">"USB тетеринг"</string>
<string name="tether_settings_title_wifi" msgid="3277144155960302049">"Алынбалы хот-спот"</string>
<string name="tether_settings_title_bluetooth" msgid="355855408317564420">"Bluetooth модем"</string>
diff --git a/packages/SettingsLib/res/values-km/strings.xml b/packages/SettingsLib/res/values-km/strings.xml
index 990320108698..6bf8a0f3266f 100644
--- a/packages/SettingsLib/res/values-km/strings.xml
+++ b/packages/SettingsLib/res/values-km/strings.xml
@@ -87,8 +87,8 @@
<string name="bluetooth_profile_sap" msgid="5764222021851283125">"ការចូលដំណើរការស៊ីម"</string>
<string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"សំឡេងកម្រិត HD៖ <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
<string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"សំឡេងកម្រិត HD"</string>
- <string name="bluetooth_profile_hearing_aid" msgid="7999237886427812595">"ឧបករណ៍​ជំនួយការ​ស្ដាប់"</string>
- <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="7188282786730266159">"បាន​ភ្ជាប់ទៅ​ឧបករណ៍​ជំនួយការ​ស្តាប់"</string>
+ <string name="bluetooth_profile_hearing_aid" msgid="6680721080542444257">"ឧបករណ៍​ជំនួយការ​ស្ដាប់"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="3051944447369418317">"បាន​ភ្ជាប់ទៅ​ឧបករណ៍​ជំនួយការ​ស្ដាប់"</string>
<string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"បា​ន​ភ្ជាប់​ទៅ​អូឌីយ៉ូ​មេឌៀ"</string>
<string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"តភ្ជាប់​ទៅ​អូឌីយ៉ូ​ទូរស័ព្ទ"</string>
<string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"បាន​តភ្ជាប់​ទៅ​ម៉ាស៊ីន​មេ​ផ្ទេរ​ឯកសារ"</string>
@@ -105,7 +105,7 @@
<string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"ប្រើ​សម្រាប់​​អូឌីយ៉ូ​ទូរស័ព្ទ"</string>
<string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"ប្រើ​សម្រាប់​ផ្ទេរ​ឯកសារ"</string>
<string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"ប្រើ​សម្រាប់​បញ្ចូល"</string>
- <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="908775281788309484">"ប្រើ​សម្រាប់​ឧបករណ៍​ជំនួយការ​ស្តាប់"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="8843499209204010224">"ប្រើ​សម្រាប់​ឧបករណ៍​ជំនួយការ​ស្តាប់"</string>
<string name="bluetooth_pairing_accept" msgid="6163520056536604875">"ផ្គូផ្គង"</string>
<string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"ផ្គូផ្គង"</string>
<string name="bluetooth_pairing_decline" msgid="4185420413578948140">"បោះ​បង់​"</string>
@@ -136,6 +136,7 @@
<string name="process_kernel_label" msgid="3916858646836739323">"ប្រព័ន្ធ​ប្រតិបត្តិការ Android"</string>
<string name="data_usage_uninstalled_apps" msgid="614263770923231598">"កម្មវិធី​ដែល​បាន​លុប"</string>
<string name="data_usage_uninstalled_apps_users" msgid="7986294489899813194">"បាន​លុប​កម្មវិធី និង​អ្នកប្រើ"</string>
+ <string name="data_usage_ota" msgid="5377889154805560860">"បច្ចុប្បន្នភាព​ប្រព័ន្ធ"</string>
<string name="tether_settings_title_usb" msgid="6688416425801386511">"ការ​ភ្ជាប់តាម USB"</string>
<string name="tether_settings_title_wifi" msgid="3277144155960302049">"ហតស្ពត​ចល័ត"</string>
<string name="tether_settings_title_bluetooth" msgid="355855408317564420">"ការ​ភ្ជាប់ប៊្លូធូស"</string>
diff --git a/packages/SettingsLib/res/values-kn/strings.xml b/packages/SettingsLib/res/values-kn/strings.xml
index 888b93fb17ad..41b0fbda408f 100644
--- a/packages/SettingsLib/res/values-kn/strings.xml
+++ b/packages/SettingsLib/res/values-kn/strings.xml
@@ -38,27 +38,20 @@
<string name="connected_via_network_scorer" msgid="5713793306870815341">"%1$s ಮೂಲಕ ಸ್ವಯಂಚಾಲಿತವಾಗಿ ಸಂಪರ್ಕಿಸಲಾಗಿದೆ"</string>
<string name="connected_via_network_scorer_default" msgid="7867260222020343104">"ನೆಟ್‌ವರ್ಕ್ ರೇಟಿಂಗ್ ಒದಗಿಸುವವರ ಮೂಲಕ ಸ್ವಯಂಚಾಲಿತವಾಗಿ ಸಂಪರ್ಕಿಸಲಾಗಿದೆ"</string>
<string name="connected_via_passpoint" msgid="2826205693803088747">"%1$s ಮೂಲಕ ಸಂಪರ್ಕಗೊಂಡಿದೆ"</string>
- <!-- no translation found for connected_via_app (5571999941988929520) -->
- <skip />
+ <string name="connected_via_app" msgid="5571999941988929520">"<xliff:g id="NAME">%1$s</xliff:g> ಆ್ಯಪ್ ಮೂಲಕ ಸಂಪರ್ಕಿಸಲಾಗಿದೆ"</string>
<string name="available_via_passpoint" msgid="1617440946846329613">"%1$s ಮೂಲಕ ಲಭ್ಯವಿದೆ"</string>
- <!-- no translation found for tap_to_sign_up (6449724763052579434) -->
- <skip />
+ <string name="tap_to_sign_up" msgid="6449724763052579434">"ಸೈನ್ ಅಪ್ ಮಾಡಲು ಟ್ಯಾಪ್‌ ಮಾಡಿ"</string>
<string name="wifi_connected_no_internet" msgid="8202906332837777829">"ಸಂಪರ್ಕಪಡಿಸಲಾಗಿದೆ, ಇಂಟರ್ನೆಟ್ ಇಲ್ಲ"</string>
<string name="wifi_status_no_internet" msgid="5784710974669608361">"ಇಂಟರ್ನೆಟ್ ಇಲ್ಲ"</string>
<string name="wifi_status_sign_in_required" msgid="123517180404752756">"ಸೈನ್ ಇನ್ ಮಾಡುವ ಅಗತ್ಯವಿದೆ"</string>
<string name="wifi_ap_unable_to_handle_new_sta" msgid="5348824313514404541">"ಪ್ರವೇಶ ಕೇಂದ್ರ ತಾತ್ಕಾಲಿಕವಾಗಿ ಭರ್ತಿಯಾಗಿದೆ"</string>
<string name="connected_via_carrier" msgid="7583780074526041912">"%1$s ಮೂಲಕ ಸಂಪರ್ಕಗೊಂಡಿದೆ"</string>
<string name="available_via_carrier" msgid="1469036129740799053">"%1$s ಮೂಲಕ ಲಭ್ಯವಿದೆ"</string>
- <!-- no translation found for osu_opening_provider (5488997661548640424) -->
- <skip />
- <!-- no translation found for osu_connect_failed (2187750899158158934) -->
- <skip />
- <!-- no translation found for osu_completing_sign_up (9037638564719197082) -->
- <skip />
- <!-- no translation found for osu_sign_up_failed (7296159750352873260) -->
- <skip />
- <!-- no translation found for osu_sign_up_complete (8207626049093289203) -->
- <skip />
+ <string name="osu_opening_provider" msgid="5488997661548640424">"<xliff:g id="PASSPOINTPROVIDER">%1$s</xliff:g> ಅನ್ನು ತೆರೆಯಲಾಗುತ್ತಿದೆ"</string>
+ <string name="osu_connect_failed" msgid="2187750899158158934">"ಸಂಪರ್ಕಿಸಲು ಸಾಧ್ಯವಾಗುತ್ತಿಲ್ಲ"</string>
+ <string name="osu_completing_sign_up" msgid="9037638564719197082">"ಸೈನ್-ಅಪ್ ಅನ್ನು ಪೂರ್ಣಗೊಳಿಸಲಾಗುತ್ತಿದೆ…"</string>
+ <string name="osu_sign_up_failed" msgid="7296159750352873260">"ಸೈನ್-ಅಪ್ ಅನ್ನು ಪೂರ್ಣಗೊಳಿಸಲು ಸಾಧ್ಯವಾಗುತ್ತಿಲ್ಲ. ಮತ್ತೊಮ್ಮೆ ಪ್ರಯತ್ನಿಸಲು ಟ್ಯಾಪ್ ಮಾಡಿ."</string>
+ <string name="osu_sign_up_complete" msgid="8207626049093289203">"ಸೈನ್-ಅಪ್ ಪೂರ್ಣಗೊಂಡಿದೆ. ಸಂಪರ್ಕಿಸಲಾಗುತ್ತಿದೆ…"</string>
<string name="speed_label_very_slow" msgid="1867055264243608530">"ತುಂಬಾ ನಿಧಾನವಾಗಿದೆ"</string>
<string name="speed_label_slow" msgid="813109590815810235">"ನಿಧಾನ"</string>
<string name="speed_label_okay" msgid="2331665440671174858">"ಸರಿ"</string>
@@ -94,8 +87,8 @@
<string name="bluetooth_profile_sap" msgid="5764222021851283125">"ಸಿಮ್ ಪ್ರವೇಶ"</string>
<string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"HD ಆಡಿಯೋ: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
<string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"HD ಆಡಿಯೋ"</string>
- <string name="bluetooth_profile_hearing_aid" msgid="7999237886427812595">"ಶ್ರವಣ ಸಾಧನ"</string>
- <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="7188282786730266159">"ಶ್ರವಣ ಸಾಧನಕ್ಕೆ ಸಂಪರ್ಕಪಡಿಸಲಾಗಿದೆ"</string>
+ <string name="bluetooth_profile_hearing_aid" msgid="6680721080542444257">"ಶ್ರವಣ ಸಾಧನಗಳು"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="3051944447369418317">"ಶ್ರವಣ ಸಾಧನಗಳಿಗೆ ಸಂಪರ್ಕಿಸಲಾಗಿದೆ"</string>
<string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"ಮಾಧ್ಯಮ ಆಡಿಯೋಗೆ ಸಂಪರ್ಕಗೊಂಡಿದೆ"</string>
<string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"ಫೋನ್ ಆಡಿಯೋಗೆ ಸಂಪರ್ಕಗೊಂಡಿದೆ"</string>
<string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"ಫೈಲ್ ವರ್ಗಾವಣೆ ಸರ್ವರ್‌ಗೆ ಸಂಪರ್ಕಗೊಂಡಿದೆ"</string>
@@ -112,7 +105,7 @@
<string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"ಫೋನ್‌ ಆಡಿಯೋಗಾಗಿ ಬಳಕೆ"</string>
<string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"ಫೈಲ್‌ ವರ್ಗಾವಣೆಗಾಗಿ ಬಳಸು"</string>
<string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"ಇನ್‌ಪುಟ್‌ಗಾಗಿ ಬಳಸು"</string>
- <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="908775281788309484">"ಶ್ರವಣ ಸಾಧನಕ್ಕಾಗಿ ಬಳಸಿ"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="8843499209204010224">"ಶ್ರವಣ ಸಾಧನಗಳಿಗಾಗಿ ಬಳಸಿ"</string>
<string name="bluetooth_pairing_accept" msgid="6163520056536604875">"ಜೋಡಿ"</string>
<string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"ಜೋಡಿ ಮಾಡು"</string>
<string name="bluetooth_pairing_decline" msgid="4185420413578948140">"ರದ್ದುಮಾಡಿ"</string>
@@ -143,6 +136,8 @@
<string name="process_kernel_label" msgid="3916858646836739323">"Android OS"</string>
<string name="data_usage_uninstalled_apps" msgid="614263770923231598">"ತೆಗೆದುಹಾಕಲಾದ ಅಪ್ಲಿಕೇಶನ್‌ಗಳು"</string>
<string name="data_usage_uninstalled_apps_users" msgid="7986294489899813194">"ಅಪ್ಲಿಕೇಶನ್‌ಗಳು ಮತ್ತು ಬಳಕೆದಾರರನ್ನು ತೆಗೆದುಹಾಕಲಾಗಿದೆ"</string>
+ <!-- no translation found for data_usage_ota (5377889154805560860) -->
+ <skip />
<string name="tether_settings_title_usb" msgid="6688416425801386511">"USB ಟೆಥರಿಂಗ್"</string>
<string name="tether_settings_title_wifi" msgid="3277144155960302049">"ಪೋರ್ಟಬಲ್ ಹಾಟ್‌ಸ್ಪಾಟ್"</string>
<string name="tether_settings_title_bluetooth" msgid="355855408317564420">"ಬ್ಲೂಟೂತ್‌‌ ಟೆಥರಿಂಗ್‌"</string>
diff --git a/packages/SettingsLib/res/values-ko/strings.xml b/packages/SettingsLib/res/values-ko/strings.xml
index d7e9488cea42..877866c7c320 100644
--- a/packages/SettingsLib/res/values-ko/strings.xml
+++ b/packages/SettingsLib/res/values-ko/strings.xml
@@ -87,8 +87,8 @@
<string name="bluetooth_profile_sap" msgid="5764222021851283125">"SIM 액세스"</string>
<string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"HD 오디오: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
<string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"HD 오디오"</string>
- <string name="bluetooth_profile_hearing_aid" msgid="7999237886427812595">"보청기"</string>
- <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="7188282786730266159">"보청기에 연결됨"</string>
+ <string name="bluetooth_profile_hearing_aid" msgid="6680721080542444257">"보청기"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="3051944447369418317">"보청기에 연결됨"</string>
<string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"미디어 오디오에 연결됨"</string>
<string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"휴대전화 오디오에 연결됨"</string>
<string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"파일 전송 서버에 연결됨"</string>
@@ -105,7 +105,7 @@
<string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"휴대전화 오디오에 사용"</string>
<string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"파일 전송에 사용"</string>
<string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"입력에 사용"</string>
- <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="908775281788309484">"보청기에 사용"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="8843499209204010224">"보청기로 사용"</string>
<string name="bluetooth_pairing_accept" msgid="6163520056536604875">"페어링"</string>
<string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"페어링"</string>
<string name="bluetooth_pairing_decline" msgid="4185420413578948140">"취소"</string>
@@ -136,6 +136,7 @@
<string name="process_kernel_label" msgid="3916858646836739323">"Android OS"</string>
<string name="data_usage_uninstalled_apps" msgid="614263770923231598">"삭제된 앱"</string>
<string name="data_usage_uninstalled_apps_users" msgid="7986294489899813194">"삭제된 앱 및 사용자"</string>
+ <string name="data_usage_ota" msgid="5377889154805560860">"시스템 업데이트"</string>
<string name="tether_settings_title_usb" msgid="6688416425801386511">"USB 테더링"</string>
<string name="tether_settings_title_wifi" msgid="3277144155960302049">"휴대용 핫스팟"</string>
<string name="tether_settings_title_bluetooth" msgid="355855408317564420">"블루투스 테더링"</string>
diff --git a/packages/SettingsLib/res/values-ky/strings.xml b/packages/SettingsLib/res/values-ky/strings.xml
index 6898c61e5b85..9e4a9a8a1250 100644
--- a/packages/SettingsLib/res/values-ky/strings.xml
+++ b/packages/SettingsLib/res/values-ky/strings.xml
@@ -87,8 +87,8 @@
<string name="bluetooth_profile_sap" msgid="5764222021851283125">"SIM картаны пайдалануу мүмкүнчүлүгү"</string>
<string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"HD форматындагы аудио: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
<string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"HD форматындагы аудио"</string>
- <string name="bluetooth_profile_hearing_aid" msgid="7999237886427812595">"Угуу аппараты"</string>
- <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="7188282786730266159">"Угуу аппаратына туташты"</string>
+ <string name="bluetooth_profile_hearing_aid" msgid="6680721080542444257">"Угуу аппараттары"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="3051944447369418317">"Угуу аппараттарына туташып турат"</string>
<string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"Медиа аудиого туташты"</string>
<string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"Телефон аудиосуна туташты"</string>
<string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"Файл өткөрүү серверине туташты"</string>
@@ -105,7 +105,7 @@
<string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"Телефон аудиосу үчүн колдонулсун"</string>
<string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"Файл өткөрүү үчүн колдонулсун"</string>
<string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"Киргизүү үчүн колдонулсун"</string>
- <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="908775281788309484">"Угуу аппараты үчүн колдонуу"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="8843499209204010224">"Угуу аппараттары үчүн колдонуу"</string>
<string name="bluetooth_pairing_accept" msgid="6163520056536604875">"Жупташтыруу"</string>
<string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"ЖУПТАШТЫРУУ"</string>
<string name="bluetooth_pairing_decline" msgid="4185420413578948140">"Жок"</string>
@@ -136,6 +136,7 @@
<string name="process_kernel_label" msgid="3916858646836739323">"Android OS"</string>
<string name="data_usage_uninstalled_apps" msgid="614263770923231598">"Алынып салынган колдонмолор"</string>
<string name="data_usage_uninstalled_apps_users" msgid="7986294489899813194">"Өчүрүлгөн колдонмолор жана колдонуучулар"</string>
+ <string name="data_usage_ota" msgid="5377889154805560860">"Тутум жаңыртуулары"</string>
<string name="tether_settings_title_usb" msgid="6688416425801386511">"USB модем"</string>
<string name="tether_settings_title_wifi" msgid="3277144155960302049">"Ташыма кошулуу чекити"</string>
<string name="tether_settings_title_bluetooth" msgid="355855408317564420">"Bluetooth модем"</string>
diff --git a/packages/SettingsLib/res/values-lo/strings.xml b/packages/SettingsLib/res/values-lo/strings.xml
index acbaf701ace2..7e6aaacea44e 100644
--- a/packages/SettingsLib/res/values-lo/strings.xml
+++ b/packages/SettingsLib/res/values-lo/strings.xml
@@ -87,8 +87,8 @@
<string name="bluetooth_profile_sap" msgid="5764222021851283125">"ການ​ເຂົ້າ​ເຖິງ SIM"</string>
<string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"ສຽງ HD: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
<string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"ສຽງ HD"</string>
- <string name="bluetooth_profile_hearing_aid" msgid="7999237886427812595">"ເຄື່ອງຊ່ວຍຟັງ"</string>
- <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="7188282786730266159">"ເຊື່ອມຕໍ່ຫາເຄື່ອງຊ່ວຍຟັງແລ້ວ"</string>
+ <string name="bluetooth_profile_hearing_aid" msgid="6680721080542444257">"ອຸປະກອນຊ່ວຍຟັງ"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="3051944447369418317">"ເຊື່ອມຕໍ່ຫາອຸປະກອນຊ່ວຍຟັງແລ້ວ"</string>
<string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"ເຊື່ອມຕໍ່ກັບສື່ດ້ານສຽງແລ້ວ"</string>
<string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"ເຊື່ອມຕໍ່ກັບສຽງໂທລະສັບແລ້ວ"</string>
<string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"ເຊື່ອມຕໍ່ກັບເຊີບເວີໂອນຍ້າຍໄຟລ໌ແລ້ວ"</string>
@@ -105,7 +105,7 @@
<string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"ໃຊ້ສຳລັບລະບົບສຽງຂອງໂທລະສັບ"</string>
<string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"ໃຊ້ເພື່ອໂອນຍ້າຍໄຟລ໌"</string>
<string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"ໃຊ້ສຳລັບການປ້ອນຂໍ້ມູນ"</string>
- <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="908775281788309484">"ໃຊ້ກັບເຄື່ອງຊ່ວຍຟັງ"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="8843499209204010224">"ໃຊ້ສຳລັບອຸປະກອນຊ່ວຍຟັງ"</string>
<string name="bluetooth_pairing_accept" msgid="6163520056536604875">"ຈັບຄູ່"</string>
<string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"ຈັບຄູ່"</string>
<string name="bluetooth_pairing_decline" msgid="4185420413578948140">"ຍົກເລີກ"</string>
@@ -136,6 +136,7 @@
<string name="process_kernel_label" msgid="3916858646836739323">"Android OS"</string>
<string name="data_usage_uninstalled_apps" msgid="614263770923231598">"ແອັບຯທີ່ຖືກລຶບອອກແລ້ວ"</string>
<string name="data_usage_uninstalled_apps_users" msgid="7986294489899813194">"ລຶບແອັບຯ ແລະຜູ່ໃຊ້ແລ້ວ"</string>
+ <string name="data_usage_ota" msgid="5377889154805560860">"ການອັບເດດລະບົບ"</string>
<string name="tether_settings_title_usb" msgid="6688416425801386511">"ການປ່ອຍສັນຍານຜ່ານ USB"</string>
<string name="tether_settings_title_wifi" msgid="3277144155960302049">"ຮັອດສະປອດເຄື່ອນທີ່"</string>
<string name="tether_settings_title_bluetooth" msgid="355855408317564420">"ປ່ອຍສັນຍານຜ່ານ Bluetooth"</string>
diff --git a/packages/SettingsLib/res/values-lt/strings.xml b/packages/SettingsLib/res/values-lt/strings.xml
index 89334517aa7d..71b8cf0ff375 100644
--- a/packages/SettingsLib/res/values-lt/strings.xml
+++ b/packages/SettingsLib/res/values-lt/strings.xml
@@ -87,8 +87,8 @@
<string name="bluetooth_profile_sap" msgid="5764222021851283125">"SIM prieiga"</string>
<string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"HD garsas: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
<string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"HD garsas"</string>
- <string name="bluetooth_profile_hearing_aid" msgid="7999237886427812595">"Klausos aparatas"</string>
- <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="7188282786730266159">"Prisijungta prie klausos aparato"</string>
+ <string name="bluetooth_profile_hearing_aid" msgid="6680721080542444257">"Klausos aparatai"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="3051944447369418317">"Prisijungta prie klausos aparatų"</string>
<string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"Prijungta prie medijos garso įrašo"</string>
<string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"Prijungta prie telefono garso"</string>
<string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"Prijungta prie failų perkėlimo serverio"</string>
@@ -105,7 +105,7 @@
<string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"Naudoti telefono garso įrašui"</string>
<string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"Naudoti failų perkėlimui"</string>
<string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"Naudoti įvedant"</string>
- <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="908775281788309484">"Klausos aparato naudojimas"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="8843499209204010224">"Naudoti su klausos aparatais"</string>
<string name="bluetooth_pairing_accept" msgid="6163520056536604875">"Susieti"</string>
<string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"SUSIETI"</string>
<string name="bluetooth_pairing_decline" msgid="4185420413578948140">"Atšaukti"</string>
@@ -136,6 +136,7 @@
<string name="process_kernel_label" msgid="3916858646836739323">"„Android“ OS"</string>
<string name="data_usage_uninstalled_apps" msgid="614263770923231598">"Pašalintos programos"</string>
<string name="data_usage_uninstalled_apps_users" msgid="7986294489899813194">"Pašalintos programos ir naudotojai"</string>
+ <string name="data_usage_ota" msgid="5377889154805560860">"Sistemos naujiniai"</string>
<string name="tether_settings_title_usb" msgid="6688416425801386511">"USB susiejimas"</string>
<string name="tether_settings_title_wifi" msgid="3277144155960302049">"Perkeliama aktyvioji sritis"</string>
<string name="tether_settings_title_bluetooth" msgid="355855408317564420">"„Bluetooth“ susiejimas"</string>
diff --git a/packages/SettingsLib/res/values-lv/strings.xml b/packages/SettingsLib/res/values-lv/strings.xml
index ac41ae082c1e..82ec0ae5b1cd 100644
--- a/packages/SettingsLib/res/values-lv/strings.xml
+++ b/packages/SettingsLib/res/values-lv/strings.xml
@@ -87,8 +87,8 @@
<string name="bluetooth_profile_sap" msgid="5764222021851283125">"Piekļuve SIM kartei"</string>
<string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"HD audio: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
<string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"HD audio"</string>
- <string name="bluetooth_profile_hearing_aid" msgid="7999237886427812595">"Dzirdes aparāts"</string>
- <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="7188282786730266159">"Izveidots savienojums ar dzirdes aparātu"</string>
+ <string name="bluetooth_profile_hearing_aid" msgid="6680721080542444257">"Dzirdes aparāti"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="3051944447369418317">"Izveidots savienojums ar dzirdes aparātiem"</string>
<string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"Savienots ar multivides audio"</string>
<string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"Savienots ar tālruņa audio"</string>
<string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"Savienots ar failu pārsūtīšanas serveri"</string>
@@ -105,7 +105,7 @@
<string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"Izmantot tālruņa skaņai"</string>
<string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"Izmantot faila pārsūtīšanai"</string>
<string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"Izmantot ievadei"</string>
- <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="908775281788309484">"Izmantot dzirdes aparātam"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="8843499209204010224">"Izmantot dzirdes aparātiem"</string>
<string name="bluetooth_pairing_accept" msgid="6163520056536604875">"Izveidot pāri"</string>
<string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"SAVIENOT PĀRĪ"</string>
<string name="bluetooth_pairing_decline" msgid="4185420413578948140">"Atcelt"</string>
@@ -136,6 +136,7 @@
<string name="process_kernel_label" msgid="3916858646836739323">"Android OS"</string>
<string name="data_usage_uninstalled_apps" msgid="614263770923231598">"Noņemtās lietotnes"</string>
<string name="data_usage_uninstalled_apps_users" msgid="7986294489899813194">"Noņemtās lietotnes un lietotāji"</string>
+ <string name="data_usage_ota" msgid="5377889154805560860">"Sistēmas atjauninājumi"</string>
<string name="tether_settings_title_usb" msgid="6688416425801386511">"USB saistīšana"</string>
<string name="tether_settings_title_wifi" msgid="3277144155960302049">"Pārnēsājams tīklājs"</string>
<string name="tether_settings_title_bluetooth" msgid="355855408317564420">"Bluetooth saistīšana"</string>
diff --git a/packages/SettingsLib/res/values-mk/strings.xml b/packages/SettingsLib/res/values-mk/strings.xml
index 5b45977a32a6..c99ef681b899 100644
--- a/packages/SettingsLib/res/values-mk/strings.xml
+++ b/packages/SettingsLib/res/values-mk/strings.xml
@@ -87,8 +87,8 @@
<string name="bluetooth_profile_sap" msgid="5764222021851283125">"Пристап до SIM"</string>
<string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"HD аудио: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
<string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"HD аудио"</string>
- <string name="bluetooth_profile_hearing_aid" msgid="7999237886427812595">"Слушно помагало"</string>
- <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="7188282786730266159">"Поврзано со слушно помагало"</string>
+ <string name="bluetooth_profile_hearing_aid" msgid="6680721080542444257">"Слушни помагала"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="3051944447369418317">"Поврзано со слушни помагала"</string>
<string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"Поврзан со аудио на медиуми"</string>
<string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"Поврзан со аудио на телефон"</string>
<string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"Поврзан со сервер за пренос на датотеки"</string>
@@ -105,7 +105,7 @@
<string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"Користи за аудио на телефон"</string>
<string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"Користи за пренос на датотеки"</string>
<string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"Користи за внес"</string>
- <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="908775281788309484">"Користете како слушно помагало"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="8843499209204010224">"Користи за слушни помагала"</string>
<string name="bluetooth_pairing_accept" msgid="6163520056536604875">"Спари"</string>
<string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"СПАРИ"</string>
<string name="bluetooth_pairing_decline" msgid="4185420413578948140">"Откажи"</string>
@@ -136,6 +136,7 @@
<string name="process_kernel_label" msgid="3916858646836739323">"Оперативен систем Android"</string>
<string name="data_usage_uninstalled_apps" msgid="614263770923231598">"Отстранети апликации"</string>
<string name="data_usage_uninstalled_apps_users" msgid="7986294489899813194">"Отстранети апликации и корисници"</string>
+ <string name="data_usage_ota" msgid="5377889154805560860">"Ажурирања на системот"</string>
<string name="tether_settings_title_usb" msgid="6688416425801386511">"Поврзување со USB"</string>
<string name="tether_settings_title_wifi" msgid="3277144155960302049">"Преносл. точка на пристап"</string>
<string name="tether_settings_title_bluetooth" msgid="355855408317564420">"Поврзување со Bluetooth"</string>
diff --git a/packages/SettingsLib/res/values-ml/strings.xml b/packages/SettingsLib/res/values-ml/strings.xml
index efe6cd6dfbc5..0292cabb73bf 100644
--- a/packages/SettingsLib/res/values-ml/strings.xml
+++ b/packages/SettingsLib/res/values-ml/strings.xml
@@ -87,8 +87,8 @@
<string name="bluetooth_profile_sap" msgid="5764222021851283125">"SIM ആക്സസ്"</string>
<string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"HD ഓഡിയോ: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
<string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"HD ഓഡിയോ"</string>
- <string name="bluetooth_profile_hearing_aid" msgid="7999237886427812595">"ശ്രവണ സഹായി"</string>
- <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="7188282786730266159">"ശ്രവണ സഹായിലേക്ക് കണക്റ്റ് ചെയ്‌‌തു"</string>
+ <string name="bluetooth_profile_hearing_aid" msgid="6680721080542444257">"ശ്രവണ സഹായികൾ"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="3051944447369418317">"ശ്രവണ സഹായികളിലേക്ക് കണക്‌റ്റ് ചെയ്‌തു"</string>
<string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"മീഡിയ ഓഡിയോയിലേക്ക് കണ‌ക്റ്റുചെയ്‌തു"</string>
<string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"ഫോൺ ഓഡിയോയിൽ കണ‌ക്റ്റുചെ‌യ്‌തു"</string>
<string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"ഫയൽ കൈമാറ്റ സെർവറിലേക്ക് കണ‌ക്റ്റുചെ‌യ്‌തു"</string>
@@ -105,7 +105,7 @@
<string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"ഫോൺ ഓഡിയോയ്ക്കായി ഉപയോഗിക്കുക"</string>
<string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"ഫയൽ കൈമാറ്റത്തിനായി ഉപയോഗിക്കുന്നു"</string>
<string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"ഇൻപുട്ടിനായി ഉപയോഗിക്കുക"</string>
- <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="908775281788309484">"ശ്രവണ സഹായത്തിനായി ഉപയോഗിക്കുക"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="8843499209204010224">"ശ്രവണ സഹായികൾക്കായി ഉപയോഗിക്കുക"</string>
<string name="bluetooth_pairing_accept" msgid="6163520056536604875">"ജോടിയാക്കുക"</string>
<string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"ജോടിയാക്കുക"</string>
<string name="bluetooth_pairing_decline" msgid="4185420413578948140">"റദ്ദാക്കുക"</string>
@@ -136,6 +136,8 @@
<string name="process_kernel_label" msgid="3916858646836739323">"Android OS"</string>
<string name="data_usage_uninstalled_apps" msgid="614263770923231598">"നീക്കംചെയ്‌ത അപ്ലിക്കേഷനുകൾ"</string>
<string name="data_usage_uninstalled_apps_users" msgid="7986294489899813194">"നീക്കംചെയ്‌ത അപ്ലിക്കേഷനുകളും ഉപയോക്താക്കളും"</string>
+ <!-- no translation found for data_usage_ota (5377889154805560860) -->
+ <skip />
<string name="tether_settings_title_usb" msgid="6688416425801386511">"USB ടെതറിംഗ്"</string>
<string name="tether_settings_title_wifi" msgid="3277144155960302049">"പോർട്ടബിൾ ഹോട്ട്സ്‌പോട്ട്"</string>
<string name="tether_settings_title_bluetooth" msgid="355855408317564420">"ബ്ലൂടൂത്ത് ടെതറിംഗ്"</string>
diff --git a/packages/SettingsLib/res/values-mn/strings.xml b/packages/SettingsLib/res/values-mn/strings.xml
index 9c3db2e99717..10c1415c7630 100644
--- a/packages/SettingsLib/res/values-mn/strings.xml
+++ b/packages/SettingsLib/res/values-mn/strings.xml
@@ -49,8 +49,8 @@
<string name="available_via_carrier" msgid="1469036129740799053">"%1$s-р боломжтой"</string>
<string name="osu_opening_provider" msgid="5488997661548640424">"<xliff:g id="PASSPOINTPROVIDER">%1$s</xliff:g>-г нээж байна"</string>
<string name="osu_connect_failed" msgid="2187750899158158934">"Холбогдож чадсангүй"</string>
- <string name="osu_completing_sign_up" msgid="9037638564719197082">"Бүртгүүлэлтийг дуусгаж байна…"</string>
- <string name="osu_sign_up_failed" msgid="7296159750352873260">"Бүртгүүлэлтийг дуусгаж чадсангүй. Дахин оролдохын тулд товшино уу."</string>
+ <string name="osu_completing_sign_up" msgid="9037638564719197082">"Бүртгэлийг дуусгаж байна…"</string>
+ <string name="osu_sign_up_failed" msgid="7296159750352873260">"Бүртгэлийг дуусгаж чадсангүй. Дахин оролдохын тулд товшино уу."</string>
<string name="osu_sign_up_complete" msgid="8207626049093289203">"Бүртгүүлж дууслаа. Холбогдож байна…"</string>
<string name="speed_label_very_slow" msgid="1867055264243608530">"Маш удаан"</string>
<string name="speed_label_slow" msgid="813109590815810235">"Удаан"</string>
@@ -87,8 +87,8 @@
<string name="bluetooth_profile_sap" msgid="5764222021851283125">"SIM Хандалт"</string>
<string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"HD аудио: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
<string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"HD аудио"</string>
- <string name="bluetooth_profile_hearing_aid" msgid="7999237886427812595">"Сонсголын төхөөрөмж"</string>
- <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="7188282786730266159">"Сонсголын төхөөрөмжид холбогдсон"</string>
+ <string name="bluetooth_profile_hearing_aid" msgid="6680721080542444257">"Сонсголын төхөөрөмж"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="3051944447369418317">"Сонсголын төхөөрөмжтэй холбосон"</string>
<string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"Медиа аудиод холбогдсон"</string>
<string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"Утасны аудид холбогдсон"</string>
<string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"Файл дамжуулах серверт холбогдсон"</string>
@@ -105,7 +105,7 @@
<string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"Утасны аудиод ашиглах"</string>
<string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"Файл дамжуулахад ашиглах"</string>
<string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"Оруулахад ашиглах"</string>
- <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="908775281788309484">"Сонсголын төхөөрөмжид ашиглах"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="8843499209204010224">"Сонсголын төхөөрөмжид ашиглах"</string>
<string name="bluetooth_pairing_accept" msgid="6163520056536604875">"Хослуулах"</string>
<string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"ХОСЛУУЛАХ"</string>
<string name="bluetooth_pairing_decline" msgid="4185420413578948140">"Цуцлах"</string>
@@ -136,6 +136,7 @@
<string name="process_kernel_label" msgid="3916858646836739323">"Андройд OS"</string>
<string name="data_usage_uninstalled_apps" msgid="614263770923231598">"Арилгасан апп-ууд"</string>
<string name="data_usage_uninstalled_apps_users" msgid="7986294489899813194">"Арилгасан апп-ууд болон хэрэглэгчид"</string>
+ <string name="data_usage_ota" msgid="5377889154805560860">"Системийн шинэчлэлт"</string>
<string name="tether_settings_title_usb" msgid="6688416425801386511">"USB модем болгох"</string>
<string name="tether_settings_title_wifi" msgid="3277144155960302049">"Зөөврийн сүлжээний цэг"</string>
<string name="tether_settings_title_bluetooth" msgid="355855408317564420">"Bluetooth модем болгох"</string>
diff --git a/packages/SettingsLib/res/values-mr/strings.xml b/packages/SettingsLib/res/values-mr/strings.xml
index a792c4f2de5e..0c2f0eefb0e7 100644
--- a/packages/SettingsLib/res/values-mr/strings.xml
+++ b/packages/SettingsLib/res/values-mr/strings.xml
@@ -87,8 +87,8 @@
<string name="bluetooth_profile_sap" msgid="5764222021851283125">"सिम प्रवेश"</string>
<string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"HD ऑडिओ: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
<string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"HD ऑडिओ"</string>
- <string name="bluetooth_profile_hearing_aid" msgid="7999237886427812595">"ऐकण्याची सुविधा"</string>
- <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="7188282786730266159">"ऐकण्याच्या सुविधेशी कनेक्ट केलेले आहे"</string>
+ <string name="bluetooth_profile_hearing_aid" msgid="6680721080542444257">"श्रवण यंत्रे"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="3051944447369418317">"श्रवण यंत्रांशी कनेक्ट केले आहे"</string>
<string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"मीडिया ऑडिओवर कनेक्ट केले"</string>
<string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"फोन ऑडिओ वर कनेक्ट केले"</string>
<string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"फाईल स्थानांतर सर्व्हरवर कनेक्ट केले"</string>
@@ -105,7 +105,7 @@
<string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"फोन ऑडिओसाठी वापरा"</string>
<string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"फाईल स्थानांतरणासाठी वापरा"</string>
<string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"इनपुट साठी वापरा"</string>
- <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="908775281788309484">"ऐकण्याच्या सुविधेसाठी वापरा"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="8843499209204010224">"श्रवण यंत्रांसाठी वापरा"</string>
<string name="bluetooth_pairing_accept" msgid="6163520056536604875">"पेअर करा"</string>
<string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"पेअर करा"</string>
<string name="bluetooth_pairing_decline" msgid="4185420413578948140">"रद्द करा"</string>
@@ -136,6 +136,8 @@
<string name="process_kernel_label" msgid="3916858646836739323">"Android OS"</string>
<string name="data_usage_uninstalled_apps" msgid="614263770923231598">"काढलेले अॅप्स"</string>
<string name="data_usage_uninstalled_apps_users" msgid="7986294489899813194">"काढलेले अॅप्स आणि वापरकर्ते"</string>
+ <!-- no translation found for data_usage_ota (5377889154805560860) -->
+ <skip />
<string name="tether_settings_title_usb" msgid="6688416425801386511">"USB टेदरिंग"</string>
<string name="tether_settings_title_wifi" msgid="3277144155960302049">"पोर्टेबल हॉटस्पॉट"</string>
<string name="tether_settings_title_bluetooth" msgid="355855408317564420">"ब्लूटूथ टेदरिंग"</string>
diff --git a/packages/SettingsLib/res/values-ms/strings.xml b/packages/SettingsLib/res/values-ms/strings.xml
index 419c6ecd069a..e98418d55fb6 100644
--- a/packages/SettingsLib/res/values-ms/strings.xml
+++ b/packages/SettingsLib/res/values-ms/strings.xml
@@ -87,8 +87,8 @@
<string name="bluetooth_profile_sap" msgid="5764222021851283125">"Akses SIM"</string>
<string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"Audio HD: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
<string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"Audio HD"</string>
- <string name="bluetooth_profile_hearing_aid" msgid="7999237886427812595">"Alat Bantu Pendengaran"</string>
- <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="7188282786730266159">"Disambungkan ke Alat Bantu Pendengaran"</string>
+ <string name="bluetooth_profile_hearing_aid" msgid="6680721080542444257">"Alat Bantu Dengar"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="3051944447369418317">"Disambungkan pada Alat Bantu Dengar"</string>
<string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"Disambungkan ke audio media"</string>
<string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"Disambungkan ke audio telefon"</string>
<string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"Bersambung ke pelayan pemindahan fail"</string>
@@ -105,7 +105,7 @@
<string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"Gunakan untuk audio telefon"</string>
<string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"Gunakan untuk pemindahan fail"</string>
<string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"Gunakan untuk input"</string>
- <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="908775281788309484">"Gunakan untuk Alat Bantu Pendengaran"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="8843499209204010224">"Gunakan untuk Alat Bantu Dengar"</string>
<string name="bluetooth_pairing_accept" msgid="6163520056536604875">"Jadikan pasangan"</string>
<string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"JADIKAN PASANGAN"</string>
<string name="bluetooth_pairing_decline" msgid="4185420413578948140">"Batal"</string>
@@ -136,6 +136,7 @@
<string name="process_kernel_label" msgid="3916858646836739323">"OS Android"</string>
<string name="data_usage_uninstalled_apps" msgid="614263770923231598">"Apl dialih keluar"</string>
<string name="data_usage_uninstalled_apps_users" msgid="7986294489899813194">"Apl dan pengguna yang dialih keluar"</string>
+ <string name="data_usage_ota" msgid="5377889154805560860">"Kemas kini sistem"</string>
<string name="tether_settings_title_usb" msgid="6688416425801386511">"Penambatan USB"</string>
<string name="tether_settings_title_wifi" msgid="3277144155960302049">"Titik panas mudah alih"</string>
<string name="tether_settings_title_bluetooth" msgid="355855408317564420">"Penambatan Bluetooth"</string>
diff --git a/packages/SettingsLib/res/values-my/strings.xml b/packages/SettingsLib/res/values-my/strings.xml
index 3e9e181209b4..ed2aae63f295 100644
--- a/packages/SettingsLib/res/values-my/strings.xml
+++ b/packages/SettingsLib/res/values-my/strings.xml
@@ -87,8 +87,8 @@
<string name="bluetooth_profile_sap" msgid="5764222021851283125">"SIM အသုံးပြုခြင်း"</string>
<string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"HD အသံ- <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
<string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"HD အသံ"</string>
- <string name="bluetooth_profile_hearing_aid" msgid="7999237886427812595">"နားကြားကိရိယာ"</string>
- <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="7188282786730266159">"နားကြားကိရိယာသို့ ချိတ်ဆက်ထားသည်"</string>
+ <string name="bluetooth_profile_hearing_aid" msgid="6680721080542444257">"နားကြားကိရိယာ"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="3051944447369418317">"နားကြားကိရိယာနှင့် ချိတ်ဆက်ပြီးပါပြီ"</string>
<string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"မီဒီယာအသံအား ချိတ်ဆက်ရန်"</string>
<string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"ဖုန်းအသံအား ချိတ်ဆက်ရန်"</string>
<string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"ဖိုင်လွှဲပြောင်းမည့်ဆာဗာနှင့် ချိတ်ဆက်ထားပြီး"</string>
@@ -105,7 +105,7 @@
<string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"ဖုန်းအသံအားအသုံးပြုရန်"</string>
<string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"ဖိုင်လွဲပြောင်းရန်အတွက်အသုံးပြုရန်"</string>
<string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"ထည့်သွင်းရန်အသုံးပြုသည်"</string>
- <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="908775281788309484">"နားကြားကိရိယာအတွက် အသုံးပြုရန်"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="8843499209204010224">"နားကြားကိရိယာအတွက် အသုံးပြုသည်"</string>
<string name="bluetooth_pairing_accept" msgid="6163520056536604875">"အတူတွဲပါ"</string>
<string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"ချိတ်တွဲရန်"</string>
<string name="bluetooth_pairing_decline" msgid="4185420413578948140">"မလုပ်တော့"</string>
@@ -136,6 +136,7 @@
<string name="process_kernel_label" msgid="3916858646836739323">"Android OS"</string>
<string name="data_usage_uninstalled_apps" msgid="614263770923231598">"ဖယ်ရှားထားသော အက်ပ်များ"</string>
<string name="data_usage_uninstalled_apps_users" msgid="7986294489899813194">"ဖယ်ရှားထားသော အပလီကေးရှင်းနှင့် သုံးစွဲသူများ"</string>
+ <string name="data_usage_ota" msgid="5377889154805560860">"စနစ် အပ်ဒိတ်လုပ်ခြင်းများ"</string>
<string name="tether_settings_title_usb" msgid="6688416425801386511">"USB သုံး၍ချိတ်ဆက်ခြင်း"</string>
<string name="tether_settings_title_wifi" msgid="3277144155960302049">"ရွေ့လျားနိုင်သောဟော့စပေါ့"</string>
<string name="tether_settings_title_bluetooth" msgid="355855408317564420">"ဘလူးတုသ်သုံးချိတ်ဆက်ခြင်း"</string>
diff --git a/packages/SettingsLib/res/values-nb/strings.xml b/packages/SettingsLib/res/values-nb/strings.xml
index 65085e8d15d4..93e53e52f968 100644
--- a/packages/SettingsLib/res/values-nb/strings.xml
+++ b/packages/SettingsLib/res/values-nb/strings.xml
@@ -87,8 +87,8 @@
<string name="bluetooth_profile_sap" msgid="5764222021851283125">"Tilgang til SIM-kortet"</string>
<string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"HD-lyd: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
<string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"HD-lyd"</string>
- <string name="bluetooth_profile_hearing_aid" msgid="7999237886427812595">"Høreapparat"</string>
- <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="7188282786730266159">"Koblet til høreapparat"</string>
+ <string name="bluetooth_profile_hearing_aid" msgid="6680721080542444257">"Høreapparater"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="3051944447369418317">"Koblet til høreapparater"</string>
<string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"Koblet til medielyd"</string>
<string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"Koblet til telefonlyd"</string>
<string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"Koblet til tjener for filoverføring"</string>
@@ -105,7 +105,7 @@
<string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"Bruk for telefonlyd"</string>
<string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"Bruk til filoverføring"</string>
<string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"Bruk for inndata"</string>
- <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="908775281788309484">"Bruk for høreapparat"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="8843499209204010224">"Bruk for høreapparater"</string>
<string name="bluetooth_pairing_accept" msgid="6163520056536604875">"Sammenkoble"</string>
<string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"KOBLE TIL"</string>
<string name="bluetooth_pairing_decline" msgid="4185420413578948140">"Avbryt"</string>
@@ -136,6 +136,7 @@
<string name="process_kernel_label" msgid="3916858646836739323">"Android-operativsystem"</string>
<string name="data_usage_uninstalled_apps" msgid="614263770923231598">"Fjernede apper"</string>
<string name="data_usage_uninstalled_apps_users" msgid="7986294489899813194">"Fjernede apper og brukere"</string>
+ <string name="data_usage_ota" msgid="5377889154805560860">"Systemoppdateringer"</string>
<string name="tether_settings_title_usb" msgid="6688416425801386511">"USB-internettdeling"</string>
<string name="tether_settings_title_wifi" msgid="3277144155960302049">"Flyttbar trådløs sone"</string>
<string name="tether_settings_title_bluetooth" msgid="355855408317564420">"Bluetooth-internettdeling"</string>
diff --git a/packages/SettingsLib/res/values-ne/strings.xml b/packages/SettingsLib/res/values-ne/strings.xml
index 16b3b070df7a..7daf9564cc9b 100644
--- a/packages/SettingsLib/res/values-ne/strings.xml
+++ b/packages/SettingsLib/res/values-ne/strings.xml
@@ -38,27 +38,20 @@
<string name="connected_via_network_scorer" msgid="5713793306870815341">"%1$s मार्फत् स्वतः जडान गरिएको"</string>
<string name="connected_via_network_scorer_default" msgid="7867260222020343104">"नेटवर्कको दर्जा प्रदायक मार्फत स्वत: जडान गरिएको"</string>
<string name="connected_via_passpoint" msgid="2826205693803088747">"%1$s मार्फत जडित"</string>
- <!-- no translation found for connected_via_app (5571999941988929520) -->
- <skip />
+ <string name="connected_via_app" msgid="5571999941988929520">"<xliff:g id="NAME">%1$s</xliff:g> मार्फत जडान गरिएको"</string>
<string name="available_via_passpoint" msgid="1617440946846329613">"%1$s मार्फत उपलब्ध"</string>
- <!-- no translation found for tap_to_sign_up (6449724763052579434) -->
- <skip />
+ <string name="tap_to_sign_up" msgid="6449724763052579434">"साइन अप गर्न ट्याप गर्नुहोस्"</string>
<string name="wifi_connected_no_internet" msgid="8202906332837777829">"जडान गरियो तर इन्टरनेट छैन"</string>
<string name="wifi_status_no_internet" msgid="5784710974669608361">"इन्टरनेटमाथिको पहुँच छैन"</string>
<string name="wifi_status_sign_in_required" msgid="123517180404752756">"साइन इन गर्न आवश्यक छ"</string>
<string name="wifi_ap_unable_to_handle_new_sta" msgid="5348824313514404541">"पहुँचसम्बन्धी स्थान अस्थायी रूपमा भरिएको छ"</string>
<string name="connected_via_carrier" msgid="7583780074526041912">"%1$s मार्फत जडान गरियो"</string>
<string name="available_via_carrier" msgid="1469036129740799053">"%1$s मार्फत उपलब्ध"</string>
- <!-- no translation found for osu_opening_provider (5488997661548640424) -->
- <skip />
- <!-- no translation found for osu_connect_failed (2187750899158158934) -->
- <skip />
- <!-- no translation found for osu_completing_sign_up (9037638564719197082) -->
- <skip />
- <!-- no translation found for osu_sign_up_failed (7296159750352873260) -->
- <skip />
- <!-- no translation found for osu_sign_up_complete (8207626049093289203) -->
- <skip />
+ <string name="osu_opening_provider" msgid="5488997661548640424">"<xliff:g id="PASSPOINTPROVIDER">%1$s</xliff:g> खोल्दै"</string>
+ <string name="osu_connect_failed" msgid="2187750899158158934">"जडान गर्न सकिएन"</string>
+ <string name="osu_completing_sign_up" msgid="9037638564719197082">"साइन अप गर्ने कार्य सम्पन्न गर्दै…"</string>
+ <string name="osu_sign_up_failed" msgid="7296159750352873260">"साइन अप गर्ने कार्य सम्पन्न गर्न सकिएन। फेरि प्रयास गर्न ट्याप गर्नुहोस्।"</string>
+ <string name="osu_sign_up_complete" msgid="8207626049093289203">"साइन अप गर्ने कार्य सम्पन्न भयो। जडान गर्दै…"</string>
<string name="speed_label_very_slow" msgid="1867055264243608530">"धेरै ढिलो"</string>
<string name="speed_label_slow" msgid="813109590815810235">"बिस्तारै"</string>
<string name="speed_label_okay" msgid="2331665440671174858">"ठिक छ"</string>
@@ -94,8 +87,8 @@
<string name="bluetooth_profile_sap" msgid="5764222021851283125">"SIM पहुँच"</string>
<string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"HD अडियो: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
<string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"HD अडियो"</string>
- <string name="bluetooth_profile_hearing_aid" msgid="7999237886427812595">"सुन्नमा मद्दत गर्ने यन्त्र"</string>
- <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="7188282786730266159">"सुन्नमा मद्दत गर्ने यन्त्रमा जडान गरियो"</string>
+ <string name="bluetooth_profile_hearing_aid" msgid="6680721080542444257">"श्रवण यन्त्रहरू"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="3051944447369418317">"श्रवण यन्त्रहरूमा जडान गरियो"</string>
<string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"मिडिया अडियोसँग जडित"</string>
<string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"फोन अडियोमा जडान गरियो"</string>
<string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"फाइल ट्रान्सफर सर्भरमा जडान गरियो"</string>
@@ -112,7 +105,7 @@
<string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"फोन अडियोको लागि प्रयोग गर्नुहोस्"</string>
<string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"फाइल ट्रान्सफरका लागि प्रयोग गर्नुहोस्"</string>
<string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"इनपुटको लागि प्रयोग गर्नुहोस्"</string>
- <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="908775281788309484">"सुन्नमा मद्दत गर्ने यन्त्रका लागि प्रयोग गर्नुहोस्"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="8843499209204010224">"श्रवण यन्त्रहरूका लागि प्रयोग गर्नुहोस्"</string>
<string name="bluetooth_pairing_accept" msgid="6163520056536604875">"जोडी"</string>
<string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"जोडी"</string>
<string name="bluetooth_pairing_decline" msgid="4185420413578948140">"रद्द गर्नुहोस्"</string>
@@ -143,6 +136,8 @@
<string name="process_kernel_label" msgid="3916858646836739323">"एन्ड्रोइड OS"</string>
<string name="data_usage_uninstalled_apps" msgid="614263770923231598">"हटाइएका अनुप्रयोगहरू"</string>
<string name="data_usage_uninstalled_apps_users" msgid="7986294489899813194">"अनुप्रयोगहरू र प्रयोगकर्ताहरू हटाइयो।"</string>
+ <!-- no translation found for data_usage_ota (5377889154805560860) -->
+ <skip />
<string name="tether_settings_title_usb" msgid="6688416425801386511">"USB टेथर गर्दै"</string>
<string name="tether_settings_title_wifi" msgid="3277144155960302049">"पोर्टेबल हटस्पट"</string>
<string name="tether_settings_title_bluetooth" msgid="355855408317564420">"ब्लुटुथ टेथर गर्दै"</string>
diff --git a/packages/SettingsLib/res/values-nl/strings.xml b/packages/SettingsLib/res/values-nl/strings.xml
index 2f8c2c2c249a..959c1eac1d7d 100644
--- a/packages/SettingsLib/res/values-nl/strings.xml
+++ b/packages/SettingsLib/res/values-nl/strings.xml
@@ -87,8 +87,8 @@
<string name="bluetooth_profile_sap" msgid="5764222021851283125">"Sim-toegang"</string>
<string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"HD-audio: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
<string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"HD-audio"</string>
- <string name="bluetooth_profile_hearing_aid" msgid="7999237886427812595">"Gehoorapparaat"</string>
- <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="7188282786730266159">"Verbonden met gehoorapparaat"</string>
+ <string name="bluetooth_profile_hearing_aid" msgid="6680721080542444257">"Gehoorapparaten"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="3051944447369418317">"Verbonden met gehoorapparaten"</string>
<string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"Verbonden met audio van medium"</string>
<string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"Verbonden met audio van telefoon"</string>
<string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"Verbonden met server voor bestandsoverdracht"</string>
@@ -105,7 +105,7 @@
<string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"Gebruiken voor audio van telefoon"</string>
<string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"Gebruiken voor bestandsoverdracht"</string>
<string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"Gebruiken voor invoer"</string>
- <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="908775281788309484">"Gebruiken voor gehoorapparaat"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="8843499209204010224">"Gebruiken voor gehoorapparaten"</string>
<string name="bluetooth_pairing_accept" msgid="6163520056536604875">"Koppelen"</string>
<string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"KOPPELEN"</string>
<string name="bluetooth_pairing_decline" msgid="4185420413578948140">"Annuleren"</string>
@@ -136,6 +136,7 @@
<string name="process_kernel_label" msgid="3916858646836739323">"Android-besturingssysteem"</string>
<string name="data_usage_uninstalled_apps" msgid="614263770923231598">"Verwijderde apps"</string>
<string name="data_usage_uninstalled_apps_users" msgid="7986294489899813194">"Verwijderde apps en gebruikers"</string>
+ <string name="data_usage_ota" msgid="5377889154805560860">"Systeemupdates"</string>
<string name="tether_settings_title_usb" msgid="6688416425801386511">"USB-tethering"</string>
<string name="tether_settings_title_wifi" msgid="3277144155960302049">"Draagbare hotspot"</string>
<string name="tether_settings_title_bluetooth" msgid="355855408317564420">"Bluetooth-tethering"</string>
diff --git a/packages/SettingsLib/res/values-or/strings.xml b/packages/SettingsLib/res/values-or/strings.xml
index 95ab7bbab027..54ddf845847e 100644
--- a/packages/SettingsLib/res/values-or/strings.xml
+++ b/packages/SettingsLib/res/values-or/strings.xml
@@ -38,27 +38,20 @@
<string name="connected_via_network_scorer" msgid="5713793306870815341">"%1$s ମାଧ୍ୟମରେ ଅଟୋମେଟିକାଲୀ ସଂଯୁକ୍ତ"</string>
<string name="connected_via_network_scorer_default" msgid="7867260222020343104">"ନେଟୱର୍କ ମୂଲ୍ୟାୟନ ପ୍ରଦାତାଙ୍କ ମାଧ୍ୟମରେ ଅଟୋମେଟିକାଲ୍ୟ ସଂଯୁକ୍ତ"</string>
<string name="connected_via_passpoint" msgid="2826205693803088747">"%1$s ମାଧ୍ୟମରେ ସଂଯୁକ୍ତ"</string>
- <!-- no translation found for connected_via_app (5571999941988929520) -->
- <skip />
+ <string name="connected_via_app" msgid="5571999941988929520">"<xliff:g id="NAME">%1$s</xliff:g> ଦ୍ବାରା ସଂଯୋଗ କରାଯାଇଛି"</string>
<string name="available_via_passpoint" msgid="1617440946846329613">"%1$s ମାଧ୍ୟମରେ ଉପଲବ୍ଧ"</string>
- <!-- no translation found for tap_to_sign_up (6449724763052579434) -->
- <skip />
+ <string name="tap_to_sign_up" msgid="6449724763052579434">"ସାଇନ୍ ଅପ୍ ପାଇଁ ଟାପ୍ କରନ୍ତୁ"</string>
<string name="wifi_connected_no_internet" msgid="8202906332837777829">"ସଂଯୁକ୍ତ, ଇଣ୍ଟର୍‌ନେଟ୍‌ ନାହିଁ"</string>
<string name="wifi_status_no_internet" msgid="5784710974669608361">"କୌଣସି ଇଣ୍ଟରନେଟ୍‌ ନାହିଁ"</string>
<string name="wifi_status_sign_in_required" msgid="123517180404752756">"ସାଇନ୍-ଇନ୍ ଆବଶ୍ୟକ"</string>
<string name="wifi_ap_unable_to_handle_new_sta" msgid="5348824313514404541">"ଆକ୍ସେସ୍ ପଏଣ୍ଟ ସାମୟିକ ଭାବେ ପୂର୍ଣ୍ଣ"</string>
<string name="connected_via_carrier" msgid="7583780074526041912">"%1$s ମାଧ୍ୟମରେ ସଂଯୁକ୍ତ"</string>
<string name="available_via_carrier" msgid="1469036129740799053">"%1$s ମାଧ୍ୟମରେ ଉପଲବ୍ଧ"</string>
- <!-- no translation found for osu_opening_provider (5488997661548640424) -->
- <skip />
- <!-- no translation found for osu_connect_failed (2187750899158158934) -->
- <skip />
- <!-- no translation found for osu_completing_sign_up (9037638564719197082) -->
- <skip />
- <!-- no translation found for osu_sign_up_failed (7296159750352873260) -->
- <skip />
- <!-- no translation found for osu_sign_up_complete (8207626049093289203) -->
- <skip />
+ <string name="osu_opening_provider" msgid="5488997661548640424">"<xliff:g id="PASSPOINTPROVIDER">%1$s</xliff:g> ଖୋଲୁଛି"</string>
+ <string name="osu_connect_failed" msgid="2187750899158158934">"ସଂଯୋଗ କରିହେଲା ନାହିଁ"</string>
+ <string name="osu_completing_sign_up" msgid="9037638564719197082">"ସାଇନ୍ ଅପ୍ ଶେଷ ହେଉଛି…"</string>
+ <string name="osu_sign_up_failed" msgid="7296159750352873260">"ସାଇନ୍ ଅପ୍ ଶେଷ ହୋଇପାରିଲା ନାହିଁ। ପୁଣି ଥରେ ଚେଷ୍ଟା କରିବା ପାଇଁ ଟାପ୍ କରନ୍ତୁ।"</string>
+ <string name="osu_sign_up_complete" msgid="8207626049093289203">"ସାଇନ୍ ଅପ୍ ଶେଷ ହୋଇଛି। ସଂଯୋଗ କରୁଛି…"</string>
<string name="speed_label_very_slow" msgid="1867055264243608530">"ବହୁତ ମନ୍ଥର"</string>
<string name="speed_label_slow" msgid="813109590815810235">"କମ୍‌ ବେଗ"</string>
<string name="speed_label_okay" msgid="2331665440671174858">"ଠିକ୍‌ ଅଛି"</string>
@@ -94,8 +87,8 @@
<string name="bluetooth_profile_sap" msgid="5764222021851283125">"ସିମ୍‌ ଆକ୍ସେସ୍‌"</string>
<string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"HD ଅଡିଓ: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
<string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"HD ଅଡିଓ"</string>
- <string name="bluetooth_profile_hearing_aid" msgid="7999237886427812595">"ଶ୍ରବଣ ଯନ୍ତ୍ର"</string>
- <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="7188282786730266159">"ଶ୍ରବଣ ଯନ୍ତ୍ର ସହିତ ସଂଯୁକ୍ତ ହେଲା"</string>
+ <string name="bluetooth_profile_hearing_aid" msgid="6680721080542444257">"ଶ୍ରବଣ ଯନ୍ତ୍ର"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="3051944447369418317">"ଶ୍ରବଣ ଯନ୍ତ୍ରକୁ ସଂଯୋଗ ହୋଇଛି"</string>
<string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"ମିଡିଆ ଅଡିଓ ସହ ସଂଯୁକ୍ତ"</string>
<string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"ଫୋନ୍‌ ଅଡିଓ ସହିତ ସଂଯୁକ୍ତ"</string>
<string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"ଫାଇଲ୍‌ ଟ୍ରାନ୍ସଫର୍‌ ସର୍ଭର୍‌ ସହ ସଂଯୁକ୍ତ"</string>
@@ -112,7 +105,7 @@
<string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"ଫୋନ୍‌ ଅଡିଓ ପାଇଁ ବ୍ୟବହାର କର"</string>
<string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"ଫାଇଲ୍‌ ଟ୍ରାନ୍ସଫର୍‌ ପାଇଁ ବ୍ୟବହାର କରନ୍ତୁ"</string>
<string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"ଇନ୍‌ପୁଟ୍‌ ପାଇଁ ବ୍ୟବହାର କରନ୍ତୁ"</string>
- <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="908775281788309484">"ଶ୍ରବଣ ଯନ୍ତ୍ର ପାଇଁ ବ୍ୟବହାର କରନ୍ତୁ"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="8843499209204010224">"ଶ୍ରବଣ ଯନ୍ତ୍ର ପାଇଁ ବ୍ୟବହାର କରନ୍ତୁ"</string>
<string name="bluetooth_pairing_accept" msgid="6163520056536604875">"ପେୟାର୍‌"</string>
<string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"ପେୟାର୍‌"</string>
<string name="bluetooth_pairing_decline" msgid="4185420413578948140">"କ୍ୟାନ୍ସଲ୍‌ କରନ୍ତୁ"</string>
@@ -143,6 +136,8 @@
<string name="process_kernel_label" msgid="3916858646836739323">"Android OS"</string>
<string name="data_usage_uninstalled_apps" msgid="614263770923231598">"କଢ଼ାଯାଇଥିବା ଆପ୍‌ଗୁଡ଼ିକ"</string>
<string name="data_usage_uninstalled_apps_users" msgid="7986294489899813194">"ଆପ୍‌ ଏବଂ ଉପଯୋଗକର୍ତ୍ତା ବାହାର କରାଗଲା"</string>
+ <!-- no translation found for data_usage_ota (5377889154805560860) -->
+ <skip />
<string name="tether_settings_title_usb" msgid="6688416425801386511">"USB ଟିଥରିଙ୍ଗ"</string>
<string name="tether_settings_title_wifi" msgid="3277144155960302049">"ପୋର୍ଟବଲ୍‌ ହଟସ୍ପଟ୍‌"</string>
<string name="tether_settings_title_bluetooth" msgid="355855408317564420">"ବ୍ଲୁଟୂଥ ଟିଥରିଙ୍ଗ"</string>
diff --git a/packages/SettingsLib/res/values-pa/strings.xml b/packages/SettingsLib/res/values-pa/strings.xml
index 1ddd862828d2..dcf3e3cb46ec 100644
--- a/packages/SettingsLib/res/values-pa/strings.xml
+++ b/packages/SettingsLib/res/values-pa/strings.xml
@@ -38,27 +38,20 @@
<string name="connected_via_network_scorer" msgid="5713793306870815341">"%1$s ਰਾਹੀਂ ਆਪਣੇ-ਆਪ ਕਨੈਕਟ ਹੋਇਆ"</string>
<string name="connected_via_network_scorer_default" msgid="7867260222020343104">"ਨੈੱਟਵਰਕ ਰੇਟਿੰਗ ਪ੍ਰਦਾਨਕ ਰਾਹੀਂ ਸਵੈਚਲਿਤ ਤੌਰ \'ਤੇ ਕਨੈਕਟ ਹੋਇਆ"</string>
<string name="connected_via_passpoint" msgid="2826205693803088747">"%1$s ਰਾਹੀਂ ਕਨੈਕਟ ਕੀਤਾ"</string>
- <!-- no translation found for connected_via_app (5571999941988929520) -->
- <skip />
+ <string name="connected_via_app" msgid="5571999941988929520">"<xliff:g id="NAME">%1$s</xliff:g> ਰਾਹੀਂ ਕਨੈਕਟ ਕੀਤਾ ਗਿਆ"</string>
<string name="available_via_passpoint" msgid="1617440946846329613">"%1$s ਰਾਹੀਂ ਉਪਲਬਧ"</string>
- <!-- no translation found for tap_to_sign_up (6449724763052579434) -->
- <skip />
+ <string name="tap_to_sign_up" msgid="6449724763052579434">"ਸਾਈਨ-ਅੱਪ ਕਰਨ ਲਈ ਟੈਪ ਕਰੋ"</string>
<string name="wifi_connected_no_internet" msgid="8202906332837777829">"ਕਨੈਕਟ ਕੀਤਾ, ਕੋਈ ਇੰਟਰਨੈੱਟ ਨਹੀਂ"</string>
<string name="wifi_status_no_internet" msgid="5784710974669608361">"ਇੰਟਰਨੈੱਟ ਨਹੀਂ"</string>
<string name="wifi_status_sign_in_required" msgid="123517180404752756">"ਸਾਈਨ-ਇਨ ਲੋੜੀਂਦਾ ਹੈ"</string>
<string name="wifi_ap_unable_to_handle_new_sta" msgid="5348824313514404541">"ਐਕਸੈੱਸ ਪੁਆਇੰਟ ਅਸਥਾਈ ਤੌਰ \'ਤੇ ਸੰਪੂਰਨ ਰੁਝੇਂਵੇਂ ਵਿੱਚ ਹੈ"</string>
<string name="connected_via_carrier" msgid="7583780074526041912">"%1$s ਰਾਹੀਂ ਕਨੈਕਟ ਕੀਤਾ"</string>
<string name="available_via_carrier" msgid="1469036129740799053">"%1$s ਰਾਹੀਂ ਉਪਲਬਧ"</string>
- <!-- no translation found for osu_opening_provider (5488997661548640424) -->
- <skip />
- <!-- no translation found for osu_connect_failed (2187750899158158934) -->
- <skip />
- <!-- no translation found for osu_completing_sign_up (9037638564719197082) -->
- <skip />
- <!-- no translation found for osu_sign_up_failed (7296159750352873260) -->
- <skip />
- <!-- no translation found for osu_sign_up_complete (8207626049093289203) -->
- <skip />
+ <string name="osu_opening_provider" msgid="5488997661548640424">"<xliff:g id="PASSPOINTPROVIDER">%1$s</xliff:g> ਖੋਲ੍ਹਿਆ ਜਾ ਰਿਹਾ ਹੈ"</string>
+ <string name="osu_connect_failed" msgid="2187750899158158934">"ਕਨੈਕਟ ਨਹੀਂ ਕੀਤਾ ਜਾ ਸਕਿਆ"</string>
+ <string name="osu_completing_sign_up" msgid="9037638564719197082">"ਸਾਈਨ-ਅੱਪ ਮੁਕੰਮਲ ਕੀਤਾ ਜਾ ਰਿਹਾ ਹੈ…"</string>
+ <string name="osu_sign_up_failed" msgid="7296159750352873260">"ਸਾਈਨ-ਅੱਪ ਮੁਕੰਮਲ ਨਹੀਂ ਕੀਤਾ ਜਾ ਸਕਿਆ। ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰਨ ਲਈ ਟੈਪ ਕਰੋ।"</string>
+ <string name="osu_sign_up_complete" msgid="8207626049093289203">"ਸਾਈਨ-ਅੱਪ ਮੁਕੰਮਲ ਹੋਇਆ ਕਨੈਕਟ ਹੋ ਰਿਹਾ ਹੈ…"</string>
<string name="speed_label_very_slow" msgid="1867055264243608530">"ਬਹੁਤ ਹੌਲੀ"</string>
<string name="speed_label_slow" msgid="813109590815810235">"ਹੌਲੀ"</string>
<string name="speed_label_okay" msgid="2331665440671174858">"ਠੀਕ ਹੈ"</string>
@@ -94,8 +87,8 @@
<string name="bluetooth_profile_sap" msgid="5764222021851283125">"ਸਿਮ ਪਹੁੰਚ"</string>
<string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"HD ਆਡੀਓ: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
<string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"HD ਆਡੀਓ"</string>
- <string name="bluetooth_profile_hearing_aid" msgid="7999237886427812595">"ਸੁਣਨ ਦਾ ਸਾਧਨ"</string>
- <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="7188282786730266159">"ਸੁਣਨ ਦੇ ਸਾਧਨ ਨਾਲ ਕਨੈਕਟ ਕੀਤਾ ਗਿਆ"</string>
+ <string name="bluetooth_profile_hearing_aid" msgid="6680721080542444257">"ਸੁਣਨ ਦੇ ਸਾਧਨ"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="3051944447369418317">"ਸੁਣਨ ਦੇ ਸਾਧਨਾਂ ਨਾਲ ਕਨੈਕਟ ਕੀਤਾ ਗਿਆ"</string>
<string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"ਮੀਡੀਆ ਆਡੀਓ ਨਾਲ ਕਨੈਕਟ ਕੀਤਾ"</string>
<string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"ਫ਼ੋਨ ਔਡੀਓ ਨਾਲ ਕਨੈਕਟ ਕੀਤਾ"</string>
<string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"ਫਾਈਲ ਟ੍ਰਾਂਸਫ਼ਰ ਸਰਵਰ ਨਾਲ ਕਨੈਕਟ ਕੀਤਾ"</string>
@@ -112,7 +105,7 @@
<string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"ਫ਼ੋਨ ਔਡੀਓ ਲਈ ਵਰਤੋ"</string>
<string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"ਫਾਈਲ ਟ੍ਰਾਂਸਫਰ ਲਈ ਵਰਤੋ"</string>
<string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"ਇਨਪੁਟ ਲਈ ਵਰਤੋ"</string>
- <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="908775281788309484">"ਸੁਣਨ ਦੇ ਸਾਧਨ ਲਈ ਵਰਤੋ"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="8843499209204010224">"ਸੁਣਨ ਦੇ ਸਾਧਨਾਂ ਲਈ ਵਰਤੋ"</string>
<string name="bluetooth_pairing_accept" msgid="6163520056536604875">"ਪੇਅਰ ਕਰੋ"</string>
<string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"ਪੇਅਰ ਕਰੋ"</string>
<string name="bluetooth_pairing_decline" msgid="4185420413578948140">"ਰੱਦ ਕਰੋ"</string>
@@ -143,6 +136,8 @@
<string name="process_kernel_label" msgid="3916858646836739323">"Android OS"</string>
<string name="data_usage_uninstalled_apps" msgid="614263770923231598">"ਹਟਾਏ ਗਏ ਐਪਸ"</string>
<string name="data_usage_uninstalled_apps_users" msgid="7986294489899813194">"ਹਟਾਏ ਗਏ ਐਪਸ ਅਤੇ ਉਪਭੋਗਤਾ"</string>
+ <!-- no translation found for data_usage_ota (5377889154805560860) -->
+ <skip />
<string name="tether_settings_title_usb" msgid="6688416425801386511">"USB ਟੈਦਰਿੰਗ"</string>
<string name="tether_settings_title_wifi" msgid="3277144155960302049">"ਪੋਰਟੇਬਲ ਹੌਟਸਪੌਟ"</string>
<string name="tether_settings_title_bluetooth" msgid="355855408317564420">"ਬਲੂਟੁੱਥ ਟੈਦਰਿੰਗ"</string>
diff --git a/packages/SettingsLib/res/values-pl/strings.xml b/packages/SettingsLib/res/values-pl/strings.xml
index e2109c8c35b0..505e3959244d 100644
--- a/packages/SettingsLib/res/values-pl/strings.xml
+++ b/packages/SettingsLib/res/values-pl/strings.xml
@@ -87,8 +87,8 @@
<string name="bluetooth_profile_sap" msgid="5764222021851283125">"Dostęp do karty SIM"</string>
<string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"Dźwięk HD: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
<string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"Dźwięk HD"</string>
- <string name="bluetooth_profile_hearing_aid" msgid="7999237886427812595">"Aparat słuchowy"</string>
- <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="7188282786730266159">"Po połączeniu z aparatem słuchowym"</string>
+ <string name="bluetooth_profile_hearing_aid" msgid="6680721080542444257">"Aparaty słuchowe"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="3051944447369418317">"Połączono z aparatami słuchowymi"</string>
<string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"Połączono z funkcją audio multimediów"</string>
<string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"Połączono z funkcją audio telefonu"</string>
<string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"Połączono z serwerem transferu plików"</string>
@@ -105,7 +105,7 @@
<string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"Użyj dla funkcji audio telefonu"</string>
<string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"Użyj do transferu plików"</string>
<string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"Użyj do wprowadzania"</string>
- <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="908775281788309484">"Użyj dla funkcji aparatu słuchowego"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="8843499209204010224">"Użyj z aparatami słuchowymi"</string>
<string name="bluetooth_pairing_accept" msgid="6163520056536604875">"Sparuj"</string>
<string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"SPARUJ"</string>
<string name="bluetooth_pairing_decline" msgid="4185420413578948140">"Anuluj"</string>
@@ -136,6 +136,7 @@
<string name="process_kernel_label" msgid="3916858646836739323">"System operacyjny Android"</string>
<string name="data_usage_uninstalled_apps" msgid="614263770923231598">"Usunięte aplikacje"</string>
<string name="data_usage_uninstalled_apps_users" msgid="7986294489899813194">"Usunięte aplikacje i użytkownicy"</string>
+ <string name="data_usage_ota" msgid="5377889154805560860">"Aktualizacje systemu"</string>
<string name="tether_settings_title_usb" msgid="6688416425801386511">"Tethering przez USB"</string>
<string name="tether_settings_title_wifi" msgid="3277144155960302049">"Przenośny punkt dostępu"</string>
<string name="tether_settings_title_bluetooth" msgid="355855408317564420">"Tethering przez Bluetooth"</string>
diff --git a/packages/SettingsLib/res/values-pt-rBR/strings.xml b/packages/SettingsLib/res/values-pt-rBR/strings.xml
index 19e22e420026..c0f31a6a5f73 100644
--- a/packages/SettingsLib/res/values-pt-rBR/strings.xml
+++ b/packages/SettingsLib/res/values-pt-rBR/strings.xml
@@ -87,8 +87,8 @@
<string name="bluetooth_profile_sap" msgid="5764222021851283125">"Acesso ao chip"</string>
<string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"Áudio HD: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
<string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"Áudio HD"</string>
- <string name="bluetooth_profile_hearing_aid" msgid="7999237886427812595">"Aparelho auditivo"</string>
- <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="7188282786730266159">"Conectado a um aparelho auditivo"</string>
+ <string name="bluetooth_profile_hearing_aid" msgid="6680721080542444257">"Aparelhos auditivos"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="3051944447369418317">"Conectado a aparelhos auditivos"</string>
<string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"Conectado ao áudio da mídia"</string>
<string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"Conectado ao áudio do smartphone"</string>
<string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"Conectado ao servidor de transferência de arquivo"</string>
@@ -105,7 +105,7 @@
<string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"Usar para áudio do smartphone"</string>
<string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"Usado para transferência de arquivo"</string>
<string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"Usar para entrada"</string>
- <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="908775281788309484">"Usar para aparelho auditivo"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="8843499209204010224">"Usar para aparelhos auditivos"</string>
<string name="bluetooth_pairing_accept" msgid="6163520056536604875">"Parear"</string>
<string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"PAREAR"</string>
<string name="bluetooth_pairing_decline" msgid="4185420413578948140">"Cancelar"</string>
@@ -136,6 +136,7 @@
<string name="process_kernel_label" msgid="3916858646836739323">"Sistema operacional Android"</string>
<string name="data_usage_uninstalled_apps" msgid="614263770923231598">"Apps removidos"</string>
<string name="data_usage_uninstalled_apps_users" msgid="7986294489899813194">"Apps e usuários removidos"</string>
+ <string name="data_usage_ota" msgid="5377889154805560860">"Atualizações do sistema"</string>
<string name="tether_settings_title_usb" msgid="6688416425801386511">"Tethering USB"</string>
<string name="tether_settings_title_wifi" msgid="3277144155960302049">"Ponto de acesso portátil"</string>
<string name="tether_settings_title_bluetooth" msgid="355855408317564420">"Tethering Bluetooth"</string>
diff --git a/packages/SettingsLib/res/values-pt-rPT/strings.xml b/packages/SettingsLib/res/values-pt-rPT/strings.xml
index 1f1072c08ffa..08c3cc82c259 100644
--- a/packages/SettingsLib/res/values-pt-rPT/strings.xml
+++ b/packages/SettingsLib/res/values-pt-rPT/strings.xml
@@ -87,8 +87,8 @@
<string name="bluetooth_profile_sap" msgid="5764222021851283125">"Acesso ao SIM"</string>
<string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"Áudio HD: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
<string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"Áudio HD"</string>
- <string name="bluetooth_profile_hearing_aid" msgid="7999237886427812595">"Aparelho auditivo"</string>
- <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="7188282786730266159">"Associar ao aparelho auditivo"</string>
+ <string name="bluetooth_profile_hearing_aid" msgid="6680721080542444257">"Aparelhos auditivos"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="3051944447369418317">"Ligado a aparelhos auditivos"</string>
<string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"Ligado ao áudio de multimédia"</string>
<string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"Ligado ao áudio do telefone"</string>
<string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"Ligado ao servidor de transferência de ficheiros"</string>
@@ -105,7 +105,7 @@
<string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"Utilizar para áudio do telefone"</string>
<string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"Utilizar para transferência de ficheiros"</string>
<string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"Utilizar para entrada"</string>
- <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="908775281788309484">"Utilizar com o aparelho auditivo"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="8843499209204010224">"Utilizar para aparelhos auditivos"</string>
<string name="bluetooth_pairing_accept" msgid="6163520056536604875">"Sincr."</string>
<string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"SINCRONIZAR"</string>
<string name="bluetooth_pairing_decline" msgid="4185420413578948140">"Cancelar"</string>
@@ -136,6 +136,7 @@
<string name="process_kernel_label" msgid="3916858646836739323">"SO Android"</string>
<string name="data_usage_uninstalled_apps" msgid="614263770923231598">"Aplicações removidas"</string>
<string name="data_usage_uninstalled_apps_users" msgid="7986294489899813194">"Aplicações e utilizadores removidos"</string>
+ <string name="data_usage_ota" msgid="5377889154805560860">"Atualizações do sistema"</string>
<string name="tether_settings_title_usb" msgid="6688416425801386511">"Ligação USB"</string>
<string name="tether_settings_title_wifi" msgid="3277144155960302049">"Hotspot portátil"</string>
<string name="tether_settings_title_bluetooth" msgid="355855408317564420">"Ligação Bluetooth"</string>
diff --git a/packages/SettingsLib/res/values-pt/strings.xml b/packages/SettingsLib/res/values-pt/strings.xml
index 19e22e420026..c0f31a6a5f73 100644
--- a/packages/SettingsLib/res/values-pt/strings.xml
+++ b/packages/SettingsLib/res/values-pt/strings.xml
@@ -87,8 +87,8 @@
<string name="bluetooth_profile_sap" msgid="5764222021851283125">"Acesso ao chip"</string>
<string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"Áudio HD: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
<string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"Áudio HD"</string>
- <string name="bluetooth_profile_hearing_aid" msgid="7999237886427812595">"Aparelho auditivo"</string>
- <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="7188282786730266159">"Conectado a um aparelho auditivo"</string>
+ <string name="bluetooth_profile_hearing_aid" msgid="6680721080542444257">"Aparelhos auditivos"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="3051944447369418317">"Conectado a aparelhos auditivos"</string>
<string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"Conectado ao áudio da mídia"</string>
<string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"Conectado ao áudio do smartphone"</string>
<string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"Conectado ao servidor de transferência de arquivo"</string>
@@ -105,7 +105,7 @@
<string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"Usar para áudio do smartphone"</string>
<string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"Usado para transferência de arquivo"</string>
<string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"Usar para entrada"</string>
- <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="908775281788309484">"Usar para aparelho auditivo"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="8843499209204010224">"Usar para aparelhos auditivos"</string>
<string name="bluetooth_pairing_accept" msgid="6163520056536604875">"Parear"</string>
<string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"PAREAR"</string>
<string name="bluetooth_pairing_decline" msgid="4185420413578948140">"Cancelar"</string>
@@ -136,6 +136,7 @@
<string name="process_kernel_label" msgid="3916858646836739323">"Sistema operacional Android"</string>
<string name="data_usage_uninstalled_apps" msgid="614263770923231598">"Apps removidos"</string>
<string name="data_usage_uninstalled_apps_users" msgid="7986294489899813194">"Apps e usuários removidos"</string>
+ <string name="data_usage_ota" msgid="5377889154805560860">"Atualizações do sistema"</string>
<string name="tether_settings_title_usb" msgid="6688416425801386511">"Tethering USB"</string>
<string name="tether_settings_title_wifi" msgid="3277144155960302049">"Ponto de acesso portátil"</string>
<string name="tether_settings_title_bluetooth" msgid="355855408317564420">"Tethering Bluetooth"</string>
diff --git a/packages/SettingsLib/res/values-ro/strings.xml b/packages/SettingsLib/res/values-ro/strings.xml
index 7fa75a8862cf..015eb9240fc5 100644
--- a/packages/SettingsLib/res/values-ro/strings.xml
+++ b/packages/SettingsLib/res/values-ro/strings.xml
@@ -87,8 +87,8 @@
<string name="bluetooth_profile_sap" msgid="5764222021851283125">"Acces la SIM"</string>
<string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"Audio HD: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
<string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"Audio HD"</string>
- <string name="bluetooth_profile_hearing_aid" msgid="7999237886427812595">"Aparat auditiv"</string>
- <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="7188282786730266159">"Conectat la aparatul auditiv"</string>
+ <string name="bluetooth_profile_hearing_aid" msgid="6680721080542444257">"Aparate auditive"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="3051944447369418317">"Conectat la aparatul auditiv"</string>
<string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"Conectat la profilul pentru conținut media audio"</string>
<string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"Conectat la componenta audio a telefonului"</string>
<string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"Conectat la serverul de transfer de fișiere"</string>
@@ -105,7 +105,7 @@
<string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"Utilizați pentru componenta audio a telefonului"</string>
<string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"Utilizați pentru transferul de fișiere"</string>
<string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"Utilizați pentru introducere date"</string>
- <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="908775281788309484">"Utilizați pentru aparatul auditiv"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="8843499209204010224">"Folosiți pentru aparatele auditive"</string>
<string name="bluetooth_pairing_accept" msgid="6163520056536604875">"Asociați"</string>
<string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"CONECTAȚI"</string>
<string name="bluetooth_pairing_decline" msgid="4185420413578948140">"Anulați"</string>
@@ -136,6 +136,7 @@
<string name="process_kernel_label" msgid="3916858646836739323">"Sistem de operare Android"</string>
<string name="data_usage_uninstalled_apps" msgid="614263770923231598">"Aplicații eliminate"</string>
<string name="data_usage_uninstalled_apps_users" msgid="7986294489899813194">"Aplicații și utilizatori eliminați"</string>
+ <string name="data_usage_ota" msgid="5377889154805560860">"Actualizări de sistem"</string>
<string name="tether_settings_title_usb" msgid="6688416425801386511">"Tethering prin USB"</string>
<string name="tether_settings_title_wifi" msgid="3277144155960302049">"Hotspot portabil"</string>
<string name="tether_settings_title_bluetooth" msgid="355855408317564420">"Tethering prin Bluetooth"</string>
diff --git a/packages/SettingsLib/res/values-ru/strings.xml b/packages/SettingsLib/res/values-ru/strings.xml
index 6cdfd3c3f318..b0b592caf6c7 100644
--- a/packages/SettingsLib/res/values-ru/strings.xml
+++ b/packages/SettingsLib/res/values-ru/strings.xml
@@ -87,8 +87,8 @@
<string name="bluetooth_profile_sap" msgid="5764222021851283125">"Доступ к SIM-карте"</string>
<string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"HD Audio: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
<string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"HD Audio"</string>
- <string name="bluetooth_profile_hearing_aid" msgid="7999237886427812595">"Слуховой аппарат"</string>
- <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="7188282786730266159">"Подключен к слуховому аппарату"</string>
+ <string name="bluetooth_profile_hearing_aid" msgid="6680721080542444257">"Слуховые аппараты"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="3051944447369418317">"Слуховой аппарат подключен"</string>
<string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"Подключено к мультимедийному аудиоустройству"</string>
<string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"Подключено к аудиоустройству телефона"</string>
<string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"Установлено подключение к серверу передачи файлов"</string>
@@ -105,7 +105,7 @@
<string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"Использовать для аудиоустройства телефона"</string>
<string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"Используется для передачи файлов"</string>
<string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"Использовать для ввода"</string>
- <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="908775281788309484">"Использовать для слухового аппарата"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="8843499209204010224">"Использовать для слухового аппарата"</string>
<string name="bluetooth_pairing_accept" msgid="6163520056536604875">"Добавить"</string>
<string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"ДОБАВИТЬ"</string>
<string name="bluetooth_pairing_decline" msgid="4185420413578948140">"Отмена"</string>
@@ -136,6 +136,7 @@
<string name="process_kernel_label" msgid="3916858646836739323">"ОС Android"</string>
<string name="data_usage_uninstalled_apps" msgid="614263770923231598">"Удаленные приложения"</string>
<string name="data_usage_uninstalled_apps_users" msgid="7986294489899813194">"Удаленные приложения и пользователи"</string>
+ <string name="data_usage_ota" msgid="5377889154805560860">"Обновления системы"</string>
<string name="tether_settings_title_usb" msgid="6688416425801386511">"USB-модем"</string>
<string name="tether_settings_title_wifi" msgid="3277144155960302049">"Точка доступа Wi-Fi"</string>
<string name="tether_settings_title_bluetooth" msgid="355855408317564420">"Bluetooth-модем"</string>
diff --git a/packages/SettingsLib/res/values-si/strings.xml b/packages/SettingsLib/res/values-si/strings.xml
index f85289c64527..ca7a96227d99 100644
--- a/packages/SettingsLib/res/values-si/strings.xml
+++ b/packages/SettingsLib/res/values-si/strings.xml
@@ -87,8 +87,8 @@
<string name="bluetooth_profile_sap" msgid="5764222021851283125">"SIM ප්‍රවේශය"</string>
<string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"HD ශ්‍රව්‍යය: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
<string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"HD ශ්‍රව්‍යය"</string>
- <string name="bluetooth_profile_hearing_aid" msgid="7999237886427812595">"ශ්‍රවණාධාරකය"</string>
- <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="7188282786730266159">"ශ්‍රවණාධාරකයට සම්බන්ධයි"</string>
+ <string name="bluetooth_profile_hearing_aid" msgid="6680721080542444257">"ශ්‍රවණාධාරක"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="3051944447369418317">"ශ්‍රවණාධාරක වෙත සම්බන්ධ කළා"</string>
<string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"මාධ්‍ය ශ්‍රව්‍යට සම්බන්ධ විය"</string>
<string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"දුරකතනයේ ශ්‍රව්‍යට සම්බන්ධ විය"</string>
<string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"ගොනු හුවමාරු සේවාදායකය සමග සම්බන්ධ විය"</string>
@@ -105,7 +105,7 @@
<string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"දුරකථන ශ්‍රව්‍ය සඳහා භාවිතා කෙරේ"</string>
<string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"ගොනු හුවමාරුව සඳහා භාවිතා කරන්න"</string>
<string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"ආදානය සඳහා භාවිතා කරන්න"</string>
- <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="908775281788309484">"ශ්‍රවණාධාරකය සඳහා භාවිත කරන්න"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="8843499209204010224">"ශ්‍රවණාධාර සඳහා භාවිත කරන්න"</string>
<string name="bluetooth_pairing_accept" msgid="6163520056536604875">"යුගල කරන්න"</string>
<string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"යුගල කරන්න"</string>
<string name="bluetooth_pairing_decline" msgid="4185420413578948140">"අවලංගු කරන්න"</string>
@@ -136,6 +136,7 @@
<string name="process_kernel_label" msgid="3916858646836739323">"Android OS"</string>
<string name="data_usage_uninstalled_apps" msgid="614263770923231598">"ඉවත් කළ යෙදුම්"</string>
<string name="data_usage_uninstalled_apps_users" msgid="7986294489899813194">"යෙදුම් සහ පරිශීලකයින් ඉවත් කරන ලදි"</string>
+ <string name="data_usage_ota" msgid="5377889154805560860">"පද්ධති යාවත්කාලීන"</string>
<string name="tether_settings_title_usb" msgid="6688416425801386511">"USB ටෙදරින්"</string>
<string name="tether_settings_title_wifi" msgid="3277144155960302049">"ජංගම හොට්ස්පොට්"</string>
<string name="tether_settings_title_bluetooth" msgid="355855408317564420">"බ්ලූටූත් ටෙදරින්"</string>
diff --git a/packages/SettingsLib/res/values-sk/strings.xml b/packages/SettingsLib/res/values-sk/strings.xml
index eae5be7952c3..dd7efdd50a59 100644
--- a/packages/SettingsLib/res/values-sk/strings.xml
+++ b/packages/SettingsLib/res/values-sk/strings.xml
@@ -87,8 +87,8 @@
<string name="bluetooth_profile_sap" msgid="5764222021851283125">"Prístup k SIM karte"</string>
<string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"HD zvuk: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
<string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"HD zvuk"</string>
- <string name="bluetooth_profile_hearing_aid" msgid="7999237886427812595">"Načúvacia pomôcka"</string>
- <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="7188282786730266159">"Pripojené k načúvacej pomôcke"</string>
+ <string name="bluetooth_profile_hearing_aid" msgid="6680721080542444257">"Načúvacie pomôcky"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="3051944447369418317">"Pripojené k načúvacím pomôckam"</string>
<string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"Pripojené ku zvukovému médiu"</string>
<string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"Pripojené ku zvuku telefónu"</string>
<string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"Pripojené na server pre prenos údajov"</string>
@@ -105,7 +105,7 @@
<string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"Použiť pre zvuk telefónu"</string>
<string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"Použiť na prenos súborov"</string>
<string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"Použiť pre vstup"</string>
- <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="908775281788309484">"Použitie načúvacej pomôcky"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="8843499209204010224">"Použiť pre načúvacie pomôcky"</string>
<string name="bluetooth_pairing_accept" msgid="6163520056536604875">"Párovať"</string>
<string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"PÁROVAŤ"</string>
<string name="bluetooth_pairing_decline" msgid="4185420413578948140">"Zrušiť"</string>
@@ -136,6 +136,7 @@
<string name="process_kernel_label" msgid="3916858646836739323">"OS Android"</string>
<string name="data_usage_uninstalled_apps" msgid="614263770923231598">"Odstránené aplikácie"</string>
<string name="data_usage_uninstalled_apps_users" msgid="7986294489899813194">"Odstránené aplikácie a používatelia"</string>
+ <string name="data_usage_ota" msgid="5377889154805560860">"Aktualizácie systému"</string>
<string name="tether_settings_title_usb" msgid="6688416425801386511">"Pripojenie cez USB"</string>
<string name="tether_settings_title_wifi" msgid="3277144155960302049">"Prenosný prístupový bod"</string>
<string name="tether_settings_title_bluetooth" msgid="355855408317564420">"Pripojenie cez Bluetooth"</string>
diff --git a/packages/SettingsLib/res/values-sl/strings.xml b/packages/SettingsLib/res/values-sl/strings.xml
index bef9a3e5aadd..fada686f00d1 100644
--- a/packages/SettingsLib/res/values-sl/strings.xml
+++ b/packages/SettingsLib/res/values-sl/strings.xml
@@ -87,8 +87,8 @@
<string name="bluetooth_profile_sap" msgid="5764222021851283125">"Dostop do kartice SIM"</string>
<string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"Zvok visoke kakovosti: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
<string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"Zvok visoke kakovosti"</string>
- <string name="bluetooth_profile_hearing_aid" msgid="7999237886427812595">"Slušni pripomoček"</string>
- <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="7188282786730266159">"Povezava s slušnim pripomočkom je vzpostavljena"</string>
+ <string name="bluetooth_profile_hearing_aid" msgid="6680721080542444257">"Slušni pripomočki"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="3051944447369418317">"Povezava s slušnimi pripomočki je vzpostavljena"</string>
<string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"Povezan s profilom za predstavnostni zvok"</string>
<string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"Povezava s profilom za zvok telefona vzpostavljena"</string>
<string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"Povezava s strežnikom za prenos datotek je vzpostavljena"</string>
@@ -105,7 +105,7 @@
<string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"Uporabi za zvok telefona"</string>
<string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"Uporabi za prenos datotek"</string>
<string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"Uporabi za vnos"</string>
- <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="908775281788309484">"Uporaba za slušni pripomoček"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="8843499209204010224">"Uporabi za slušne pripomočke"</string>
<string name="bluetooth_pairing_accept" msgid="6163520056536604875">"Seznani"</string>
<string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"SEZNANI"</string>
<string name="bluetooth_pairing_decline" msgid="4185420413578948140">"Prekliči"</string>
@@ -136,6 +136,7 @@
<string name="process_kernel_label" msgid="3916858646836739323">"OS Android"</string>
<string name="data_usage_uninstalled_apps" msgid="614263770923231598">"Odstranjene aplikacije"</string>
<string name="data_usage_uninstalled_apps_users" msgid="7986294489899813194">"Odstranjene aplikacije in uporabniki"</string>
+ <string name="data_usage_ota" msgid="5377889154805560860">"Posodobitve sistema"</string>
<string name="tether_settings_title_usb" msgid="6688416425801386511">"Internet prek USB-ja"</string>
<string name="tether_settings_title_wifi" msgid="3277144155960302049">"Prenosna dostopna točka"</string>
<string name="tether_settings_title_bluetooth" msgid="355855408317564420">"Internet prek Bluetootha"</string>
diff --git a/packages/SettingsLib/res/values-sq/strings.xml b/packages/SettingsLib/res/values-sq/strings.xml
index 8bb67f9a348f..2132767193c5 100644
--- a/packages/SettingsLib/res/values-sq/strings.xml
+++ b/packages/SettingsLib/res/values-sq/strings.xml
@@ -87,8 +87,8 @@
<string name="bluetooth_profile_sap" msgid="5764222021851283125">"Qasje në kartën SIM"</string>
<string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"Audio HD: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
<string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"Audio HD"</string>
- <string name="bluetooth_profile_hearing_aid" msgid="7999237886427812595">"Aparati i dëgjimit"</string>
- <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="7188282786730266159">"Lidhur me aparatin e dëgjimit"</string>
+ <string name="bluetooth_profile_hearing_aid" msgid="6680721080542444257">"Aparatet e dëgjimit"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="3051944447369418317">"Lidhur me aparatet e dëgjimit"</string>
<string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"U lidh me audion e medias"</string>
<string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"U lidh me audion e telefonit"</string>
<string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"U lidh me serverin e transferimit të skedarëve"</string>
@@ -105,7 +105,7 @@
<string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"Përdor për audion e telefonit"</string>
<string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"Përdor për transferimin e skedarëve"</string>
<string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"Përdore për hyrjen"</string>
- <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="908775281788309484">"Përdore për aparatin e dëgjimit"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="8843499209204010224">"Përdore për aparatet e dëgjimit"</string>
<string name="bluetooth_pairing_accept" msgid="6163520056536604875">"Çifto"</string>
<string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"ÇIFTO"</string>
<string name="bluetooth_pairing_decline" msgid="4185420413578948140">"Anulo"</string>
@@ -136,6 +136,7 @@
<string name="process_kernel_label" msgid="3916858646836739323">"Sistemi operativ Android"</string>
<string name="data_usage_uninstalled_apps" msgid="614263770923231598">"Aplikacionet e hequra"</string>
<string name="data_usage_uninstalled_apps_users" msgid="7986294489899813194">"Aplikacionet dhe përdoruesit e hequr"</string>
+ <string name="data_usage_ota" msgid="5377889154805560860">"Përditësimet e sistemit"</string>
<string name="tether_settings_title_usb" msgid="6688416425801386511">"Ndarje përmes USB-së"</string>
<string name="tether_settings_title_wifi" msgid="3277144155960302049">"Zona e qasjes e lëvizshme"</string>
<string name="tether_settings_title_bluetooth" msgid="355855408317564420">"Ndarje interneti përmes Bluetooth-it"</string>
diff --git a/packages/SettingsLib/res/values-sr/strings.xml b/packages/SettingsLib/res/values-sr/strings.xml
index 4378a463c839..6cf4b208c544 100644
--- a/packages/SettingsLib/res/values-sr/strings.xml
+++ b/packages/SettingsLib/res/values-sr/strings.xml
@@ -87,8 +87,8 @@
<string name="bluetooth_profile_sap" msgid="5764222021851283125">"Приступ SIM картици"</string>
<string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"HD звук: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
<string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"HD звук"</string>
- <string name="bluetooth_profile_hearing_aid" msgid="7999237886427812595">"Слушни апарат"</string>
- <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="7188282786730266159">"Повезано са слушним апаратом"</string>
+ <string name="bluetooth_profile_hearing_aid" msgid="6680721080542444257">"Слушни апарати"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="3051944447369418317">"Повезано са слушним апаратима"</string>
<string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"Повезано са звуком медија"</string>
<string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"Повезано са звуком телефона"</string>
<string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"Повезано са сервером за пренос датотека"</string>
@@ -105,7 +105,7 @@
<string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"Коришћење за аудио телефона"</string>
<string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"Коришћење за пренос датотека"</string>
<string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"Користи за улаз"</string>
- <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="908775281788309484">"Користи за слушни апарат"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="8843499209204010224">"Користи за слушне апарате"</string>
<string name="bluetooth_pairing_accept" msgid="6163520056536604875">"Упари"</string>
<string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"УПАРИ"</string>
<string name="bluetooth_pairing_decline" msgid="4185420413578948140">"Откажи"</string>
@@ -136,6 +136,7 @@
<string name="process_kernel_label" msgid="3916858646836739323">"Android ОС"</string>
<string name="data_usage_uninstalled_apps" msgid="614263770923231598">"Уклоњене апликације"</string>
<string name="data_usage_uninstalled_apps_users" msgid="7986294489899813194">"Уклоњене апликације и корисници"</string>
+ <string name="data_usage_ota" msgid="5377889154805560860">"Ажурирања система"</string>
<string name="tether_settings_title_usb" msgid="6688416425801386511">"USB Интернет повезивање"</string>
<string name="tether_settings_title_wifi" msgid="3277144155960302049">"Преносни хотспот"</string>
<string name="tether_settings_title_bluetooth" msgid="355855408317564420">"Bluetooth привезивање"</string>
diff --git a/packages/SettingsLib/res/values-sv/strings.xml b/packages/SettingsLib/res/values-sv/strings.xml
index 3fcb6dc80713..f2950dcf2808 100644
--- a/packages/SettingsLib/res/values-sv/strings.xml
+++ b/packages/SettingsLib/res/values-sv/strings.xml
@@ -87,8 +87,8 @@
<string name="bluetooth_profile_sap" msgid="5764222021851283125">"SIM-åtkomst"</string>
<string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"HD-ljud: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
<string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"HD-ljud"</string>
- <string name="bluetooth_profile_hearing_aid" msgid="7999237886427812595">"Hörapparat"</string>
- <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="7188282786730266159">"Ansluten till hörapparat"</string>
+ <string name="bluetooth_profile_hearing_aid" msgid="6680721080542444257">"Hörapparater"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="3051944447369418317">"Ansluten till hörapparater"</string>
<string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"Ansluten till medialjud"</string>
<string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"Ansluten till telefonens ljud"</string>
<string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"Ansluten till filöverföringsserver"</string>
@@ -105,7 +105,7 @@
<string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"Använd för telefonens ljud"</string>
<string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"Använd för filöverföring"</string>
<string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"Använd för inmatning"</string>
- <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="908775281788309484">"Använd med hörapparat"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="8843499209204010224">"Använd med hörapparater"</string>
<string name="bluetooth_pairing_accept" msgid="6163520056536604875">"Parkoppling"</string>
<string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"PARKOPPLA"</string>
<string name="bluetooth_pairing_decline" msgid="4185420413578948140">"Avbryt"</string>
@@ -136,6 +136,7 @@
<string name="process_kernel_label" msgid="3916858646836739323">"Operativsystemet Android"</string>
<string name="data_usage_uninstalled_apps" msgid="614263770923231598">"Borttagna appar"</string>
<string name="data_usage_uninstalled_apps_users" msgid="7986294489899813194">"Borttagna appar och användare"</string>
+ <string name="data_usage_ota" msgid="5377889154805560860">"Systemuppdateringar"</string>
<string name="tether_settings_title_usb" msgid="6688416425801386511">"Internetdelning via USB"</string>
<string name="tether_settings_title_wifi" msgid="3277144155960302049">"Mobil surfzon"</string>
<string name="tether_settings_title_bluetooth" msgid="355855408317564420">"Delning via Bluetooth"</string>
diff --git a/packages/SettingsLib/res/values-sw/strings.xml b/packages/SettingsLib/res/values-sw/strings.xml
index 47c7bb2187ef..d8a74a14c40f 100644
--- a/packages/SettingsLib/res/values-sw/strings.xml
+++ b/packages/SettingsLib/res/values-sw/strings.xml
@@ -87,8 +87,8 @@
<string name="bluetooth_profile_sap" msgid="5764222021851283125">"Ufikiaji wa SIM"</string>
<string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"Sauti ya HD: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
<string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"Sauti ya HD"</string>
- <string name="bluetooth_profile_hearing_aid" msgid="7999237886427812595">"Visaidizi vya Kusikia"</string>
- <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="7188282786730266159">"Imeunganishwa kwenye Visaidizi vya Kusikia"</string>
+ <string name="bluetooth_profile_hearing_aid" msgid="6680721080542444257">"Vifaa vya Kusaidia Kusikia"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="3051944447369418317">"Imeunganishwa kwenye Vifaa vya Kusaidia Kusikia"</string>
<string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"Imeunganishwa kwenye sikika ya njia ya mawasiliano"</string>
<string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"Imeunganishwa kwenye sauti ya simu"</string>
<string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"Imeunganishwa kwenye seva ya kuhamisha faili"</string>
@@ -105,7 +105,7 @@
<string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"Tumia kwa sauti ya simu"</string>
<string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"Tumia kwa hali faili"</string>
<string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"Tumia kwa kuingiza"</string>
- <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="908775281788309484">"Tumia katika Visaidizi vya Kusikia"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="8843499209204010224">"Tumia kwenye Vifaa vya Kusaidia Kusikia"</string>
<string name="bluetooth_pairing_accept" msgid="6163520056536604875">"Oanisha"</string>
<string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"OANISHA"</string>
<string name="bluetooth_pairing_decline" msgid="4185420413578948140">"Ghairi"</string>
@@ -136,6 +136,7 @@
<string name="process_kernel_label" msgid="3916858646836739323">"OS ya Android"</string>
<string name="data_usage_uninstalled_apps" msgid="614263770923231598">"Programu zilizoondolewa"</string>
<string name="data_usage_uninstalled_apps_users" msgid="7986294489899813194">"Watumiaji na programu ziilizoondolewa"</string>
+ <string name="data_usage_ota" msgid="5377889154805560860">"Masasisho ya mfumo"</string>
<string name="tether_settings_title_usb" msgid="6688416425801386511">"Shiriki intaneti kwa USB"</string>
<string name="tether_settings_title_wifi" msgid="3277144155960302049">"Intaneti ya kusambazwa"</string>
<string name="tether_settings_title_bluetooth" msgid="355855408317564420">"Shiriki intaneti kwa Bluetooth"</string>
diff --git a/packages/SettingsLib/res/values-ta/strings.xml b/packages/SettingsLib/res/values-ta/strings.xml
index 63c6cd9b11f2..71716cec6886 100644
--- a/packages/SettingsLib/res/values-ta/strings.xml
+++ b/packages/SettingsLib/res/values-ta/strings.xml
@@ -38,27 +38,20 @@
<string name="connected_via_network_scorer" msgid="5713793306870815341">"%1$s மூலம் தானாக இணைக்கப்பட்டது"</string>
<string name="connected_via_network_scorer_default" msgid="7867260222020343104">"நெட்வொர்க் மதிப்பீடு வழங்குநரால் தானாக இணைக்கப்பட்டது"</string>
<string name="connected_via_passpoint" msgid="2826205693803088747">"%1$s வழியாக இணைக்கப்பட்டது"</string>
- <!-- no translation found for connected_via_app (5571999941988929520) -->
- <skip />
+ <string name="connected_via_app" msgid="5571999941988929520">"<xliff:g id="NAME">%1$s</xliff:g> மூலம் இணைக்கப்பட்டது"</string>
<string name="available_via_passpoint" msgid="1617440946846329613">"%1$s வழியாகக் கிடைக்கிறது"</string>
- <!-- no translation found for tap_to_sign_up (6449724763052579434) -->
- <skip />
+ <string name="tap_to_sign_up" msgid="6449724763052579434">"பதிவு செய்யத் தட்டவும்"</string>
<string name="wifi_connected_no_internet" msgid="8202906332837777829">"இணைக்கப்பட்டுள்ளது, ஆனால் இண்டர்நெட் இல்லை"</string>
<string name="wifi_status_no_internet" msgid="5784710974669608361">"இணைய இணைப்பு இல்லை"</string>
<string name="wifi_status_sign_in_required" msgid="123517180404752756">"உள்நுழைய வேண்டும்"</string>
<string name="wifi_ap_unable_to_handle_new_sta" msgid="5348824313514404541">"தற்காலிகமாக அணுகல் புள்ளி நிரம்பியுள்ளது"</string>
<string name="connected_via_carrier" msgid="7583780074526041912">"%1$s வழியாக இணைக்கப்பட்டது"</string>
<string name="available_via_carrier" msgid="1469036129740799053">"%1$s வழியாகக் கிடைக்கிறது"</string>
- <!-- no translation found for osu_opening_provider (5488997661548640424) -->
- <skip />
- <!-- no translation found for osu_connect_failed (2187750899158158934) -->
- <skip />
- <!-- no translation found for osu_completing_sign_up (9037638564719197082) -->
- <skip />
- <!-- no translation found for osu_sign_up_failed (7296159750352873260) -->
- <skip />
- <!-- no translation found for osu_sign_up_complete (8207626049093289203) -->
- <skip />
+ <string name="osu_opening_provider" msgid="5488997661548640424">"<xliff:g id="PASSPOINTPROVIDER">%1$s</xliff:g> திறக்கப்படுகிறது"</string>
+ <string name="osu_connect_failed" msgid="2187750899158158934">"இணைக்க முடியவில்லை"</string>
+ <string name="osu_completing_sign_up" msgid="9037638564719197082">"பதிவு செய்வது நிறைவடைகிறது…"</string>
+ <string name="osu_sign_up_failed" msgid="7296159750352873260">"பதிவு செய்வதை நிறைவுசெய்ய இயலவில்லை மீண்டும் முயற்சிக்கத் தட்டவும்."</string>
+ <string name="osu_sign_up_complete" msgid="8207626049093289203">"பதிவு செய்வது நிறைவடைந்தது. இணைக்கிறது…"</string>
<string name="speed_label_very_slow" msgid="1867055264243608530">"மிகவும் வேகம் குறைவானது"</string>
<string name="speed_label_slow" msgid="813109590815810235">"வேகம் குறைவு"</string>
<string name="speed_label_okay" msgid="2331665440671174858">"சரி"</string>
@@ -94,8 +87,8 @@
<string name="bluetooth_profile_sap" msgid="5764222021851283125">"சிம் அணுகல்"</string>
<string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"HD ஆடியோ: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
<string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"HD ஆடியோ"</string>
- <string name="bluetooth_profile_hearing_aid" msgid="7999237886427812595">"செவித்துணைக் கருவி"</string>
- <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="7188282786730266159">"செவித்துணைக் கருவியுடன் இணைக்கப்பட்டிருக்கிறது"</string>
+ <string name="bluetooth_profile_hearing_aid" msgid="6680721080542444257">"செவித்துணை கருவிகள்"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="3051944447369418317">"செவித்துணை கருவிகளுடன் இணைக்கப்பட்டது"</string>
<string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"மீடியா ஆடியோவுடன் இணைக்கப்பட்டது"</string>
<string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"மொபைல் ஆடியோவுடன் இணைக்கப்பட்டது"</string>
<string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"கோப்பைப் பரிமாற்றும் சேவையகத்துடன் இணைக்கப்பட்டது"</string>
@@ -112,7 +105,7 @@
<string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"மொபைல் ஆடியோவைப் பயன்படுத்து"</string>
<string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"கோப்பு பரிமாற்றத்திற்காகப் பயன்படுத்து"</string>
<string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"உள்ளீட்டுக்குப் பயன்படுத்து"</string>
- <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="908775281788309484">"செவித்துணைக் கருவிக்காகப் பயன்படுத்து"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="8843499209204010224">"செவித்துணை கருவிகளுக்குப் பயன்படுத்தவும்"</string>
<string name="bluetooth_pairing_accept" msgid="6163520056536604875">"இணை"</string>
<string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"இணை"</string>
<string name="bluetooth_pairing_decline" msgid="4185420413578948140">"ரத்துசெய்"</string>
@@ -143,6 +136,8 @@
<string name="process_kernel_label" msgid="3916858646836739323">"Android OS"</string>
<string name="data_usage_uninstalled_apps" msgid="614263770923231598">"அகற்றப்பட்ட பயன்பாடுகள்"</string>
<string name="data_usage_uninstalled_apps_users" msgid="7986294489899813194">"அகற்றப்பட்ட பயன்பாடுகள் மற்றும் பயனர்கள்"</string>
+ <!-- no translation found for data_usage_ota (5377889154805560860) -->
+ <skip />
<string name="tether_settings_title_usb" msgid="6688416425801386511">"USB டெதெரிங்"</string>
<string name="tether_settings_title_wifi" msgid="3277144155960302049">"போர்ட்டபிள் ஹாட்ஸ்பாட்"</string>
<string name="tether_settings_title_bluetooth" msgid="355855408317564420">"புளூடூத் டெதெரிங்"</string>
@@ -203,7 +198,7 @@
<string name="vpn_settings_not_available" msgid="956841430176985598">"இவரால் VPN அமைப்புகளை மாற்ற முடியாது"</string>
<string name="tethering_settings_not_available" msgid="6765770438438291012">"இவரால் இணைப்புமுறை அமைப்புகளை மாற்ற முடியாது"</string>
<string name="apn_settings_not_available" msgid="7873729032165324000">"இவரால் ஆக்சஸ் பாயிண்ட் நேம் அமைப்புகளை மாற்ற முடியாது"</string>
- <string name="enable_adb" msgid="7982306934419797485">"USB பிழைத்திருத்தம்"</string>
+ <string name="enable_adb" msgid="7982306934419797485">"USB பிழைதிருத்தம்"</string>
<string name="enable_adb_summary" msgid="4881186971746056635">"USB இணைக்கப்பட்டிருக்கும்போது பிழைத்திருத்தப் பயன்முறையை அமை"</string>
<string name="clear_adb_keys" msgid="4038889221503122743">"USB பிழைத்திருத்த அங்கீகரிப்புகளை நிராகரி"</string>
<string name="bugreport_in_power" msgid="7923901846375587241">"பிழைப் புகாருக்கான ஷார்ட்கட்"</string>
@@ -263,8 +258,8 @@
<string name="debug_view_attributes" msgid="6485448367803310384">"காட்சி பண்புக்கூறு சோதனையை இயக்கு"</string>
<string name="mobile_data_always_on_summary" msgid="8149773901431697910">"வைஃபை இயங்கும் போதும் (வேகமான நெட்வொர்க் மாற்றத்திற்கு), மொபைல் டேட்டாவை எப்போதும் இயக்கத்தில் வைக்கும்."</string>
<string name="tethering_hardware_offload_summary" msgid="7726082075333346982">"வன்பொருள் விரைவுப்படுத்துதல் இணைப்பு முறை கிடைக்கும் போது, அதைப் பயன்படுத்தும்"</string>
- <string name="adb_warning_title" msgid="6234463310896563253">"USB பிழைத்திருத்தத்தை அனுமதிக்கவா?"</string>
- <string name="adb_warning_message" msgid="7316799925425402244">"USB பிழைத்திருத்தம் மேம்படுத்தல் நோக்கங்களுக்காக மட்டுமே. அதை உங்கள் கணினி மற்றும் சாதனத்திற்கு இடையில் தரவை நகலெடுக்கவும், அறிவிப்பு இல்லாமல் உங்கள் சாதனத்தில் பயன்பாடுகளை நிறுவவும், பதிவு தரவைப் படிக்கவும் பயன்படுத்தவும்."</string>
+ <string name="adb_warning_title" msgid="6234463310896563253">"USB பிழைதிருத்தத்தை அனுமதிக்கவா?"</string>
+ <string name="adb_warning_message" msgid="7316799925425402244">"USB பிழைதிருத்தம் மேம்படுத்தல் நோக்கங்களுக்காக மட்டுமே. அதை உங்கள் கணினி மற்றும் சாதனத்திற்கு இடையில் தரவை நகலெடுக்கவும், அறிவிப்பு இல்லாமல் உங்கள் சாதனத்தில் பயன்பாடுகளை நிறுவவும், பதிவு தரவைப் படிக்கவும் பயன்படுத்தவும்."</string>
<string name="adb_keys_warning_message" msgid="5659849457135841625">"நீங்கள் ஏற்கனவே அனுமதித்த எல்லா கணினிகளிலிருந்தும் USB பிழைத்திருத்தத்திற்கான அணுகலைத் திரும்பப்பெற வேண்டுமா?"</string>
<string name="dev_settings_warning_title" msgid="7244607768088540165">"மேம்பட்ட அமைப்புகளை அனுமதிக்கவா?"</string>
<string name="dev_settings_warning_message" msgid="2298337781139097964">"இந்த அமைப்பு மேம்பட்டப் பயன்பாட்டிற்காக மட்டுமே. உங்கள் சாதனம் மற்றும் அதில் உள்ள பயன்பாடுகளைச் சிதைக்கும் அல்லது தவறாகச் செயல்படும் வகையில் பாதிப்பை ஏற்படுத்தும்."</string>
@@ -276,10 +271,10 @@
<string name="enable_terminal_summary" msgid="67667852659359206">"அக ஷெல் அணுகலை வழங்கும் இறுதிப் பயன்பாட்டை இயக்கு"</string>
<string name="hdcp_checking_title" msgid="8605478913544273282">"HDCP சரிபார்ப்பு"</string>
<string name="hdcp_checking_dialog_title" msgid="5141305530923283">"HDCP சரிபார்க்கும் செயல்பாடுகளை அமை"</string>
- <string name="debug_debugging_category" msgid="6781250159513471316">"பிழைத்திருத்தம்"</string>
+ <string name="debug_debugging_category" msgid="6781250159513471316">"பிழைதிருத்தம்"</string>
<string name="debug_app" msgid="8349591734751384446">"பிழைத்திருத்தப் பயன்பாட்டைத் தேர்ந்தெடுக்கவும்"</string>
<string name="debug_app_not_set" msgid="718752499586403499">"பிழைத்திருத்தப் பயன்பாடு அமைக்கப்படவில்லை"</string>
- <string name="debug_app_set" msgid="2063077997870280017">"பிழைத்திருத்தும் பயன்பாடு: <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+ <string name="debug_app_set" msgid="2063077997870280017">"பிழைதிருத்தும் பயன்பாடு: <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
<string name="select_application" msgid="5156029161289091703">"பயன்பாட்டைத் தேர்ந்தெடுக்கவும்"</string>
<string name="no_application" msgid="2813387563129153880">"ஒன்றுமில்லை"</string>
<string name="wait_for_debugger" msgid="1202370874528893091">"பிழைதிருத்திக்குக் காத்திருக்கவும்"</string>
diff --git a/packages/SettingsLib/res/values-te/strings.xml b/packages/SettingsLib/res/values-te/strings.xml
index d8ec167c8e50..e4dd85f8d248 100644
--- a/packages/SettingsLib/res/values-te/strings.xml
+++ b/packages/SettingsLib/res/values-te/strings.xml
@@ -87,8 +87,8 @@
<string name="bluetooth_profile_sap" msgid="5764222021851283125">"SIM యాక్సెస్"</string>
<string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"HD ఆడియో: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
<string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"HD ఆడియో"</string>
- <string name="bluetooth_profile_hearing_aid" msgid="7999237886427812595">"వినికిడి పరికరం"</string>
- <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="7188282786730266159">"వినికిడి పరికరానికి కనెక్ట్ చేస్తోంది"</string>
+ <string name="bluetooth_profile_hearing_aid" msgid="6680721080542444257">"వినికిడి మద్దతు ఉపకరణాలు"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="3051944447369418317">"వినికిడి మద్దతు ఉపకరణాలకు కనెక్ట్ చేయబడింది"</string>
<string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"మీడియా ఆడియోకు కనెక్ట్ చేయబడింది"</string>
<string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"ఫోన్ ఆడియోకు కనెక్ట్ చేయబడింది"</string>
<string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"ఫైల్ బదిలీ సర్వర్‌కు కనెక్ట్ చేయబడింది"</string>
@@ -105,7 +105,7 @@
<string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"ఫోన్ ఆడియో కోసం ఉపయోగించు"</string>
<string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"ఫైల్ బదిలీ కోసం ఉపయోగించు"</string>
<string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"ఇన్‌పుట్ కోసం ఉపయోగించు"</string>
- <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="908775281788309484">"వినికిడి పరికరం కోసం ఉపయోగించు"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="8843499209204010224">"వినికిడి మద్దతు ఉపకరణాలకు ఉపయోగించండి"</string>
<string name="bluetooth_pairing_accept" msgid="6163520056536604875">"జత చేయి"</string>
<string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"జత చేయి"</string>
<string name="bluetooth_pairing_decline" msgid="4185420413578948140">"రద్దు చేయి"</string>
@@ -136,6 +136,7 @@
<string name="process_kernel_label" msgid="3916858646836739323">"Android OS"</string>
<string name="data_usage_uninstalled_apps" msgid="614263770923231598">"తీసివేయబడిన అనువర్తనాలు"</string>
<string name="data_usage_uninstalled_apps_users" msgid="7986294489899813194">"తీసివేయబడిన అనువర్తనాలు మరియు వినియోగదారులు"</string>
+ <string name="data_usage_ota" msgid="5377889154805560860">"సిస్టమ్ అప్‌డేట్‌లు"</string>
<string name="tether_settings_title_usb" msgid="6688416425801386511">"USB టీథరింగ్"</string>
<string name="tether_settings_title_wifi" msgid="3277144155960302049">"పోర్టబుల్ హాట్‌స్పాట్"</string>
<string name="tether_settings_title_bluetooth" msgid="355855408317564420">"బ్లూటూత్ టీథరింగ్"</string>
diff --git a/packages/SettingsLib/res/values-th/strings.xml b/packages/SettingsLib/res/values-th/strings.xml
index 1f4c727dd227..cf8362fe4d37 100644
--- a/packages/SettingsLib/res/values-th/strings.xml
+++ b/packages/SettingsLib/res/values-th/strings.xml
@@ -87,8 +87,8 @@
<string name="bluetooth_profile_sap" msgid="5764222021851283125">"การเข้าถึงซิม"</string>
<string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"เสียง HD: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
<string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"เสียง HD"</string>
- <string name="bluetooth_profile_hearing_aid" msgid="7999237886427812595">"เครื่องช่วยการได้ยิน"</string>
- <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="7188282786730266159">"เชื่อมต่อเครื่องช่วยการได้ยินแล้ว"</string>
+ <string name="bluetooth_profile_hearing_aid" msgid="6680721080542444257">"เครื่องช่วยการได้ยิน"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="3051944447369418317">"เชื่อมต่อกับเครื่องช่วยการได้ยินแล้ว"</string>
<string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"เชื่อมต่อกับระบบเสียงของสื่อแล้ว"</string>
<string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"เชื่อมต่อกับระบบเสียงของโทรศัพท์แล้ว"</string>
<string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"เชื่อมต่อกับเซิร์ฟเวอร์สำหรับโอนไฟล์แล้ว"</string>
@@ -105,7 +105,7 @@
<string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"ใช้สำหรับระบบเสียงของโทรศัพท์"</string>
<string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"ใช้สำหรับการโอนไฟล์"</string>
<string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"ใช้สำหรับการป้อนข้อมูล"</string>
- <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="908775281788309484">"ใช้สำหรับเครื่องช่วยการได้ยิน"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="8843499209204010224">"ใช้สำหรับเครื่องช่วยการได้ยิน"</string>
<string name="bluetooth_pairing_accept" msgid="6163520056536604875">"จับคู่อุปกรณ์"</string>
<string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"จับคู่อุปกรณ์"</string>
<string name="bluetooth_pairing_decline" msgid="4185420413578948140">"ยกเลิก"</string>
@@ -136,6 +136,7 @@
<string name="process_kernel_label" msgid="3916858646836739323">"ระบบปฏิบัติการของ Android"</string>
<string name="data_usage_uninstalled_apps" msgid="614263770923231598">"แอปพลิเคชันที่นำออก"</string>
<string name="data_usage_uninstalled_apps_users" msgid="7986294489899813194">"แอปพลิเคชันและผู้ใช้ที่นำออก"</string>
+ <string name="data_usage_ota" msgid="5377889154805560860">"การอัปเดตระบบ"</string>
<string name="tether_settings_title_usb" msgid="6688416425801386511">"ปล่อยสัญญาณผ่าน USB"</string>
<string name="tether_settings_title_wifi" msgid="3277144155960302049">"ฮอตสปอตแบบพกพาได้"</string>
<string name="tether_settings_title_bluetooth" msgid="355855408317564420">"ปล่อยสัญญาณบลูทูธ"</string>
diff --git a/packages/SettingsLib/res/values-tl/strings.xml b/packages/SettingsLib/res/values-tl/strings.xml
index 7a31cc9ee3b1..e690800eb9a7 100644
--- a/packages/SettingsLib/res/values-tl/strings.xml
+++ b/packages/SettingsLib/res/values-tl/strings.xml
@@ -87,8 +87,8 @@
<string name="bluetooth_profile_sap" msgid="5764222021851283125">"Access sa SIM"</string>
<string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"HD audio: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
<string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"HD audio"</string>
- <string name="bluetooth_profile_hearing_aid" msgid="7999237886427812595">"Hearing Aid"</string>
- <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="7188282786730266159">"Nakakonekta sa Hearing Aid"</string>
+ <string name="bluetooth_profile_hearing_aid" msgid="6680721080542444257">"Mga Hearing Aid"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="3051944447369418317">"Nakakonekta sa Mga Hearing Aid"</string>
<string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"Konektado sa media audio"</string>
<string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"Nakakonekta sa audio ng telepono"</string>
<string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"Nakakonekta sa server sa paglilipat ng file"</string>
@@ -105,7 +105,7 @@
<string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"Ginagamit para sa audio ng telepono"</string>
<string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"Ginagamit para sa paglilipat ng file"</string>
<string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"Gamitin para sa input"</string>
- <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="908775281788309484">"Gamitin para sa Hearing Aid"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="8843499209204010224">"Gamitin para sa Mga Hearing Aid"</string>
<string name="bluetooth_pairing_accept" msgid="6163520056536604875">"Pares"</string>
<string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"IPARES"</string>
<string name="bluetooth_pairing_decline" msgid="4185420413578948140">"Kanselahin"</string>
@@ -136,6 +136,7 @@
<string name="process_kernel_label" msgid="3916858646836739323">"Android OS"</string>
<string name="data_usage_uninstalled_apps" msgid="614263770923231598">"Mga inalis na app"</string>
<string name="data_usage_uninstalled_apps_users" msgid="7986294489899813194">"Mga inalis na apps at user"</string>
+ <string name="data_usage_ota" msgid="5377889154805560860">"Mga pag-update ng system"</string>
<string name="tether_settings_title_usb" msgid="6688416425801386511">"Pag-tether sa USB"</string>
<string name="tether_settings_title_wifi" msgid="3277144155960302049">"Portable na hotspot"</string>
<string name="tether_settings_title_bluetooth" msgid="355855408317564420">"Pag-tether ng Bluetooth"</string>
diff --git a/packages/SettingsLib/res/values-tr/strings.xml b/packages/SettingsLib/res/values-tr/strings.xml
index 28fc38fcd8a5..ea340e8e92e6 100644
--- a/packages/SettingsLib/res/values-tr/strings.xml
+++ b/packages/SettingsLib/res/values-tr/strings.xml
@@ -87,8 +87,8 @@
<string name="bluetooth_profile_sap" msgid="5764222021851283125">"SIM Erişimi"</string>
<string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"HD ses: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
<string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"HD ses"</string>
- <string name="bluetooth_profile_hearing_aid" msgid="7999237886427812595">"İşitme Cihazı"</string>
- <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="7188282786730266159">"İşitme Cihazına bağlandı"</string>
+ <string name="bluetooth_profile_hearing_aid" msgid="6680721080542444257">"İşitme Cihazları"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="3051944447369418317">"İşitme Cihazlarına Bağlandı"</string>
<string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"Medya sesine bağlanıldı"</string>
<string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"Telefon sesine bağlandı"</string>
<string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"Dosya aktarım sunucusuna bağlandı"</string>
@@ -105,7 +105,7 @@
<string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"Telefon sesi için kullan"</string>
<string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"Dosya aktarımı için kullan"</string>
<string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"Giriş için kullan"</string>
- <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="908775281788309484">"İşitme Cihazı için kullan"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="8843499209204010224">"İşitme Cihazları için kullan"</string>
<string name="bluetooth_pairing_accept" msgid="6163520056536604875">"Eşle"</string>
<string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"EŞLE"</string>
<string name="bluetooth_pairing_decline" msgid="4185420413578948140">"İptal"</string>
@@ -136,6 +136,7 @@
<string name="process_kernel_label" msgid="3916858646836739323">"Android OS"</string>
<string name="data_usage_uninstalled_apps" msgid="614263770923231598">"Kaldırılan uygulamalar"</string>
<string name="data_usage_uninstalled_apps_users" msgid="7986294489899813194">"Kaldırılmış kullanıcılar ve uygulamalar"</string>
+ <string name="data_usage_ota" msgid="5377889154805560860">"Sistem güncellemeleri"</string>
<string name="tether_settings_title_usb" msgid="6688416425801386511">"USB tethering"</string>
<string name="tether_settings_title_wifi" msgid="3277144155960302049">"Taşınabilir hotspot"</string>
<string name="tether_settings_title_bluetooth" msgid="355855408317564420">"Bluetooth tethering"</string>
diff --git a/packages/SettingsLib/res/values-uk/strings.xml b/packages/SettingsLib/res/values-uk/strings.xml
index c63f7e0e0761..cf90ed16efaf 100644
--- a/packages/SettingsLib/res/values-uk/strings.xml
+++ b/packages/SettingsLib/res/values-uk/strings.xml
@@ -87,8 +87,8 @@
<string name="bluetooth_profile_sap" msgid="5764222021851283125">"Доступ до SIM-карти"</string>
<string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"HD-аудіо: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
<string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"HD-аудіо"</string>
- <string name="bluetooth_profile_hearing_aid" msgid="7999237886427812595">"Слуховий апарат"</string>
- <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="7188282786730266159">"Під’єднано до слухового апарата"</string>
+ <string name="bluetooth_profile_hearing_aid" msgid="6680721080542444257">"Слухові апарати"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="3051944447369418317">"Підключено до слухових апаратів"</string>
<string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"Підключено до аудіоджерела"</string>
<string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"Підключено до звуку телеф."</string>
<string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"Підключ. до сервера передачі файлів"</string>
@@ -105,7 +105,7 @@
<string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"Викор. для звуку тел."</string>
<string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"Викор. для перед. файлів"</string>
<string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"Викор. для введ."</string>
- <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="908775281788309484">"Використовувати для слухового апарата"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="8843499209204010224">"Використовувати для слухових апаратів"</string>
<string name="bluetooth_pairing_accept" msgid="6163520056536604875">"Підключити"</string>
<string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"ПІДКЛЮЧИТИСЯ"</string>
<string name="bluetooth_pairing_decline" msgid="4185420413578948140">"Скасувати"</string>
@@ -136,6 +136,7 @@
<string name="process_kernel_label" msgid="3916858646836739323">"ОС Android"</string>
<string name="data_usage_uninstalled_apps" msgid="614263770923231598">"Видалені програми"</string>
<string name="data_usage_uninstalled_apps_users" msgid="7986294489899813194">"Видалені програми та користувачі"</string>
+ <string name="data_usage_ota" msgid="5377889154805560860">"Оновлення системи"</string>
<string name="tether_settings_title_usb" msgid="6688416425801386511">"USB-модем"</string>
<string name="tether_settings_title_wifi" msgid="3277144155960302049">"Порт. точка дост."</string>
<string name="tether_settings_title_bluetooth" msgid="355855408317564420">"Bluetooth-модем"</string>
diff --git a/packages/SettingsLib/res/values-ur/strings.xml b/packages/SettingsLib/res/values-ur/strings.xml
index 27aa730b6a8b..65ed110d3c46 100644
--- a/packages/SettingsLib/res/values-ur/strings.xml
+++ b/packages/SettingsLib/res/values-ur/strings.xml
@@ -38,27 +38,20 @@
<string name="connected_via_network_scorer" msgid="5713793306870815341">"‏‎%1$s کے ذریعے از خود منسلک کردہ"</string>
<string name="connected_via_network_scorer_default" msgid="7867260222020343104">"نیٹ ورک درجہ بندی کے فراہم کنندہ کے ذریعے از خود منسلک"</string>
<string name="connected_via_passpoint" msgid="2826205693803088747">"‏منسلک بذریعہ ‎%1$s"</string>
- <!-- no translation found for connected_via_app (5571999941988929520) -->
- <skip />
+ <string name="connected_via_app" msgid="5571999941988929520">"<xliff:g id="NAME">%1$s</xliff:g> کے ذریعے منسلک"</string>
<string name="available_via_passpoint" msgid="1617440946846329613">"‏دستیاب بذریعہ ‎%1$s"</string>
- <!-- no translation found for tap_to_sign_up (6449724763052579434) -->
- <skip />
+ <string name="tap_to_sign_up" msgid="6449724763052579434">"سائن اپ کے لیے تھپتھپائیں"</string>
<string name="wifi_connected_no_internet" msgid="8202906332837777829">"منسلک، انٹرنیٹ نہیں ہے"</string>
<string name="wifi_status_no_internet" msgid="5784710974669608361">"انٹرنیٹ نہیں ہے"</string>
<string name="wifi_status_sign_in_required" msgid="123517180404752756">"سائن ان درکار ہے"</string>
<string name="wifi_ap_unable_to_handle_new_sta" msgid="5348824313514404541">"رسائی پوائنٹ عارضی طور پر فُل ہے"</string>
<string name="connected_via_carrier" msgid="7583780074526041912">"‏منسلک بذریعہ ‎%1$s"</string>
<string name="available_via_carrier" msgid="1469036129740799053">"‏دستیاب بذریعہ ‎%1$s"</string>
- <!-- no translation found for osu_opening_provider (5488997661548640424) -->
- <skip />
- <!-- no translation found for osu_connect_failed (2187750899158158934) -->
- <skip />
- <!-- no translation found for osu_completing_sign_up (9037638564719197082) -->
- <skip />
- <!-- no translation found for osu_sign_up_failed (7296159750352873260) -->
- <skip />
- <!-- no translation found for osu_sign_up_complete (8207626049093289203) -->
- <skip />
+ <string name="osu_opening_provider" msgid="5488997661548640424">"<xliff:g id="PASSPOINTPROVIDER">%1$s</xliff:g> کھل رہا ہے"</string>
+ <string name="osu_connect_failed" msgid="2187750899158158934">"منسلک نہیں کیا جا سکا"</string>
+ <string name="osu_completing_sign_up" msgid="9037638564719197082">"سائن اپ مکمل ہو رہا ہے…"</string>
+ <string name="osu_sign_up_failed" msgid="7296159750352873260">"سائن اپ مکمل نہیں ہو سکا۔ دوبارہ کوشش کرنے کے لیے تھپتھپائیں۔"</string>
+ <string name="osu_sign_up_complete" msgid="8207626049093289203">"سائن اپ مکمل ہو گیا۔ منسلک ہو رہا ہے…"</string>
<string name="speed_label_very_slow" msgid="1867055264243608530">"بہت سست"</string>
<string name="speed_label_slow" msgid="813109590815810235">"سست"</string>
<string name="speed_label_okay" msgid="2331665440671174858">"ٹھیک ہے"</string>
@@ -94,8 +87,8 @@
<string name="bluetooth_profile_sap" msgid="5764222021851283125">"‏SIM رسائی"</string>
<string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"‏HD آڈیو: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
<string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"‏HD آڈیو"</string>
- <string name="bluetooth_profile_hearing_aid" msgid="7999237886427812595">"سماعتی آلہ"</string>
- <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="7188282786730266159">"سماعتی آلے سے منسلک"</string>
+ <string name="bluetooth_profile_hearing_aid" msgid="6680721080542444257">"سماعتی آلات"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="3051944447369418317">"سماعتی آلات سے منسلک ہے"</string>
<string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"میڈیا آڈیو سے مربوط"</string>
<string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"فون آڈیو سے مربوط"</string>
<string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"فائل منتقلی سرور سے مربوط ہو گیا ہے"</string>
@@ -112,7 +105,7 @@
<string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"فون آڈیو کیلئے استعمال کریں"</string>
<string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"فائل منتقل کرنے کیلئے استعمال کریں"</string>
<string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"ان پٹ کیلئے استعمال"</string>
- <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="908775281788309484">"سماعتی آلے کیلئے استعمال کریں"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="8843499209204010224">"سماعتی آلات کے لیے استعمال کریں"</string>
<string name="bluetooth_pairing_accept" msgid="6163520056536604875">"جوڑا بنائیں"</string>
<string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"جوڑا بنائیں"</string>
<string name="bluetooth_pairing_decline" msgid="4185420413578948140">"منسوخ کریں"</string>
@@ -143,6 +136,8 @@
<string name="process_kernel_label" msgid="3916858646836739323">"Android OS"</string>
<string name="data_usage_uninstalled_apps" msgid="614263770923231598">"ہٹائی گئی ایپس"</string>
<string name="data_usage_uninstalled_apps_users" msgid="7986294489899813194">"ہٹائی گئی ایپس اور صارفین"</string>
+ <!-- no translation found for data_usage_ota (5377889154805560860) -->
+ <skip />
<string name="tether_settings_title_usb" msgid="6688416425801386511">"‏USB ٹیدرنگ"</string>
<string name="tether_settings_title_wifi" msgid="3277144155960302049">"پورٹیبل ہاٹ اسپاٹ"</string>
<string name="tether_settings_title_bluetooth" msgid="355855408317564420">"بلوٹوتھ ٹیدرنگ"</string>
diff --git a/packages/SettingsLib/res/values-uz/strings.xml b/packages/SettingsLib/res/values-uz/strings.xml
index bcb4d27d94d4..2851bafd4639 100644
--- a/packages/SettingsLib/res/values-uz/strings.xml
+++ b/packages/SettingsLib/res/values-uz/strings.xml
@@ -87,8 +87,8 @@
<string name="bluetooth_profile_sap" msgid="5764222021851283125">"SIM-kartaga kirish"</string>
<string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"HD audio: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
<string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"HD audio"</string>
- <string name="bluetooth_profile_hearing_aid" msgid="7999237886427812595">"Eshitish apparati"</string>
- <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="7188282786730266159">"Eshitish apparatiga ulangan"</string>
+ <string name="bluetooth_profile_hearing_aid" msgid="6680721080542444257">"Eshitish apparatlari"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="3051944447369418317">"Eshitish apparatlariga ulangan"</string>
<string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"Audio qurilmasiga ulangan"</string>
<string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"Telefon karnayiga ulanildi"</string>
<string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"Fayl almashinish serveriga ulanildi"</string>
@@ -105,7 +105,7 @@
<string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"Dok’dan karnay sifatida foydalanish"</string>
<string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"Fayl almashinish uchun foydalanish"</string>
<string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"Kiritish qurilmasi sifatida foydalanish"</string>
- <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="908775281788309484">"Eshitish apparati uchun foydalanish"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="8843499209204010224">"Eshitish apparatlari uchun foydalanish"</string>
<string name="bluetooth_pairing_accept" msgid="6163520056536604875">"Biriktirish"</string>
<string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"ULANISH"</string>
<string name="bluetooth_pairing_decline" msgid="4185420413578948140">"Bekor qilish"</string>
@@ -136,6 +136,7 @@
<string name="process_kernel_label" msgid="3916858646836739323">"Android OS"</string>
<string name="data_usage_uninstalled_apps" msgid="614263770923231598">"O‘chirilgan ilovalar"</string>
<string name="data_usage_uninstalled_apps_users" msgid="7986294489899813194">"O‘chirib tashlangan ilova va foydalanuvchilar"</string>
+ <string name="data_usage_ota" msgid="5377889154805560860">"Tizimni yangilash"</string>
<string name="tether_settings_title_usb" msgid="6688416425801386511">"USB modem"</string>
<string name="tether_settings_title_wifi" msgid="3277144155960302049">"Ixcham hotspot"</string>
<string name="tether_settings_title_bluetooth" msgid="355855408317564420">"Bluetooth modem"</string>
diff --git a/packages/SettingsLib/res/values-vi/strings.xml b/packages/SettingsLib/res/values-vi/strings.xml
index d03b2f175f60..3fb101e6deec 100644
--- a/packages/SettingsLib/res/values-vi/strings.xml
+++ b/packages/SettingsLib/res/values-vi/strings.xml
@@ -87,8 +87,8 @@
<string name="bluetooth_profile_sap" msgid="5764222021851283125">"Quyền truy cập SIM"</string>
<string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"Âm thanh HD: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
<string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"Âm thanh HD"</string>
- <string name="bluetooth_profile_hearing_aid" msgid="7999237886427812595">"Trợ thính"</string>
- <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="7188282786730266159">"Đã kết nối với thiết bị trợ thính"</string>
+ <string name="bluetooth_profile_hearing_aid" msgid="6680721080542444257">"Thiết bị trợ thính"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="3051944447369418317">"Đã kết nối với Thiết bị trợ thính"</string>
<string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"Đã kết nối với âm thanh phương tiện"</string>
<string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"Đã kết nối với âm thanh điện thoại"</string>
<string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"Đã kết nối với máy chủ chuyển tệp"</string>
@@ -105,7 +105,7 @@
<string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"Sử dụng cho âm thanh điện thoại"</string>
<string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"Sử dụng để chuyển tệp"</string>
<string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"Sử dụng để nhập"</string>
- <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="908775281788309484">"Sử dụng cho thiết bị trợ thính"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="8843499209204010224">"Dùng cho Thiết bị trợ thính"</string>
<string name="bluetooth_pairing_accept" msgid="6163520056536604875">"Ghép nối"</string>
<string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"GHÉP NỐI"</string>
<string name="bluetooth_pairing_decline" msgid="4185420413578948140">"Hủy"</string>
@@ -136,6 +136,7 @@
<string name="process_kernel_label" msgid="3916858646836739323">"Hệ điều hành Android"</string>
<string name="data_usage_uninstalled_apps" msgid="614263770923231598">"Ứng dụng đã xóa"</string>
<string name="data_usage_uninstalled_apps_users" msgid="7986294489899813194">"Ứng dụng và người dùng bị xóa"</string>
+ <string name="data_usage_ota" msgid="5377889154805560860">"Bản cập nhật hệ thống"</string>
<string name="tether_settings_title_usb" msgid="6688416425801386511">"Chia sẻ kết nối Internet qua USB"</string>
<string name="tether_settings_title_wifi" msgid="3277144155960302049">"Điểm phát sóng di động"</string>
<string name="tether_settings_title_bluetooth" msgid="355855408317564420">"Chia sẻ kết nối Internet qua Bluetooth"</string>
diff --git a/packages/SettingsLib/res/values-zh-rCN/strings.xml b/packages/SettingsLib/res/values-zh-rCN/strings.xml
index 69674472028c..0a318d752ae7 100644
--- a/packages/SettingsLib/res/values-zh-rCN/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rCN/strings.xml
@@ -87,8 +87,8 @@
<string name="bluetooth_profile_sap" msgid="5764222021851283125">"SIM 卡存取权限"</string>
<string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"HD 音频:<xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
<string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"HD 音频"</string>
- <string name="bluetooth_profile_hearing_aid" msgid="7999237886427812595">"助听器"</string>
- <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="7188282786730266159">"已连接到助听器"</string>
+ <string name="bluetooth_profile_hearing_aid" msgid="6680721080542444257">"助听器"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="3051944447369418317">"已连接到助听器"</string>
<string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"已连接到媒体音频"</string>
<string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"已连接到手机音频"</string>
<string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"已连接到文件传输服务器"</string>
@@ -105,7 +105,7 @@
<string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"用于手机音频"</string>
<string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"用于文件传输"</string>
<string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"用于输入"</string>
- <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="908775281788309484">"用于助听器"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="8843499209204010224">"用于助听器"</string>
<string name="bluetooth_pairing_accept" msgid="6163520056536604875">"配对"</string>
<string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"配对"</string>
<string name="bluetooth_pairing_decline" msgid="4185420413578948140">"取消"</string>
@@ -136,6 +136,7 @@
<string name="process_kernel_label" msgid="3916858646836739323">"Android 操作系统"</string>
<string name="data_usage_uninstalled_apps" msgid="614263770923231598">"已删除的应用"</string>
<string name="data_usage_uninstalled_apps_users" msgid="7986294489899813194">"已删除的应用和用户"</string>
+ <string name="data_usage_ota" msgid="5377889154805560860">"系统更新"</string>
<string name="tether_settings_title_usb" msgid="6688416425801386511">"USB 网络共享"</string>
<string name="tether_settings_title_wifi" msgid="3277144155960302049">"便携式热点"</string>
<string name="tether_settings_title_bluetooth" msgid="355855408317564420">"蓝牙网络共享"</string>
diff --git a/packages/SettingsLib/res/values-zh-rHK/strings.xml b/packages/SettingsLib/res/values-zh-rHK/strings.xml
index 5394afc32334..06bee941ff0c 100644
--- a/packages/SettingsLib/res/values-zh-rHK/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rHK/strings.xml
@@ -38,9 +38,9 @@
<string name="connected_via_network_scorer" msgid="5713793306870815341">"已透過 %1$s 自動連線"</string>
<string name="connected_via_network_scorer_default" msgid="7867260222020343104">"已透過網絡評分供應商自動連線"</string>
<string name="connected_via_passpoint" msgid="2826205693803088747">"已透過 %1$s 連線"</string>
- <string name="connected_via_app" msgid="5571999941988929520">"透過「<xliff:g id="NAME">%1$s</xliff:g>」連線"</string>
+ <string name="connected_via_app" msgid="5571999941988929520">"已透過「<xliff:g id="NAME">%1$s</xliff:g>」連線"</string>
<string name="available_via_passpoint" msgid="1617440946846329613">"可透過 %1$s 連線"</string>
- <string name="tap_to_sign_up" msgid="6449724763052579434">"輕觸即可註冊"</string>
+ <string name="tap_to_sign_up" msgid="6449724763052579434">"輕按即可登入"</string>
<string name="wifi_connected_no_internet" msgid="8202906332837777829">"已連線,但沒有互聯網"</string>
<string name="wifi_status_no_internet" msgid="5784710974669608361">"沒有互聯網連線"</string>
<string name="wifi_status_sign_in_required" msgid="123517180404752756">"必須登入"</string>
@@ -48,10 +48,10 @@
<string name="connected_via_carrier" msgid="7583780074526041912">"已透過 %1$s 連線"</string>
<string name="available_via_carrier" msgid="1469036129740799053">"可透過 %1$s 連線"</string>
<string name="osu_opening_provider" msgid="5488997661548640424">"正在開啟 <xliff:g id="PASSPOINTPROVIDER">%1$s</xliff:g>"</string>
- <string name="osu_connect_failed" msgid="2187750899158158934">"無法連線"</string>
- <string name="osu_completing_sign_up" msgid="9037638564719197082">"正在完成註冊程序…"</string>
- <string name="osu_sign_up_failed" msgid="7296159750352873260">"無法完成註冊程序。輕觸即可重試。"</string>
- <string name="osu_sign_up_complete" msgid="8207626049093289203">"註冊完成。連線中…"</string>
+ <string name="osu_connect_failed" msgid="2187750899158158934">"無法連接"</string>
+ <string name="osu_completing_sign_up" msgid="9037638564719197082">"正在完成申請…"</string>
+ <string name="osu_sign_up_failed" msgid="7296159750352873260">"無法完成申請。輕按即可重試。"</string>
+ <string name="osu_sign_up_complete" msgid="8207626049093289203">"已完成申請。連接中…"</string>
<string name="speed_label_very_slow" msgid="1867055264243608530">"非常慢"</string>
<string name="speed_label_slow" msgid="813109590815810235">"慢"</string>
<string name="speed_label_okay" msgid="2331665440671174858">"良好"</string>
@@ -87,8 +87,8 @@
<string name="bluetooth_profile_sap" msgid="5764222021851283125">"SIM 卡存取"</string>
<string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"高清音訊:<xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
<string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"高清音訊"</string>
- <string name="bluetooth_profile_hearing_aid" msgid="7999237886427812595">"助聽器"</string>
- <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="7188282786730266159">"已連線至助聽器"</string>
+ <string name="bluetooth_profile_hearing_aid" msgid="6680721080542444257">"助聽器"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="3051944447369418317">"已連接助聽器"</string>
<string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"已連接媒體音頻裝置"</string>
<string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"已連接手機耳機"</string>
<string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"已連線至檔案傳輸伺服器"</string>
@@ -105,7 +105,7 @@
<string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"用於手機音效"</string>
<string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"用於傳輸檔案"</string>
<string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"用於輸入"</string>
- <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="908775281788309484">"用於助聽器"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="8843499209204010224">"用於助聽器"</string>
<string name="bluetooth_pairing_accept" msgid="6163520056536604875">"配對"</string>
<string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"配對"</string>
<string name="bluetooth_pairing_decline" msgid="4185420413578948140">"取消"</string>
@@ -136,6 +136,7 @@
<string name="process_kernel_label" msgid="3916858646836739323">"Android 作業系統"</string>
<string name="data_usage_uninstalled_apps" msgid="614263770923231598">"已移除的應用程式"</string>
<string name="data_usage_uninstalled_apps_users" msgid="7986294489899813194">"已移除的應用程式和使用者"</string>
+ <string name="data_usage_ota" msgid="5377889154805560860">"系統更新"</string>
<string name="tether_settings_title_usb" msgid="6688416425801386511">"USB 網絡共享"</string>
<string name="tether_settings_title_wifi" msgid="3277144155960302049">"可攜式熱點"</string>
<string name="tether_settings_title_bluetooth" msgid="355855408317564420">"藍牙網絡共享"</string>
diff --git a/packages/SettingsLib/res/values-zh-rTW/strings.xml b/packages/SettingsLib/res/values-zh-rTW/strings.xml
index 107eb6de564f..a5074d9db005 100644
--- a/packages/SettingsLib/res/values-zh-rTW/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rTW/strings.xml
@@ -87,8 +87,8 @@
<string name="bluetooth_profile_sap" msgid="5764222021851283125">"SIM 卡存取權"</string>
<string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"HD 高解析音訊:<xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
<string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"HD 高解析音訊"</string>
- <string name="bluetooth_profile_hearing_aid" msgid="7999237886427812595">"助聽器"</string>
- <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="7188282786730266159">"已連接到助聽器"</string>
+ <string name="bluetooth_profile_hearing_aid" msgid="6680721080542444257">"助聽器"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="3051944447369418317">"已連接到助聽器"</string>
<string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"連接至媒體音訊"</string>
<string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"連接至電話音訊"</string>
<string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"已連線到檔案傳輸伺服器"</string>
@@ -105,7 +105,7 @@
<string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"用於電話音訊"</string>
<string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"用於傳輸檔案"</string>
<string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"用於輸入"</string>
- <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="908775281788309484">"用於助聽器"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="8843499209204010224">"用於助聽器"</string>
<string name="bluetooth_pairing_accept" msgid="6163520056536604875">"配對"</string>
<string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"配對"</string>
<string name="bluetooth_pairing_decline" msgid="4185420413578948140">"取消"</string>
@@ -136,6 +136,7 @@
<string name="process_kernel_label" msgid="3916858646836739323">"Android 作業系統"</string>
<string name="data_usage_uninstalled_apps" msgid="614263770923231598">"移除的應用程式"</string>
<string name="data_usage_uninstalled_apps_users" msgid="7986294489899813194">"已移除的應用程式和使用者"</string>
+ <string name="data_usage_ota" msgid="5377889154805560860">"系統更新"</string>
<string name="tether_settings_title_usb" msgid="6688416425801386511">"USB 網路共用"</string>
<string name="tether_settings_title_wifi" msgid="3277144155960302049">"可攜式無線基地台"</string>
<string name="tether_settings_title_bluetooth" msgid="355855408317564420">"藍牙網路共用"</string>
diff --git a/packages/SettingsLib/res/values-zu/strings.xml b/packages/SettingsLib/res/values-zu/strings.xml
index 920df4b81475..589209399839 100644
--- a/packages/SettingsLib/res/values-zu/strings.xml
+++ b/packages/SettingsLib/res/values-zu/strings.xml
@@ -87,8 +87,8 @@
<string name="bluetooth_profile_sap" msgid="5764222021851283125">"Ukufinyelela kwe-SIM"</string>
<string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"Umsindo we-HD: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
<string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"Umsindo we-HD"</string>
- <string name="bluetooth_profile_hearing_aid" msgid="7999237886427812595">"Usizo lokuzwa"</string>
- <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="7188282786730266159">"Ixhunywe kokokusiza ukuzwa"</string>
+ <string name="bluetooth_profile_hearing_aid" msgid="6680721080542444257">"Izinsiza zokuzwa"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="3051944447369418317">"Kuxhumeke kwizinsiza zokuzwa"</string>
<string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"Ixhume emsindweni wemidiya"</string>
<string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"Ixhunywe kumsindo wefoni"</string>
<string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"Ixhunywe kwiseva yokudlulisa ifayela"</string>
@@ -105,7 +105,7 @@
<string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"Sebenziselwa umsindo wefoni"</string>
<string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"Sebenziselwa ukudlulisa ifayela"</string>
<string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"Isetshenziselwa okufakwayo"</string>
- <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="908775281788309484">"Sebenzisela usizo lokuzwa"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="8843499209204010224">"Sebenzisa izinsiza zokuzwa"</string>
<string name="bluetooth_pairing_accept" msgid="6163520056536604875">"Bhangqa"</string>
<string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"BHANQA"</string>
<string name="bluetooth_pairing_decline" msgid="4185420413578948140">"Khansela"</string>
@@ -136,6 +136,7 @@
<string name="process_kernel_label" msgid="3916858646836739323">"I-Android OS"</string>
<string name="data_usage_uninstalled_apps" msgid="614263770923231598">"Izinhlelo zokusebenza zisusiwe"</string>
<string name="data_usage_uninstalled_apps_users" msgid="7986294489899813194">"Izinhelo zokusebenza nabasebenzisi abasusiwe"</string>
+ <string name="data_usage_ota" msgid="5377889154805560860">"Izibuyekezo zesistimu"</string>
<string name="tether_settings_title_usb" msgid="6688416425801386511">"Imodemu nge-USB"</string>
<string name="tether_settings_title_wifi" msgid="3277144155960302049">"I-hotspot ephathekayo"</string>
<string name="tether_settings_title_bluetooth" msgid="355855408317564420">"Imodemu nge-Bluetooth"</string>
diff --git a/packages/SettingsLib/src/com/android/settingslib/SliceBroadcastRelay.java b/packages/SettingsLib/src/com/android/settingslib/SliceBroadcastRelay.java
index e92b36a45645..b7f7ad256505 100644
--- a/packages/SettingsLib/src/com/android/settingslib/SliceBroadcastRelay.java
+++ b/packages/SettingsLib/src/com/android/settingslib/SliceBroadcastRelay.java
@@ -23,6 +23,10 @@ import android.content.IntentFilter;
import android.net.Uri;
import android.os.Process;
import android.os.UserHandle;
+import android.util.ArraySet;
+import android.util.Log;
+
+import java.util.Set;
/**
* Utility class that allows Settings to use SystemUI to relay broadcasts related to pinned slices.
@@ -38,12 +42,22 @@ public class SliceBroadcastRelay {
public static final String EXTRA_URI = "uri";
public static final String EXTRA_RECEIVER = "receiver";
public static final String EXTRA_FILTER = "filter";
+ private static final String TAG = "SliceBroadcastRelay";
+
+ private static final Set<Uri> sRegisteredUris = new ArraySet<>();
- public static void registerReceiver(Context context, Uri registerKey,
+ /**
+ * Associate intent filter/sliceUri with corresponding receiver.
+ */
+ public static void registerReceiver(Context context, Uri sliceUri,
Class<? extends BroadcastReceiver> receiver, IntentFilter filter) {
+
+ Log.d(TAG, "Registering Uri for broadcast relay: " + sliceUri);
+ sRegisteredUris.add(sliceUri);
+
Intent registerBroadcast = new Intent(ACTION_REGISTER);
registerBroadcast.setPackage(SYSTEMUI_PACKAGE);
- registerBroadcast.putExtra(EXTRA_URI, ContentProvider.maybeAddUserId(registerKey,
+ registerBroadcast.putExtra(EXTRA_URI, ContentProvider.maybeAddUserId(sliceUri,
Process.myUserHandle().getIdentifier()));
registerBroadcast.putExtra(EXTRA_RECEIVER,
new ComponentName(context.getPackageName(), receiver.getName()));
@@ -52,12 +66,21 @@ public class SliceBroadcastRelay {
context.sendBroadcastAsUser(registerBroadcast, UserHandle.SYSTEM);
}
- public static void unregisterReceivers(Context context, Uri registerKey) {
- Intent registerBroadcast = new Intent(ACTION_UNREGISTER);
+ /**
+ * Unregisters all receivers for a given slice uri.
+ */
+
+ public static void unregisterReceivers(Context context, Uri sliceUri) {
+ if (!sRegisteredUris.contains(sliceUri)) {
+ return;
+ }
+ Log.d(TAG, "Unregistering uri broadcast relay: " + sliceUri);
+ final Intent registerBroadcast = new Intent(ACTION_UNREGISTER);
registerBroadcast.setPackage(SYSTEMUI_PACKAGE);
- registerBroadcast.putExtra(EXTRA_URI, ContentProvider.maybeAddUserId(registerKey,
+ registerBroadcast.putExtra(EXTRA_URI, ContentProvider.maybeAddUserId(sliceUri,
Process.myUserHandle().getIdentifier()));
context.sendBroadcastAsUser(registerBroadcast, UserHandle.SYSTEM);
+ sRegisteredUris.remove(sliceUri);
}
}
diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java b/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java
index ac2c2c946725..43affcdfefe9 100644
--- a/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java
+++ b/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java
@@ -1065,7 +1065,7 @@ public class AccessPoint implements Comparable<AccessPoint> {
}
public boolean isSaved() {
- return networkId != WifiConfiguration.INVALID_NETWORK_ID;
+ return mConfig != null;
}
public Object getTag() {
diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml
index 4a5388be2c1e..265d464d9c71 100644
--- a/packages/SystemUI/AndroidManifest.xml
+++ b/packages/SystemUI/AndroidManifest.xml
@@ -22,6 +22,11 @@
android:sharedUserId="android.uid.systemui"
coreApp="true">
+ <!-- Using OpenGL ES 2.0 -->
+ <uses-feature
+ android:glEsVersion="0x00020000"
+ android:required="true" />
+
<!-- SysUI must be the one to define this permission; its name is
referenced by the core OS. -->
<permission android:name="android.permission.systemui.IDENTITY"
diff --git a/packages/SystemUI/res/drawable/privacy_chip_bg.xml b/packages/SystemUI/res/drawable/privacy_chip_bg.xml
index f1158ef11ccc..b7b21fa53b62 100644
--- a/packages/SystemUI/res/drawable/privacy_chip_bg.xml
+++ b/packages/SystemUI/res/drawable/privacy_chip_bg.xml
@@ -16,8 +16,8 @@
-->
<shape xmlns:android="http://schemas.android.com/apk/res/android">
- <solid android:color="#4a4a4a" />
+ <solid android:color="#242424" /> <!-- 14% of white -->
<padding android:paddingTop="@dimen/ongoing_appops_chip_bg_padding"
- android:paddingBottom="@dimen/ongoing_appops_chip_bg_padding"/>
+ android:paddingBottom="@dimen/ongoing_appops_chip_bg_padding" />
<corners android:radius="@dimen/ongoing_appops_chip_bg_corner_radius" />
</shape> \ No newline at end of file
diff --git a/packages/SystemUI/res/layout/ongoing_privacy_chip.xml b/packages/SystemUI/res/layout/ongoing_privacy_chip.xml
index 58fe81109731..f64a64e619a0 100644
--- a/packages/SystemUI/res/layout/ongoing_privacy_chip.xml
+++ b/packages/SystemUI/res/layout/ongoing_privacy_chip.xml
@@ -15,6 +15,7 @@
limitations under the License.
-->
+
<com.android.systemui.privacy.OngoingPrivacyChip
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/privacy_chip"
@@ -22,47 +23,39 @@
android:layout_width="wrap_content"
android:layout_marginLeft="@dimen/ongoing_appops_chip_margin"
android:layout_marginRight="@dimen/ongoing_appops_chip_margin"
- android:layout_marginTop="@dimen/ongoing_appops_top_chip_margin"
- android:layout_marginBottom="@dimen/ongoing_appops_top_chip_margin"
- android:gravity="center_vertical|center_horizontal"
android:layout_gravity="center_vertical|start"
+ android:gravity="center_vertical"
android:orientation="horizontal"
- android:paddingStart="@dimen/ongoing_appops_chip_side_padding"
- android:paddingEnd="@dimen/ongoing_appops_chip_side_padding"
android:focusable="true">
- <TextView
- android:id="@+id/in_use_text"
- android:layout_height="match_parent"
- android:layout_width="wrap_content"
- android:layout_gravity="center_vertical|start"
- android:layout_marginEnd="@dimen/ongoing_appops_chip_icon_margin_collapsed"
- android:gravity="center_vertical"
- android:textAppearance="@style/TextAppearance.StatusBar.Clock"
- android:textColor="@color/status_bar_clock_color"
- android:text="@string/ongoing_privacy_chip_in_use"
- />
-
<LinearLayout
- android:id="@+id/icons_container"
- android:layout_height="match_parent"
+ android:id="@+id/background"
+ android:layout_height="@dimen/ongoing_appops_chip_height"
android:layout_width="wrap_content"
- android:layout_gravity="center_vertical"
- android:gravity="center_vertical"
- />
+ >
+ <LinearLayout
+ android:id="@+id/icons_container"
+ android:layout_height="match_parent"
+ android:layout_width="wrap_content"
+ android:layout_marginStart="@dimen/ongoing_appops_chip_items_margin"
+ android:layout_gravity="center_vertical"
+ android:gravity="center_vertical"
+ />
- <TextView
- android:id="@+id/text_container"
- android:layout_height="match_parent"
- android:layout_width="wrap_content"
- android:singleLine="true"
- android:ellipsize="end"
- android:lines="1"
- android:layout_gravity="center_vertical|end"
- android:gravity="center_vertical"
- android:textAppearance="@style/TextAppearance.StatusBar.Clock"
- android:textColor="@color/status_bar_clock_color"
- android:layout_marginStart="@dimen/ongoing_appops_chip_icon_margin_collapsed"
- android:layout_marginEnd="@dimen/ongoing_appops_chip_icon_margin_collapsed"
- />
+ <TextView
+ android:id="@+id/text_container"
+ android:layout_height="match_parent"
+ android:layout_width="wrap_content"
+ android:layout_gravity="center_vertical|end"
+ android:paddingStart="@dimen/ongoing_appops_chip_text_padding"
+ android:paddingEnd="@dimen/ongoing_appops_chip_text_padding"
+ android:gravity="center_vertical"
+ android:singleLine="true"
+ android:ellipsize="end"
+ android:lines="1"
+ android:textAppearance="@style/TextAppearance.StatusBar.Clock"
+ android:textSize="@dimen/ongoing_appops_chip_text_size"
+ android:textColor="@color/status_bar_clock_color"
+ />
+ </LinearLayout>
</com.android.systemui.privacy.OngoingPrivacyChip> \ No newline at end of file
diff --git a/packages/SystemUI/res/raw/image_wallpaper_fragment_shader.glsl b/packages/SystemUI/res/raw/image_wallpaper_fragment_shader.glsl
new file mode 100644
index 000000000000..586cdf3fbaae
--- /dev/null
+++ b/packages/SystemUI/res/raw/image_wallpaper_fragment_shader.glsl
@@ -0,0 +1,27 @@
+precision mediump float;
+
+uniform sampler2D uTexture;
+uniform float uCenterReveal;
+uniform float uReveal;
+uniform float uAod2Opacity;
+varying vec2 vTextureCoordinates;
+
+vec3 luminosity(vec3 color) {
+ float lum = 0.2126 * color.r + 0.7152 * color.g + 0.0722 * color.b;
+ return vec3(lum);
+}
+
+vec4 transform(vec3 diffuse) {
+ // TODO: Add well comments here, tracking on b/123615467.
+ vec3 lum = luminosity(diffuse);
+ diffuse = mix(diffuse, lum, smoothstep(0., uCenterReveal, uReveal));
+ float val = mix(uReveal, uCenterReveal, step(uCenterReveal, uReveal));
+ diffuse = smoothstep(val, 1.0, diffuse);
+ diffuse *= uAod2Opacity * (1. - smoothstep(uCenterReveal, 1., uReveal));
+ return vec4(diffuse.r, diffuse.g, diffuse.b, 1.);
+}
+
+void main() {
+ vec4 fragColor = texture2D(uTexture, vTextureCoordinates);
+ gl_FragColor = transform(fragColor.rgb);
+} \ No newline at end of file
diff --git a/packages/SystemUI/res/raw/image_wallpaper_vertex_shader.glsl b/packages/SystemUI/res/raw/image_wallpaper_vertex_shader.glsl
new file mode 100644
index 000000000000..4393e2bb0ebf
--- /dev/null
+++ b/packages/SystemUI/res/raw/image_wallpaper_vertex_shader.glsl
@@ -0,0 +1,8 @@
+attribute vec4 aPosition;
+attribute vec2 aTextureCoordinates;
+varying vec2 vTextureCoordinates;
+
+void main() {
+ vTextureCoordinates = aTextureCoordinates;
+ gl_Position = aPosition;
+} \ No newline at end of file
diff --git a/packages/SystemUI/res/values-land/dimens.xml b/packages/SystemUI/res/values-land/dimens.xml
index df858f0c54e2..bb0c6f6acb06 100644
--- a/packages/SystemUI/res/values-land/dimens.xml
+++ b/packages/SystemUI/res/values-land/dimens.xml
@@ -34,5 +34,4 @@
<bool name="quick_settings_wide">true</bool>
<dimen name="qs_detail_margin_top">0dp</dimen>
<dimen name="qs_paged_tile_layout_padding_bottom">0dp</dimen>
- <dimen name="ongoing_appops_top_chip_margin">2dp</dimen>
</resources>
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index 1e1245fe0d86..1c7ee3667c16 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -980,26 +980,32 @@
<dimen name="ongoing_appops_dialog_items_bottom_margin">24dp</dimen>
<!-- Top and bottom margin of title in Ongoing App Ops dialog -->
<dimen name="ongoing_appops_dialog_title_margin_top_bottom">18dp</dimen>
+ <!-- Text size for Ongoing App Ops dialog title -->
+ <dimen name="ongoing_appops_dialog_title_size">20sp</dimen>
+ <!-- Text size for Ongoing App Ops dialog items -->
+ <dimen name="ongoing_appops_dialog_item_size">16sp</dimen>
<!-- Side margins around the Ongoing App Ops chip-->
- <dimen name="ongoing_appops_chip_margin">12dp</dimen>
- <!-- Top and bottom margins around the Ongoing App Ops chip -->
- <dimen name="ongoing_appops_top_chip_margin">12dp</dimen>
+ <dimen name="ongoing_appops_chip_margin">0dp</dimen>
+ <!-- Height of the Ongoing App Ops chip -->
+ <dimen name="ongoing_appops_chip_height">32dp</dimen>
<!-- Start and End padding for Ongoing App Ops chip -->
- <dimen name="ongoing_appops_chip_side_padding">6dp</dimen>
+ <dimen name="ongoing_appops_chip_text_padding">8dp</dimen>
<!-- Padding between background of Ongoing App Ops chip and content -->
<dimen name="ongoing_appops_chip_bg_padding">0dp</dimen>
+ <!-- Side padding between background of Ongoing App Ops chip and content -->
+ <dimen name="ongoing_appops_chip_side_padding">8dp</dimen>
<!-- Margin between icons of Ongoing App Ops chip when QQS-->
<dimen name="ongoing_appops_chip_icon_margin_collapsed">0dp</dimen>
<!-- Margin between icons of Ongoing App Ops chip when QS-->
- <dimen name="ongoing_appops_chip_icon_margin_expanded">8dp</dimen>
+ <dimen name="ongoing_appops_chip_icon_margin_expanded">2dp</dimen>
<!-- Icon size of Ongoing App Ops chip -->
- <dimen name="ongoing_appops_chip_icon_size">18dp</dimen>
+ <dimen name="ongoing_appops_chip_icon_size">@*android:dimen/status_bar_icon_size</dimen>
<!-- Radius of Ongoing App Ops chip corners -->
- <dimen name="ongoing_appops_chip_bg_corner_radius">4dp</dimen>
- <!-- Text size for Ongoing App Ops dialog title -->
- <dimen name="ongoing_appops_dialog_title_size">20sp</dimen>
- <!-- Text size for Ongoing App Ops dialog items -->
- <dimen name="ongoing_appops_dialog_item_size">16sp</dimen>
+ <dimen name="ongoing_appops_chip_bg_corner_radius">16dp</dimen>
+ <!-- Size of text of Ongoing App Ops chip -->
+ <dimen name="ongoing_appops_chip_text_size">12sp</dimen>
+ <!-- Margin between items in Ongoing App Ops chip -->
+ <dimen name="ongoing_appops_chip_items_margin">8dp</dimen>
<!-- How much a bubble is elevated -->
<dimen name="bubble_elevation">8dp</dimen>
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index b4131d738d13..01595f0705be 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -1582,19 +1582,19 @@
<!-- Notification Inline controls: continue receiving notifications prompt, channel level -->
<string name="inline_keep_showing">Keep showing these notifications?</string>
- <!-- Notification inline controls: block notifications button -->
+ <!-- Notification inline controls: block notifications button [CHAR_LIMIT=25] -->
<string name="inline_stop_button">Stop notifications</string>
<!-- Notification inline controls: button to deliver notifications silently from this channel [CHAR_LIMIT=35] -->
<string name="inline_deliver_silently_button">Deliver Silently</string>
- <!-- Notification inline controls: button to block notifications from this channel [CHAR_LIMIT=35] -->
+ <!-- Notification inline controls: button to block notifications from this channel [CHAR_LIMIT=20] -->
<string name="inline_block_button">Block</string>
- <!-- Notification inline controls: keep getting notifications button -->
+ <!-- Notification inline controls: keep getting notifications button [CHAR_LIMIT=25] -->
<string name="inline_keep_button">Keep showing</string>
- <!-- Notification inline controls: minimize notifications button -->
+ <!-- Notification inline controls: minimize notifications button [CHAR_LIMIT=20] -->
<string name="inline_minimize_button">Minimize</string>
<!-- Notification inline controls: button to show notifications silently, without alerting the user [CHAR_LIMIT=35] -->
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
index f277c4303ac1..3ac7fd4c61c1 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
@@ -724,6 +724,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener {
}
private void handleFaceAuthFailed() {
+ setFaceRunningState(BIOMETRIC_STATE_STOPPED);
for (int i = 0; i < mCallbacks.size(); i++) {
KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
if (cb != null) {
diff --git a/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java b/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java
index 2aecc24e83c0..7e645ab77a63 100644
--- a/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java
+++ b/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java
@@ -28,7 +28,9 @@ import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.Region.Op;
import android.hardware.display.DisplayManager;
+import android.opengl.GLSurfaceView;
import android.os.AsyncTask;
+import android.os.Build;
import android.os.Handler;
import android.os.Trace;
import android.service.wallpaper.WallpaperService;
@@ -39,6 +41,7 @@ import android.view.Surface;
import android.view.SurfaceHolder;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.systemui.glwallpaper.ImageWallpaperRenderer;
import java.io.FileDescriptor;
import java.io.IOException;
@@ -73,10 +76,78 @@ public class ImageWallpaper extends WallpaperService {
@Override
public Engine onCreateEngine() {
- mEngine = new DrawableEngine();
- return mEngine;
+ if (Build.IS_DEBUGGABLE) {
+ Log.v(TAG, "We are using GLEngine");
+ }
+ return new GLEngine(this);
+ }
+
+ class GLEngine extends Engine {
+ private GLWallpaperSurfaceView mWallpaperSurfaceView;
+
+ GLEngine(Context context) {
+ mWallpaperSurfaceView = new GLWallpaperSurfaceView(context);
+ mWallpaperSurfaceView.setRenderer(
+ new ImageWallpaperRenderer(context, mWallpaperSurfaceView));
+ mWallpaperSurfaceView.setRenderMode(GLSurfaceView.RENDERMODE_WHEN_DIRTY);
+ setOffsetNotificationsEnabled(true);
+ }
+
+ @Override
+ public void onAmbientModeChanged(boolean inAmbientMode, long animationDuration) {
+ if (mWallpaperSurfaceView != null) {
+ mWallpaperSurfaceView.notifyAmbientModeChanged(inAmbientMode, animationDuration);
+ }
+ }
+
+ @Override
+ public void onOffsetsChanged(float xOffset, float yOffset, float xOffsetStep,
+ float yOffsetStep, int xPixelOffset, int yPixelOffset) {
+ if (mWallpaperSurfaceView != null) {
+ mWallpaperSurfaceView.notifyOffsetsChanged(xOffset, yOffset);
+ }
+ }
+
+ private class GLWallpaperSurfaceView extends GLSurfaceView implements ImageGLView {
+ private WallpaperStatusListener mWallpaperChangedListener;
+
+ GLWallpaperSurfaceView(Context context) {
+ super(context);
+ setEGLContextClientVersion(2);
+ }
+
+ @Override
+ public SurfaceHolder getHolder() {
+ return getSurfaceHolder();
+ }
+
+ @Override
+ public void setRenderer(Renderer renderer) {
+ super.setRenderer(renderer);
+ mWallpaperChangedListener = (WallpaperStatusListener) renderer;
+ }
+
+ private void notifyAmbientModeChanged(boolean inAmbient, long duration) {
+ if (mWallpaperChangedListener != null) {
+ mWallpaperChangedListener.onAmbientModeChanged(inAmbient, duration);
+ }
+ }
+
+ private void notifyOffsetsChanged(float xOffset, float yOffset) {
+ if (mWallpaperChangedListener != null) {
+ mWallpaperChangedListener.onOffsetsChanged(
+ xOffset, yOffset, getHolder().getSurfaceFrame());
+ }
+ }
+
+ @Override
+ public void render() {
+ requestRender();
+ }
+ }
}
+ // TODO: Remove this engine, tracking on b/123617158.
class DrawableEngine extends Engine {
private final Runnable mUnloadWallpaperCallback = () -> {
unloadWallpaper(false /* forgetSize */);
@@ -564,4 +635,35 @@ public class ImageWallpaper extends WallpaperService {
}
}
}
+
+ /**
+ * A listener to trace status of image wallpaper.
+ */
+ public interface WallpaperStatusListener {
+
+ /**
+ * Called back while ambient mode changes.
+ * @param inAmbientMode true if is in ambient mode, false otherwise.
+ * @param duration the duration of animation.
+ */
+ void onAmbientModeChanged(boolean inAmbientMode, long duration);
+
+ /**
+ * Called back while wallpaper offsets.
+ * @param xOffset The offset portion along x.
+ * @param yOffset The offset portion along y.
+ */
+ void onOffsetsChanged(float xOffset, float yOffset, Rect frame);
+ }
+
+ /**
+ * An abstraction for view of GLRenderer.
+ */
+ public interface ImageGLView {
+
+ /**
+ * Ask the view to render.
+ */
+ void render();
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java b/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java
index 6d583df6082b..6bb4fb5ef94a 100644
--- a/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java
+++ b/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java
@@ -41,6 +41,7 @@ import com.android.systemui.statusbar.KeyguardIndicationController;
import com.android.systemui.statusbar.NotificationListener;
import com.android.systemui.statusbar.NotificationLockscreenUserManager;
import com.android.systemui.statusbar.NotificationLockscreenUserManagerImpl;
+import com.android.systemui.statusbar.NotificationMediaManager;
import com.android.systemui.statusbar.ScrimView;
import com.android.systemui.statusbar.notification.NotificationEntryManager;
import com.android.systemui.statusbar.notification.NotificationInterruptionStateProvider;
@@ -141,7 +142,7 @@ public class SystemUIFactory {
StatusBar statusBar, StatusBarStateController statusBarStateController,
NotificationListener listener) {
return new NotificationIconAreaController(context, statusBar, statusBarStateController,
- listener);
+ listener, Dependency.get(NotificationMediaManager.class));
}
public KeyguardIndicationController createKeyguardIndicationController(Context context,
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java
index be2dd679bba5..e62c77de0051 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java
@@ -52,7 +52,7 @@ import com.android.systemui.statusbar.notification.NotificationEntryListener;
import com.android.systemui.statusbar.notification.NotificationEntryManager;
import com.android.systemui.statusbar.notification.NotificationInterruptionStateProvider;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
-import com.android.systemui.statusbar.notification.row.NotificationInflater;
+import com.android.systemui.statusbar.notification.row.NotificationContentInflater.InflationFlag;
import com.android.systemui.statusbar.phone.StatusBarWindowController;
import java.util.List;
@@ -315,8 +315,7 @@ public class BubbleController implements BubbleExpandedView.OnBubbleBlockedListe
}
@Override
- public void onEntryInflated(NotificationEntry entry,
- @NotificationInflater.InflationFlag int inflatedFlags) {
+ public void onEntryInflated(NotificationEntry entry, @InflationFlag int inflatedFlags) {
if (!areBubblesEnabled(mContext)) {
return;
}
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java
index 62cc8895ac73..ed9b38b85156 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java
@@ -58,7 +58,7 @@ import java.math.RoundingMode;
/**
* Renders bubbles in a stack and handles animating expanded and collapsed states.
*/
-public class BubbleStackView extends FrameLayout implements BubbleTouchHandler.FloatingView {
+public class BubbleStackView extends FrameLayout {
private static final String TAG = "BubbleStackView";
/**
@@ -146,8 +146,9 @@ public class BubbleStackView extends FrameLayout implements BubbleTouchHandler.F
mBubbleData = data;
mInflater = LayoutInflater.from(context);
- mTouchHandler = new BubbleTouchHandler(context);
+ mTouchHandler = new BubbleTouchHandler(context, this);
setOnTouchListener(mTouchHandler);
+ mInflater = LayoutInflater.from(context);
Resources res = getResources();
mBubbleSize = res.getDimensionPixelSize(R.dimen.individual_bubble_size);
@@ -199,6 +200,8 @@ public class BubbleStackView extends FrameLayout implements BubbleTouchHandler.F
.setDampingRatio(SpringForce.DAMPING_RATIO_LOW_BOUNCY));
setClipChildren(false);
+
+ mBubbleContainer.bringToFront();
}
@Override
@@ -484,9 +487,10 @@ public class BubbleStackView extends FrameLayout implements BubbleTouchHandler.F
if (shouldExpand) {
mBubbleContainer.setController(mExpandedAnimationController);
mExpandedAnimationController.expandFromStack(
- mStackAnimationController.getStackPosition(), () -> {
- updatePointerPosition();
- updateAfter.run();
+ mStackAnimationController.getStackPosition(),
+ () -> {
+ updatePointerPosition();
+ updateAfter.run();
});
} else {
mBubbleContainer.cancelAllAnimations();
@@ -544,55 +548,49 @@ public class BubbleStackView extends FrameLayout implements BubbleTouchHandler.F
: null;
}
- @Override
- public void setPosition(float x, float y) {
- mStackAnimationController.moveFirstBubbleWithStackFollowing(x, y);
- }
-
- @Override
- public void setPositionX(float x) {
- // Unsupported, use setPosition(x, y).
- }
-
- @Override
- public void setPositionY(float y) {
- // Unsupported, use setPosition(x, y).
- }
-
- @Override
- public PointF getPosition() {
+ public PointF getStackPosition() {
return mStackAnimationController.getStackPosition();
}
/** Called when a drag operation on an individual bubble has started. */
- public void onBubbleDragStart(BubbleView bubble) {
- // TODO: Save position and snap back if not dismissed.
+ public void onBubbleDragStart(View bubble) {
+ mExpandedAnimationController.prepareForBubbleDrag(bubble);
}
/** Called with the coordinates to which an individual bubble has been dragged. */
- public void onBubbleDragged(BubbleView bubble, float x, float y) {
- bubble.setTranslationX(x);
- bubble.setTranslationY(y);
+ public void onBubbleDragged(View bubble, float x, float y) {
+ if (!mIsExpanded || mIsAnimating) {
+ return;
+ }
+
+ mExpandedAnimationController.dragBubbleOut(bubble, x, y);
}
/** Called when a drag operation on an individual bubble has finished. */
- public void onBubbleDragFinish(BubbleView bubble, float x, float y, float velX, float velY) {
- // TODO: Add fling to bottom to dismiss.
+ public void onBubbleDragFinish(
+ View bubble, float x, float y, float velX, float velY, boolean dismissed) {
+ if (!mIsExpanded || mIsAnimating) {
+ return;
+ }
+
+ if (dismissed) {
+ mExpandedAnimationController.prepareForDismissalWithVelocity(bubble, velX, velY);
+ } else {
+ mExpandedAnimationController.snapBubbleBack(bubble, velX, velY);
+ }
}
void onDragStart() {
- if (mIsExpanded) {
+ if (mIsExpanded || mIsAnimating) {
return;
}
mStackAnimationController.cancelStackPositionAnimations();
mBubbleContainer.setController(mStackAnimationController);
- mIsAnimating = false;
}
void onDragged(float x, float y) {
- // TODO: We can drag if animating - just need to reroute inflight anims to drag point.
- if (mIsExpanded) {
+ if (mIsExpanded || mIsAnimating) {
return;
}
@@ -744,9 +742,9 @@ public class BubbleStackView extends FrameLayout implements BubbleTouchHandler.F
private void updatePointerPosition() {
if (mExpandedBubble != null) {
- float pointerPosition = mExpandedBubble.iconView.getPosition().x
+ float pointerPosition = mExpandedBubble.iconView.getTranslationX()
+ (mExpandedBubble.iconView.getWidth() / 2f);
- mExpandedBubble.expandedView.setPointerPosition(pointerPosition);
+ mExpandedBubble.expandedView.setPointerPosition((int) pointerPosition);
}
}
@@ -772,7 +770,7 @@ public class BubbleStackView extends FrameLayout implements BubbleTouchHandler.F
* @return the normalized x-axis position of the bubble stack rounded to 4 decimal places.
*/
public float getNormalizedXPosition() {
- return new BigDecimal(getPosition().x / mDisplaySize.x)
+ return new BigDecimal(getStackPosition().x / mDisplaySize.x)
.setScale(4, RoundingMode.CEILING.HALF_UP)
.floatValue();
}
@@ -781,7 +779,7 @@ public class BubbleStackView extends FrameLayout implements BubbleTouchHandler.F
* @return the normalized y-axis position of the bubble stack rounded to 4 decimal places.
*/
public float getNormalizedYPosition() {
- return new BigDecimal(getPosition().y / mDisplaySize.y)
+ return new BigDecimal(getStackPosition().y / mDisplaySize.y)
.setScale(4, RoundingMode.CEILING.HALF_UP)
.floatValue();
}
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleTouchHandler.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleTouchHandler.java
index 7d3c0f85c0f7..165eb1dda077 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleTouchHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleTouchHandler.java
@@ -34,17 +34,16 @@ import com.android.systemui.pip.phone.PipDismissViewController;
* dismissing, and flings.
*/
class BubbleTouchHandler implements View.OnTouchListener {
+ /** Velocity required to dismiss a bubble without dragging it into the dismiss target. */
+ private static final float DISMISS_MIN_VELOCITY = 4000f;
+
+ private final PointF mTouchDown = new PointF();
+ private final PointF mViewPositionOnTouchDown = new PointF();
+ private final BubbleStackView mStack;
private BubbleController mController = Dependency.get(BubbleController.class);
private PipDismissViewController mDismissViewController;
- // The position of the bubble on down event
- private float mBubbleDownPosX;
- private float mBubbleDownPosY;
- // The touch position on down event
- private float mDownX = -1;
- private float mDownY = -1;
-
private boolean mMovedEnough;
private int mTouchSlopSquared;
private VelocityTracker mVelocityTracker;
@@ -58,65 +57,42 @@ class BubbleTouchHandler implements View.OnTouchListener {
}
};
- // Bubble being dragged from the row of bubbles when the stack is expanded
- private BubbleView mBubbleDraggingOut;
-
- /**
- * Views movable by this touch handler should implement this interface.
- */
- public interface FloatingView {
-
- /**
- * Sets the position of the view.
- */
- void setPosition(float x, float y);
-
- /**
- * Sets the x position of the view.
- */
- void setPositionX(float x);
-
- /**
- * Sets the y position of the view.
- */
- void setPositionY(float y);
-
- /**
- * @return the position of the view.
- */
- PointF getPosition();
- }
+ /** View that was initially touched, when we received the first ACTION_DOWN event. */
+ private View mTouchedView;
- public BubbleTouchHandler(Context context) {
+ BubbleTouchHandler(Context context, BubbleStackView stackView) {
final int touchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
mTouchSlopSquared = touchSlop * touchSlop;
mDismissViewController = new PipDismissViewController(context);
+ mStack = stackView;
}
@Override
public boolean onTouch(View v, MotionEvent event) {
- int action = event.getActionMasked();
-
- BubbleStackView stack = (BubbleStackView) v;
- View targetView = mBubbleDraggingOut != null
- ? mBubbleDraggingOut
- : stack.getTargetView(event);
- boolean isFloating = targetView instanceof FloatingView;
- if (!isFloating || targetView == null || action == MotionEvent.ACTION_OUTSIDE) {
- stack.collapseStack();
+ final int action = event.getActionMasked();
+
+ // If we aren't currently in the process of touching a view, figure out what we're touching.
+ // It'll be the stack, an individual bubble, or nothing.
+ if (mTouchedView == null) {
+ mTouchedView = mStack.getTargetView(event);
+ }
+
+ // If this is an ACTION_OUTSIDE event, or the stack reported that we aren't touching
+ // anything, collapse the stack.
+ if (action == MotionEvent.ACTION_OUTSIDE || mTouchedView == null) {
+ mStack.collapseStack();
cleanUpDismissTarget();
- resetTouches();
+ mTouchedView = null;
return false;
}
- FloatingView floatingView = (FloatingView) targetView;
- boolean isBubbleStack = floatingView instanceof BubbleStackView;
+ final boolean isStack = mStack.equals(mTouchedView);
+ final float rawX = event.getRawX();
+ final float rawY = event.getRawY();
- PointF startPos = floatingView.getPosition();
- float rawX = event.getRawX();
- float rawY = event.getRawY();
- float x = mBubbleDownPosX + rawX - mDownX;
- float y = mBubbleDownPosY + rawY - mDownY;
+ // The coordinates of the touch event, in terms of the touched view's position.
+ final float viewX = mViewPositionOnTouchDown.x + rawX - mTouchDown.x;
+ final float viewY = mViewPositionOnTouchDown.y + rawY - mTouchDown.y;
switch (action) {
case MotionEvent.ACTION_DOWN:
trackMovement(event);
@@ -124,87 +100,83 @@ class BubbleTouchHandler implements View.OnTouchListener {
mDismissViewController.createDismissTarget();
mHandler.postDelayed(mShowDismissAffordance, SHOW_TARGET_DELAY);
- mBubbleDownPosX = startPos.x;
- mBubbleDownPosY = startPos.y;
- mDownX = rawX;
- mDownY = rawY;
- mMovedEnough = false;
+ mTouchDown.set(rawX, rawY);
- if (isBubbleStack) {
- stack.onDragStart();
+ if (isStack) {
+ mViewPositionOnTouchDown.set(mStack.getStackPosition());
+ mStack.onDragStart();
} else {
- stack.onBubbleDragStart((BubbleView) floatingView);
+ mViewPositionOnTouchDown.set(
+ mTouchedView.getTranslationX(), mTouchedView.getTranslationY());
+ mStack.onBubbleDragStart(mTouchedView);
}
break;
-
case MotionEvent.ACTION_MOVE:
trackMovement(event);
+ final float deltaX = rawX - mTouchDown.x;
+ final float deltaY = rawY - mTouchDown.y;
- if (mBubbleDownPosX == -1 || mDownX == -1) {
- mBubbleDownPosX = startPos.x;
- mBubbleDownPosY = startPos.y;
- mDownX = rawX;
- mDownY = rawY;
- }
- final float deltaX = rawX - mDownX;
- final float deltaY = rawY - mDownY;
if ((deltaX * deltaX) + (deltaY * deltaY) > mTouchSlopSquared && !mMovedEnough) {
mMovedEnough = true;
}
if (mMovedEnough) {
- if (floatingView instanceof BubbleView) {
- mBubbleDraggingOut = ((BubbleView) floatingView);
- stack.onBubbleDragged(mBubbleDraggingOut, x, y);
+ if (isStack) {
+ mStack.onDragged(viewX, viewY);
} else {
- stack.onDragged(x, y);
+ mStack.onBubbleDragged(mTouchedView, viewX, viewY);
}
}
+
// TODO - when we're in the target stick to it / animate in some way?
mInDismissTarget = mDismissViewController.updateTarget(
- isBubbleStack ? stack.getBubbleAt(0) : (View) floatingView);
+ isStack ? mStack.getBubbleAt(0) : mTouchedView);
break;
case MotionEvent.ACTION_CANCEL:
- resetTouches();
+ mTouchedView = null;
cleanUpDismissTarget();
break;
case MotionEvent.ACTION_UP:
trackMovement(event);
- if (mInDismissTarget) {
- if (isBubbleStack) {
- mController.dismissStack();
- } else {
- mController.removeBubble(((BubbleView) floatingView).getKey());
- }
+ if (mInDismissTarget && isStack) {
+ mController.dismissStack();
} else if (mMovedEnough) {
mVelocityTracker.computeCurrentVelocity(1000);
final float velX = mVelocityTracker.getXVelocity();
final float velY = mVelocityTracker.getYVelocity();
- if (isBubbleStack) {
- stack.onDragFinish(x, y, velX, velY);
+ if (isStack) {
+ mStack.onDragFinish(viewX, viewY, velX, velY);
} else {
- stack.onBubbleDragFinish(mBubbleDraggingOut, x, y, velX, velY);
+ final boolean dismissed = mInDismissTarget || velY > DISMISS_MIN_VELOCITY;
+ mStack.onBubbleDragFinish(
+ mTouchedView, viewX, viewY, velX, velY, /* dismissed */ dismissed);
+ if (dismissed) {
+ mController.removeBubble(((BubbleView) mTouchedView).getKey());
+ }
}
- } else if (floatingView.equals(stack.getExpandedBubbleView())) {
- stack.collapseStack();
- } else if (isBubbleStack) {
- if (stack.isExpanded()) {
- stack.collapseStack();
+ } else if (mTouchedView.equals(mStack.getExpandedBubbleView())) {
+ mStack.collapseStack();
+ } else if (isStack) {
+ if (mStack.isExpanded()) {
+ mStack.collapseStack();
} else {
- stack.expandStack();
+ mStack.expandStack();
}
} else {
- stack.setExpandedBubble(((BubbleView) floatingView).getKey());
+ mStack.setExpandedBubble(((BubbleView) mTouchedView).getKey());
}
+
cleanUpDismissTarget();
mVelocityTracker.recycle();
mVelocityTracker = null;
- resetTouches();
+ mTouchedView = null;
+ mMovedEnough = false;
break;
}
+
return true;
}
@@ -216,16 +188,6 @@ class BubbleTouchHandler implements View.OnTouchListener {
mDismissViewController.destroyDismissTarget();
}
- /**
- * Resets anything we care about after a gesture is complete.
- */
- private void resetTouches() {
- mDownX = -1;
- mDownY = -1;
- mBubbleDownPosX = -1;
- mBubbleDownPosY = -1;
- mBubbleDraggingOut = null;
- }
private void trackMovement(MotionEvent event) {
if (mVelocityTracker == null) {
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleView.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleView.java
index 1a4b19940e34..b409a3181e2b 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleView.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleView.java
@@ -20,7 +20,6 @@ import android.annotation.Nullable;
import android.app.Notification;
import android.content.Context;
import android.graphics.Color;
-import android.graphics.PointF;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.Icon;
@@ -39,7 +38,7 @@ import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow
/**
* A floating object on the screen that can post message updates.
*/
-public class BubbleView extends FrameLayout implements BubbleTouchHandler.FloatingView {
+public class BubbleView extends FrameLayout {
private static final String TAG = "BubbleView";
// Same value as Launcher3 badge code
@@ -217,25 +216,4 @@ public class BubbleView extends FrameLayout implements BubbleTouchHandler.Floati
// XXX: should we pull from the drawable, app icon, notif tint?
return ColorUtils.blendARGB(defaultTint, Color.WHITE, WHITE_SCRIM_ALPHA);
}
-
- @Override
- public void setPosition(float x, float y) {
- setPositionX(x);
- setPositionY(y);
- }
-
- @Override
- public void setPositionX(float x) {
- setTranslationX(x);
- }
-
- @Override
- public void setPositionY(float y) {
- setTranslationY(y);
- }
-
- @Override
- public PointF getPosition() {
- return new PointF(getTranslationX(), getTranslationY());
- }
}
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/animation/ExpandedAnimationController.java b/packages/SystemUI/src/com/android/systemui/bubbles/animation/ExpandedAnimationController.java
index 5b158e906356..9fd26b80e385 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/animation/ExpandedAnimationController.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/animation/ExpandedAnimationController.java
@@ -44,6 +44,9 @@ public class ExpandedAnimationController
*/
private static final int ANIMATE_TRANSLATION_FACTOR = 4;
+ /** How much to scale down bubbles when they're animating in/out. */
+ private static final float ANIMATE_SCALE_PERCENT = 0.5f;
+
/**
* The stack position from which the bubbles were expanded. Saved in {@link #expandFromStack}
* and used to return to stack form in {@link #collapseBackToStack}.
@@ -59,6 +62,22 @@ public class ExpandedAnimationController
/** Height of the status bar. */
private float mStatusBarHeight;
+ /**
+ * Whether the individual bubble has been dragged out of the row of bubbles far enough to cause
+ * the rest of the bubbles to animate to fill the gap.
+ */
+ private boolean mBubbleDraggedOutEnough = false;
+
+ /** The bubble currently being dragged out of the row (to potentially be dismissed). */
+ private View mBubbleDraggingOut;
+
+ /**
+ * Drag velocities for the dragging-out bubble when the drag finished. These are used by
+ * {@link #onChildRemoved} to animate out the bubble while respecting touch velocity.
+ */
+ private float mBubbleDraggingOutVelX;
+ private float mBubbleDraggingOutVelY;
+
@Override
protected void setLayout(PhysicsAnimationLayout layout) {
super.setLayout(layout);
@@ -102,6 +121,87 @@ public class ExpandedAnimationController
runAfterTranslationsEnd(after);
}
+ /** Prepares the given bubble to be dragged out. */
+ public void prepareForBubbleDrag(View bubble) {
+ mLayout.cancelAnimationsOnView(bubble);
+
+ mBubbleDraggingOut = bubble;
+ mBubbleDraggingOut.setTranslationZ(Short.MAX_VALUE);
+ }
+
+ /**
+ * Drags an individual bubble to the given coordinates. Bubbles to the right will animate to
+ * take its place once it's dragged out of the row of bubbles, and animate out of the way if the
+ * bubble is dragged back into the row.
+ */
+ public void dragBubbleOut(View bubbleView, float x, float y) {
+ bubbleView.setTranslationX(x);
+ bubbleView.setTranslationY(y);
+
+ final boolean draggedOutEnough =
+ y > getExpandedY() + mBubbleSizePx || y < getExpandedY() - mBubbleSizePx;
+ if (draggedOutEnough != mBubbleDraggedOutEnough) {
+ animateStackByBubbleWidthsStartingFrom(
+ /* numBubbleWidths */ draggedOutEnough ? -1 : 0,
+ /* startIndex */ mLayout.indexOfChild(bubbleView) + 1);
+ mBubbleDraggedOutEnough = draggedOutEnough;
+ }
+ }
+
+ /**
+ * Snaps a bubble back to its position within the bubble row, and animates the rest of the
+ * bubbles to accommodate it if it was previously dragged out past the threshold.
+ */
+ public void snapBubbleBack(View bubbleView, float velX, float velY) {
+ final int index = mLayout.indexOfChild(bubbleView);
+
+ // Snap the bubble back, respecting its current velocity.
+ mLayout.animateValueForChildAtIndex(
+ DynamicAnimation.TRANSLATION_X, index, getXForChildAtIndex(index), velX);
+ mLayout.animateValueForChildAtIndex(
+ DynamicAnimation.TRANSLATION_Y, index, getExpandedY(), velY);
+ mLayout.setEndListenerForProperties(
+ mLayout.new OneTimeMultiplePropertyEndListener() {
+ @Override
+ void onAllAnimationsForPropertiesEnd() {
+ // Reset Z translation once the bubble is done snapping back.
+ bubbleView.setTranslationZ(0f);
+ }
+ },
+ DynamicAnimation.TRANSLATION_X, DynamicAnimation.TRANSLATION_Y);
+
+ animateStackByBubbleWidthsStartingFrom(
+ /* numBubbleWidths */ 0, /* startIndex */ index + 1);
+
+ mBubbleDraggingOut = null;
+ mBubbleDraggedOutEnough = false;
+ }
+
+ /**
+ * Sets configuration variables so that when the given bubble is removed, the animations are
+ * started with the given velocities.
+ */
+ public void prepareForDismissalWithVelocity(View bubbleView, float velX, float velY) {
+ mBubbleDraggingOut = bubbleView;
+ mBubbleDraggingOutVelX = velX;
+ mBubbleDraggingOutVelY = velY;
+ mBubbleDraggedOutEnough = false;
+ }
+
+ /**
+ * Animates the bubbles, starting at the given index, to the left or right by the given number
+ * of bubble widths. Passing zero for numBubbleWidths will animate the bubbles to their normal
+ * positions.
+ */
+ private void animateStackByBubbleWidthsStartingFrom(int numBubbleWidths, int startIndex) {
+ for (int i = startIndex; i < mLayout.getChildCount(); i++) {
+ mLayout.animateValueForChildAtIndex(
+ DynamicAnimation.TRANSLATION_X,
+ i,
+ getXForChildAtIndex(i + numBubbleWidths));
+ }
+ }
+
/** The Y value of the row of expanded bubbles. */
private float getExpandedY() {
final WindowInsets insets = mLayout.getRootWindowInsets();
@@ -165,12 +265,7 @@ public class ExpandedAnimationController
child.setTranslationX(getXForChildAtIndex(index));
child.setTranslationY(getExpandedY() - mBubbleSizePx * ANIMATE_TRANSLATION_FACTOR);
mLayout.animateValueForChild(DynamicAnimation.TRANSLATION_Y, child, getExpandedY());
-
- // Animate the remaining bubbles to the correct X position.
- for (int i = index + 1; i < mLayout.getChildCount(); i++) {
- mLayout.animateValueForChildAtIndex(
- DynamicAnimation.TRANSLATION_X, i, getXForChildAtIndex(i));
- }
+ animateBubblesAfterIndexToCorrectX(index);
}
@Override
@@ -179,16 +274,36 @@ public class ExpandedAnimationController
// TODO: Reverse this when bubbles are at the bottom.
mLayout.animateValueForChild(
DynamicAnimation.ALPHA, child, 0f, finishRemoval);
- mLayout.animateValueForChild(
- DynamicAnimation.TRANSLATION_Y,
- child,
- getExpandedY() - mBubbleSizePx * ANIMATE_TRANSLATION_FACTOR);
- // Animate the remaining bubbles to the correct X position.
- for (int i = index; i < mLayout.getChildCount(); i++) {
- mLayout.animateValueForChildAtIndex(
- DynamicAnimation.TRANSLATION_X, i, getXForChildAtIndex(i));
+ // If we're removing the dragged-out bubble, that means it got dismissed.
+ if (child.equals(mBubbleDraggingOut)) {
+ // Throw it to the bottom of the screen, towards the center horizontally.
+ mLayout.animateValueForChild(
+ DynamicAnimation.TRANSLATION_X,
+ child,
+ mLayout.getWidth() / 2f - mBubbleSizePx / 2f,
+ mBubbleDraggingOutVelX);
+ mLayout.animateValueForChild(
+ DynamicAnimation.TRANSLATION_Y,
+ child,
+ mLayout.getHeight() + mBubbleSizePx,
+ mBubbleDraggingOutVelY);
+
+ // Scale it down a bit so it looks like it's disappearing.
+ mLayout.animateValueForChild(DynamicAnimation.SCALE_X, child, ANIMATE_SCALE_PERCENT);
+ mLayout.animateValueForChild(DynamicAnimation.SCALE_Y, child, ANIMATE_SCALE_PERCENT);
+
+ mBubbleDraggingOut = null;
+ } else {
+ // If we're removing some random bubble just throw it off the top.
+ mLayout.animateValueForChild(
+ DynamicAnimation.TRANSLATION_Y,
+ child,
+ getExpandedY() - mBubbleSizePx * ANIMATE_TRANSLATION_FACTOR);
}
+
+ // Animate all the other bubbles to their new positions sans this bubble.
+ animateBubblesAfterIndexToCorrectX(index);
}
@Override
@@ -207,6 +322,23 @@ public class ExpandedAnimationController
() -> super.setChildVisibility(child, index, visibility));
}
+ /**
+ * Animates the bubbles after the given index to the X position they should be in according to
+ * {@link #getXForChildAtIndex}.
+ */
+ private void animateBubblesAfterIndexToCorrectX(int start) {
+ for (int i = start; i < mLayout.getChildCount(); i++) {
+ final View bubble = mLayout.getChildAt(i);
+
+ // Don't animate the dragging out bubble, or it'll jump around while being dragged. It
+ // will be snapped to the correct X value after the drag (if it's not dismissed).
+ if (!bubble.equals(mBubbleDraggingOut)) {
+ mLayout.animateValueForChild(
+ DynamicAnimation.TRANSLATION_X, bubble, getXForChildAtIndex(i));
+ }
+ }
+ }
+
/** Returns the appropriate X translation value for a bubble at the given index. */
private float getXForChildAtIndex(int index) {
return mBubblePaddingPx + (mBubbleSizePx + mBubblePaddingPx) * index;
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/animation/PhysicsAnimationLayout.java b/packages/SystemUI/src/com/android/systemui/bubbles/animation/PhysicsAnimationLayout.java
index a4ddbf752316..dfdcfc9f3b74 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/animation/PhysicsAnimationLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/animation/PhysicsAnimationLayout.java
@@ -187,6 +187,20 @@ public class PhysicsAnimationLayout extends FrameLayout {
}
/**
+ * Sets an end listener that will be called whenever any of the given properties' animations
+ * end. For example, setting a listener for TRANSLATION_X and TRANSLATION_Y will result in that
+ * listener being called twice - once when all TRANSLATION_X animations end, and again when all
+ * TRANSLATION_Y animations end.
+ */
+ public void setEndListenerForProperties(
+ DynamicAnimation.OnAnimationEndListener endListener,
+ DynamicAnimation.ViewProperty... properties) {
+ for (DynamicAnimation.ViewProperty property : properties) {
+ setEndListenerForProperty(endListener, property);
+ }
+ }
+
+ /**
* Removes the end listener that would have been called when all child animations for a given
* property stopped running.
*/
@@ -197,7 +211,6 @@ public class PhysicsAnimationLayout extends FrameLayout {
@Override
public void addView(View child, int index, ViewGroup.LayoutParams params) {
super.addView(child, index, params);
- setChildrenVisibility();
// Set up animations for the new view, if the controller is set. If it isn't set, we'll be
// setting up animations for all children when setController is called.
@@ -208,6 +221,8 @@ public class PhysicsAnimationLayout extends FrameLayout {
mController.onChildAdded(child, index);
}
+
+ setChildrenVisibility();
}
@Override
@@ -294,6 +309,13 @@ public class PhysicsAnimationLayout extends FrameLayout {
}
}
+ /** Cancels all of the physics animations running on the given view. */
+ public void cancelAnimationsOnView(View view) {
+ for (DynamicAnimation.ViewProperty property : mController.getAnimatedProperties()) {
+ getAnimationFromView(property, view).cancel();
+ }
+ }
+
/**
* Animates the property of the given child view, then runs the callback provided when the
* animation ends.
@@ -318,6 +340,11 @@ public class PhysicsAnimationLayout extends FrameLayout {
});
}
+ // Set the start velocity if it's something other than the not-set value.
+ if (startVel != Float.MAX_VALUE) {
+ animation.setStartVelocity(startVel);
+ }
+
animation.animateToFinalPosition(value);
}
}
@@ -337,6 +364,14 @@ public class PhysicsAnimationLayout extends FrameLayout {
animateValueForChild(property, view, value, Float.MAX_VALUE, /* after */ null);
}
+ protected void animateValueForChild(
+ DynamicAnimation.ViewProperty property,
+ View view,
+ float value,
+ float startVel) {
+ animateValueForChild(property, view, value, startVel, /* after */ null);
+ }
+
/**
* Animates the property of the child at the given index to the given value, then runs the
* callback provided when the animation ends.
@@ -414,7 +449,13 @@ public class PhysicsAnimationLayout extends FrameLayout {
*/
private SpringAnimation getAnimationAtIndex(
DynamicAnimation.ViewProperty property, int index) {
- return (SpringAnimation) getChildAt(index).getTag(getTagIdForProperty(property));
+ return getAnimationFromView(property, getChildAt(index));
+ }
+
+ /** Retrieves the animation of the given property from the view via the view tag system. */
+ private SpringAnimation getAnimationFromView(
+ DynamicAnimation.ViewProperty property, View view) {
+ return (SpringAnimation) view.getTag(getTagIdForProperty(property));
}
/** Sets up SpringAnimations of the given property for each child view in the layout. */
@@ -528,4 +569,33 @@ public class PhysicsAnimationLayout extends FrameLayout {
}
}
}
+
+ /**
+ * One time end listener that waits for every animation on every given property to finish. At
+ * that point, it calls {@link #onAllAnimationsForPropertiesEnd} and then removes itself as an
+ * end listener from each property.
+ */
+ public abstract class OneTimeMultiplePropertyEndListener
+ implements DynamicAnimation.OnAnimationEndListener {
+ final DynamicAnimation.ViewProperty[] mViewProperties;
+
+ OneTimeMultiplePropertyEndListener(DynamicAnimation.ViewProperty... properties) {
+ mViewProperties = properties;
+ }
+
+ @Override
+ public void onAnimationEnd(DynamicAnimation animation, boolean canceled, float value,
+ float velocity) {
+ if (!arePropertiesAnimating(mViewProperties)) {
+ onAllAnimationsForPropertiesEnd();
+
+ for (DynamicAnimation.ViewProperty property : mViewProperties) {
+ removeEndListenerForProperty(property);
+ }
+ }
+ }
+
+ /** Called when every animation for every property has finished. */
+ abstract void onAllAnimationsForPropertiesEnd();
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/glwallpaper/ImageGLProgram.java b/packages/SystemUI/src/com/android/systemui/glwallpaper/ImageGLProgram.java
new file mode 100644
index 000000000000..d03b00bcfc85
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/glwallpaper/ImageGLProgram.java
@@ -0,0 +1,115 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.glwallpaper;
+
+import static android.opengl.GLES20.GL_FRAGMENT_SHADER;
+import static android.opengl.GLES20.GL_VERTEX_SHADER;
+import static android.opengl.GLES20.glAttachShader;
+import static android.opengl.GLES20.glCompileShader;
+import static android.opengl.GLES20.glCreateProgram;
+import static android.opengl.GLES20.glCreateShader;
+import static android.opengl.GLES20.glGetAttribLocation;
+import static android.opengl.GLES20.glGetUniformLocation;
+import static android.opengl.GLES20.glLinkProgram;
+import static android.opengl.GLES20.glShaderSource;
+import static android.opengl.GLES20.glUseProgram;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.util.Log;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
+
+/**
+ * This class takes charge of linking shader codes and then return a handle for OpenGL ES program.
+ */
+class ImageGLProgram {
+ private static final String TAG = ImageGLProgram.class.getSimpleName();
+
+ private Context mContext;
+ private int mProgramHandle;
+
+ ImageGLProgram(Context context) {
+ mContext = context.getApplicationContext();
+ }
+
+ private int loadShaderProgram(int vertexId, int fragmentId) {
+ final String vertexSrc = getShaderResource(vertexId);
+ final String fragmentSrc = getShaderResource(fragmentId);
+ final int vertexHandle = getShaderHandle(GL_VERTEX_SHADER, vertexSrc);
+ final int fragmentHandle = getShaderHandle(GL_FRAGMENT_SHADER, fragmentSrc);
+ return getProgramHandle(vertexHandle, fragmentHandle);
+ }
+
+ private String getShaderResource(int shaderId) {
+ Resources res = mContext.getResources();
+ StringBuilder code = new StringBuilder();
+
+ try (BufferedReader reader = new BufferedReader(
+ new InputStreamReader(res.openRawResource(shaderId)))) {
+ String nextLine;
+ while ((nextLine = reader.readLine()) != null) {
+ code.append(nextLine).append("\n");
+ }
+ } catch (IOException | Resources.NotFoundException ex) {
+ Log.d(TAG, "Can not read the shader source", ex);
+ code = null;
+ }
+
+ return code == null ? "" : code.toString();
+ }
+
+ private int getShaderHandle(int type, String src) {
+ final int shader = glCreateShader(type);
+ if (shader == 0) {
+ Log.d(TAG, "Create shader failed, type=" + type);
+ return 0;
+ }
+ glShaderSource(shader, src);
+ glCompileShader(shader);
+ return shader;
+ }
+
+ private int getProgramHandle(int vertexHandle, int fragmentHandle) {
+ final int program = glCreateProgram();
+ if (program == 0) {
+ Log.d(TAG, "Can not create OpenGL ES program");
+ return 0;
+ }
+
+ glAttachShader(program, vertexHandle);
+ glAttachShader(program, fragmentHandle);
+ glLinkProgram(program);
+ return program;
+ }
+
+ boolean useGLProgram(int vertexResId, int fragmentResId) {
+ mProgramHandle = loadShaderProgram(vertexResId, fragmentResId);
+ glUseProgram(mProgramHandle);
+ return true;
+ }
+
+ int getAttributeHandle(String name) {
+ return glGetAttribLocation(mProgramHandle, name);
+ }
+
+ int getUniformHandle(String name) {
+ return glGetUniformLocation(mProgramHandle, name);
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/glwallpaper/ImageGLWallpaper.java b/packages/SystemUI/src/com/android/systemui/glwallpaper/ImageGLWallpaper.java
new file mode 100644
index 000000000000..19d85b155cba
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/glwallpaper/ImageGLWallpaper.java
@@ -0,0 +1,259 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.glwallpaper;
+
+import static android.opengl.GLES20.GL_FLOAT;
+import static android.opengl.GLES20.GL_LINEAR;
+import static android.opengl.GLES20.GL_TEXTURE0;
+import static android.opengl.GLES20.GL_TEXTURE_2D;
+import static android.opengl.GLES20.GL_TEXTURE_MAG_FILTER;
+import static android.opengl.GLES20.GL_TEXTURE_MIN_FILTER;
+import static android.opengl.GLES20.GL_TRIANGLES;
+import static android.opengl.GLES20.glActiveTexture;
+import static android.opengl.GLES20.glBindTexture;
+import static android.opengl.GLES20.glDrawArrays;
+import static android.opengl.GLES20.glEnableVertexAttribArray;
+import static android.opengl.GLES20.glGenTextures;
+import static android.opengl.GLES20.glTexParameteri;
+import static android.opengl.GLES20.glUniform1i;
+import static android.opengl.GLES20.glVertexAttribPointer;
+
+import android.graphics.Bitmap;
+import android.opengl.GLUtils;
+import android.os.Build;
+import android.util.Log;
+
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.nio.FloatBuffer;
+
+/**
+ * This class takes charge of the geometry data like vertices and texture coordinates.
+ * It delivers these data to opengl runtime and triggers draw calls if necessary.
+ */
+class ImageGLWallpaper {
+ private static final String TAG = ImageGLWallpaper.class.getSimpleName();
+
+ static final String A_POSITION = "aPosition";
+ static final String A_TEXTURE_COORDINATES = "aTextureCoordinates";
+ static final String U_CENTER_REVEAL = "uCenterReveal";
+ static final String U_REVEAL = "uReveal";
+ static final String U_AOD2OPACITY = "uAod2Opacity";
+ static final String U_TEXTURE = "uTexture";
+
+ private static final int HANDLE_UNDEFINED = -1;
+ private static final int POSITION_COMPONENT_COUNT = 2;
+ private static final int TEXTURE_COMPONENT_COUNT = 2;
+ private static final int BYTES_PER_FLOAT = 4;
+
+ // Vertices to define the square with 2 triangles.
+ private static final float[] VERTICES = {
+ -1.0f, -1.0f,
+ +1.0f, -1.0f,
+ +1.0f, +1.0f,
+ +1.0f, +1.0f,
+ -1.0f, +1.0f,
+ -1.0f, -1.0f
+ };
+
+ // Texture coordinates that maps to vertices.
+ private static final float[] TEXTURES = {
+ 0f, 1f,
+ 1f, 1f,
+ 1f, 0f,
+ 1f, 0f,
+ 0f, 0f,
+ 0f, 1f
+ };
+
+ private final FloatBuffer mVertexBuffer;
+ private final FloatBuffer mTextureBuffer;
+ private final ImageGLProgram mProgram;
+
+ private int mAttrPosition;
+ private int mAttrTextureCoordinates;
+ private int mUniAod2Opacity;
+ private int mUniCenterReveal;
+ private int mUniReveal;
+ private int mUniTexture;
+ private int mTextureId;
+
+ ImageGLWallpaper(ImageGLProgram program) {
+ mProgram = program;
+
+ // Create an float array in opengles runtime (native) and put vertex data.
+ mVertexBuffer = ByteBuffer.allocateDirect(VERTICES.length * BYTES_PER_FLOAT)
+ .order(ByteOrder.nativeOrder())
+ .asFloatBuffer();
+ mVertexBuffer.put(VERTICES);
+ mVertexBuffer.position(0);
+
+ // Create an float array in opengles runtime (native) and put texture data.
+ mTextureBuffer = ByteBuffer.allocateDirect(TEXTURES.length * BYTES_PER_FLOAT)
+ .order(ByteOrder.nativeOrder())
+ .asFloatBuffer();
+ mTextureBuffer.put(TEXTURES);
+ mTextureBuffer.position(0);
+ }
+
+ void setup() {
+ setupAttributes();
+ setupUniforms();
+ }
+
+ private void setupAttributes() {
+ mAttrPosition = mProgram.getAttributeHandle(A_POSITION);
+ mVertexBuffer.position(0);
+ glVertexAttribPointer(mAttrPosition, POSITION_COMPONENT_COUNT, GL_FLOAT,
+ false, 0, mVertexBuffer);
+ glEnableVertexAttribArray(mAttrPosition);
+
+ mAttrTextureCoordinates = mProgram.getAttributeHandle(A_TEXTURE_COORDINATES);
+ mTextureBuffer.position(0);
+ glVertexAttribPointer(mAttrTextureCoordinates, TEXTURE_COMPONENT_COUNT, GL_FLOAT,
+ false, 0, mTextureBuffer);
+ glEnableVertexAttribArray(mAttrTextureCoordinates);
+ }
+
+ private void setupUniforms() {
+ mUniAod2Opacity = mProgram.getUniformHandle(U_AOD2OPACITY);
+ mUniCenterReveal = mProgram.getUniformHandle(U_CENTER_REVEAL);
+ mUniReveal = mProgram.getUniformHandle(U_REVEAL);
+ mUniTexture = mProgram.getUniformHandle(U_TEXTURE);
+ }
+
+ int getHandle(String name) {
+ switch (name) {
+ case A_POSITION:
+ return mAttrPosition;
+ case A_TEXTURE_COORDINATES:
+ return mAttrTextureCoordinates;
+ case U_AOD2OPACITY:
+ return mUniAod2Opacity;
+ case U_CENTER_REVEAL:
+ return mUniCenterReveal;
+ case U_REVEAL:
+ return mUniReveal;
+ case U_TEXTURE:
+ return mUniTexture;
+ default:
+ return HANDLE_UNDEFINED;
+ }
+ }
+
+ void draw() {
+ glDrawArrays(GL_TRIANGLES, 0, VERTICES.length / 2);
+ }
+
+ void setupTexture(Bitmap bitmap) {
+ final int[] tids = new int[1];
+
+ if (bitmap == null) {
+ Log.w(TAG, "setupTexture: invalid bitmap");
+ return;
+ }
+
+ // Generate one texture object and store the id in tids[0].
+ glGenTextures(1, tids, 0);
+ if (tids[0] == 0) {
+ Log.w(TAG, "setupTexture: glGenTextures() failed");
+ return;
+ }
+
+ // Bind a named texture to a texturing target.
+ glBindTexture(GL_TEXTURE_2D, tids[0]);
+ // Load the bitmap data and copy it over into the texture object that is currently bound.
+ GLUtils.texImage2D(GL_TEXTURE_2D, 0, bitmap, 0);
+ // Use bilinear texture filtering when minification.
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ // Use bilinear texture filtering when magnification.
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+
+ mTextureId = tids[0];
+ }
+
+ void useTexture() {
+ // Set the active texture unit to texture unit 0.
+ glActiveTexture(GL_TEXTURE0);
+ // Bind the texture to this unit.
+ glBindTexture(GL_TEXTURE_2D, mTextureId);
+ // Let the texture sampler in fragment shader to read form this texture unit.
+ glUniform1i(mUniTexture, 0);
+ }
+
+ void adjustTextureCoordinates(Bitmap bitmap, int surfaceWidth, int surfaceHeight,
+ float xOffset, float yOffset) {
+ if (bitmap == null) {
+ Log.d(TAG, "adjustTextureCoordinates: invalid bitmap");
+ return;
+ }
+
+ int bitmapWidth = bitmap.getWidth();
+ int bitmapHeight = bitmap.getHeight();
+ float ratioW = 1f;
+ float ratioH = 1f;
+ float rX = 0f;
+ float rY = 0f;
+ float[] coordinates = null;
+
+ final boolean adjustWidth = bitmapWidth > surfaceWidth;
+ final boolean adjustHeight = bitmapHeight > surfaceHeight;
+
+ if (adjustWidth || adjustHeight) {
+ coordinates = TEXTURES.clone();
+ }
+
+ if (adjustWidth) {
+ float x = (float) Math.round((bitmapWidth - surfaceWidth) * xOffset) / bitmapWidth;
+ ratioW = (float) surfaceWidth / bitmapWidth;
+ float referenceX = x + ratioW > 1f ? 1f - ratioW : x;
+ for (int i = 0; i < coordinates.length; i += 2) {
+ if (i == 2 || i == 4 || i == 6) {
+ coordinates[i] = Math.min(1f, referenceX + ratioW);
+ } else {
+ coordinates[i] = referenceX;
+ }
+ }
+ rX = referenceX;
+ }
+
+
+ if (adjustHeight) {
+ float y = (float) Math.round((bitmapHeight - surfaceHeight) * yOffset) / bitmapHeight;
+ ratioH = (float) surfaceHeight / bitmapHeight;
+ float referenceY = y + ratioH > 1f ? 1f - ratioH : y;
+ for (int i = 1; i < coordinates.length; i += 2) {
+ if (i == 1 || i == 3 || i == 11) {
+ coordinates[i] = Math.min(1f, referenceY + ratioH);
+ } else {
+ coordinates[i] = referenceY;
+ }
+ }
+ rY = referenceY;
+ }
+
+ if (adjustWidth || adjustHeight) {
+ if (Build.IS_DEBUGGABLE) {
+ Log.d(TAG, "adjustTextureCoordinates: sW=" + surfaceWidth + ", sH=" + surfaceHeight
+ + ", bW=" + bitmapWidth + ", bH=" + bitmapHeight
+ + ", rW=" + ratioW + ", rH=" + ratioH + ", rX=" + rX + ", rY=" + rY);
+ }
+ mTextureBuffer.put(coordinates);
+ mTextureBuffer.position(0);
+ }
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/glwallpaper/ImageProcessHelper.java b/packages/SystemUI/src/com/android/systemui/glwallpaper/ImageProcessHelper.java
new file mode 100644
index 000000000000..477e7d7ebf72
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/glwallpaper/ImageProcessHelper.java
@@ -0,0 +1,144 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.glwallpaper;
+
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.ColorMatrix;
+import android.graphics.ColorMatrixColorFilter;
+import android.graphics.Matrix;
+import android.graphics.Paint;
+import android.os.AsyncTask;
+import android.os.Handler;
+import android.os.Handler.Callback;
+import android.os.Message;
+import android.util.Log;
+
+/**
+ * A helper class that computes histogram and percentile 85 from a bitmap.
+ * Percentile 85 will be computed each time the user picks a new image wallpaper.
+ */
+class ImageProcessHelper {
+ private static final String TAG = ImageProcessHelper.class.getSimpleName();
+ private static final float DEFAULT_PER85 = 0.8f;
+ private static final int MSG_UPDATE_PER85 = 1;
+
+ /**
+ * This color matrix will be applied to each pixel to get luminance from rgb by below formula:
+ * Luminance = .2126f * r + .7152f * g + .0722f * b.
+ */
+ private static final float[] LUMINOSITY_MATRIX = new float[] {
+ .2126f, .0000f, .0000f, .0000f, .0000f,
+ .0000f, .7152f, .0000f, .0000f, .0000f,
+ .0000f, .0000f, .0722f, .0000f, .0000f,
+ .0000f, .0000f, .0000f, 1.000f, .0000f
+ };
+
+ private final Handler mHandler = new Handler(new Callback() {
+ @Override
+ public boolean handleMessage(Message msg) {
+ switch (msg.what) {
+ case MSG_UPDATE_PER85:
+ mPer85 = (float) msg.obj;
+ return true;
+ default:
+ return false;
+ }
+ }
+ });
+
+ private float mPer85 = DEFAULT_PER85;
+
+ void startComputingPercentile85(Bitmap bitmap) {
+ new Per85ComputeTask(mHandler).execute(bitmap);
+ }
+
+ float getPercentile85() {
+ return mPer85;
+ }
+
+ private static class Per85ComputeTask extends AsyncTask<Bitmap, Void, Float> {
+ private Handler mUpdateHandler;
+
+ Per85ComputeTask(Handler handler) {
+ super(handler);
+ mUpdateHandler = handler;
+ }
+
+ @Override
+ protected Float doInBackground(Bitmap... bitmaps) {
+ Bitmap bitmap = bitmaps[0];
+ if (bitmap != null) {
+ int[] histogram = processHistogram(bitmap);
+ return computePercentile85(bitmap, histogram);
+ }
+ Log.e(TAG, "Per85ComputeTask: Can't get bitmap");
+ return DEFAULT_PER85;
+ }
+
+ @Override
+ protected void onPostExecute(Float result) {
+ Message msg = mUpdateHandler.obtainMessage(MSG_UPDATE_PER85, result);
+ mUpdateHandler.sendMessage(msg);
+ }
+
+ private int[] processHistogram(Bitmap bitmap) {
+ int width = bitmap.getWidth();
+ int height = bitmap.getHeight();
+
+ Bitmap target = Bitmap.createBitmap(width, height, bitmap.getConfig());
+ Canvas canvas = new Canvas(target);
+ ColorMatrix cm = new ColorMatrix(LUMINOSITY_MATRIX);
+ Paint paint = new Paint();
+ paint.setColorFilter(new ColorMatrixColorFilter(cm));
+ canvas.drawBitmap(bitmap, new Matrix(), paint);
+
+ // TODO: Fine tune the performance here, tracking on b/123615079.
+ int[] histogram = new int[256];
+ for (int row = 0; row < height; row++) {
+ for (int col = 0; col < width; col++) {
+ int pixel = target.getPixel(col, row);
+ int y = Color.red(pixel) + Color.green(pixel) + Color.blue(pixel);
+ histogram[y]++;
+ }
+ }
+
+ return histogram;
+ }
+
+ private float computePercentile85(Bitmap bitmap, int[] histogram) {
+ float per85 = DEFAULT_PER85;
+ int pixelCount = bitmap.getWidth() * bitmap.getHeight();
+ float[] acc = new float[256];
+ for (int i = 0; i < acc.length; i++) {
+ acc[i] = (float) histogram[i] / pixelCount;
+ float prev = i == 0 ? 0f : acc[i - 1];
+ float next = acc[i];
+ float idx = (float) (i + 1) / 255;
+ float sum = prev + next;
+ if (prev < 0.85f && sum >= 0.85f) {
+ per85 = idx;
+ }
+ if (i > 0) {
+ acc[i] += acc[i - 1];
+ }
+ }
+ return per85;
+ }
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/glwallpaper/ImageRevealHelper.java b/packages/SystemUI/src/com/android/systemui/glwallpaper/ImageRevealHelper.java
new file mode 100644
index 000000000000..5914236ab349
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/glwallpaper/ImageRevealHelper.java
@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.glwallpaper;
+
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
+import android.animation.ValueAnimator;
+
+import com.android.systemui.Interpolators;
+
+/**
+ * Use ValueAnimator and appropriate interpolator to control the progress of reveal transition.
+ * The transition will happen while getting awake and quit events.
+ */
+class ImageRevealHelper {
+ private static final String TAG = ImageRevealHelper.class.getSimpleName();
+ private static final float MAX_REVEAL = 0f;
+ private static final float MIN_REVEAL = 1f;
+
+ private final ValueAnimator mAnimator;
+ private final RevealStateListener mRevealListener;
+ private float mReveal = MAX_REVEAL;
+ private boolean mAwake = false;
+
+ ImageRevealHelper(RevealStateListener listener) {
+ mRevealListener = listener;
+ mAnimator = ValueAnimator.ofFloat();
+ mAnimator.setInterpolator(Interpolators.FAST_OUT_SLOW_IN);
+ mAnimator.addUpdateListener(animator -> {
+ mReveal = (float) animator.getAnimatedValue();
+ if (mRevealListener != null) {
+ mRevealListener.onRevealStateChanged();
+ }
+ });
+ mAnimator.addListener(new AnimatorListenerAdapter() {
+ private boolean mIsCanceled;
+
+ @Override
+ public void onAnimationCancel(Animator animation) {
+ mIsCanceled = true;
+ }
+
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ if (!mIsCanceled) {
+ mAwake = !mAwake;
+ }
+ mIsCanceled = false;
+ }
+ });
+ }
+
+ private void animate() {
+ mAnimator.cancel();
+ mAnimator.setFloatValues(mReveal, !mAwake ? MIN_REVEAL : MAX_REVEAL);
+ mAnimator.start();
+ }
+
+ public float getReveal() {
+ return mReveal;
+ }
+
+ public boolean isAwake() {
+ return mAwake;
+ }
+
+ void updateAwake(boolean awake, long duration) {
+ mAwake = awake;
+ mAnimator.setDuration(duration);
+ animate();
+ }
+
+ /**
+ * A listener to trace value changes of reveal.
+ */
+ public interface RevealStateListener {
+
+ /**
+ * Called back while reveal status changes.
+ */
+ void onRevealStateChanged();
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/glwallpaper/ImageWallpaperRenderer.java b/packages/SystemUI/src/com/android/systemui/glwallpaper/ImageWallpaperRenderer.java
new file mode 100644
index 000000000000..991b1161dde2
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/glwallpaper/ImageWallpaperRenderer.java
@@ -0,0 +1,150 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.glwallpaper;
+
+import static android.opengl.GLES20.GL_COLOR_BUFFER_BIT;
+import static android.opengl.GLES20.glClear;
+import static android.opengl.GLES20.glClearColor;
+import static android.opengl.GLES20.glUniform1f;
+import static android.opengl.GLES20.glViewport;
+
+import android.app.WallpaperManager;
+import android.content.Context;
+import android.graphics.Bitmap;
+import android.graphics.Rect;
+import android.opengl.GLSurfaceView;
+import android.os.Build;
+import android.util.Log;
+
+import com.android.systemui.ImageWallpaper;
+import com.android.systemui.ImageWallpaper.ImageGLView;
+import com.android.systemui.R;
+
+import javax.microedition.khronos.egl.EGLConfig;
+import javax.microedition.khronos.opengles.GL10;
+
+/**
+ * A GL renderer for image wallpaper.
+ */
+public class ImageWallpaperRenderer implements GLSurfaceView.Renderer,
+ ImageWallpaper.WallpaperStatusListener, ImageRevealHelper.RevealStateListener {
+ private static final String TAG = ImageWallpaperRenderer.class.getSimpleName();
+
+ private final WallpaperManager mWallpaperManager;
+ private final ImageGLProgram mProgram;
+ private final ImageGLWallpaper mWallpaper;
+ private final ImageProcessHelper mImageProcessHelper;
+ private final ImageRevealHelper mImageRevealHelper;
+ private final ImageGLView mGLView;
+ private float mXOffset = 0f;
+ private float mYOffset = 0f;
+
+ public ImageWallpaperRenderer(Context context, ImageGLView glView) {
+ mWallpaperManager = context.getSystemService(WallpaperManager.class);
+ if (mWallpaperManager == null) {
+ Log.w(TAG, "WallpaperManager not available");
+ }
+
+ mProgram = new ImageGLProgram(context);
+ mWallpaper = new ImageGLWallpaper(mProgram);
+ mImageProcessHelper = new ImageProcessHelper();
+ mImageRevealHelper = new ImageRevealHelper(this);
+ mGLView = glView;
+
+ if (mWallpaperManager != null) {
+ // Compute per85 as transition threshold, this is an async work.
+ mImageProcessHelper.startComputingPercentile85(mWallpaperManager.getBitmap());
+ }
+ }
+
+ @Override
+ public void onSurfaceCreated(GL10 gl, EGLConfig config) {
+ glClearColor(0f, 0f, 0f, 1.0f);
+ mProgram.useGLProgram(
+ R.raw.image_wallpaper_vertex_shader, R.raw.image_wallpaper_fragment_shader);
+ mWallpaper.setup();
+ mWallpaper.setupTexture(mWallpaperManager.getBitmap());
+ }
+
+ @Override
+ public void onSurfaceChanged(GL10 gl, int width, int height) {
+ glViewport(0, 0, width, height);
+ if (Build.IS_DEBUGGABLE) {
+ Log.d(TAG, "onSurfaceChanged: width=" + width + ", height=" + height
+ + ", xOffset=" + mXOffset + ", yOffset=" + mYOffset);
+ }
+ mWallpaper.adjustTextureCoordinates(mWallpaperManager.getBitmap(),
+ width, height, mXOffset, mYOffset);
+ }
+
+ @Override
+ public void onDrawFrame(GL10 gl) {
+ float threshold = mImageProcessHelper.getPercentile85();
+ float reveal = mImageRevealHelper.getReveal();
+
+ glClear(GL_COLOR_BUFFER_BIT);
+
+ glUniform1f(mWallpaper.getHandle(ImageGLWallpaper.U_AOD2OPACITY), 1);
+ glUniform1f(mWallpaper.getHandle(ImageGLWallpaper.U_CENTER_REVEAL), threshold);
+ glUniform1f(mWallpaper.getHandle(ImageGLWallpaper.U_REVEAL), reveal);
+
+ mWallpaper.useTexture();
+ mWallpaper.draw();
+ }
+
+ @Override
+ public void onAmbientModeChanged(boolean inAmbientMode, long duration) {
+ mImageRevealHelper.updateAwake(!inAmbientMode, duration);
+ requestRender();
+ }
+
+ @Override
+ public void onOffsetsChanged(float xOffset, float yOffset, Rect frame) {
+ if (frame == null || mWallpaperManager == null
+ || (xOffset == mXOffset && yOffset == mYOffset)) {
+ return;
+ }
+
+ Bitmap bitmap = mWallpaperManager.getBitmap();
+ if (bitmap == null) {
+ return;
+ }
+
+ int width = frame.width();
+ int height = frame.height();
+ mXOffset = xOffset;
+ mYOffset = yOffset;
+
+ if (Build.IS_DEBUGGABLE) {
+ Log.d(TAG, "onOffsetsChanged: width=" + width + ", height=" + height
+ + ", xOffset=" + mXOffset + ", yOffset=" + mYOffset);
+ }
+ mWallpaper.adjustTextureCoordinates(bitmap, width, height, mXOffset, mYOffset);
+ requestRender();
+ }
+
+ @Override
+ public void onRevealStateChanged() {
+ requestRender();
+ }
+
+ private void requestRender() {
+ if (mGLView != null) {
+ mGLView.render();
+ }
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/privacy/OngoingPrivacyChip.kt b/packages/SystemUI/src/com/android/systemui/privacy/OngoingPrivacyChip.kt
index 1765dc866c66..15dc43f041f4 100644
--- a/packages/SystemUI/src/com/android/systemui/privacy/OngoingPrivacyChip.kt
+++ b/packages/SystemUI/src/com/android/systemui/privacy/OngoingPrivacyChip.kt
@@ -16,7 +16,6 @@ package com.android.systemui.privacy
import android.content.Context
import android.util.AttributeSet
-import android.view.View
import android.view.ViewGroup
import android.widget.ImageView
import android.widget.LinearLayout
@@ -40,10 +39,12 @@ class OngoingPrivacyChip @JvmOverloads constructor(
context.resources.getDimensionPixelSize(R.dimen.ongoing_appops_chip_icon_size)
private val iconColor = context.resources.getColor(
R.color.status_bar_clock_color, context.theme)
+ private val sidePadding =
+ context.resources.getDimensionPixelSize(R.dimen.ongoing_appops_chip_side_padding)
private val backgroundDrawable = context.getDrawable(R.drawable.privacy_chip_bg)
private lateinit var text: TextView
private lateinit var iconsContainer: LinearLayout
- private lateinit var inUseText: TextView
+ private lateinit var back: LinearLayout
var expanded = false
set(value) {
if (value != field) {
@@ -64,15 +65,15 @@ class OngoingPrivacyChip @JvmOverloads constructor(
override fun onFinishInflate() {
super.onFinishInflate()
- inUseText = findViewById(R.id.in_use_text)
+ back = findViewById(R.id.background)
text = findViewById(R.id.text_container)
iconsContainer = findViewById(R.id.icons_container)
}
// Should only be called if the builder icons or app changed
private fun updateView() {
- inUseText.visibility = if (expanded) View.GONE else View.VISIBLE
- background = if (expanded) backgroundDrawable else null
+ back.background = if (expanded) backgroundDrawable else null
+ back.setPaddingRelative(0, 0, if (expanded) sidePadding else 0, 0)
fun setIcons(dialogBuilder: PrivacyDialogBuilder, iconsContainer: ViewGroup) {
iconsContainer.removeAllViews()
dialogBuilder.generateIcons().forEachIndexed { i, it ->
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java b/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java
index c0f87cb37e50..6a8c19ad0e77 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java
@@ -81,6 +81,7 @@ import com.android.systemui.statusbar.policy.DateView;
import com.android.systemui.statusbar.policy.NextAlarmController;
import com.android.systemui.statusbar.policy.ZenModeController;
+import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import java.util.Objects;
@@ -200,6 +201,8 @@ public class QuickStatusBarHeader extends RelativeLayout implements
mSystemIconsView = findViewById(R.id.quick_status_bar_system_icons);
mQuickQsStatusIcons = findViewById(R.id.quick_qs_status_icons);
StatusIconContainer iconContainer = findViewById(R.id.statusIcons);
+ // Ignore privacy icons because they show in the space above QQS
+ iconContainer.addIgnoredSlots(getIgnoredIconSlots());
iconContainer.setShouldRestrictIcons(false);
mIconManager = new TintedIconManager(iconContainer);
@@ -241,6 +244,18 @@ public class QuickStatusBarHeader extends RelativeLayout implements
updateShowPercent();
}
+ private List<String> getIgnoredIconSlots() {
+ ArrayList<String> ignored = new ArrayList<>();
+ ignored.add(mContext.getResources().getString(
+ com.android.internal.R.string.status_bar_camera));
+ ignored.add(mContext.getResources().getString(
+ com.android.internal.R.string.status_bar_microphone));
+ ignored.add(mContext.getResources().getString(
+ com.android.internal.R.string.status_bar_location));
+
+ return ignored;
+ }
+
private void updateStatusText() {
boolean changed = updateRingerStatus() || updateAlarmStatus();
@@ -372,15 +387,6 @@ public class QuickStatusBarHeader extends RelativeLayout implements
setLayoutParams(lp);
- if (mPrivacyChip != null) {
- MarginLayoutParams lm = (MarginLayoutParams) mPrivacyChip.getLayoutParams();
- int sideMargins = lm.leftMargin;
- int topBottomMargins = resources.getDimensionPixelSize(
- R.dimen.ongoing_appops_top_chip_margin);
- lm.setMargins(sideMargins, topBottomMargins, sideMargins, topBottomMargins);
- mPrivacyChip.setLayoutParams(lm);
- }
-
updateStatusIconAlphaAnimator();
updateHeaderTextContainerAlphaAnimator();
updatePrivacyChipAlphaAnimator();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/AlertingNotificationManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/AlertingNotificationManager.java
index 2f1963057ad4..a6af82a28bce 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/AlertingNotificationManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/AlertingNotificationManager.java
@@ -28,7 +28,7 @@ import android.view.accessibility.AccessibilityEvent;
import com.android.internal.annotations.VisibleForTesting;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
-import com.android.systemui.statusbar.notification.row.NotificationInflater.InflationFlag;
+import com.android.systemui.statusbar.notification.row.NotificationContentInflater.InflationFlag;
import java.util.stream.Stream;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/AmbientPulseManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/AmbientPulseManager.java
index a3beb96780d3..57d058880118 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/AmbientPulseManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/AmbientPulseManager.java
@@ -16,7 +16,7 @@
package com.android.systemui.statusbar;
-import static com.android.systemui.statusbar.notification.row.NotificationInflater.FLAG_CONTENT_VIEW_AMBIENT;
+import static com.android.systemui.statusbar.notification.row.NotificationContentInflater.FLAG_CONTENT_VIEW_AMBIENT;
import android.annotation.NonNull;
import android.content.Context;
@@ -26,7 +26,7 @@ import android.util.ArraySet;
import com.android.internal.annotations.VisibleForTesting;
import com.android.systemui.R;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
-import com.android.systemui.statusbar.notification.row.NotificationInflater.InflationFlag;
+import com.android.systemui.statusbar.notification.row.NotificationContentInflater.InflationFlag;
import javax.inject.Inject;
import javax.inject.Singleton;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/MediaArtworkProcessor.kt b/packages/SystemUI/src/com/android/systemui/statusbar/MediaArtworkProcessor.kt
index 494473242a90..52b8cc2b685b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/MediaArtworkProcessor.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/MediaArtworkProcessor.kt
@@ -49,7 +49,7 @@ class MediaArtworkProcessor @Inject constructor() {
context.display.getSize(mTmpSize)
val renderScript = RenderScript.create(context)
- val rect = Rect(0, 0,artwork.width, artwork.height)
+ val rect = Rect(0, 0, artwork.width, artwork.height)
MathUtils.fitRect(rect, Math.max(mTmpSize.x / DOWNSAMPLE, mTmpSize.y / DOWNSAMPLE))
val inBitmap = Bitmap.createScaledBitmap(artwork, rect.width(), rect.height(),
true /* filter */)
@@ -67,6 +67,7 @@ class MediaArtworkProcessor @Inject constructor() {
input.destroy()
output.destroy()
inBitmap.recycle()
+ blur.destroy()
val canvas = Canvas(outBitmap)
canvas.drawColor(ColorUtils.setAlphaComponent(color, COLOR_ALPHA))
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationAlertingManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationAlertingManager.java
index 5605f3db90fb..f6d3cdfddb31 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationAlertingManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationAlertingManager.java
@@ -17,8 +17,8 @@
package com.android.systemui.statusbar.notification;
import static com.android.systemui.statusbar.NotificationRemoteInputManager.FORCE_REMOTE_INPUT_HISTORY;
-import static com.android.systemui.statusbar.notification.row.NotificationInflater.FLAG_CONTENT_VIEW_AMBIENT;
-import static com.android.systemui.statusbar.notification.row.NotificationInflater.FLAG_CONTENT_VIEW_HEADS_UP;
+import static com.android.systemui.statusbar.notification.row.NotificationContentInflater.FLAG_CONTENT_VIEW_AMBIENT;
+import static com.android.systemui.statusbar.notification.row.NotificationContentInflater.FLAG_CONTENT_VIEW_HEADS_UP;
import android.app.Notification;
import android.service.notification.StatusBarNotification;
@@ -30,7 +30,7 @@ import com.android.systemui.statusbar.AmbientPulseManager;
import com.android.systemui.statusbar.NotificationListener;
import com.android.systemui.statusbar.NotificationRemoteInputManager;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
-import com.android.systemui.statusbar.notification.row.NotificationInflater;
+import com.android.systemui.statusbar.notification.row.NotificationContentInflater.InflationFlag;
import com.android.systemui.statusbar.phone.ShadeController;
import com.android.systemui.statusbar.policy.HeadsUpManager;
@@ -102,8 +102,7 @@ public class NotificationAlertingManager {
* @param entry entry to add
* @param inflatedFlags flags representing content views that were inflated
*/
- private void showAlertingView(NotificationEntry entry,
- @NotificationInflater.InflationFlag int inflatedFlags) {
+ private void showAlertingView(NotificationEntry entry, @InflationFlag int inflatedFlags) {
if ((inflatedFlags & FLAG_CONTENT_VIEW_HEADS_UP) != 0) {
// Possible for shouldHeadsUp to change between the inflation starting and ending.
// If it does and we no longer need to heads up, we should free the view.
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryListener.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryListener.java
index 1ed671fdb6fb..a5a6d87c2030 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryListener.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryListener.java
@@ -20,7 +20,7 @@ import android.service.notification.StatusBarNotification;
import com.android.internal.statusbar.NotificationVisibility;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
-import com.android.systemui.statusbar.notification.row.NotificationInflater;
+import com.android.systemui.statusbar.notification.row.NotificationContentInflater.InflationFlag;
/**
* Listener interface for changes sent by NotificationEntryManager.
@@ -65,8 +65,7 @@ public interface NotificationEntryListener {
/**
* Called when a notification's views are inflated for the first time.
*/
- default void onEntryInflated(NotificationEntry entry,
- @NotificationInflater.InflationFlag int inflatedFlags) {
+ default void onEntryInflated(NotificationEntry entry, @InflationFlag int inflatedFlags) {
}
/**
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java
index 56922be73bec..3fbc64163759 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java
@@ -36,8 +36,8 @@ import com.android.systemui.statusbar.notification.collection.NotificationData;
import com.android.systemui.statusbar.notification.collection.NotificationData.KeyguardEnvironment;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.logging.NotificationLogger;
-import com.android.systemui.statusbar.notification.row.NotificationInflater;
-import com.android.systemui.statusbar.notification.row.NotificationInflater.InflationFlag;
+import com.android.systemui.statusbar.notification.row.NotificationContentInflater;
+import com.android.systemui.statusbar.notification.row.NotificationContentInflater.InflationFlag;
import com.android.systemui.statusbar.notification.stack.NotificationListContainer;
import com.android.systemui.statusbar.policy.HeadsUpManager;
import com.android.systemui.util.leak.LeakDetector;
@@ -56,7 +56,7 @@ import java.util.Map;
*/
public class NotificationEntryManager implements
Dumpable,
- NotificationInflater.InflationCallback,
+ NotificationContentInflater.InflationCallback,
NotificationUpdateHandler,
VisualStabilityManager.Callback {
private static final String TAG = "NotificationEntryMgr";
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationRowBinder.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationRowBinder.java
index f1bb0d77deaa..6f5baf9faf39 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationRowBinder.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationRowBinder.java
@@ -19,8 +19,8 @@ package com.android.systemui.statusbar.notification;
import static com.android.internal.util.Preconditions.checkNotNull;
import static com.android.systemui.Dependency.ALLOW_NOTIFICATION_LONG_PRESS_NAME;
import static com.android.systemui.statusbar.NotificationRemoteInputManager.ENABLE_REMOTE_INPUT;
-import static com.android.systemui.statusbar.notification.row.NotificationInflater.FLAG_CONTENT_VIEW_AMBIENT;
-import static com.android.systemui.statusbar.notification.row.NotificationInflater.FLAG_CONTENT_VIEW_HEADS_UP;
+import static com.android.systemui.statusbar.notification.row.NotificationContentInflater.FLAG_CONTENT_VIEW_AMBIENT;
+import static com.android.systemui.statusbar.notification.row.NotificationContentInflater.FLAG_CONTENT_VIEW_HEADS_UP;
import android.annotation.Nullable;
import android.content.Context;
@@ -42,8 +42,8 @@ import com.android.systemui.statusbar.NotificationUiAdjustment;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.logging.NotificationLogger;
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
+import com.android.systemui.statusbar.notification.row.NotificationContentInflater;
import com.android.systemui.statusbar.notification.row.NotificationGutsManager;
-import com.android.systemui.statusbar.notification.row.NotificationInflater;
import com.android.systemui.statusbar.notification.row.RowInflaterTask;
import com.android.systemui.statusbar.notification.stack.NotificationListContainer;
import com.android.systemui.statusbar.phone.NotificationGroupManager;
@@ -78,7 +78,7 @@ public class NotificationRowBinder {
private NotificationPresenter mPresenter;
private NotificationListContainer mListContainer;
private HeadsUpManager mHeadsUpManager;
- private NotificationInflater.InflationCallback mInflationCallback;
+ private NotificationContentInflater.InflationCallback mInflationCallback;
private ExpandableNotificationRow.OnAppOpsClickListener mOnAppOpsClickListener;
private BindRowCallback mBindRowCallback;
private NotificationClicker mNotificationClicker;
@@ -105,7 +105,7 @@ public class NotificationRowBinder {
public void setUpWithPresenter(NotificationPresenter presenter,
NotificationListContainer listContainer,
HeadsUpManager headsUpManager,
- NotificationInflater.InflationCallback inflationCallback,
+ NotificationContentInflater.InflationCallback inflationCallback,
BindRowCallback bindRowCallback) {
mPresenter = presenter;
mListContainer = listContainer;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationEntry.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationEntry.java
index f6d4ce22e905..3bf4d4beb4f9 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationEntry.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationEntry.java
@@ -54,8 +54,8 @@ import com.android.systemui.statusbar.InflationTask;
import com.android.systemui.statusbar.StatusBarIconView;
import com.android.systemui.statusbar.notification.InflationException;
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
+import com.android.systemui.statusbar.notification.row.NotificationContentInflater.InflationFlag;
import com.android.systemui.statusbar.notification.row.NotificationGuts;
-import com.android.systemui.statusbar.notification.row.NotificationInflater;
import java.util.ArrayList;
import java.util.Collections;
@@ -515,7 +515,7 @@ public final class NotificationEntry {
if (row != null) row.resetUserExpansion();
}
- public void freeContentViewWhenSafe(@NotificationInflater.InflationFlag int inflationFlag) {
+ public void freeContentViewWhenSafe(@InflationFlag int inflationFlag) {
if (row != null) row.freeContentViewWhenSafe(inflationFlag);
}
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 69828c166463..2b643d0a2fea 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
@@ -17,13 +17,13 @@
package com.android.systemui.statusbar.notification.row;
import static com.android.systemui.statusbar.notification.ActivityLaunchAnimator.ExpandAnimationParameters;
+import static com.android.systemui.statusbar.notification.row.NotificationContentInflater.FLAG_CONTENT_VIEW_AMBIENT;
+import static com.android.systemui.statusbar.notification.row.NotificationContentInflater.FLAG_CONTENT_VIEW_HEADS_UP;
+import static com.android.systemui.statusbar.notification.row.NotificationContentInflater.FLAG_CONTENT_VIEW_PUBLIC;
+import static com.android.systemui.statusbar.notification.row.NotificationContentInflater.InflationCallback;
import static com.android.systemui.statusbar.notification.row.NotificationContentView.VISIBLE_TYPE_AMBIENT;
import static com.android.systemui.statusbar.notification.row.NotificationContentView.VISIBLE_TYPE_CONTRACTED;
import static com.android.systemui.statusbar.notification.row.NotificationContentView.VISIBLE_TYPE_HEADSUP;
-import static com.android.systemui.statusbar.notification.row.NotificationInflater.FLAG_CONTENT_VIEW_AMBIENT;
-import static com.android.systemui.statusbar.notification.row.NotificationInflater.FLAG_CONTENT_VIEW_HEADS_UP;
-import static com.android.systemui.statusbar.notification.row.NotificationInflater.FLAG_CONTENT_VIEW_PUBLIC;
-import static com.android.systemui.statusbar.notification.row.NotificationInflater.InflationCallback;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
@@ -89,7 +89,7 @@ import com.android.systemui.statusbar.notification.NotificationUtils;
import com.android.systemui.statusbar.notification.VisualStabilityManager;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.logging.NotificationCounters;
-import com.android.systemui.statusbar.notification.row.NotificationInflater.InflationFlag;
+import com.android.systemui.statusbar.notification.row.NotificationContentInflater.InflationFlag;
import com.android.systemui.statusbar.notification.row.wrapper.NotificationMediaTemplateViewWrapper;
import com.android.systemui.statusbar.notification.row.wrapper.NotificationViewWrapper;
import com.android.systemui.statusbar.notification.stack.AmbientState;
@@ -134,7 +134,7 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
}
private LayoutListener mLayoutListener;
- private final NotificationInflater mNotificationInflater;
+ private final NotificationContentInflater mNotificationInflater;
private int mIconTransformContentShift;
private int mIconTransformContentShiftNoIcon;
private int mMaxHeadsUpHeightBeforeN;
@@ -1616,7 +1616,7 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
}
@VisibleForTesting
- public NotificationInflater getNotificationInflater() {
+ public NotificationContentInflater getNotificationInflater() {
return mNotificationInflater;
}
@@ -1631,7 +1631,7 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
public ExpandableNotificationRow(Context context, AttributeSet attrs) {
super(context, attrs);
mFalsingManager = FalsingManager.getInstance(context);
- mNotificationInflater = new NotificationInflater(this);
+ mNotificationInflater = new NotificationContentInflater(this);
mMenuRow = new NotificationMenuRow(mContext);
mImageResolver = new NotificationInlineImageResolver(context,
new NotificationInlineImageCache());
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationInflater.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentInflater.java
index 42ebfceca334..b34907dfebf1 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationInflater.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentInflater.java
@@ -55,9 +55,9 @@ import java.util.concurrent.atomic.AtomicInteger;
/**
* A utility that inflates the right kind of contentView based on the state
*/
-public class NotificationInflater {
+public class NotificationContentInflater {
- public static final String TAG = "NotificationInflater";
+ public static final String TAG = "NotifContentInflater";
@Retention(RetentionPolicy.SOURCE)
@IntDef(flag = true,
@@ -127,7 +127,7 @@ public class NotificationInflater {
private boolean mRedactAmbient;
private final ArrayMap<Integer, RemoteViews> mCachedContentViews = new ArrayMap<>();
- public NotificationInflater(ExpandableNotificationRow row) {
+ public NotificationContentInflater(ExpandableNotificationRow row) {
mRow = row;
}
@@ -232,8 +232,7 @@ public class NotificationInflater {
* will reinflate it.
*
* @param reInflateFlags flags which views should be inflated. Should be a subset of
- * {@link NotificationInflater#mInflationFlags} as only those will be
- * inflated/reinflated.
+ * {@link #mInflationFlags} as only those will be inflated/reinflated.
*/
private void inflateNotificationViews(@InflationFlag int reInflateFlags) {
if (mRow.isRemoved()) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationInlineImageCache.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationInlineImageCache.java
index a5411ecb4bd0..6eb376b58586 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationInlineImageCache.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationInlineImageCache.java
@@ -52,7 +52,7 @@ public class NotificationInlineImageCache implements NotificationInlineImageReso
@Override
public void preload(Uri uri) {
PreloadImageTask newTask = new PreloadImageTask(mResolver);
- newTask.executeOnExecutor(NotificationInflater.EXECUTOR, uri);
+ newTask.executeOnExecutor(NotificationContentInflater.EXECUTOR, uri);
mCache.put(uri, newTask);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationViewWrapper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationViewWrapper.java
index 4c06ff6f5e49..3808702176a9 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationViewWrapper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationViewWrapper.java
@@ -26,12 +26,15 @@ import android.graphics.ColorMatrixColorFilter;
import android.graphics.Paint;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
+import android.os.Build;
import android.view.NotificationHeaderView;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
+import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.graphics.ColorUtils;
+import com.android.internal.util.ContrastColorUtil;
import com.android.systemui.statusbar.CrossFadeHelper;
import com.android.systemui.statusbar.TransformableView;
import com.android.systemui.statusbar.notification.TransformState;
@@ -108,6 +111,11 @@ public abstract class NotificationViewWrapper implements TransformableView {
return false;
}
+ // Apps targeting Q should fix their dark mode bugs.
+ if (mRow.getEntry().targetSdk >= Build.VERSION_CODES.Q) {
+ return false;
+ }
+
int background = getBackgroundColor(view);
if (background == Color.TRANSPARENT) {
background = defaultBackgroundColor;
@@ -138,17 +146,19 @@ public abstract class NotificationViewWrapper implements TransformableView {
}
}
- private boolean childrenNeedInversion(@ColorInt int parentBackground, ViewGroup viewGroup) {
+ @VisibleForTesting
+ boolean childrenNeedInversion(@ColorInt int parentBackground, ViewGroup viewGroup) {
if (viewGroup == null) {
return false;
}
+ int backgroundColor = getBackgroundColor(viewGroup);
+ if (Color.alpha(backgroundColor) != 255) {
+ backgroundColor = ContrastColorUtil.compositeColors(backgroundColor, parentBackground);
+ backgroundColor = ColorUtils.setAlphaComponent(backgroundColor, 255);
+ }
for (int i = 0; i < viewGroup.getChildCount(); i++) {
View child = viewGroup.getChildAt(i);
- int backgroundColor = getBackgroundColor(viewGroup);
- if (backgroundColor == Color.TRANSPARENT) {
- backgroundColor = parentBackground;
- }
if (child instanceof TextView) {
int foreground = ((TextView) child).getCurrentTextColor();
if (ColorUtils.calculateContrast(foreground, backgroundColor) < 3) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CollapsedStatusBarFragment.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CollapsedStatusBarFragment.java
index 6410860a852d..195d02d9ca72 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CollapsedStatusBarFragment.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CollapsedStatusBarFragment.java
@@ -191,7 +191,7 @@ public class CollapsedStatusBarFragment extends Fragment implements CommandQueue
}
protected int adjustDisableFlags(int state) {
- if (!mStatusBarComponent.isLaunchTransitionFadingAway()
+ if (!mKeyguardMonitor.isLaunchTransitionFadingAway()
&& !mKeyguardMonitor.isKeyguardFadingAway()
&& shouldHideNotificationIcons()) {
state |= DISABLE_NOTIFICATION_ICONS;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarEdgePanel.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarEdgePanel.java
index dae4da7355c7..64209a7b9e73 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarEdgePanel.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarEdgePanel.java
@@ -16,9 +16,17 @@
package com.android.systemui.statusbar.phone;
+import android.animation.ObjectAnimator;
import android.annotation.NonNull;
import android.content.Context;
+import android.graphics.Canvas;
+import android.graphics.Paint;
import android.graphics.PixelFormat;
+import android.util.FloatProperty;
+import android.util.MathUtils;
+import android.view.Gravity;
+import android.view.HapticFeedbackConstants;
+import android.view.MotionEvent;
import android.view.View;
import android.view.WindowManager;
@@ -27,6 +35,71 @@ import com.android.systemui.R;
public class NavigationBarEdgePanel extends View {
private static final String TAG = "NavigationBarEdgePanel";
+ // TODO: read from resources once drawing is finalized.
+ private static final boolean SHOW_PROTECTION_STROKE = true;
+ private static final int PROTECTION_COLOR = 0xffc0c0c0;
+ private static final int STROKE_COLOR = 0xffe5e5e5;
+ private static final int PROTECTION_WIDTH_PX = 4;
+ private static final int BASE_EXTENT = 32;
+ private static final int ARROW_HEIGHT_DP = 32;
+ private static final int POINT_EXTENT_DP = 8;
+ private static final int ARROW_THICKNESS_DP = 4;
+ private static final float TRACK_LENGTH_MULTIPLIER = 1.5f;
+ private static final float START_POINTING_RATIO = 0.3f;
+ private static final float POINTEDNESS_BEFORE_SNAP_RATIO = 0.4f;
+ private static final int ANIM_DURATION_MS = 150;
+
+ private final Paint mPaint = new Paint();
+ private final Paint mProtectionPaint = new Paint();
+
+ private final ObjectAnimator mEndAnimator;
+ private final ObjectAnimator mLegAnimator;
+
+ private final float mDensity;
+ private final float mBaseExtent;
+ private final float mPointExtent;
+ private final float mHeight;
+ private final float mStrokeThickness;
+ private final boolean mIsLeftPanel;
+
+ private float mStartY;
+ private float mStartX;
+
+ private boolean mGestureDetected;
+ private boolean mArrowsPointLeft;
+ private float mGestureLength;
+ private float mLegProgress;
+ private float mDragProgress;
+
+ // How much the "legs" of the back arrow have proceeded from being a line to an arrow.
+ private static final FloatProperty<NavigationBarEdgePanel> LEG_PROGRESS =
+ new FloatProperty<NavigationBarEdgePanel>("legProgress") {
+ @Override
+ public void setValue(NavigationBarEdgePanel object, float value) {
+ object.setLegProgress(value);
+ }
+
+ @Override
+ public Float get(NavigationBarEdgePanel object) {
+ return object.getLegProgress();
+ }
+ };
+
+ // How far across the view the arrow should be drawn.
+ private static final FloatProperty<NavigationBarEdgePanel> DRAG_PROGRESS =
+ new FloatProperty<NavigationBarEdgePanel>("dragProgress") {
+
+ @Override
+ public void setValue(NavigationBarEdgePanel object, float value) {
+ object.setDragProgress(value);
+ }
+
+ @Override
+ public Float get(NavigationBarEdgePanel object) {
+ return object.getDragProgress();
+ }
+ };
+
public static NavigationBarEdgePanel create(@NonNull Context context, int width, int height,
int gravity) {
final WindowManager.LayoutParams lp = new WindowManager.LayoutParams(width, height,
@@ -40,13 +113,43 @@ public class NavigationBarEdgePanel extends View {
lp.setTitle(TAG + context.getDisplayId());
lp.accessibilityTitle = context.getString(R.string.nav_bar_edge_panel);
lp.windowAnimations = 0;
- NavigationBarEdgePanel panel = new NavigationBarEdgePanel(context);
+ NavigationBarEdgePanel panel = new NavigationBarEdgePanel(
+ context, (gravity & Gravity.LEFT) == Gravity.LEFT);
panel.setLayoutParams(lp);
return panel;
}
- private NavigationBarEdgePanel(Context context) {
+ private NavigationBarEdgePanel(Context context, boolean isLeftPanel) {
super(context);
+
+ mEndAnimator = ObjectAnimator.ofFloat(this, DRAG_PROGRESS, 1f);
+ mEndAnimator.setAutoCancel(true);
+ mEndAnimator.setDuration(ANIM_DURATION_MS);
+
+ mLegAnimator = ObjectAnimator.ofFloat(this, LEG_PROGRESS, 1f);
+ mLegAnimator.setAutoCancel(true);
+ mLegAnimator.setDuration(ANIM_DURATION_MS);
+
+ mDensity = context.getResources().getDisplayMetrics().density;
+
+ mBaseExtent = dp(BASE_EXTENT);
+ mHeight = dp(ARROW_HEIGHT_DP);
+ mPointExtent = dp(POINT_EXTENT_DP);
+ mStrokeThickness = dp(ARROW_THICKNESS_DP);
+
+ mPaint.setStrokeWidth(mStrokeThickness);
+ mPaint.setStrokeCap(Paint.Cap.ROUND);
+ mPaint.setColor(STROKE_COLOR);
+ mPaint.setAntiAlias(true);
+
+ mProtectionPaint.setStrokeWidth(mStrokeThickness + PROTECTION_WIDTH_PX);
+ mProtectionPaint.setStrokeCap(Paint.Cap.ROUND);
+ mProtectionPaint.setColor(PROTECTION_COLOR);
+ mProtectionPaint.setAntiAlias(true);
+
+ // Both panels arrow point the same way
+ mArrowsPointLeft = getLayoutDirection() == LAYOUT_DIRECTION_LTR;
+ mIsLeftPanel = isLeftPanel;
}
public void setWindowFlag(int flags, boolean enable) {
@@ -62,6 +165,58 @@ public class NavigationBarEdgePanel extends View {
updateLayout(lp);
}
+ @Override
+ public boolean onTouchEvent(MotionEvent event) {
+ switch (event.getActionMasked()) {
+ case MotionEvent.ACTION_DOWN : {
+ show(event.getX(), event.getY());
+ break;
+ }
+ case MotionEvent.ACTION_MOVE: {
+ handleNewSwipePoint(event.getX());
+ break;
+ }
+ // Fall through
+ case MotionEvent.ACTION_UP:
+ case MotionEvent.ACTION_CANCEL: {
+ hide();
+ break;
+ }
+ }
+
+ return false;
+ }
+
+ @Override
+ protected void onDraw(Canvas canvas) {
+ float edgeOffset = mBaseExtent * mDragProgress - mStrokeThickness;
+ float animatedOffset = mPointExtent * mLegProgress;
+ canvas.save();
+ canvas.translate(
+ mIsLeftPanel ? edgeOffset : getWidth() - edgeOffset,
+ mStartY - mHeight * 0.5f);
+
+ float outsideX = mArrowsPointLeft ? animatedOffset : 0;
+ float middleX = mArrowsPointLeft ? 0 : animatedOffset;
+
+ if (SHOW_PROTECTION_STROKE) {
+ canvas.drawLine(outsideX, 0, middleX, mHeight * 0.5f, mProtectionPaint);
+ canvas.drawLine(middleX, mHeight * 0.5f, outsideX, mHeight, mProtectionPaint);
+ }
+
+ canvas.drawLine(outsideX, 0, middleX, mHeight * 0.5f, mPaint);
+ canvas.drawLine(middleX, mHeight * 0.5f, outsideX, mHeight, mPaint);
+ canvas.restore();
+ }
+
+ @Override
+ protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
+ super.onLayout(changed, left, top, right, bottom);
+
+ // TODO: read the gesture length from the nav controller.
+ mGestureLength = getWidth();
+ }
+
public void setDimensions(int width, int height) {
final WindowManager.LayoutParams lp = (WindowManager.LayoutParams) getLayoutParams();
if (lp.width != width || lp.height != height) {
@@ -71,8 +226,81 @@ public class NavigationBarEdgePanel extends View {
}
}
+ private void setLegProgress(float progress) {
+ mLegProgress = progress;
+ invalidate();
+ }
+
+ private float getLegProgress() {
+ return mLegProgress;
+ }
+
+ private void setDragProgress(float dragProgress) {
+ mDragProgress = dragProgress;
+ invalidate();
+ }
+
+ private float getDragProgress() {
+ return mDragProgress;
+ }
+
+ private void hide() {
+ animate().alpha(0f).setDuration(ANIM_DURATION_MS);
+ }
+
+ private void show(float x, float y) {
+ mEndAnimator.cancel();
+ mLegAnimator.cancel();
+ setLegProgress(0f);
+ setDragProgress(0f);
+ setAlpha(1f);
+
+ float halfHeight = mHeight * 0.5f;
+ mStartY = MathUtils.constrain(y, halfHeight, getHeight() - halfHeight);
+ mStartX = x;
+ }
+
+ private void handleNewSwipePoint(float x) {
+ float dist = MathUtils.abs(x - mStartX);
+
+ setDragProgress(MathUtils.constrainedMap(
+ 0, 1.0f,
+ 0, mGestureLength * TRACK_LENGTH_MULTIPLIER,
+ dist));
+
+ if (dist < mGestureLength) {
+ float calculatedLegProgress = MathUtils.constrainedMap(
+ 0f, POINTEDNESS_BEFORE_SNAP_RATIO,
+ mGestureLength * START_POINTING_RATIO, mGestureLength,
+ dist);
+
+ // Blend animated value with drag calculated value, allow the gesture to continue
+ // while the animation is playing with jump cuts in the animation.
+ setLegProgress(MathUtils.lerp(calculatedLegProgress, mLegProgress, mDragProgress));
+
+ if (mGestureDetected) {
+ mGestureDetected = false;
+
+ mLegAnimator.setFloatValues(POINTEDNESS_BEFORE_SNAP_RATIO);
+ mLegAnimator.start();
+ }
+ } else {
+ if (!mGestureDetected) {
+ performHapticFeedback(HapticFeedbackConstants.CLOCK_TICK);
+ mGestureDetected = true;
+
+ mLegAnimator.setFloatValues(1f);
+ mLegAnimator.start();
+ }
+ }
+ }
+
private void updateLayout(WindowManager.LayoutParams lp) {
WindowManager wm = (WindowManager) getContext().getSystemService(Context.WINDOW_SERVICE);
wm.updateViewLayout(this, lp);
}
+
+ private float dp(float dp) {
+ return mDensity * dp;
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
index ebd420478c0f..8152206aa2ed 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
@@ -1227,10 +1227,11 @@ public class NavigationBarView extends FrameLayout implements PluginListener<Nav
.getSystemService(Context.WINDOW_SERVICE);
int width = mPrototypeController.getEdgeSensitivityWidth();
int height = mPrototypeController.getEdgeSensitivityHeight();
+ // Explicitly left and right, not start and end as this is device relative.
mLeftEdgePanel = NavigationBarEdgePanel.create(getContext(), width, height,
- Gravity.START | Gravity.BOTTOM);
+ Gravity.LEFT | Gravity.BOTTOM);
mRightEdgePanel = NavigationBarEdgePanel.create(getContext(), width, height,
- Gravity.END | Gravity.BOTTOM);
+ Gravity.RIGHT | Gravity.BOTTOM);
mLeftEdgePanel.setOnTouchListener(mEdgePanelTouchListener);
mRightEdgePanel.setOnTouchListener(mEdgePanelTouchListener);
wm.addView(mLeftEdgePanel, mLeftEdgePanel.getLayoutParams());
@@ -1252,15 +1253,12 @@ public class NavigationBarView extends FrameLayout implements PluginListener<Nav
mButtonDispatchers.valueAt(i).onDestroy();
}
- if (mPrototypeController.isEnabled()) {
- WindowManager wm = (WindowManager) getContext()
- .getSystemService(Context.WINDOW_SERVICE);
- if (mLeftEdgePanel != null) {
- wm.removeView(mLeftEdgePanel);
- }
- if (mRightEdgePanel != null) {
- wm.removeView(mRightEdgePanel);
- }
+ WindowManager wm = (WindowManager) getContext().getSystemService(Context.WINDOW_SERVICE);
+ if (mLeftEdgePanel != null) {
+ wm.removeView(mLeftEdgePanel);
+ }
+ if (mRightEdgePanel != null) {
+ wm.removeView(mRightEdgePanel);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationGroupAlertTransferHelper.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationGroupAlertTransferHelper.java
index b613e8efa8ee..4dbd8545efb9 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationGroupAlertTransferHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationGroupAlertTransferHelper.java
@@ -34,8 +34,8 @@ import com.android.systemui.statusbar.InflationTask;
import com.android.systemui.statusbar.notification.NotificationEntryListener;
import com.android.systemui.statusbar.notification.NotificationEntryManager;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
-import com.android.systemui.statusbar.notification.row.NotificationInflater.AsyncInflationTask;
-import com.android.systemui.statusbar.notification.row.NotificationInflater.InflationFlag;
+import com.android.systemui.statusbar.notification.row.NotificationContentInflater.AsyncInflationTask;
+import com.android.systemui.statusbar.notification.row.NotificationContentInflater.InflationFlag;
import com.android.systemui.statusbar.phone.NotificationGroupManager.NotificationGroup;
import com.android.systemui.statusbar.phone.NotificationGroupManager.OnGroupChangeListener;
import com.android.systemui.statusbar.policy.HeadsUpManager;
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 62f85fe8a00e..99269cf17141 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconAreaController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconAreaController.java
@@ -24,6 +24,7 @@ import com.android.systemui.plugins.DarkIconDispatcher;
import com.android.systemui.plugins.DarkIconDispatcher.DarkReceiver;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.NotificationListener;
+import com.android.systemui.statusbar.NotificationMediaManager;
import com.android.systemui.statusbar.NotificationShelf;
import com.android.systemui.statusbar.StatusBarIconView;
import com.android.systemui.statusbar.notification.NotificationEntryManager;
@@ -47,6 +48,7 @@ public class NotificationIconAreaController implements DarkReceiver,
private final NotificationEntryManager mEntryManager;
private final Runnable mUpdateStatusBarIcons = this::updateStatusBarIcons;
private final StatusBarStateController mStatusBarStateController;
+ private final NotificationMediaManager mMediaManager;
@VisibleForTesting
final NotificationListener.NotificationSettingsListener mSettingsListener =
new NotificationListener.NotificationSettingsListener() {
@@ -93,13 +95,15 @@ public class NotificationIconAreaController implements DarkReceiver,
public NotificationIconAreaController(Context context, StatusBar statusBar,
StatusBarStateController statusBarStateController,
- NotificationListener notificationListener) {
+ NotificationListener notificationListener,
+ NotificationMediaManager notificationMediaManager) {
mStatusBar = statusBar;
mContrastColorUtil = ContrastColorUtil.getInstance(context);
mContext = context;
mEntryManager = Dependency.get(NotificationEntryManager.class);
mStatusBarStateController = statusBarStateController;
mStatusBarStateController.addCallback(this);
+ mMediaManager = notificationMediaManager;
notificationListener.addNotificationSettingsListener(mSettingsListener);
initializeNotificationAreaViews(context);
@@ -192,10 +196,13 @@ public class NotificationIconAreaController implements DarkReceiver,
protected boolean shouldShowNotificationIcon(NotificationEntry entry,
boolean showAmbient, boolean showLowPriority, boolean hideDismissed,
- boolean hideRepliedMessages) {
+ boolean hideRepliedMessages, boolean hideCurrentMedia) {
if (mEntryManager.getNotificationData().isAmbient(entry.key) && !showAmbient) {
return false;
}
+ if (hideCurrentMedia && entry.key.equals(mMediaManager.getMediaNotificationKey())) {
+ return false;
+ }
if (!showLowPriority && !entry.isHighPriority()) {
return false;
}
@@ -235,14 +242,16 @@ public class NotificationIconAreaController implements DarkReceiver,
private void updateShelfIcons() {
updateIconsForLayout(entry -> entry.expandedIcon, mShelfIcons,
true /* showAmbient */, !mFullyDark /* showLowPriority */,
- false /* hideDismissed */, mFullyDark /* hideRepliedMessages */);
+ false /* hideDismissed */, mFullyDark /* hideRepliedMessages */,
+ mFullyDark /* hideCurrentMedia */);
}
public void updateStatusBarIcons() {
updateIconsForLayout(entry -> entry.icon, mNotificationIcons,
false /* showAmbient */, mShowLowPriority /* showLowPriority */,
true /* hideDismissed */,
- true /* hideRepliedMessages */);
+ true /* hideRepliedMessages */,
+ false /* hideCurrentMedia */);
}
@VisibleForTesting
@@ -261,7 +270,7 @@ public class NotificationIconAreaController implements DarkReceiver,
*/
private void updateIconsForLayout(Function<NotificationEntry, StatusBarIconView> function,
NotificationIconContainer hostLayout, boolean showAmbient, boolean showLowPriority,
- boolean hideDismissed, boolean hideRepliedMessages) {
+ boolean hideDismissed, boolean hideRepliedMessages, boolean hideCurrentMedia) {
ArrayList<StatusBarIconView> toShow = new ArrayList<>(
mNotificationScrollLayout.getChildCount());
@@ -271,7 +280,7 @@ public class NotificationIconAreaController implements DarkReceiver,
if (view instanceof ExpandableNotificationRow) {
NotificationEntry ent = ((ExpandableNotificationRow) view).getEntry();
if (shouldShowNotificationIcon(ent, showAmbient, showLowPriority, hideDismissed,
- hideRepliedMessages)) {
+ hideRepliedMessages, hideCurrentMedia)) {
toShow.add(function.apply(ent));
}
}
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 e42004a1ca13..008eeefa8341 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -117,7 +117,6 @@ import android.view.WindowManagerGlobal;
import android.view.accessibility.AccessibilityManager;
import android.view.animation.AccelerateInterpolator;
import android.widget.DateTimeView;
-import android.widget.ImageView;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.colorextraction.ColorExtractor;
@@ -460,9 +459,6 @@ public class StatusBar extends SystemUI implements DemoMode,
protected boolean mDozing;
private boolean mDozingRequested;
- protected BackDropView mBackdrop;
- protected ImageView mBackdropFront, mBackdropBack;
-
private NotificationMediaManager mMediaManager;
protected NotificationLockscreenUserManager mLockscreenUserManager;
protected NotificationRemoteInputManager mRemoteInputManager;
@@ -483,8 +479,7 @@ public class StatusBar extends SystemUI implements DemoMode,
updateAodMaskVisibility(deviceSupportsAodWallpaper && aodImageWallpaperEnabled);
// If WallpaperInfo is null, it must be ImageWallpaper.
final boolean supportsAmbientMode = deviceSupportsAodWallpaper
- && (info == null && aodImageWallpaperEnabled
- || info != null && info.supportsAmbientMode());
+ && (info == null || info.supportsAmbientMode());
mStatusBarWindowController.setWallpaperSupportsAmbientMode(supportsAmbientMode);
mScrimController.setWallpaperSupportsAmbientMode(supportsAmbientMode);
@@ -492,7 +487,6 @@ public class StatusBar extends SystemUI implements DemoMode,
};
private Runnable mLaunchTransitionEndRunnable;
- protected boolean mLaunchTransitionFadingAway;
private NotificationEntry mDraggedDownEntry;
private boolean mLaunchCameraOnScreenTurningOn;
private boolean mLaunchCameraOnFinishedGoingToSleep;
@@ -932,11 +926,9 @@ public class StatusBar extends SystemUI implements DemoMode,
mHeadsUpManager, mNotificationIconAreaController, mScrimController);
mDozeScrimController = new DozeScrimController(DozeParameters.getInstance(context));
- mBackdrop = mStatusBarWindow.findViewById(R.id.backdrop);
- mBackdropFront = mBackdrop.findViewById(R.id.backdrop_front);
- mBackdropBack = mBackdrop.findViewById(R.id.backdrop_back);
- mMediaManager.setup(mBackdrop, mBackdropFront, mBackdropBack,
- mScrimController, mLockscreenWallpaper);
+ BackDropView backdrop = mStatusBarWindow.findViewById(R.id.backdrop);
+ mMediaManager.setup(backdrop, backdrop.findViewById(R.id.backdrop_front),
+ backdrop.findViewById(R.id.backdrop_back), mScrimController, mLockscreenWallpaper);
// Other icons
mVolumeComponent = getComponent(VolumeComponent.class);
@@ -1592,10 +1584,6 @@ public class StatusBar extends SystemUI implements DemoMode,
return mPulsing;
}
- public boolean isLaunchTransitionFadingAway() {
- return mLaunchTransitionFadingAway;
- }
-
public boolean hideStatusBarIconsWhenExpanded() {
return mNotificationPanel.hideStatusBarIconsWhenExpanded();
}
@@ -2974,7 +2962,7 @@ public class StatusBar extends SystemUI implements DemoMode,
public void showKeyguardImpl() {
mIsKeyguard = true;
- if (mLaunchTransitionFadingAway) {
+ if (mKeyguardMonitor.isLaunchTransitionFadingAway()) {
mNotificationPanel.animate().cancel();
onLaunchTransitionFadingEnded();
}
@@ -3006,7 +2994,7 @@ public class StatusBar extends SystemUI implements DemoMode,
mNotificationPanel.onAffordanceLaunchEnded();
releaseGestureWakeLock();
runLaunchTransitionEndRunnable();
- mLaunchTransitionFadingAway = false;
+ mKeyguardMonitor.setLaunchTransitionFadingAway(false);
mPresenter.updateMediaMetaData(true /* metaDataChanged */, true);
}
@@ -3032,7 +3020,6 @@ public class StatusBar extends SystemUI implements DemoMode,
mLaunchTransitionEndRunnable = endRunnable;
Runnable hideRunnable = () -> {
mKeyguardMonitor.setLaunchTransitionFadingAway(true);
- mLaunchTransitionFadingAway = true;
if (beforeFading != null) {
beforeFading.run();
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusIconContainer.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusIconContainer.java
index 6495910359bb..6e36c019bb28 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusIconContainer.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusIconContainer.java
@@ -38,6 +38,7 @@ import com.android.systemui.statusbar.notification.stack.AnimationProperties;
import com.android.systemui.statusbar.notification.stack.ViewState;
import java.util.ArrayList;
+import java.util.List;
/**
* A container for Status bar system icons. Limits the number of system icons and handles overflow
@@ -67,6 +68,8 @@ public class StatusIconContainer extends AlphaOptimizedLinearLayout {
private ArrayList<StatusIconState> mLayoutStates = new ArrayList<>();
// So we can count and measure properly
private ArrayList<View> mMeasureViews = new ArrayList<>();
+ // Any ignored icon will never be added as a child
+ private ArrayList<String> mIgnoredSlots = new ArrayList<>();
public StatusIconContainer(Context context) {
this(context, null);
@@ -146,7 +149,8 @@ public class StatusIconContainer extends AlphaOptimizedLinearLayout {
// Collect all of the views which want to be laid out
for (int i = 0; i < count; i++) {
StatusIconDisplayable icon = (StatusIconDisplayable) getChildAt(i);
- if (icon.isIconVisible() && !icon.isIconBlocked()) {
+ if (icon.isIconVisible() && !icon.isIconBlocked()
+ && !mIgnoredSlots.contains(icon.getSlot())) {
mMeasureViews.add((View) icon);
}
}
@@ -205,6 +209,47 @@ public class StatusIconContainer extends AlphaOptimizedLinearLayout {
}
/**
+ * Add a name of an icon slot to be ignored. It will not show up nor be measured
+ * @param slotName name of the icon as it exists in
+ * frameworks/base/core/res/res/values/config.xml
+ */
+ public void addIgnoredSlot(String slotName) {
+ addIgnoredSlotInternal(slotName);
+ requestLayout();
+ }
+
+ /**
+ * Add a list of slots to be ignored
+ * @param slots names of the icons to ignore
+ */
+ public void addIgnoredSlots(List<String> slots) {
+ for (String slot : slots) {
+ addIgnoredSlotInternal(slot);
+ }
+
+ requestLayout();
+ }
+
+ private void addIgnoredSlotInternal(String slotName) {
+ if (!mIgnoredSlots.contains(slotName)) {
+ mIgnoredSlots.add(slotName);
+ }
+ }
+
+ /**
+ * Remove a slot from the list of ignored icon slots. It will then be shown when set to visible
+ * by the {@link StatusBarIconController}.
+ * @param slotName name of the icon slot to remove from the ignored list
+ */
+ public void removeIgnoredSlot(String slotName) {
+ if (mIgnoredSlots.contains(slotName)) {
+ mIgnoredSlots.remove(slotName);
+ }
+
+ requestLayout();
+ }
+
+ /**
* Layout is happening from end -> start
*/
private void calculateIconTranslations() {
@@ -223,7 +268,8 @@ public class StatusIconContainer extends AlphaOptimizedLinearLayout {
StatusIconDisplayable iconView = (StatusIconDisplayable) child;
StatusIconState childState = getViewStateFromChild(child);
- if (!iconView.isIconVisible() || iconView.isIconBlocked()) {
+ if (!iconView.isIconVisible() || iconView.isIconBlocked()
+ || mIgnoredSlots.contains(iconView.getSlot())) {
childState.visibleState = STATE_HIDDEN;
if (DEBUG) Log.d(TAG, "skipping child (" + iconView.getSlot() + ") not visible");
continue;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManager.java
index fd3f680e5e77..0461057bf2e9 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManager.java
@@ -16,7 +16,7 @@
package com.android.systemui.statusbar.policy;
-import static com.android.systemui.statusbar.notification.row.NotificationInflater.FLAG_CONTENT_VIEW_HEADS_UP;
+import static com.android.systemui.statusbar.notification.row.NotificationContentInflater.FLAG_CONTENT_VIEW_HEADS_UP;
import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -31,7 +31,7 @@ import com.android.internal.logging.MetricsLogger;
import com.android.systemui.R;
import com.android.systemui.statusbar.AlertingNotificationManager;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
-import com.android.systemui.statusbar.notification.row.NotificationInflater.InflationFlag;
+import com.android.systemui.statusbar.notification.row.NotificationContentInflater.InflationFlag;
import java.io.FileDescriptor;
import java.io.PrintWriter;
diff --git a/packages/SystemUI/src/com/android/systemui/wallpaper/AodMaskView.java b/packages/SystemUI/src/com/android/systemui/wallpaper/AodMaskView.java
index 6ee341dd974c..f446cefb7b6f 100644
--- a/packages/SystemUI/src/com/android/systemui/wallpaper/AodMaskView.java
+++ b/packages/SystemUI/src/com/android/systemui/wallpaper/AodMaskView.java
@@ -156,6 +156,8 @@ public class AodMaskView extends ImageView implements StatusBarStateController.S
private boolean checkIfNeedMask() {
// We need mask for ImageWallpaper / LockScreen Wallpaper (Music album art).
+ // Because of conflicting with another wallpaper feature,
+ // we only support LockScreen wallpaper currently.
return mWallpaperManager.getWallpaperInfo() == null || ScrimState.AOD.hasBackdrop();
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/bubbles/animation/ExpandedAnimationControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/bubbles/animation/ExpandedAnimationControllerTest.java
index c0aac7ee8793..3bd582f955af 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/bubbles/animation/ExpandedAnimationControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/bubbles/animation/ExpandedAnimationControllerTest.java
@@ -22,6 +22,8 @@ import android.content.res.Resources;
import android.graphics.PointF;
import android.support.test.filters.SmallTest;
import android.testing.AndroidTestingRunner;
+import android.view.View;
+import android.widget.FrameLayout;
import androidx.dynamicanimation.animation.DynamicAnimation;
@@ -63,15 +65,13 @@ public class ExpandedAnimationControllerTest extends PhysicsAnimationLayoutTestC
public void testExpansionAndCollapse() throws InterruptedException {
Runnable afterExpand = Mockito.mock(Runnable.class);
mExpandedController.expandFromStack(mExpansionPoint, afterExpand);
-
waitForPropertyAnimations(DynamicAnimation.TRANSLATION_X, DynamicAnimation.TRANSLATION_Y);
- testExpanded();
+ testBubblesInCorrectExpandedPositions();
Mockito.verify(afterExpand).run();
Runnable afterCollapse = Mockito.mock(Runnable.class);
mExpandedController.collapseBackToStack(afterCollapse);
-
waitForPropertyAnimations(DynamicAnimation.TRANSLATION_X, DynamicAnimation.TRANSLATION_Y);
testStackedAtPosition(mExpansionPoint.x, mExpansionPoint.y, -1);
@@ -79,17 +79,70 @@ public class ExpandedAnimationControllerTest extends PhysicsAnimationLayoutTestC
}
@Test
- public void testOnChildRemoved() throws InterruptedException {
- Runnable afterExpand = Mockito.mock(Runnable.class);
- mExpandedController.expandFromStack(mExpansionPoint, afterExpand);
+ public void testOnChildAdded() throws InterruptedException {
+ expand();
+
+ // Add another new view and wait for its animation.
+ final View newView = new FrameLayout(getContext());
+ mLayout.addView(newView, 0);
waitForPropertyAnimations(DynamicAnimation.TRANSLATION_X, DynamicAnimation.TRANSLATION_Y);
- testExpanded();
+
+ testBubblesInCorrectExpandedPositions();
+ }
+
+ @Test
+ public void testOnChildRemoved() throws InterruptedException {
+ expand();
// Remove some views and see if the remaining child views still pass the expansion test.
mLayout.removeView(mViews.get(0));
mLayout.removeView(mViews.get(3));
waitForPropertyAnimations(DynamicAnimation.TRANSLATION_X, DynamicAnimation.TRANSLATION_Y);
- testExpanded();
+ testBubblesInCorrectExpandedPositions();
+ }
+
+ @Test
+ public void testBubbleDraggedNotDismissedSnapsBack() throws InterruptedException {
+ expand();
+
+ final View draggedBubble = mViews.get(0);
+ mExpandedController.prepareForBubbleDrag(draggedBubble);
+ mExpandedController.dragBubbleOut(draggedBubble, 500f, 500f);
+
+ assertEquals(500f, draggedBubble.getTranslationX(), 1f);
+ assertEquals(500f, draggedBubble.getTranslationY(), 1f);
+
+ // Snap it back and make sure it made it back correctly.
+ mExpandedController.snapBubbleBack(draggedBubble, 0f, 0f);
+ waitForPropertyAnimations(DynamicAnimation.TRANSLATION_X, DynamicAnimation.TRANSLATION_Y);
+ testBubblesInCorrectExpandedPositions();
+ }
+
+ @Test
+ public void testBubbleDismissed() throws InterruptedException {
+ expand();
+
+ final View draggedBubble = mViews.get(0);
+ mExpandedController.prepareForBubbleDrag(draggedBubble);
+ mExpandedController.dragBubbleOut(draggedBubble, 500f, 500f);
+
+ assertEquals(500f, draggedBubble.getTranslationX(), 1f);
+ assertEquals(500f, draggedBubble.getTranslationY(), 1f);
+
+ // Snap it back and make sure it made it back correctly.
+ mExpandedController.prepareForDismissalWithVelocity(draggedBubble, 0f, 0f);
+ mLayout.removeView(draggedBubble);
+ waitForLayoutMessageQueue();
+ waitForPropertyAnimations(DynamicAnimation.TRANSLATION_X, DynamicAnimation.TRANSLATION_Y);
+
+ assertEquals(-1, mLayout.indexOfChild(draggedBubble));
+ testBubblesInCorrectExpandedPositions();
+ }
+
+ /** Expand the stack and wait for animations to finish. */
+ private void expand() throws InterruptedException {
+ mExpandedController.expandFromStack(mExpansionPoint, Mockito.mock(Runnable.class));
+ waitForPropertyAnimations(DynamicAnimation.TRANSLATION_X, DynamicAnimation.TRANSLATION_Y);
}
/** Check that children are in the correct positions for being stacked. */
@@ -108,7 +161,7 @@ public class ExpandedAnimationControllerTest extends PhysicsAnimationLayoutTestC
}
/** Check that children are in the correct positions for being expanded. */
- private void testExpanded() {
+ private void testBubblesInCorrectExpandedPositions() {
// Check all the visible bubbles to see if they're in the right place.
for (int i = 0; i < Math.min(mLayout.getChildCount(), mMaxRenderedBubbles); i++) {
assertEquals(mBubblePadding + (i * (mBubbleSize + mBubblePadding)),
diff --git a/packages/SystemUI/tests/src/com/android/systemui/bubbles/animation/PhysicsAnimationLayoutTestCase.java b/packages/SystemUI/tests/src/com/android/systemui/bubbles/animation/PhysicsAnimationLayoutTestCase.java
index 31e44d7b3051..d94b6694c7fa 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/bubbles/animation/PhysicsAnimationLayoutTestCase.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/bubbles/animation/PhysicsAnimationLayoutTestCase.java
@@ -155,6 +155,11 @@ public class PhysicsAnimationLayoutTestCase extends SysuiTestCase {
}
@Override
+ public void cancelAnimationsOnView(View view) {
+ mMainThreadHandler.post(() -> super.cancelAnimationsOnView(view));
+ }
+
+ @Override
protected void animateValueForChildAtIndex(DynamicAnimation.ViewProperty property,
int index, float value, float startVel, Runnable after) {
mMainThreadHandler.post(() ->
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/AlertingNotificationManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/AlertingNotificationManagerTest.java
index 660f853b3c7b..7b1253af12c6 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/AlertingNotificationManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/AlertingNotificationManagerTest.java
@@ -17,7 +17,7 @@
package com.android.systemui.statusbar;
-import static com.android.systemui.statusbar.notification.row.NotificationInflater.FLAG_CONTENT_VIEW_CONTRACTED;
+import static com.android.systemui.statusbar.notification.row.NotificationContentInflater.FLAG_CONTENT_VIEW_CONTRACTED;
import static junit.framework.Assert.assertFalse;
import static junit.framework.Assert.assertTrue;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationTestHelper.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationTestHelper.java
index a2c880a5bf9b..3c919a17df6c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationTestHelper.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationTestHelper.java
@@ -39,8 +39,8 @@ import com.android.systemui.R;
import com.android.systemui.bubbles.BubblesTestActivity;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
-import com.android.systemui.statusbar.notification.row.NotificationInflater.InflationFlag;
-import com.android.systemui.statusbar.notification.row.NotificationInflaterTest;
+import com.android.systemui.statusbar.notification.row.NotificationContentInflater.InflationFlag;
+import com.android.systemui.statusbar.notification.row.NotificationContentInflaterTest;
import com.android.systemui.statusbar.phone.HeadsUpManagerPhone;
import com.android.systemui.statusbar.phone.NotificationGroupManager;
import com.android.systemui.statusbar.policy.HeadsUpManager;
@@ -279,7 +279,7 @@ public class NotificationTestHelper {
entry.channel.setBlockableSystem(true);
row.setEntry(entry);
row.getNotificationInflater().addInflationFlags(extraInflationFlags);
- NotificationInflaterTest.runThenWaitForInflation(
+ NotificationContentInflaterTest.runThenWaitForInflation(
() -> row.inflateViews(),
row.getNotificationInflater());
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationEntryManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationEntryManagerTest.java
index 79bc0a39d59c..04e7cab406ea 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationEntryManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationEntryManagerTest.java
@@ -68,8 +68,8 @@ import com.android.systemui.statusbar.notification.collection.NotificationData;
import com.android.systemui.statusbar.notification.collection.NotificationData.KeyguardEnvironment;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
+import com.android.systemui.statusbar.notification.row.NotificationContentInflater.InflationFlag;
import com.android.systemui.statusbar.notification.row.NotificationGutsManager;
-import com.android.systemui.statusbar.notification.row.NotificationInflater;
import com.android.systemui.statusbar.notification.row.RowInflaterTask;
import com.android.systemui.statusbar.notification.stack.NotificationListContainer;
import com.android.systemui.statusbar.phone.NotificationGroupManager;
@@ -143,7 +143,7 @@ public class NotificationEntryManagerTest extends SysuiTestCase {
@Override
public void onAsyncInflationFinished(NotificationEntry entry,
- @NotificationInflater.InflationFlag int inflatedFlags) {
+ @InflationFlag int inflatedFlags) {
super.onAsyncInflationFinished(entry, inflatedFlags);
mCountDownLatch.countDown();
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowTest.java
index 6d3553912701..f6fb4163bfc4 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowTest.java
@@ -18,9 +18,9 @@ package com.android.systemui.statusbar.notification.row;
import static android.app.NotificationManager.IMPORTANCE_DEFAULT;
-import static com.android.systemui.statusbar.notification.row.NotificationInflater.FLAG_CONTENT_VIEW_ALL;
-import static com.android.systemui.statusbar.notification.row.NotificationInflater.FLAG_CONTENT_VIEW_HEADS_UP;
-import static com.android.systemui.statusbar.notification.row.NotificationInflater.FLAG_CONTENT_VIEW_PUBLIC;
+import static com.android.systemui.statusbar.notification.row.NotificationContentInflater.FLAG_CONTENT_VIEW_ALL;
+import static com.android.systemui.statusbar.notification.row.NotificationContentInflater.FLAG_CONTENT_VIEW_HEADS_UP;
+import static com.android.systemui.statusbar.notification.row.NotificationContentInflater.FLAG_CONTENT_VIEW_PUBLIC;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationInflaterTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationContentInflaterTest.java
index 648df3cab33c..dfaa76a58e2d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationInflaterTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationContentInflaterTest.java
@@ -16,11 +16,11 @@
package com.android.systemui.statusbar.notification.row;
-import static com.android.systemui.statusbar.notification.row.NotificationInflater.FLAG_CONTENT_VIEW_ALL;
-import static com.android.systemui.statusbar.notification.row.NotificationInflater.FLAG_CONTENT_VIEW_AMBIENT;
-import static com.android.systemui.statusbar.notification.row.NotificationInflater.FLAG_CONTENT_VIEW_EXPANDED;
-import static com.android.systemui.statusbar.notification.row.NotificationInflater.FLAG_CONTENT_VIEW_HEADS_UP;
-import static com.android.systemui.statusbar.notification.row.NotificationInflater.FLAG_CONTENT_VIEW_PUBLIC;
+import static com.android.systemui.statusbar.notification.row.NotificationContentInflater.FLAG_CONTENT_VIEW_ALL;
+import static com.android.systemui.statusbar.notification.row.NotificationContentInflater.FLAG_CONTENT_VIEW_AMBIENT;
+import static com.android.systemui.statusbar.notification.row.NotificationContentInflater.FLAG_CONTENT_VIEW_EXPANDED;
+import static com.android.systemui.statusbar.notification.row.NotificationContentInflater.FLAG_CONTENT_VIEW_HEADS_UP;
+import static com.android.systemui.statusbar.notification.row.NotificationContentInflater.FLAG_CONTENT_VIEW_PUBLIC;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
@@ -49,6 +49,7 @@ import com.android.systemui.SysuiTestCase;
import com.android.systemui.statusbar.InflationTask;
import com.android.systemui.statusbar.NotificationTestHelper;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
+import com.android.systemui.statusbar.notification.row.NotificationContentInflater.InflationCallback;
import org.junit.Assert;
import org.junit.Before;
@@ -64,9 +65,9 @@ import java.util.concurrent.TimeUnit;
@SmallTest
@RunWith(AndroidTestingRunner.class)
@RunWithLooper(setAsMainLooper = true)
-public class NotificationInflaterTest extends SysuiTestCase {
+public class NotificationContentInflaterTest extends SysuiTestCase {
- private NotificationInflater mNotificationInflater;
+ private NotificationContentInflater mNotificationInflater;
private Notification.Builder mBuilder;
private ExpandableNotificationRow mRow;
@@ -80,8 +81,8 @@ public class NotificationInflaterTest extends SysuiTestCase {
ExpandableNotificationRow row = new NotificationTestHelper(mContext).createRow(
mBuilder.build());
mRow = spy(row);
- mNotificationInflater = new NotificationInflater(mRow);
- mNotificationInflater.setInflationCallback(new NotificationInflater.InflationCallback() {
+ mNotificationInflater = new NotificationContentInflater(mRow);
+ mNotificationInflater.setInflationCallback(new InflationCallback() {
@Override
public void handleInflationException(StatusBarNotification notification,
Exception e) {
@@ -89,7 +90,7 @@ public class NotificationInflaterTest extends SysuiTestCase {
@Override
public void onAsyncInflationFinished(NotificationEntry entry,
- @NotificationInflater.InflationFlag int inflatedFlags) {
+ @NotificationContentInflater.InflationFlag int inflatedFlags) {
}
});
}
@@ -158,14 +159,14 @@ public class NotificationInflaterTest extends SysuiTestCase {
@Test
@Ignore
public void testInflationIsRetriedIfAsyncFails() throws Exception {
- NotificationInflater.InflationProgress result =
- new NotificationInflater.InflationProgress();
+ NotificationContentInflater.InflationProgress result =
+ new NotificationContentInflater.InflationProgress();
result.packageContext = mContext;
CountDownLatch countDownLatch = new CountDownLatch(1);
- NotificationInflater.applyRemoteView(result, FLAG_CONTENT_VIEW_EXPANDED, 0,
+ NotificationContentInflater.applyRemoteView(result, FLAG_CONTENT_VIEW_EXPANDED, 0,
new ArrayMap() /* cachedContentViews */, mRow, false /* redactAmbient */,
true /* isNewView */, (v, p, r) -> true,
- new NotificationInflater.InflationCallback() {
+ new InflationCallback() {
@Override
public void handleInflationException(StatusBarNotification notification,
Exception e) {
@@ -175,11 +176,11 @@ public class NotificationInflaterTest extends SysuiTestCase {
@Override
public void onAsyncInflationFinished(NotificationEntry entry,
- @NotificationInflater.InflationFlag int inflatedFlags) {
+ @NotificationContentInflater.InflationFlag int inflatedFlags) {
countDownLatch.countDown();
}
}, mRow.getPrivateLayout(), null, null, new HashMap<>(),
- new NotificationInflater.ApplyCallback() {
+ new NotificationContentInflater.ApplyCallback() {
@Override
public void setResultView(View v) {
}
@@ -199,8 +200,8 @@ public class NotificationInflaterTest extends SysuiTestCase {
mNotificationInflater.updateInflationFlag(FLAG_CONTENT_VIEW_PUBLIC, true);
mNotificationInflater.updateNeedsRedaction(true);
- NotificationInflater.AsyncInflationTask asyncInflationTask =
- (NotificationInflater.AsyncInflationTask) mRow.getEntry().getRunningTask();
+ NotificationContentInflater.AsyncInflationTask asyncInflationTask =
+ (NotificationContentInflater.AsyncInflationTask) mRow.getEntry().getRunningTask();
assertEquals(FLAG_CONTENT_VIEW_AMBIENT | FLAG_CONTENT_VIEW_PUBLIC,
asyncInflationTask.getReInflateFlags());
asyncInflationTask.abort();
@@ -217,8 +218,8 @@ public class NotificationInflaterTest extends SysuiTestCase {
mNotificationInflater.setIsChildInGroup(true);
InflationTask runningTask = mRow.getEntry().getRunningTask();
- NotificationInflater.AsyncInflationTask asyncInflationTask =
- (NotificationInflater.AsyncInflationTask) runningTask;
+ NotificationContentInflater.AsyncInflationTask asyncInflationTask =
+ (NotificationContentInflater.AsyncInflationTask) runningTask;
assertEquals("Successive inflations don't inherit the previous flags!",
FLAG_CONTENT_VIEW_ALL, asyncInflationTask.getReInflateFlags());
runningTask.abort();
@@ -233,19 +234,19 @@ public class NotificationInflaterTest extends SysuiTestCase {
R.layout.custom_view_dark));
RemoteViews decoratedMediaView = mBuilder.createContentView();
Assert.assertFalse("The decorated media style doesn't allow a view to be reapplied!",
- NotificationInflater.canReapplyRemoteView(mediaView, decoratedMediaView));
+ NotificationContentInflater.canReapplyRemoteView(mediaView, decoratedMediaView));
}
public static void runThenWaitForInflation(Runnable block,
- NotificationInflater inflater) throws Exception {
+ NotificationContentInflater inflater) throws Exception {
runThenWaitForInflation(block, false /* expectingException */, inflater);
}
private static void runThenWaitForInflation(Runnable block, boolean expectingException,
- NotificationInflater inflater) throws Exception {
+ NotificationContentInflater inflater) throws Exception {
CountDownLatch countDownLatch = new CountDownLatch(1);
final ExceptionHolder exceptionHolder = new ExceptionHolder();
- inflater.setInflationCallback(new NotificationInflater.InflationCallback() {
+ inflater.setInflationCallback(new InflationCallback() {
@Override
public void handleInflationException(StatusBarNotification notification,
Exception e) {
@@ -257,7 +258,7 @@ public class NotificationInflaterTest extends SysuiTestCase {
@Override
public void onAsyncInflationFinished(NotificationEntry entry,
- @NotificationInflater.InflationFlag int inflatedFlags) {
+ @NotificationContentInflater.InflationFlag int inflatedFlags) {
if (expectingException) {
exceptionHolder.setException(new RuntimeException(
"Inflation finished even though there should be an error"));
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationViewWrapperTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationViewWrapperTest.java
index 24aa772e2fc1..637b30c6bc00 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationViewWrapperTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationViewWrapperTest.java
@@ -14,7 +14,9 @@
* limitations under the License.
*/
-package com.android.systemui.statusbar.notification;
+package com.android.systemui.statusbar.notification.row.wrapper;
+
+import static org.mockito.Mockito.mock;
import android.content.Context;
import android.support.test.filters.SmallTest;
@@ -22,13 +24,15 @@ import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
import android.testing.TestableLooper.RunWithLooper;
import android.view.View;
+import android.widget.LinearLayout;
+import android.widget.TextView;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.statusbar.NotificationTestHelper;
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
-import com.android.systemui.statusbar.notification.row.wrapper.NotificationViewWrapper;
import com.android.systemui.util.Assert;
+import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -37,12 +41,26 @@ import org.junit.runner.RunWith;
@RunWithLooper
public class NotificationViewWrapperTest extends SysuiTestCase {
- @Test
- public void constructor_doesntUseViewContext() throws Exception {
+ private View mView;
+ private ExpandableNotificationRow mRow;
+ private TestableNotificationViewWrapper mNotificationViewWrapper;
+
+ @Before
+ public void setup() throws Exception {
Assert.sMainLooper = TestableLooper.get(this).getLooper();
- new TestableNotificationViewWrapper(mContext,
- new View(mContext),
- new NotificationTestHelper(getContext()).createRow());
+ mView = mock(View.class);
+ mRow = new NotificationTestHelper(getContext()).createRow();
+ mNotificationViewWrapper = new TestableNotificationViewWrapper(mContext, mView, mRow);
+ }
+
+ @Test
+ public void childrenNeedInversion_doesntCrash_whenOpacity() {
+ LinearLayout viewGroup = new LinearLayout(mContext);
+ TextView textView = new TextView(mContext);
+ textView.setTextColor(0xcc000000);
+ viewGroup.addView(textView);
+
+ mNotificationViewWrapper.childrenNeedInversion(0xcc000000, viewGroup);
}
static class TestableNotificationViewWrapper extends NotificationViewWrapper {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationIconAreaControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationIconAreaControllerTest.java
index 608dd8b0d281..120d0b093e0e 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationIconAreaControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationIconAreaControllerTest.java
@@ -29,6 +29,7 @@ import android.testing.TestableLooper;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.NotificationListener;
+import com.android.systemui.statusbar.NotificationMediaManager;
import org.junit.Before;
import org.junit.Test;
@@ -47,6 +48,8 @@ public class NotificationIconAreaControllerTest extends SysuiTestCase {
StatusBar mStatusBar;
@Mock
StatusBarStateController mStatusBarStateController;
+ @Mock
+ private NotificationMediaManager mMediaManager;
private NotificationIconAreaController mController;
@Before
@@ -54,7 +57,7 @@ public class NotificationIconAreaControllerTest extends SysuiTestCase {
MockitoAnnotations.initMocks(this);
mController = new NotificationIconAreaController(mContext, mStatusBar,
- mStatusBarStateController, mListener);
+ mStatusBarStateController, mListener, mMediaManager);
}
@Test
diff --git a/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureManagerService.java b/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureManagerService.java
index 4afbc641ea6c..4bd50ec21d84 100644
--- a/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureManagerService.java
+++ b/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureManagerService.java
@@ -45,6 +45,7 @@ import android.provider.Settings;
import android.util.LocalLog;
import android.util.Slog;
import android.util.SparseBooleanArray;
+import android.view.contentcapture.ContentCaptureHelper;
import android.view.contentcapture.ContentCaptureManager;
import android.view.contentcapture.IContentCaptureManager;
import android.view.contentcapture.UserDataRemovalRequest;
@@ -79,7 +80,8 @@ public final class ContentCaptureManagerService extends
private final LocalService mLocalService = new LocalService();
- private final LocalLog mRequestsHistory = new LocalLog(20);
+ @Nullable
+ final LocalLog mRequestsHistory;
@GuardedBy("mLock")
private ActivityManagerInternal mAm;
@@ -105,15 +107,19 @@ public final class ContentCaptureManagerService extends
UserManager.DISALLOW_CONTENT_CAPTURE);
DeviceConfig.addOnPropertyChangedListener(DeviceConfig.NAMESPACE_CONTENT_CAPTURE,
ActivityThread.currentApplication().getMainExecutor(),
- (namespace, key, value) -> {
- if (!ContentCaptureManager.DEVICE_CONFIG_PROPERTY_SERVICE_EXPLICITLY_ENABLED
- .equals(key)) {
- Slog.i(mTag, "Ignoring change on " + key);
- return;
- }
- setDisabledByDeviceConfig(value);
- });
- setDisabledByDeviceConfig();
+ (namespace, key, value) -> onDeviceConfigChange(key, value));
+ setLoggingLevelFromDeviceConfig();
+ setDisabledFromDeviceConfig();
+
+ final int loggingSize = ContentCaptureHelper.getIntDeviceConfigProperty(
+ ContentCaptureManager.DEVICE_CONFIG_PROPERTY_LOG_HISTORY_SIZE, 20);
+ if (loggingSize > 0) {
+ if (debug) Slog.d(mTag, "log history size: " + loggingSize);
+ mRequestsHistory = new LocalLog(loggingSize);
+ } else {
+ if (debug) Slog.d(mTag, "disabled log history because size is " + loggingSize);
+ mRequestsHistory = null;
+ }
// Sets which services are disabled
final UserManager um = getContext().getSystemService(UserManager.class);
@@ -213,7 +219,33 @@ public final class ContentCaptureManagerService extends
return false;
}
- private void setDisabledByDeviceConfig() {
+ private void onDeviceConfigChange(@NonNull String key, @Nullable String value) {
+ switch (key) {
+ case ContentCaptureManager.DEVICE_CONFIG_PROPERTY_SERVICE_EXPLICITLY_ENABLED:
+ setDisabledByDeviceConfig(value);
+ return;
+ case ContentCaptureManager.DEVICE_CONFIG_PROPERTY_LOGGING_LEVEL:
+ setLoggingLevelFromDeviceConfig();
+ return;
+ case ContentCaptureManager.DEVICE_CONFIG_PROPERTY_MAX_BUFFER_SIZE:
+ case ContentCaptureManager.DEVICE_CONFIG_PROPERTY_IDLE_FLUSH_FREQUENCY:
+ case ContentCaptureManager.DEVICE_CONFIG_PROPERTY_LOG_HISTORY_SIZE:
+ case ContentCaptureManager.DEVICE_CONFIG_PROPERTY_TEXT_CHANGE_FLUSH_FREQUENCY:
+ // TODO(b/123096662): implement it
+ Slog.d(mTag, "changes on " + key + " not supported yet");
+ return;
+ default:
+ Slog.i(mTag, "Ignoring change on " + key);
+ }
+ }
+
+ private void setLoggingLevelFromDeviceConfig() {
+ ContentCaptureHelper.setLoggingLevel();
+ verbose = ContentCaptureHelper.sVerbose;
+ debug = ContentCaptureHelper.sDebug;
+ }
+
+ private void setDisabledFromDeviceConfig() {
final String value = DeviceConfig.getProperty(DeviceConfig.NAMESPACE_CONTENT_CAPTURE,
ContentCaptureManager.DEVICE_CONFIG_PROPERTY_SERVICE_EXPLICITLY_ENABLED);
setDisabledByDeviceConfig(value);
@@ -327,13 +359,6 @@ public final class ContentCaptureManagerService extends
}
}
- /**
- * Logs a request so it's dumped later...
- */
- void logRequestLocked(@NonNull String historyItem) {
- mRequestsHistory.log(historyItem);
- }
-
private ActivityManagerInternal getAmInternal() {
synchronized (mLock) {
if (mAm == null) {
@@ -527,9 +552,13 @@ public final class ContentCaptureManagerService extends
synchronized (mLock) {
dumpLocked("", pw);
}
- if (showHistory) {
- pw.println(); pw.println("Requests history:"); pw.println();
+ pw.print("Requests history: ");
+ if (mRequestsHistory == null) {
+ pw.println("disabled by device config");
+ } else if (showHistory) {
+ pw.println();
mRequestsHistory.reverseDump(fd, pw, args);
+ pw.println();
}
}
diff --git a/services/contentcapture/java/com/android/server/contentcapture/ContentCapturePerUserService.java b/services/contentcapture/java/com/android/server/contentcapture/ContentCapturePerUserService.java
index 7102b82d5e18..360f064bdf0d 100644
--- a/services/contentcapture/java/com/android/server/contentcapture/ContentCapturePerUserService.java
+++ b/services/contentcapture/java/com/android/server/contentcapture/ContentCapturePerUserService.java
@@ -21,6 +21,7 @@ import static android.view.contentcapture.ContentCaptureSession.STATE_DISABLED;
import static android.view.contentcapture.ContentCaptureSession.STATE_DUPLICATED_ID;
import static android.view.contentcapture.ContentCaptureSession.STATE_INTERNAL_ERROR;
import static android.view.contentcapture.ContentCaptureSession.STATE_NO_SERVICE;
+import static android.view.contentcapture.ContentCaptureSession.STATE_PACKAGE_NOT_WHITELISTED;
import static com.android.server.wm.ActivityTaskManagerInternal.ASSIST_KEY_CONTENT;
import static com.android.server.wm.ActivityTaskManagerInternal.ASSIST_KEY_DATA;
@@ -47,7 +48,7 @@ import android.service.contentcapture.ContentCaptureService;
import android.service.contentcapture.IContentCaptureServiceCallback;
import android.service.contentcapture.SnapshotData;
import android.util.ArrayMap;
-import android.util.Log;
+import android.util.ArraySet;
import android.util.Slog;
import android.view.contentcapture.UserDataRemovalRequest;
@@ -87,6 +88,12 @@ final class ContentCapturePerUserService
private final ContentCaptureServiceRemoteCallback mRemoteServiceCallback =
new ContentCaptureServiceRemoteCallback();
+ /**
+ * List of packages that are whitelisted to be content captured.
+ */
+ @GuardedBy("mLock")
+ private final ArraySet<String> mWhitelistedPackages = new ArraySet<>();
+
// TODO(b/111276913): add mechanism to prune stale sessions, similar to Autofill's
ContentCapturePerUserService(@NonNull ContentCaptureManagerService master,
@@ -185,15 +192,19 @@ final class ContentCapturePerUserService
final int taskId = activityPresentationInfo.taskId;
final int displayId = activityPresentationInfo.displayId;
final ComponentName componentName = activityPresentationInfo.componentName;
+ final boolean whitelisted = isWhitelistedLocked(componentName);
final ComponentName serviceComponentName = getServiceComponentName();
final boolean enabled = isEnabledLocked();
- final String historyItem =
- "id=" + sessionId + " uid=" + uid
- + " a=" + ComponentName.flattenToShortString(componentName)
- + " t=" + taskId + " d=" + displayId
- + " s=" + ComponentName.flattenToShortString(serviceComponentName)
- + " u=" + mUserId + " f=" + flags + (enabled ? "" : " (disabled)");
- mMaster.logRequestLocked(historyItem);
+ if (mMaster.mRequestsHistory != null) {
+ final String historyItem =
+ "id=" + sessionId + " uid=" + uid
+ + " a=" + ComponentName.flattenToShortString(componentName)
+ + " t=" + taskId + " d=" + displayId
+ + " s=" + ComponentName.flattenToShortString(serviceComponentName)
+ + " u=" + mUserId + " f=" + flags + (enabled ? "" : " (disabled)")
+ + " w=" + whitelisted;
+ mMaster.mRequestsHistory.log(historyItem);
+ }
if (!enabled) {
// TODO: it would be better to split in differet reasons, like
@@ -212,6 +223,16 @@ final class ContentCapturePerUserService
return;
}
+ if (!whitelisted) {
+ if (mMaster.debug) {
+ Slog.d(TAG, "startSession(" + componentName + "): not whitelisted");
+ }
+ // TODO(b/122595322): need to return STATE_ACTIVITY_NOT_WHITELISTED as well
+ setClientState(clientReceiver, STATE_DISABLED | STATE_PACKAGE_NOT_WHITELISTED,
+ /* binder= */ null);
+ return;
+ }
+
final ContentCaptureServerSession existingSession = mSessions.get(sessionId);
if (existingSession != null) {
Slog.w(TAG, "startSession(id=" + existingSession + ", token=" + activityToken
@@ -245,6 +266,26 @@ final class ContentCapturePerUserService
newSession.notifySessionStartedLocked(clientReceiver);
}
+ @GuardedBy("mLock")
+ private boolean isWhitelistedLocked(@NonNull ComponentName componentName) {
+ // TODO(b/122595322): need to check whitelisted activities as well.
+ final String packageName = componentName.getPackageName();
+ return mWhitelistedPackages.contains(packageName);
+ }
+
+ private void whitelistPackages(@NonNull List<String> packages) {
+ // TODO(b/122595322): add CTS test for when it's null
+ synchronized (mLock) {
+ if (packages == null) {
+ if (mMaster.verbose) Slog.v(TAG, "clearing all whitelisted packages");
+ mWhitelistedPackages.clear();
+ } else {
+ if (mMaster.verbose) Slog.v(TAG, "whitelisting packages: " + packages);
+ mWhitelistedPackages.addAll(packages);
+ }
+ }
+ }
+
// TODO(b/119613670): log metrics
@GuardedBy("mLock")
public void finishSessionLocked(@NonNull String sessionId) {
@@ -376,15 +417,23 @@ final class ContentCapturePerUserService
mRemoteService.dump(prefix2, pw);
}
+ final int whitelistSize = mWhitelistedPackages.size();
+ pw.print(prefix); pw.print("Whitelisted packages: "); pw.println(whitelistSize);
+ for (int i = 0; i < whitelistSize; i++) {
+ final String whitelistedPkg = mWhitelistedPackages.valueAt(i);
+ pw.print(prefix2); pw.print(i + 1); pw.print(": "); pw.println(whitelistedPkg);
+ }
+
if (mSessions.isEmpty()) {
pw.print(prefix); pw.println("no sessions");
} else {
- final int size = mSessions.size();
- pw.print(prefix); pw.print("number sessions: "); pw.println(size);
- for (int i = 0; i < size; i++) {
- pw.print(prefix); pw.print("session@"); pw.println(i);
+ final int sessionsSize = mSessions.size();
+ pw.print(prefix); pw.print("number sessions: "); pw.println(sessionsSize);
+ for (int i = 0; i < sessionsSize; i++) {
+ pw.print(prefix); pw.print("#"); pw.println(i);
final ContentCaptureServerSession session = mSessions.valueAt(i);
session.dumpLocked(prefix2, pw);
+ pw.println();
}
}
}
@@ -410,10 +459,12 @@ final class ContentCapturePerUserService
public void setContentCaptureWhitelist(List<String> packages,
List<ComponentName> activities) {
if (mMaster.verbose) {
- Log.v(TAG, "setContentCaptureWhitelist(packages=" + packages + ", activities="
+ Slog.v(TAG, "setContentCaptureWhitelist(packages=" + packages + ", activities="
+ activities + ")");
}
- // TODO(b/122595322): implement
+ whitelistPackages(packages);
+
+ // TODO(b/122595322): whitelist activities as well
// TODO(b/119613670): log metrics
}
}
diff --git a/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureServerSession.java b/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureServerSession.java
index 4ed5c3d263b6..40948432751d 100644
--- a/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureServerSession.java
+++ b/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureServerSession.java
@@ -20,6 +20,7 @@ import android.content.ComponentName;
import android.os.IBinder;
import android.service.contentcapture.ContentCaptureService;
import android.service.contentcapture.SnapshotData;
+import android.util.LocalLog;
import android.util.Slog;
import android.view.contentcapture.ContentCaptureContext;
import android.view.contentcapture.ContentCaptureSessionId;
@@ -86,7 +87,10 @@ final class ContentCaptureServerSession {
*/
@GuardedBy("mLock")
public void sendActivitySnapshotLocked(@NonNull SnapshotData snapshotData) {
- mService.getMaster().logRequestLocked("snapshot: id=" + mId);
+ final LocalLog logHistory = mService.getMaster().mRequestsHistory;
+ if (logHistory != null) {
+ logHistory.log("snapshot: id=" + mId);
+ }
mRemoteService.onActivitySnapshotRequest(mId, snapshotData);
}
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index dad428acbfee..915c131ff0fb 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -57,8 +57,10 @@ import android.content.Intent;
import android.content.IntentFilter;
import android.content.res.Configuration;
import android.database.ContentObserver;
+import android.net.CaptivePortal;
import android.net.ConnectionInfo;
import android.net.ConnectivityManager;
+import android.net.ICaptivePortal;
import android.net.IConnectivityManager;
import android.net.IIpConnectivityMetrics;
import android.net.INetd;
@@ -86,6 +88,7 @@ import android.net.NetworkQuotaInfo;
import android.net.NetworkRequest;
import android.net.NetworkSpecifier;
import android.net.NetworkStack;
+import android.net.NetworkStackClient;
import android.net.NetworkState;
import android.net.NetworkUtils;
import android.net.NetworkWatchlistManager;
@@ -917,7 +920,8 @@ public class ConnectivityService extends IConnectivityManager.Stub
mPermissionMonitor = new PermissionMonitor(mContext, mNMS);
- //set up the listener for user state for creating user VPNs
+ // Set up the listener for user state for creating user VPNs.
+ // Should run on mHandler to avoid any races.
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(Intent.ACTION_USER_STARTED);
intentFilter.addAction(Intent.ACTION_USER_STOPPED);
@@ -925,7 +929,11 @@ public class ConnectivityService extends IConnectivityManager.Stub
intentFilter.addAction(Intent.ACTION_USER_REMOVED);
intentFilter.addAction(Intent.ACTION_USER_UNLOCKED);
mContext.registerReceiverAsUser(
- mIntentReceiver, UserHandle.ALL, intentFilter, null, null);
+ mIntentReceiver,
+ UserHandle.ALL,
+ intentFilter,
+ null /* broadcastPermission */,
+ mHandler);
mContext.registerReceiverAsUser(mUserPresentReceiver, UserHandle.SYSTEM,
new IntentFilter(Intent.ACTION_USER_PRESENT), null, null);
@@ -936,7 +944,11 @@ public class ConnectivityService extends IConnectivityManager.Stub
intentFilter.addAction(Intent.ACTION_PACKAGE_REMOVED);
intentFilter.addDataScheme("package");
mContext.registerReceiverAsUser(
- mIntentReceiver, UserHandle.ALL, intentFilter, null, null);
+ mIntentReceiver,
+ UserHandle.ALL,
+ intentFilter,
+ null /* broadcastPermission */,
+ mHandler);
try {
mNMS.registerObserver(mTethering);
@@ -2690,11 +2702,6 @@ public class ConnectivityService extends IConnectivityManager.Stub
EVENT_PROVISIONING_NOTIFICATION, PROVISIONING_NOTIFICATION_HIDE,
mNai.network.netId));
}
-
- @Override
- public void logCaptivePortalLoginEvent(int eventId, String packageName) {
- new MetricsLogger().action(eventId, packageName);
- }
}
private boolean networkRequiresValidation(NetworkAgentInfo nai) {
@@ -3249,22 +3256,63 @@ public class ConnectivityService extends IConnectivityManager.Stub
/**
* NetworkStack endpoint to start the captive portal app. The NetworkStack needs to use this
* endpoint as it does not have INTERACT_ACROSS_USERS_FULL itself.
+ * @param network Network on which the captive portal was detected.
* @param appExtras Bundle to use as intent extras for the captive portal application.
* Must be treated as opaque to avoid preventing the captive portal app to
* update its arguments.
*/
@Override
- public void startCaptivePortalAppInternal(Bundle appExtras) {
+ public void startCaptivePortalAppInternal(Network network, Bundle appExtras) {
mContext.checkCallingOrSelfPermission(NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK);
final Intent appIntent = new Intent(ConnectivityManager.ACTION_CAPTIVE_PORTAL_SIGN_IN);
appIntent.putExtras(appExtras);
+ appIntent.putExtra(ConnectivityManager.EXTRA_CAPTIVE_PORTAL,
+ new CaptivePortal(new CaptivePortalImpl(network).asBinder()));
appIntent.setFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT | Intent.FLAG_ACTIVITY_NEW_TASK);
Binder.withCleanCallingIdentity(() ->
mContext.startActivityAsUser(appIntent, UserHandle.CURRENT));
}
+ private class CaptivePortalImpl extends ICaptivePortal.Stub {
+ private final Network mNetwork;
+
+ private CaptivePortalImpl(Network network) {
+ mNetwork = network;
+ }
+
+ @Override
+ public void appResponse(final int response) throws RemoteException {
+ if (response == CaptivePortal.APP_RETURN_WANTED_AS_IS) {
+ enforceSettingsPermission();
+ }
+
+ // getNetworkAgentInfoForNetwork is thread-safe
+ final NetworkAgentInfo nai = getNetworkAgentInfoForNetwork(mNetwork);
+ if (nai == null) return;
+
+ // nai.networkMonitor() is thread-safe
+ final INetworkMonitor nm = nai.networkMonitor();
+ if (nm == null) return;
+
+ final long token = Binder.clearCallingIdentity();
+ try {
+ nm.notifyCaptivePortalAppFinished(response);
+ } finally {
+ // Not using Binder.withCleanCallingIdentity() to keep the checked RemoteException
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+
+ @Override
+ public void logEvent(int eventId, String packageName) {
+ enforceSettingsPermission();
+
+ new MetricsLogger().action(eventId, packageName);
+ }
+ }
+
public boolean avoidBadWifi() {
return mMultinetworkPolicyTracker.getAvoidBadWifi();
}
@@ -4099,17 +4147,27 @@ public class ConnectivityService extends IConnectivityManager.Stub
* handler thread through their agent, this is asynchronous. When the capabilities objects
* are computed they will be up-to-date as they are computed synchronously from here and
* this is running on the ConnectivityService thread.
- * TODO : Fix this and call updateCapabilities inline to remove out-of-order events.
*/
private void updateAllVpnsCapabilities() {
+ Network defaultNetwork = getNetwork(getDefaultNetwork());
synchronized (mVpns) {
for (int i = 0; i < mVpns.size(); i++) {
final Vpn vpn = mVpns.valueAt(i);
- vpn.updateCapabilities();
+ NetworkCapabilities nc = vpn.updateCapabilities(defaultNetwork);
+ updateVpnCapabilities(vpn, nc);
}
}
}
+ private void updateVpnCapabilities(Vpn vpn, @Nullable NetworkCapabilities nc) {
+ ensureRunningOnConnectivityServiceThread();
+ NetworkAgentInfo vpnNai = getNetworkAgentInfoForNetId(vpn.getNetId());
+ if (vpnNai == null || nc == null) {
+ return;
+ }
+ updateCapabilities(vpnNai.getCurrentScore(), vpnNai, nc);
+ }
+
@Override
public boolean updateLockdownVpn() {
if (Binder.getCallingUid() != Process.SYSTEM_UID) {
@@ -4450,22 +4508,28 @@ public class ConnectivityService extends IConnectivityManager.Stub
private void onUserAdded(int userId) {
mPermissionMonitor.onUserAdded(userId);
+ Network defaultNetwork = getNetwork(getDefaultNetwork());
synchronized (mVpns) {
final int vpnsSize = mVpns.size();
for (int i = 0; i < vpnsSize; i++) {
Vpn vpn = mVpns.valueAt(i);
vpn.onUserAdded(userId);
+ NetworkCapabilities nc = vpn.updateCapabilities(defaultNetwork);
+ updateVpnCapabilities(vpn, nc);
}
}
}
private void onUserRemoved(int userId) {
mPermissionMonitor.onUserRemoved(userId);
+ Network defaultNetwork = getNetwork(getDefaultNetwork());
synchronized (mVpns) {
final int vpnsSize = mVpns.size();
for (int i = 0; i < vpnsSize; i++) {
Vpn vpn = mVpns.valueAt(i);
vpn.onUserRemoved(userId);
+ NetworkCapabilities nc = vpn.updateCapabilities(defaultNetwork);
+ updateVpnCapabilities(vpn, nc);
}
}
}
@@ -4534,6 +4598,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
private BroadcastReceiver mIntentReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
+ ensureRunningOnConnectivityServiceThread();
final String action = intent.getAction();
final int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, UserHandle.USER_NULL);
final int uid = intent.getIntExtra(Intent.EXTRA_UID, -1);
@@ -5043,6 +5108,19 @@ public class ConnectivityService extends IConnectivityManager.Stub
return getNetworkForRequest(mDefaultRequest.requestId);
}
+ @Nullable
+ private Network getNetwork(@Nullable NetworkAgentInfo nai) {
+ return nai != null ? nai.network : null;
+ }
+
+ private void ensureRunningOnConnectivityServiceThread() {
+ if (mHandler.getLooper().getThread() != Thread.currentThread()) {
+ throw new IllegalStateException(
+ "Not running on ConnectivityService thread: "
+ + Thread.currentThread().getName());
+ }
+ }
+
private boolean isDefaultNetwork(NetworkAgentInfo nai) {
return nai == getDefaultNetwork();
}
@@ -5099,7 +5177,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
if (DBG) log("registerNetworkAgent " + nai);
final long token = Binder.clearCallingIdentity();
try {
- mContext.getSystemService(NetworkStack.class).makeNetworkMonitor(
+ getNetworkStack().makeNetworkMonitor(
toStableParcelable(nai.network), name, new NetworkMonitorCallbacks(nai));
} finally {
Binder.restoreCallingIdentity(token);
@@ -5111,6 +5189,11 @@ public class ConnectivityService extends IConnectivityManager.Stub
return nai.network.netId;
}
+ @VisibleForTesting
+ protected NetworkStackClient getNetworkStack() {
+ return NetworkStackClient.getInstance();
+ }
+
private void handleRegisterNetworkAgent(NetworkAgentInfo nai, INetworkMonitor networkMonitor) {
nai.onNetworkMonitorCreated(networkMonitor);
if (VDBG) log("Got NetworkAgent Messenger");
@@ -5669,6 +5752,8 @@ public class ConnectivityService extends IConnectivityManager.Stub
updateTcpBufferSizes(newNetwork.linkProperties.getTcpBufferSizes());
mDnsManager.setDefaultDnsSystemProperties(newNetwork.linkProperties.getDnsServers());
notifyIfacesChangedForNetworkStats();
+ // Fix up the NetworkCapabilities of any VPNs that don't specify underlying networks.
+ updateAllVpnsCapabilities();
}
private void processListenRequests(NetworkAgentInfo nai, boolean capabilitiesChanged) {
@@ -6108,6 +6193,10 @@ public class ConnectivityService extends IConnectivityManager.Stub
// doing.
updateSignalStrengthThresholds(networkAgent, "CONNECT", null);
+ if (networkAgent.isVPN()) {
+ updateAllVpnsCapabilities();
+ }
+
// Consider network even though it is not yet validated.
final long now = SystemClock.elapsedRealtime();
rematchNetworkAndRequests(networkAgent, ReapUnvalidatedNetworks.REAP, now);
@@ -6369,7 +6458,11 @@ public class ConnectivityService extends IConnectivityManager.Stub
success = mVpns.get(user).setUnderlyingNetworks(networks);
}
if (success) {
- mHandler.post(() -> notifyIfacesChangedForNetworkStats());
+ mHandler.post(() -> {
+ // Update VPN's capabilities based on updated underlying network set.
+ updateAllVpnsCapabilities();
+ notifyIfacesChangedForNetworkStats();
+ });
}
return success;
}
diff --git a/services/core/java/com/android/server/ExtconUEventObserver.java b/services/core/java/com/android/server/ExtconUEventObserver.java
index eb591528bc90..775e4c8cf4ed 100644
--- a/services/core/java/com/android/server/ExtconUEventObserver.java
+++ b/services/core/java/com/android/server/ExtconUEventObserver.java
@@ -68,7 +68,7 @@ public abstract class ExtconUEventObserver extends UEventObserver {
* Subclasses of ExtconUEventObserver should override this method to handle UEvents.
*
* @param extconInfo that matches the {@code DEVPATH} of {@code event}
- * @param event the event
+ * @param event the event
*/
protected abstract void onUEvent(ExtconInfo extconInfo, UEvent event);
@@ -91,6 +91,9 @@ public abstract class ExtconUEventObserver extends UEventObserver {
/** Returns a new list of all external connections whose name matches {@code regex}. */
public static List<ExtconInfo> getExtconInfos(@Nullable String regex) {
+ if (!extconExists()) {
+ return new ArrayList<>(0); // Always return a new list.
+ }
Pattern p = regex == null ? null : Pattern.compile(regex);
File file = new File("/sys/class/extcon");
File[] files = file.listFiles();
diff --git a/services/core/java/com/android/server/FgThread.java b/services/core/java/com/android/server/FgThread.java
index fe30057fc820..5d0e308f6649 100644
--- a/services/core/java/com/android/server/FgThread.java
+++ b/services/core/java/com/android/server/FgThread.java
@@ -17,9 +17,12 @@
package com.android.server;
import android.os.Handler;
+import android.os.HandlerExecutor;
import android.os.Looper;
import android.os.Trace;
+import java.util.concurrent.Executor;
+
/**
* Shared singleton foreground thread for the system. This is a thread for regular
* foreground service operations, which shouldn't be blocked by anything running in
@@ -34,6 +37,7 @@ public final class FgThread extends ServiceThread {
private static FgThread sInstance;
private static Handler sHandler;
+ private static HandlerExecutor sHandlerExecutor;
private FgThread() {
super("android.fg", android.os.Process.THREAD_PRIORITY_DEFAULT, true /*allowIo*/);
@@ -48,6 +52,7 @@ public final class FgThread extends ServiceThread {
looper.setSlowLogThresholdMs(
SLOW_DISPATCH_THRESHOLD_MS, SLOW_DELIVERY_THRESHOLD_MS);
sHandler = new Handler(sInstance.getLooper());
+ sHandlerExecutor = new HandlerExecutor(sHandler);
}
}
@@ -64,4 +69,11 @@ public final class FgThread extends ServiceThread {
return sHandler;
}
}
+
+ public static Executor getExecutor() {
+ synchronized (FgThread.class) {
+ ensureThreadLocked();
+ return sHandlerExecutor;
+ }
+ }
}
diff --git a/services/core/java/com/android/server/IoThread.java b/services/core/java/com/android/server/IoThread.java
index bfe825a3a89e..21fd29c3bbef 100644
--- a/services/core/java/com/android/server/IoThread.java
+++ b/services/core/java/com/android/server/IoThread.java
@@ -17,8 +17,11 @@
package com.android.server;
import android.os.Handler;
+import android.os.HandlerExecutor;
import android.os.Trace;
+import java.util.concurrent.Executor;
+
/**
* Shared singleton I/O thread for the system. This is a thread for non-background
* service operations that can potential block briefly on network IO operations
@@ -27,6 +30,7 @@ import android.os.Trace;
public final class IoThread extends ServiceThread {
private static IoThread sInstance;
private static Handler sHandler;
+ private static HandlerExecutor sHandlerExecutor;
private IoThread() {
super("android.io", android.os.Process.THREAD_PRIORITY_DEFAULT, true /*allowIo*/);
@@ -38,6 +42,7 @@ public final class IoThread extends ServiceThread {
sInstance.start();
sInstance.getLooper().setTraceTag(Trace.TRACE_TAG_SYSTEM_SERVER);
sHandler = new Handler(sInstance.getLooper());
+ sHandlerExecutor = new HandlerExecutor(sHandler);
}
}
@@ -54,4 +59,11 @@ public final class IoThread extends ServiceThread {
return sHandler;
}
}
+
+ public static Executor getExecutor() {
+ synchronized (IoThread.class) {
+ ensureThreadLocked();
+ return sHandlerExecutor;
+ }
+ }
}
diff --git a/services/core/java/com/android/server/LocationManagerService.java b/services/core/java/com/android/server/LocationManagerService.java
index 9d92ea2b5b45..5989a46c5a0a 100644
--- a/services/core/java/com/android/server/LocationManagerService.java
+++ b/services/core/java/com/android/server/LocationManagerService.java
@@ -2136,6 +2136,13 @@ public class LocationManagerService extends ILocationManager.Stub {
}
}
+ @Override
+ public String[] getIgnoreSettingsWhitelist() {
+ synchronized (mLock) {
+ return mIgnoreSettingsPackageWhitelist.toArray(new String[0]);
+ }
+ }
+
@GuardedBy("mLock")
private boolean isThrottlingExemptLocked(CallerIdentity callerIdentity) {
if (callerIdentity.mUid == Process.SYSTEM_UID) {
@@ -2794,8 +2801,7 @@ public class LocationManagerService extends ILocationManager.Stub {
} catch (RemoteException e) {
// if the remote process registering the listener is already dead, just swallow the
// exception and return
- Log.w(TAG, "Could not link " + linkedListener.mListenerName + " death callback.",
- e);
+ Log.w(TAG, "Could not link " + linkedListener.mListenerName + " death callback.", e);
return false;
}
}
@@ -2808,8 +2814,7 @@ public class LocationManagerService extends ILocationManager.Stub {
} catch (NoSuchElementException e) {
// if the death callback isn't connected (it should be...), log error,
// swallow the exception and return
- Log.w(TAG, "Could not unlink " + linkedListener.mListenerName + " death callback.",
- e);
+ Log.w(TAG, "Could not unlink " + linkedListener.mListenerName + " death callback.", e);
return false;
}
}
diff --git a/services/core/java/com/android/server/UiModeManagerService.java b/services/core/java/com/android/server/UiModeManagerService.java
index 6b57fcd31450..710a0ba34d4f 100644
--- a/services/core/java/com/android/server/UiModeManagerService.java
+++ b/services/core/java/com/android/server/UiModeManagerService.java
@@ -30,11 +30,13 @@ import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
+import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.os.BatteryManager;
import android.os.Binder;
+import android.os.Build;
import android.os.Handler;
import android.os.PowerManager;
import android.os.PowerManager.ServiceType;
@@ -354,8 +356,12 @@ final class UiModeManagerService extends SystemService {
try {
synchronized (mLock) {
if (mNightMode != mode) {
- Settings.Secure.putIntForUser(getContext().getContentResolver(),
- Settings.Secure.UI_NIGHT_MODE, mode, user);
+ // Only persist setting if not transient night mode or not in car mode
+ if (!shouldTransientNightWhenInCarMode() || !mCarModeEnabled) {
+ Settings.Secure.putIntForUser(getContext().getContentResolver(),
+ Settings.Secure.UI_NIGHT_MODE, mode, user);
+ }
+
mNightMode = mode;
updateLocked(0, 0);
}
@@ -438,9 +444,39 @@ final class UiModeManagerService extends SystemService {
}
}
+ // Night mode settings in car mode are only persisted below Q.
+ // When targeting Q, changes are not saved and night mode will be re-read
+ // from settings when exiting car mode.
+ private boolean shouldTransientNightWhenInCarMode() {
+ int uid = Binder.getCallingUid();
+ PackageManager packageManager = getContext().getPackageManager();
+ String[] packagesForUid = packageManager.getPackagesForUid(uid);
+ if (packagesForUid == null || packagesForUid.length == 0) {
+ return false;
+ }
+
+ try {
+ ApplicationInfo appInfo = packageManager.getApplicationInfoAsUser(
+ packagesForUid[0], 0, uid);
+
+ return appInfo.targetSdkVersion >= Build.VERSION_CODES.Q;
+ } catch (PackageManager.NameNotFoundException ignored) {
+ }
+
+ return false;
+ }
+
void setCarModeLocked(boolean enabled, int flags) {
if (mCarModeEnabled != enabled) {
mCarModeEnabled = enabled;
+
+ // When transient night mode and exiting car mode, restore night mode from settings
+ if (shouldTransientNightWhenInCarMode() && !mCarModeEnabled) {
+ Context context = getContext();
+ updateNightModeFromSettings(context,
+ context.getResources(),
+ UserHandle.getCallingUserId());
+ }
}
mCarModeEnableFlags = flags;
}
@@ -498,7 +534,9 @@ final class UiModeManagerService extends SystemService {
uiMode |= mNightMode << 4;
}
- if (mPowerSave) {
+ // Override night mode in power save mode if not transient night mode or not in car mode
+ boolean shouldOverrideNight = !mCarModeEnabled || !shouldTransientNightWhenInCarMode();
+ if (mPowerSave && shouldOverrideNight) {
uiMode &= ~Configuration.UI_MODE_NIGHT_NO;
uiMode |= Configuration.UI_MODE_NIGHT_YES;
}
diff --git a/services/core/java/com/android/server/am/OomAdjuster.java b/services/core/java/com/android/server/am/OomAdjuster.java
index 93a71e5a2ed4..4e03b72e6ce6 100644
--- a/services/core/java/com/android/server/am/OomAdjuster.java
+++ b/services/core/java/com/android/server/am/OomAdjuster.java
@@ -1692,7 +1692,8 @@ public final class OomAdjuster {
(app.curAdj == ProcessList.PREVIOUS_APP_ADJ ||
app.curAdj == ProcessList.HOME_APP_ADJ)) {
mAppCompact.compactAppSome(app);
- } else if (app.setAdj < ProcessList.CACHED_APP_MIN_ADJ
+ } else if ((app.setAdj < ProcessList.CACHED_APP_MIN_ADJ
+ || app.setAdj > ProcessList.CACHED_APP_MAX_ADJ)
&& app.curAdj >= ProcessList.CACHED_APP_MIN_ADJ
&& app.curAdj <= ProcessList.CACHED_APP_MAX_ADJ) {
mAppCompact.compactAppFull(app);
diff --git a/services/core/java/com/android/server/appbinding/finders/CarrierMessagingClientServiceFinder.java b/services/core/java/com/android/server/appbinding/finders/CarrierMessagingClientServiceFinder.java
index 753d3b0cc10e..3663518bf7b9 100644
--- a/services/core/java/com/android/server/appbinding/finders/CarrierMessagingClientServiceFinder.java
+++ b/services/core/java/com/android/server/appbinding/finders/CarrierMessagingClientServiceFinder.java
@@ -99,7 +99,7 @@ public class CarrierMessagingClientServiceFinder
@Override
public void startMonitoring() {
mRoleManager.addOnRoleHoldersChangedListenerAsUser(
- mContext.getMainExecutor(), mRoleHolderChangedListener, UserHandle.ALL);
+ BackgroundThread.getExecutor(), mRoleHolderChangedListener, UserHandle.ALL);
}
@Override
@@ -120,9 +120,7 @@ public class CarrierMessagingClientServiceFinder
private final OnRoleHoldersChangedListener mRoleHolderChangedListener = (role, user) -> {
if (RoleManager.ROLE_SMS.equals(role)) {
- BackgroundThread.getHandler().post(() -> {
- mListener.accept(CarrierMessagingClientServiceFinder.this, user.getIdentifier());
- });
+ mListener.accept(CarrierMessagingClientServiceFinder.this, user.getIdentifier());
}
};
}
diff --git a/services/core/java/com/android/server/attention/AttentionManagerService.java b/services/core/java/com/android/server/attention/AttentionManagerService.java
index 9a1d7bf0053d..47c9b8639760 100644
--- a/services/core/java/com/android/server/attention/AttentionManagerService.java
+++ b/services/core/java/com/android/server/attention/AttentionManagerService.java
@@ -104,8 +104,7 @@ public class AttentionManagerService extends SystemService {
@Override
public void onSwitchUser(int userId) {
- cancelAndUnbindLocked(peekUserStateLocked(userId),
- AttentionService.ATTENTION_FAILURE_UNKNOWN);
+ cancelAndUnbindLocked(peekUserStateLocked(userId));
}
/** Resolves and sets up the attention service if it had not been done yet. */
@@ -152,7 +151,8 @@ public class AttentionManagerService extends SystemService {
}
synchronized (mLock) {
- unbindAfterTimeoutLocked();
+ final long now = SystemClock.uptimeMillis();
+ freeIfInactiveLocked();
final UserState userState = getOrCreateCurrentUserStateLocked();
// lazily start the service, which should be very lightweight to start
@@ -172,7 +172,7 @@ public class AttentionManagerService extends SystemService {
try {
// throttle frequent requests
final AttentionCheckCache attentionCheckCache = userState.mAttentionCheckCache;
- if (attentionCheckCache != null && SystemClock.uptimeMillis()
+ if (attentionCheckCache != null && now
< attentionCheckCache.mLastComputed + STALE_AFTER_MILLIS) {
callback.onSuccess(requestCode, attentionCheckCache.mResult,
attentionCheckCache.mTimestamp);
@@ -190,6 +190,7 @@ public class AttentionManagerService extends SystemService {
userState.mAttentionCheckCache = new AttentionCheckCache(
SystemClock.uptimeMillis(), result,
timestamp);
+ userState.mCurrentAttentionCheckIsFulfilled = true;
}
StatsLog.write(StatsLog.ATTENTION_MANAGER_SERVICE_RESULT_REPORTED,
result);
@@ -198,14 +199,10 @@ public class AttentionManagerService extends SystemService {
@Override
public void onFailure(int requestCode, int error) {
callback.onFailure(requestCode, error);
+ userState.mCurrentAttentionCheckIsFulfilled = true;
StatsLog.write(StatsLog.ATTENTION_MANAGER_SERVICE_RESULT_REPORTED,
error);
}
-
- @Override
- public IBinder asBinder() {
- return null;
- }
});
} catch (RemoteException e) {
Slog.e(LOG_TAG, "Cannot call into the AttentionService");
@@ -219,7 +216,10 @@ public class AttentionManagerService extends SystemService {
/** Cancels the specified attention check. */
public void cancelAttentionCheck(int requestCode) {
synchronized (mLock) {
- final UserState userState = getOrCreateCurrentUserStateLocked();
+ final UserState userState = peekCurrentUserStateLocked();
+ if (userState == null) {
+ return;
+ }
if (userState.mService == null) {
if (userState.mPendingAttentionCheck != null
&& userState.mPendingAttentionCheck.mRequestCode == requestCode) {
@@ -236,8 +236,12 @@ public class AttentionManagerService extends SystemService {
}
@GuardedBy("mLock")
- private void unbindAfterTimeoutLocked() {
- mAttentionHandler.sendEmptyMessageDelayed(AttentionHandler.CONNECTION_EXPIRED,
+ private void freeIfInactiveLocked() {
+ // If we are called here, it means someone used the API again - reset the timer then.
+ mAttentionHandler.removeMessages(AttentionHandler.CHECK_CONNECTION_EXPIRATION);
+
+ // Schedule resources cleanup if no one calls the API again.
+ mAttentionHandler.sendEmptyMessageDelayed(AttentionHandler.CHECK_CONNECTION_EXPIRATION,
CONNECTION_TTL_MILLIS);
}
@@ -264,12 +268,14 @@ public class AttentionManagerService extends SystemService {
}
@GuardedBy("mLock")
- UserState peekCurrentUserStateLocked() {
+ @Nullable
+ private UserState peekCurrentUserStateLocked() {
return peekUserStateLocked(ActivityManager.getCurrentUser());
}
@GuardedBy("mLock")
- UserState peekUserStateLocked(int userId) {
+ @Nullable
+ private UserState peekUserStateLocked(int userId) {
return mUserStates.get(userId);
}
@@ -406,6 +412,8 @@ public class AttentionManagerService extends SystemService {
@GuardedBy("mLock")
int mCurrentAttentionCheckRequestCode;
@GuardedBy("mLock")
+ boolean mCurrentAttentionCheckIsFulfilled;
+ @GuardedBy("mLock")
PendingAttentionCheck mPendingAttentionCheck;
@GuardedBy("mLock")
@@ -501,7 +509,7 @@ public class AttentionManagerService extends SystemService {
}
private class AttentionHandler extends Handler {
- private static final int CONNECTION_EXPIRED = 1;
+ private static final int CHECK_CONNECTION_EXPIRATION = 1;
private static final int ATTENTION_CHECK_TIMEOUT = 2;
AttentionHandler() {
@@ -511,19 +519,26 @@ public class AttentionManagerService extends SystemService {
public void handleMessage(Message msg) {
switch (msg.what) {
// Do not occupy resources when not in use - unbind proactively.
- case CONNECTION_EXPIRED: {
+ case CHECK_CONNECTION_EXPIRATION: {
for (int i = 0; i < mUserStates.size(); i++) {
- cancelAndUnbindLocked(mUserStates.valueAt(i),
- AttentionService.ATTENTION_FAILURE_UNKNOWN);
+ cancelAndUnbindLocked(mUserStates.valueAt(i));
}
-
}
break;
// Callee is no longer interested in the attention check result - cancel.
case ATTENTION_CHECK_TIMEOUT: {
- cancelAndUnbindLocked(peekCurrentUserStateLocked(),
- AttentionService.ATTENTION_FAILURE_TIMED_OUT);
+ synchronized (mLock) {
+ final UserState userState = peekCurrentUserStateLocked();
+ if (userState != null) {
+ // If not called back already.
+ if (!userState.mCurrentAttentionCheckIsFulfilled) {
+ cancel(userState,
+ AttentionService.ATTENTION_FAILURE_TIMED_OUT);
+ }
+
+ }
+ }
}
break;
@@ -533,25 +548,29 @@ public class AttentionManagerService extends SystemService {
}
}
+ private void cancel(UserState userState, @AttentionFailureCodes int failureCode) {
+ if (userState != null && userState.mService != null) {
+ try {
+ userState.mService.cancelAttentionCheck(
+ userState.mCurrentAttentionCheckRequestCode);
+ } catch (RemoteException e) {
+ Slog.e(LOG_TAG, "Unable to cancel attention check");
+ }
+
+ if (userState.mPendingAttentionCheck != null) {
+ userState.mPendingAttentionCheck.cancel(failureCode);
+ }
+ }
+ }
+
@GuardedBy("mLock")
- private void cancelAndUnbindLocked(UserState userState,
- @AttentionFailureCodes int failureCode) {
+ private void cancelAndUnbindLocked(UserState userState) {
synchronized (mLock) {
- if (userState != null && userState.mService != null) {
- try {
- userState.mService.cancelAttentionCheck(
- userState.mCurrentAttentionCheckRequestCode);
- } catch (RemoteException e) {
- Slog.e(LOG_TAG, "Unable to cancel attention check");
- }
+ cancel(userState, AttentionService.ATTENTION_FAILURE_UNKNOWN);
- if (userState.mPendingAttentionCheck != null) {
- userState.mPendingAttentionCheck.cancel(failureCode);
- }
- mContext.unbindService(userState.mConnection);
- userState.mConnection.cleanupService();
- mUserStates.remove(userState.mUserId);
- }
+ mContext.unbindService(userState.mConnection);
+ userState.mConnection.cleanupService();
+ mUserStates.remove(userState.mUserId);
}
}
@@ -563,8 +582,7 @@ public class AttentionManagerService extends SystemService {
@Override
public void onReceive(Context context, Intent intent) {
if (Intent.ACTION_SCREEN_OFF.equals(intent.getAction())) {
- cancelAndUnbindLocked(peekCurrentUserStateLocked(),
- AttentionService.ATTENTION_FAILURE_UNKNOWN);
+ cancelAndUnbindLocked(peekCurrentUserStateLocked());
}
}
}
diff --git a/services/core/java/com/android/server/audio/AudioDeviceBroker.java b/services/core/java/com/android/server/audio/AudioDeviceBroker.java
index 6df60d6bdd3a..9af57daa259b 100644
--- a/services/core/java/com/android/server/audio/AudioDeviceBroker.java
+++ b/services/core/java/com/android/server/audio/AudioDeviceBroker.java
@@ -280,9 +280,9 @@ import java.util.ArrayList;
AudioSystem.FOR_COMMUNICATION, mForcedUseForComm, eventSource);
sendIILMsgNoDelay(MSG_IIL_SET_FORCE_USE, SENDMSG_QUEUE,
AudioSystem.FOR_RECORD, mForcedUseForComm, eventSource);
- // Un-mute ringtone stream volume
- mAudioService.setUpdateRingerModeServiceInt();
}
+ // Un-mute ringtone stream volume
+ mAudioService.postUpdateRingerModeServiceInt();
}
/*package*/ AudioRoutesInfo startWatchingRoutes(IAudioRoutesObserver observer) {
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index a6643d49c79f..d902201df212 100644
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -248,6 +248,7 @@ public class AudioService extends IAudioService.Stub
private static final int MSG_NOTIFY_VOL_EVENT = 22;
private static final int MSG_DISPATCH_AUDIO_SERVER_STATE = 23;
private static final int MSG_ENABLE_SURROUND_FORMATS = 24;
+ private static final int MSG_UPDATE_RINGER_MODE = 25;
// start of messages handled under wakelock
// these messages can only be queued, i.e. sent with queueMsgUnderWakeLock(),
// and not with sendMsg(..., ..., SENDMSG_QUEUE, ...)
@@ -753,6 +754,7 @@ public class AudioService extends IAudioService.Stub
intentFilter.addAction(Intent.ACTION_USER_FOREGROUND);
intentFilter.addAction(UsbManager.ACTION_USB_DEVICE_ATTACHED);
intentFilter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED);
+ intentFilter.addAction(Intent.ACTION_PACKAGES_SUSPENDED);
intentFilter.addAction(Intent.ACTION_CONFIGURATION_CHANGED);
mMonitorRotation = SystemProperties.getBoolean("ro.audio.monitorRotation", false);
@@ -2720,7 +2722,11 @@ public class AudioService extends IAudioService.Stub
}
}
- /*package*/ void setUpdateRingerModeServiceInt() {
+ /*package*/ void postUpdateRingerModeServiceInt() {
+ sendMsg(mAudioHandler, MSG_UPDATE_RINGER_MODE, SENDMSG_QUEUE, 0, 0, null, 0);
+ }
+
+ private void onUpdateRingerModeServiceInt() {
setRingerModeInt(getRingerModeInternal(), false);
}
@@ -3217,6 +3223,21 @@ public class AudioService extends IAudioService.Stub
if (!checkAudioSettingsPermission("setSpeakerphoneOn()")) {
return;
}
+
+ if (mContext.checkCallingOrSelfPermission(
+ android.Manifest.permission.MODIFY_PHONE_STATE)
+ != PackageManager.PERMISSION_GRANTED) {
+ synchronized (mSetModeDeathHandlers) {
+ for (SetModeDeathHandler h : mSetModeDeathHandlers) {
+ if (h.getMode() == AudioSystem.MODE_IN_CALL) {
+ Log.w(TAG, "getMode is call, Permission Denial: setSpeakerphoneOn from pid="
+ + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid());
+ return;
+ }
+ }
+ }
+ }
+
// for logging only
final String eventSource = new StringBuilder("setSpeakerphoneOn(").append(on)
.append(") from u/pid:").append(Binder.getCallingUid()).append("/")
@@ -4944,6 +4965,10 @@ public class AudioService extends IAudioService.Stub
case MSG_ENABLE_SURROUND_FORMATS:
onEnableSurroundFormats((ArrayList<Integer>) msg.obj);
break;
+
+ case MSG_UPDATE_RINGER_MODE:
+ onUpdateRingerModeServiceInt();
+ break;
}
}
}
@@ -5159,6 +5184,20 @@ public class AudioService extends IAudioService.Stub
} else if (action.equals(AudioEffect.ACTION_OPEN_AUDIO_EFFECT_CONTROL_SESSION) ||
action.equals(AudioEffect.ACTION_CLOSE_AUDIO_EFFECT_CONTROL_SESSION)) {
handleAudioEffectBroadcast(context, intent);
+ } else if (action.equals(Intent.ACTION_PACKAGES_SUSPENDED)) {
+ final int[] suspendedUids = intent.getIntArrayExtra(Intent.EXTRA_CHANGED_UID_LIST);
+ final String[] suspendedPackages =
+ intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
+ if (suspendedPackages == null || suspendedUids == null
+ || suspendedPackages.length != suspendedUids.length) {
+ return;
+ }
+ for (int i = 0; i < suspendedUids.length; i++) {
+ if (!TextUtils.isEmpty(suspendedPackages[i])) {
+ mMediaFocusControl.noFocusForSuspendedApp(
+ suspendedPackages[i], suspendedUids[i]);
+ }
+ }
}
}
} // end class AudioServiceBroadcastReceiver
@@ -5323,6 +5362,11 @@ public class AudioService extends IAudioService.Stub
}
}
+ if (callingPackageName == null || clientId == null || aa == null) {
+ Log.e(TAG, "Invalid null parameter to request audio focus");
+ return AudioManager.AUDIOFOCUS_REQUEST_FAILED;
+ }
+
return mMediaFocusControl.requestAudioFocus(aa, durationHint, cb, fd,
clientId, callingPackageName, flags, sdk,
forceFocusDuckingForAccessibility(aa, durationHint, Binder.getCallingUid()));
diff --git a/services/core/java/com/android/server/audio/FocusRequester.java b/services/core/java/com/android/server/audio/FocusRequester.java
index 99f08405a375..db55138e446d 100644
--- a/services/core/java/com/android/server/audio/FocusRequester.java
+++ b/services/core/java/com/android/server/audio/FocusRequester.java
@@ -45,8 +45,8 @@ public class FocusRequester {
private AudioFocusDeathHandler mDeathHandler; // may be null
private IAudioFocusDispatcher mFocusDispatcher; // may be null
private final IBinder mSourceRef; // may be null
- private final String mClientId;
- private final String mPackageName;
+ private final @NonNull String mClientId;
+ private final @NonNull String mPackageName;
private final int mCallingUid;
private final MediaFocusControl mFocusController; // never null
private final int mSdkTarget;
@@ -72,7 +72,7 @@ public class FocusRequester {
/**
* the audio attributes associated with the focus request
*/
- private final AudioAttributes mAttributes;
+ private final @NonNull AudioAttributes mAttributes;
/**
* Class constructor
@@ -87,9 +87,10 @@ public class FocusRequester {
* @param uid
* @param ctlr cannot be null
*/
- FocusRequester(AudioAttributes aa, int focusRequest, int grantFlags,
- IAudioFocusDispatcher afl, IBinder source, String id, AudioFocusDeathHandler hdlr,
- String pn, int uid, @NonNull MediaFocusControl ctlr, int sdk) {
+ FocusRequester(@NonNull AudioAttributes aa, int focusRequest, int grantFlags,
+ IAudioFocusDispatcher afl, IBinder source, @NonNull String id,
+ AudioFocusDeathHandler hdlr, @NonNull String pn, int uid,
+ @NonNull MediaFocusControl ctlr, int sdk) {
mAttributes = aa;
mFocusDispatcher = afl;
mSourceRef = source;
@@ -124,11 +125,7 @@ public class FocusRequester {
}
boolean hasSameClient(String otherClient) {
- try {
- return mClientId.compareTo(otherClient) == 0;
- } catch (NullPointerException e) {
- return false;
- }
+ return mClientId.compareTo(otherClient) == 0;
}
boolean isLockedFocusOwner() {
@@ -143,12 +140,8 @@ public class FocusRequester {
return (mFocusDispatcher != null) && mFocusDispatcher.equals(fd);
}
- boolean hasSamePackage(String pack) {
- try {
- return mPackageName.compareTo(pack) == 0;
- } catch (NullPointerException e) {
- return false;
- }
+ boolean hasSamePackage(@NonNull String pack) {
+ return mPackageName.compareTo(pack) == 0;
}
boolean hasSameUid(int uid) {
diff --git a/services/core/java/com/android/server/audio/MediaFocusControl.java b/services/core/java/com/android/server/audio/MediaFocusControl.java
index d023bd7827ff..b4bbbc729505 100644
--- a/services/core/java/com/android/server/audio/MediaFocusControl.java
+++ b/services/core/java/com/android/server/audio/MediaFocusControl.java
@@ -24,7 +24,6 @@ import android.media.AudioFocusInfo;
import android.media.AudioManager;
import android.media.AudioSystem;
import android.media.IAudioFocusDispatcher;
-import android.media.audiopolicy.AudioPolicy;
import android.media.audiopolicy.IAudioPolicyCallback;
import android.os.Binder;
import android.os.Build;
@@ -35,6 +34,7 @@ import android.util.Log;
import com.android.internal.annotations.GuardedBy;
import java.io.PrintWriter;
+import java.text.DateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
@@ -44,7 +44,6 @@ import java.util.List;
import java.util.Map.Entry;
import java.util.Set;
import java.util.Stack;
-import java.text.DateFormat;
/**
* @hide
@@ -138,6 +137,30 @@ public class MediaFocusControl implements PlayerFocusEnforcer {
private static final AudioEventLogger mEventLogger = new AudioEventLogger(50,
"focus commands as seen by MediaFocusControl");
+ /*package*/ void noFocusForSuspendedApp(@NonNull String packageName, int uid) {
+ synchronized (mAudioFocusLock) {
+ final Iterator<FocusRequester> stackIterator = mFocusStack.iterator();
+ List<String> clientsToRemove = new ArrayList<>();
+ while (stackIterator.hasNext()) {
+ final FocusRequester focusOwner = stackIterator.next();
+ if (focusOwner.hasSameUid(uid) && focusOwner.hasSamePackage(packageName)) {
+ clientsToRemove.add(focusOwner.getClientId());
+ mEventLogger.log((new AudioEventLogger.StringEvent(
+ "focus owner:" + focusOwner.getClientId()
+ + " in uid:" + uid + " pack: " + packageName
+ + " getting AUDIOFOCUS_LOSS due to app suspension"))
+ .printLog(TAG));
+ // make the suspended app lose focus through its focus listener (if any)
+ focusOwner.dispatchFocusChange(AudioManager.AUDIOFOCUS_LOSS);
+ }
+ }
+ for (String clientToRemove : clientsToRemove) {
+ // update the stack but don't signal the change.
+ removeFocusStackEntry(clientToRemove, false, true);
+ }
+ }
+ }
+
/**
* Discard the current audio focus owner.
* Notify top of audio focus stack that it lost focus (regardless of possibility to reassign
@@ -688,9 +711,9 @@ public class MediaFocusControl implements PlayerFocusEnforcer {
}
/** @see AudioManager#requestAudioFocus(AudioManager.OnAudioFocusChangeListener, int, int, int) */
- protected int requestAudioFocus(AudioAttributes aa, int focusChangeHint, IBinder cb,
- IAudioFocusDispatcher fd, String clientId, String callingPackageName, int flags,
- int sdk, boolean forceDuck) {
+ protected int requestAudioFocus(@NonNull AudioAttributes aa, int focusChangeHint, IBinder cb,
+ IAudioFocusDispatcher fd, @NonNull String clientId, @NonNull String callingPackageName,
+ int flags, int sdk, boolean forceDuck) {
mEventLogger.log((new AudioEventLogger.StringEvent(
"requestAudioFocus() from uid/pid " + Binder.getCallingUid()
+ "/" + Binder.getCallingPid()
diff --git a/services/core/java/com/android/server/connectivity/Tethering.java b/services/core/java/com/android/server/connectivity/Tethering.java
index 19bdc0969e6d..c91e1a12078e 100644
--- a/services/core/java/com/android/server/connectivity/Tethering.java
+++ b/services/core/java/com/android/server/connectivity/Tethering.java
@@ -1859,7 +1859,7 @@ public class Tethering extends BaseNetworkObserver {
final TetherState tetherState = new TetherState(
new IpServer(iface, mLooper, interfaceType, mLog, mNMService, mStatsService,
makeControlCallback(), mConfig.enableLegacyDhcpServer,
- mDeps.getIpServerDependencies(mContext)));
+ mDeps.getIpServerDependencies()));
mTetherStates.put(iface, tetherState);
tetherState.ipServer.start();
}
diff --git a/services/core/java/com/android/server/connectivity/Vpn.java b/services/core/java/com/android/server/connectivity/Vpn.java
index e1af81b2f658..da547eaf8db2 100644
--- a/services/core/java/com/android/server/connectivity/Vpn.java
+++ b/services/core/java/com/android/server/connectivity/Vpn.java
@@ -241,7 +241,7 @@ public class Vpn {
mNetworkCapabilities = new NetworkCapabilities();
mNetworkCapabilities.addTransportType(NetworkCapabilities.TRANSPORT_VPN);
mNetworkCapabilities.removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VPN);
- updateCapabilities();
+ updateCapabilities(null /* defaultNetwork */);
loadAlwaysOnPackage();
}
@@ -268,22 +268,44 @@ public class Vpn {
updateAlwaysOnNotification(detailedState);
}
- public void updateCapabilities() {
- final Network[] underlyingNetworks = (mConfig != null) ? mConfig.underlyingNetworks : null;
- // Only apps targeting Q and above can explicitly declare themselves as metered.
- final boolean isAlwaysMetered =
- mIsPackageTargetingAtLeastQ && (mConfig == null || mConfig.isMetered);
- updateCapabilities(mContext.getSystemService(ConnectivityManager.class), underlyingNetworks,
- mNetworkCapabilities, isAlwaysMetered);
+ /**
+ * Updates {@link #mNetworkCapabilities} based on current underlying networks and returns a
+ * defensive copy.
+ *
+ * <p>Does not propagate updated capabilities to apps.
+ *
+ * @param defaultNetwork underlying network for VPNs following platform's default
+ */
+ public synchronized NetworkCapabilities updateCapabilities(
+ @Nullable Network defaultNetwork) {
+ if (mConfig == null) {
+ // VPN is not running.
+ return null;
+ }
- if (mNetworkAgent != null) {
- mNetworkAgent.sendNetworkCapabilities(mNetworkCapabilities);
+ Network[] underlyingNetworks = mConfig.underlyingNetworks;
+ if (underlyingNetworks == null && defaultNetwork != null) {
+ // null underlying networks means to track the default.
+ underlyingNetworks = new Network[] { defaultNetwork };
}
+ // Only apps targeting Q and above can explicitly declare themselves as metered.
+ final boolean isAlwaysMetered = mIsPackageTargetingAtLeastQ && mConfig.isMetered;
+
+ applyUnderlyingCapabilities(
+ mContext.getSystemService(ConnectivityManager.class),
+ underlyingNetworks,
+ mNetworkCapabilities,
+ isAlwaysMetered);
+
+ return new NetworkCapabilities(mNetworkCapabilities);
}
@VisibleForTesting
- public static void updateCapabilities(ConnectivityManager cm, Network[] underlyingNetworks,
- NetworkCapabilities caps, boolean isAlwaysMetered) {
+ public static void applyUnderlyingCapabilities(
+ ConnectivityManager cm,
+ Network[] underlyingNetworks,
+ NetworkCapabilities caps,
+ boolean isAlwaysMetered) {
int[] transportTypes = new int[] { NetworkCapabilities.TRANSPORT_VPN };
int downKbps = NetworkCapabilities.LINK_BANDWIDTH_UNSPECIFIED;
int upKbps = NetworkCapabilities.LINK_BANDWIDTH_UNSPECIFIED;
@@ -296,6 +318,7 @@ public class Vpn {
boolean hadUnderlyingNetworks = false;
if (null != underlyingNetworks) {
for (Network underlying : underlyingNetworks) {
+ // TODO(b/124469351): Get capabilities directly from ConnectivityService instead.
final NetworkCapabilities underlyingCaps = cm.getNetworkCapabilities(underlying);
if (underlyingCaps == null) continue;
hadUnderlyingNetworks = true;
@@ -1007,9 +1030,8 @@ public class Vpn {
}
/**
- * Establish a VPN network and return the file descriptor of the VPN
- * interface. This methods returns {@code null} if the application is
- * revoked or not prepared.
+ * Establish a VPN network and return the file descriptor of the VPN interface. This methods
+ * returns {@code null} if the application is revoked or not prepared.
*
* @param config The parameters to configure the network.
* @return The file descriptor of the VPN interface.
@@ -1101,8 +1123,6 @@ public class Vpn {
// as rules are deleted. This prevents data leakage as the rules are moved over.
agentDisconnect(oldNetworkAgent);
}
- // Set up VPN's capabilities such as meteredness.
- updateCapabilities();
if (oldConnection != null) {
mContext.unbindService(oldConnection);
@@ -1258,6 +1278,11 @@ public class Vpn {
return ranges;
}
+ /**
+ * Updates UID ranges for this VPN and also updates its internal capabilities.
+ *
+ * <p>Should be called on primary ConnectivityService thread.
+ */
public void onUserAdded(int userHandle) {
// If the user is restricted tie them to the parent user's VPN
UserInfo user = UserManager.get(mContext).getUserInfo(userHandle);
@@ -1268,8 +1293,9 @@ public class Vpn {
try {
addUserToRanges(existingRanges, userHandle, mConfig.allowedApplications,
mConfig.disallowedApplications);
+ // ConnectivityService will call {@link #updateCapabilities} and apply
+ // those for VPN network.
mNetworkCapabilities.setUids(existingRanges);
- updateCapabilities();
} catch (Exception e) {
Log.wtf(TAG, "Failed to add restricted user to owner", e);
}
@@ -1279,6 +1305,11 @@ public class Vpn {
}
}
+ /**
+ * Updates UID ranges for this VPN and also updates its capabilities.
+ *
+ * <p>Should be called on primary ConnectivityService thread.
+ */
public void onUserRemoved(int userHandle) {
// clean up if restricted
UserInfo user = UserManager.get(mContext).getUserInfo(userHandle);
@@ -1290,8 +1321,9 @@ public class Vpn {
final List<UidRange> removedRanges =
uidRangesForUser(userHandle, existingRanges);
existingRanges.removeAll(removedRanges);
+ // ConnectivityService will call {@link #updateCapabilities} and
+ // apply those for VPN network.
mNetworkCapabilities.setUids(existingRanges);
- updateCapabilities();
} catch (Exception e) {
Log.wtf(TAG, "Failed to remove restricted user to owner", e);
}
@@ -1504,6 +1536,12 @@ public class Vpn {
return success;
}
+ /**
+ * Updates underlying network set.
+ *
+ * <p>Note: Does not updates capabilities. Call {@link #updateCapabilities} from
+ * ConnectivityService thread to get updated capabilities.
+ */
public synchronized boolean setUnderlyingNetworks(Network[] networks) {
if (!isCallerEstablishedOwnerLocked()) {
return false;
@@ -1520,7 +1558,6 @@ public class Vpn {
}
}
}
- updateCapabilities();
return true;
}
diff --git a/services/core/java/com/android/server/connectivity/tethering/TetheringDependencies.java b/services/core/java/com/android/server/connectivity/tethering/TetheringDependencies.java
index 3fddac111ec5..173d7860e4ac 100644
--- a/services/core/java/com/android/server/connectivity/tethering/TetheringDependencies.java
+++ b/services/core/java/com/android/server/connectivity/tethering/TetheringDependencies.java
@@ -61,8 +61,8 @@ public class TetheringDependencies {
/**
* Get dependencies to be used by IpServer.
*/
- public IpServer.Dependencies getIpServerDependencies(Context context) {
- return new IpServer.Dependencies(context);
+ public IpServer.Dependencies getIpServerDependencies() {
+ return new IpServer.Dependencies();
}
/**
diff --git a/services/core/java/com/android/server/display/ColorDisplayService.java b/services/core/java/com/android/server/display/ColorDisplayService.java
index 45f169ca0b6f..7dd3b363810d 100644
--- a/services/core/java/com/android/server/display/ColorDisplayService.java
+++ b/services/core/java/com/android/server/display/ColorDisplayService.java
@@ -129,240 +129,9 @@ public final class ColorDisplayService extends SystemService {
private final NightDisplayTintController mNightDisplayTintController =
new NightDisplayTintController();
- private final TintController mDisplayWhiteBalanceTintController = new TintController() {
- // Three chromaticity coordinates per color: X, Y, and Z
- private final int NUM_VALUES_PER_PRIMARY = 3;
- // Four colors: red, green, blue, and white
- private final int NUM_DISPLAY_PRIMARIES_VALS = 4 * NUM_VALUES_PER_PRIMARY;
-
- private final Object mLock = new Object();
- private int mTemperatureMin;
- private int mTemperatureMax;
- private int mTemperatureDefault;
- private float[] mDisplayNominalWhiteXYZ = new float[NUM_VALUES_PER_PRIMARY];
- private ColorSpace.Rgb mDisplayColorSpaceRGB;
- private float[] mChromaticAdaptationMatrix;
- private int mCurrentColorTemperature;
- private float[] mCurrentColorTemperatureXYZ;
- private boolean mSetUp = false;
- private float[] mMatrixDisplayWhiteBalance = new float[16];
- private Boolean mIsAvailable;
-
- @Override
- public void setUp(Context context, boolean needsLinear) {
- mSetUp = false;
- final Resources res = context.getResources();
-
- ColorSpace.Rgb displayColorSpaceRGB = getDisplayColorSpaceFromSurfaceControl();
- if (displayColorSpaceRGB == null) {
- Slog.w(TAG, "Failed to get display color space from SurfaceControl, trying res");
- displayColorSpaceRGB = getDisplayColorSpaceFromResources(res);
- if (displayColorSpaceRGB == null) {
- Slog.e(TAG, "Failed to get display color space from resources");
- return;
- }
- }
-
- final String[] nominalWhiteValues = res.getStringArray(
- R.array.config_displayWhiteBalanceDisplayNominalWhite);
- float[] displayNominalWhiteXYZ = new float[NUM_VALUES_PER_PRIMARY];
- for (int i = 0; i < nominalWhiteValues.length; i++) {
- displayNominalWhiteXYZ[i] = Float.parseFloat(nominalWhiteValues[i]);
- }
-
- final int colorTemperatureMin = res.getInteger(
- R.integer.config_displayWhiteBalanceColorTemperatureMin);
- if (colorTemperatureMin <= 0) {
- Slog.e(TAG, "Display white balance minimum temperature must be greater than 0");
- return;
- }
-
- final int colorTemperatureMax = res.getInteger(
- R.integer.config_displayWhiteBalanceColorTemperatureMax);
- if (colorTemperatureMax < colorTemperatureMin) {
- Slog.e(TAG, "Display white balance max temp must be greater or equal to min");
- return;
- }
-
- final int colorTemperature = res.getInteger(
- R.integer.config_displayWhiteBalanceColorTemperatureDefault);
-
- synchronized (mLock) {
- mDisplayColorSpaceRGB = displayColorSpaceRGB;
- mDisplayNominalWhiteXYZ = displayNominalWhiteXYZ;
- mTemperatureMin = colorTemperatureMin;
- mTemperatureMax = colorTemperatureMax;
- mTemperatureDefault = colorTemperature;
- mSetUp = true;
- }
-
- setMatrix(mTemperatureDefault);
- }
-
- @Override
- public float[] getMatrix() {
- return mSetUp && isActivated() ? mMatrixDisplayWhiteBalance : MATRIX_IDENTITY;
- }
-
- @Override
- public void setMatrix(int cct) {
- if (!mSetUp) {
- Slog.w(TAG, "Can't set display white balance temperature: uninitialized");
- return;
- }
-
- if (cct < mTemperatureMin) {
- Slog.w(TAG, "Requested display color temperature is below allowed minimum");
- cct = mTemperatureMin;
- } else if (cct > mTemperatureMax) {
- Slog.w(TAG, "Requested display color temperature is above allowed maximum");
- cct = mTemperatureMax;
- }
-
- Slog.d(TAG, "setDisplayWhiteBalanceTemperatureMatrix: cct = " + cct);
-
- synchronized (mLock) {
- mCurrentColorTemperature = cct;
-
- // Adapt the display's nominal white point to match the requested CCT value
- mCurrentColorTemperatureXYZ = ColorSpace.cctToIlluminantdXyz(cct);
-
- mChromaticAdaptationMatrix =
- ColorSpace.chromaticAdaptation(ColorSpace.Adaptation.BRADFORD,
- mDisplayNominalWhiteXYZ, mCurrentColorTemperatureXYZ);
-
- // Convert the adaptation matrix to RGB space
- float[] result = ColorSpace.mul3x3(mChromaticAdaptationMatrix,
- mDisplayColorSpaceRGB.getTransform());
- result = ColorSpace.mul3x3(mDisplayColorSpaceRGB.getInverseTransform(), result);
-
- // Normalize the transform matrix to peak white value in RGB space
- final float adaptedMaxR = result[0] + result[3] + result[6];
- final float adaptedMaxG = result[1] + result[4] + result[7];
- final float adaptedMaxB = result[2] + result[5] + result[8];
- final float denum = Math.max(Math.max(adaptedMaxR, adaptedMaxG), adaptedMaxB);
- for (int i = 0; i < result.length; i++) {
- result[i] /= denum;
- }
-
- Matrix.setIdentityM(mMatrixDisplayWhiteBalance, 0);
- java.lang.System.arraycopy(result, 0, mMatrixDisplayWhiteBalance, 0, 3);
- java.lang.System.arraycopy(result, 3, mMatrixDisplayWhiteBalance, 4, 3);
- java.lang.System.arraycopy(result, 6, mMatrixDisplayWhiteBalance, 8, 3);
- }
- }
-
- @Override
- public int getLevel() {
- return LEVEL_COLOR_MATRIX_DISPLAY_WHITE_BALANCE;
- }
-
- @Override
- public boolean isAvailable(Context context) {
- if (mIsAvailable == null) {
- mIsAvailable = ColorDisplayManager.isDisplayWhiteBalanceAvailable(context);
- }
- return mIsAvailable;
- }
-
- /**
- * Format a given matrix into a string.
- *
- * @param matrix the matrix to format
- * @param cols number of columns in the matrix
- */
- private String matrixToString(float[] matrix, int cols) {
- if (matrix == null || cols <= 0) {
- Slog.e(TAG, "Invalid arguments when formatting matrix to string");
- return "";
- }
-
- StringBuilder sb = new StringBuilder("");
- for (int i = 0; i < matrix.length; i++) {
- if (i % cols == 0) {
- sb.append("\n ");
- }
- sb.append(String.format("%9.6f ", matrix[i]));
- }
- return sb.toString();
- }
-
- @Override
- public void dump(PrintWriter pw) {
- synchronized (mLock) {
- pw.println(" mSetUp = " + mSetUp);
- if (!mSetUp) {
- return;
- }
-
- pw.println(" isActivated = " + isActivated());
- pw.println(" mTemperatureMin = " + mTemperatureMin);
- pw.println(" mTemperatureMax = " + mTemperatureMax);
- pw.println(" mTemperatureDefault = " + mTemperatureDefault);
- pw.println(" mCurrentColorTemperature = " + mCurrentColorTemperature);
- pw.println(" mCurrentColorTemperatureXYZ = " +
- matrixToString(mCurrentColorTemperatureXYZ, 3));
- pw.println(" mDisplayColorSpaceRGB RGB-to-XYZ = " +
- matrixToString(mDisplayColorSpaceRGB.getTransform(), 3));
- pw.println(" mChromaticAdaptationMatrix = " +
- matrixToString(mChromaticAdaptationMatrix, 3));
- pw.println(" mDisplayColorSpaceRGB XYZ-to-RGB = " +
- matrixToString(mDisplayColorSpaceRGB.getInverseTransform(), 3));
- pw.println(" mMatrixDisplayWhiteBalance = " +
- matrixToString(mMatrixDisplayWhiteBalance, 4));
- }
- }
-
- private ColorSpace.Rgb makeRgbColorSpaceFromXYZ(float[] redGreenBlueXYZ, float[] whiteXYZ) {
- return new ColorSpace.Rgb(
- "Display Color Space",
- redGreenBlueXYZ,
- whiteXYZ,
- 2.2f // gamma, unused for display white balance
- );
- }
-
- private ColorSpace.Rgb getDisplayColorSpaceFromSurfaceControl() {
- final IBinder displayToken = SurfaceControl.getInternalDisplayToken();
- if (displayToken == null) {
- return null;
- }
-
- DisplayPrimaries primaries = SurfaceControl.getDisplayNativePrimaries(displayToken);
- if (primaries == null || primaries.red == null || primaries.green == null ||
- primaries.blue == null || primaries.white == null) {
- return null;
- }
-
- return makeRgbColorSpaceFromXYZ(
- new float[] {
- primaries.red.X, primaries.red.Y, primaries.red.Z,
- primaries.green.X, primaries.green.Y, primaries.green.Z,
- primaries.blue.X, primaries.blue.Y, primaries.blue.Z,
- },
- new float[] { primaries.white.X, primaries.white.Y, primaries.white.Z }
- );
- }
-
- private ColorSpace.Rgb getDisplayColorSpaceFromResources(Resources res) {
- final String[] displayPrimariesValues = res.getStringArray(
- R.array.config_displayWhiteBalanceDisplayPrimaries);
- float[] displayRedGreenBlueXYZ =
- new float[NUM_DISPLAY_PRIMARIES_VALS - NUM_VALUES_PER_PRIMARY];
- float[] displayWhiteXYZ = new float[NUM_VALUES_PER_PRIMARY];
-
- for (int i = 0; i < displayRedGreenBlueXYZ.length; i++) {
- displayRedGreenBlueXYZ[i] = Float.parseFloat(displayPrimariesValues[i]);
- }
-
- for (int i = 0; i < displayWhiteXYZ.length; i++) {
- displayWhiteXYZ[i] = Float.parseFloat(
- displayPrimariesValues[displayRedGreenBlueXYZ.length + i]);
- }
-
- return makeRgbColorSpaceFromXYZ(displayRedGreenBlueXYZ, displayWhiteXYZ);
- }
- };
+ @VisibleForTesting
+ final DisplayWhiteBalanceTintController mDisplayWhiteBalanceTintController =
+ new DisplayWhiteBalanceTintController();
private final TintController mGlobalSaturationTintController = new TintController() {
@@ -860,7 +629,8 @@ public final class ColorDisplayService extends SystemService {
return ldt.isBefore(compareTime) ? ldt.plusDays(1) : ldt;
}
- private void updateDisplayWhiteBalanceStatus() {
+ @VisibleForTesting
+ void updateDisplayWhiteBalanceStatus() {
boolean oldActivated = mDisplayWhiteBalanceTintController.isActivated();
mDisplayWhiteBalanceTintController.setActivated(isDisplayWhiteBalanceSettingEnabled() &&
!mNightDisplayTintController.isActivated() &&
@@ -1101,6 +871,7 @@ public final class ColorDisplayService extends SystemService {
pw.println("Display white balance:");
if (mDisplayWhiteBalanceTintController.isAvailable(getContext())) {
pw.println(" Activated: " + mDisplayWhiteBalanceTintController.isActivated());
+ mDisplayWhiteBalanceTintController.dump(pw);
} else {
pw.println(" Not available");
}
@@ -1533,6 +1304,244 @@ public final class ColorDisplayService extends SystemService {
}
}
+ final class DisplayWhiteBalanceTintController extends TintController {
+ // Three chromaticity coordinates per color: X, Y, and Z
+ private final int NUM_VALUES_PER_PRIMARY = 3;
+ // Four colors: red, green, blue, and white
+ private final int NUM_DISPLAY_PRIMARIES_VALS = 4 * NUM_VALUES_PER_PRIMARY;
+
+ private final Object mLock = new Object();
+ @VisibleForTesting
+ int mTemperatureMin;
+ @VisibleForTesting
+ int mTemperatureMax;
+ private int mTemperatureDefault;
+ private float[] mDisplayNominalWhiteXYZ = new float[NUM_VALUES_PER_PRIMARY];
+ @VisibleForTesting
+ ColorSpace.Rgb mDisplayColorSpaceRGB;
+ private float[] mChromaticAdaptationMatrix;
+ @VisibleForTesting
+ int mCurrentColorTemperature;
+ private float[] mCurrentColorTemperatureXYZ;
+ private boolean mSetUp = false;
+ private float[] mMatrixDisplayWhiteBalance = new float[16];
+ private Boolean mIsAvailable;
+
+ @Override
+ public void setUp(Context context, boolean needsLinear) {
+ mSetUp = false;
+ final Resources res = context.getResources();
+
+ ColorSpace.Rgb displayColorSpaceRGB = getDisplayColorSpaceFromSurfaceControl();
+ if (displayColorSpaceRGB == null) {
+ Slog.w(TAG, "Failed to get display color space from SurfaceControl, trying res");
+ displayColorSpaceRGB = getDisplayColorSpaceFromResources(res);
+ if (displayColorSpaceRGB == null) {
+ Slog.e(TAG, "Failed to get display color space from resources");
+ return;
+ }
+ }
+
+ final String[] nominalWhiteValues = res.getStringArray(
+ R.array.config_displayWhiteBalanceDisplayNominalWhite);
+ float[] displayNominalWhiteXYZ = new float[NUM_VALUES_PER_PRIMARY];
+ for (int i = 0; i < nominalWhiteValues.length; i++) {
+ displayNominalWhiteXYZ[i] = Float.parseFloat(nominalWhiteValues[i]);
+ }
+
+ final int colorTemperatureMin = res.getInteger(
+ R.integer.config_displayWhiteBalanceColorTemperatureMin);
+ if (colorTemperatureMin <= 0) {
+ Slog.e(TAG, "Display white balance minimum temperature must be greater than 0");
+ return;
+ }
+
+ final int colorTemperatureMax = res.getInteger(
+ R.integer.config_displayWhiteBalanceColorTemperatureMax);
+ if (colorTemperatureMax < colorTemperatureMin) {
+ Slog.e(TAG, "Display white balance max temp must be greater or equal to min");
+ return;
+ }
+
+ final int colorTemperature = res.getInteger(
+ R.integer.config_displayWhiteBalanceColorTemperatureDefault);
+
+ synchronized (mLock) {
+ mDisplayColorSpaceRGB = displayColorSpaceRGB;
+ mDisplayNominalWhiteXYZ = displayNominalWhiteXYZ;
+ mTemperatureMin = colorTemperatureMin;
+ mTemperatureMax = colorTemperatureMax;
+ mTemperatureDefault = colorTemperature;
+ mSetUp = true;
+ }
+
+ setMatrix(mTemperatureDefault);
+ }
+
+ @Override
+ public float[] getMatrix() {
+ return mSetUp && isActivated() ? mMatrixDisplayWhiteBalance : MATRIX_IDENTITY;
+ }
+
+ @Override
+ public void setMatrix(int cct) {
+ if (!mSetUp) {
+ Slog.w(TAG, "Can't set display white balance temperature: uninitialized");
+ return;
+ }
+
+ if (cct < mTemperatureMin) {
+ Slog.w(TAG, "Requested display color temperature is below allowed minimum");
+ cct = mTemperatureMin;
+ } else if (cct > mTemperatureMax) {
+ Slog.w(TAG, "Requested display color temperature is above allowed maximum");
+ cct = mTemperatureMax;
+ }
+
+ Slog.d(TAG, "setDisplayWhiteBalanceTemperatureMatrix: cct = " + cct);
+
+ synchronized (mLock) {
+ mCurrentColorTemperature = cct;
+
+ // Adapt the display's nominal white point to match the requested CCT value
+ mCurrentColorTemperatureXYZ = ColorSpace.cctToIlluminantdXyz(cct);
+
+ mChromaticAdaptationMatrix =
+ ColorSpace.chromaticAdaptation(ColorSpace.Adaptation.BRADFORD,
+ mDisplayNominalWhiteXYZ, mCurrentColorTemperatureXYZ);
+
+ // Convert the adaptation matrix to RGB space
+ float[] result = ColorSpace.mul3x3(mChromaticAdaptationMatrix,
+ mDisplayColorSpaceRGB.getTransform());
+ result = ColorSpace.mul3x3(mDisplayColorSpaceRGB.getInverseTransform(), result);
+
+ // Normalize the transform matrix to peak white value in RGB space
+ final float adaptedMaxR = result[0] + result[3] + result[6];
+ final float adaptedMaxG = result[1] + result[4] + result[7];
+ final float adaptedMaxB = result[2] + result[5] + result[8];
+ final float denum = Math.max(Math.max(adaptedMaxR, adaptedMaxG), adaptedMaxB);
+ for (int i = 0; i < result.length; i++) {
+ result[i] /= denum;
+ }
+
+ Matrix.setIdentityM(mMatrixDisplayWhiteBalance, 0);
+ java.lang.System.arraycopy(result, 0, mMatrixDisplayWhiteBalance, 0, 3);
+ java.lang.System.arraycopy(result, 3, mMatrixDisplayWhiteBalance, 4, 3);
+ java.lang.System.arraycopy(result, 6, mMatrixDisplayWhiteBalance, 8, 3);
+ }
+ }
+
+ @Override
+ public int getLevel() {
+ return LEVEL_COLOR_MATRIX_DISPLAY_WHITE_BALANCE;
+ }
+
+ @Override
+ public boolean isAvailable(Context context) {
+ if (mIsAvailable == null) {
+ mIsAvailable = ColorDisplayManager.isDisplayWhiteBalanceAvailable(context);
+ }
+ return mIsAvailable;
+ }
+
+ /**
+ * Format a given matrix into a string.
+ *
+ * @param matrix the matrix to format
+ * @param cols number of columns in the matrix
+ */
+ private String matrixToString(float[] matrix, int cols) {
+ if (matrix == null || cols <= 0) {
+ Slog.e(TAG, "Invalid arguments when formatting matrix to string");
+ return "";
+ }
+
+ StringBuilder sb = new StringBuilder("");
+ for (int i = 0; i < matrix.length; i++) {
+ if (i % cols == 0) {
+ sb.append("\n ");
+ }
+ sb.append(String.format("%9.6f ", matrix[i]));
+ }
+ return sb.toString();
+ }
+
+ @Override
+ public void dump(PrintWriter pw) {
+ synchronized (mLock) {
+ pw.println(" mSetUp = " + mSetUp);
+ if (!mSetUp) {
+ return;
+ }
+
+ pw.println(" mTemperatureMin = " + mTemperatureMin);
+ pw.println(" mTemperatureMax = " + mTemperatureMax);
+ pw.println(" mTemperatureDefault = " + mTemperatureDefault);
+ pw.println(" mCurrentColorTemperature = " + mCurrentColorTemperature);
+ pw.println(" mCurrentColorTemperatureXYZ = " +
+ matrixToString(mCurrentColorTemperatureXYZ, 3));
+ pw.println(" mDisplayColorSpaceRGB RGB-to-XYZ = " +
+ matrixToString(mDisplayColorSpaceRGB.getTransform(), 3));
+ pw.println(" mChromaticAdaptationMatrix = " +
+ matrixToString(mChromaticAdaptationMatrix, 3));
+ pw.println(" mDisplayColorSpaceRGB XYZ-to-RGB = " +
+ matrixToString(mDisplayColorSpaceRGB.getInverseTransform(), 3));
+ pw.println(" mMatrixDisplayWhiteBalance = " +
+ matrixToString(mMatrixDisplayWhiteBalance, 4));
+ }
+ }
+
+ private ColorSpace.Rgb makeRgbColorSpaceFromXYZ(float[] redGreenBlueXYZ, float[] whiteXYZ) {
+ return new ColorSpace.Rgb(
+ "Display Color Space",
+ redGreenBlueXYZ,
+ whiteXYZ,
+ 2.2f // gamma, unused for display white balance
+ );
+ }
+
+ private ColorSpace.Rgb getDisplayColorSpaceFromSurfaceControl() {
+ final IBinder displayToken = SurfaceControl.getInternalDisplayToken();
+ if (displayToken == null) {
+ return null;
+ }
+
+ DisplayPrimaries primaries = SurfaceControl.getDisplayNativePrimaries(displayToken);
+ if (primaries == null || primaries.red == null || primaries.green == null ||
+ primaries.blue == null || primaries.white == null) {
+ return null;
+ }
+
+ return makeRgbColorSpaceFromXYZ(
+ new float[] {
+ primaries.red.X, primaries.red.Y, primaries.red.Z,
+ primaries.green.X, primaries.green.Y, primaries.green.Z,
+ primaries.blue.X, primaries.blue.Y, primaries.blue.Z,
+ },
+ new float[] { primaries.white.X, primaries.white.Y, primaries.white.Z }
+ );
+ }
+
+ private ColorSpace.Rgb getDisplayColorSpaceFromResources(Resources res) {
+ final String[] displayPrimariesValues = res.getStringArray(
+ R.array.config_displayWhiteBalanceDisplayPrimaries);
+ float[] displayRedGreenBlueXYZ =
+ new float[NUM_DISPLAY_PRIMARIES_VALS - NUM_VALUES_PER_PRIMARY];
+ float[] displayWhiteXYZ = new float[NUM_VALUES_PER_PRIMARY];
+
+ for (int i = 0; i < displayRedGreenBlueXYZ.length; i++) {
+ displayRedGreenBlueXYZ[i] = Float.parseFloat(displayPrimariesValues[i]);
+ }
+
+ for (int i = 0; i < displayWhiteXYZ.length; i++) {
+ displayWhiteXYZ[i] = Float.parseFloat(
+ displayPrimariesValues[displayRedGreenBlueXYZ.length + i]);
+ }
+
+ return makeRgbColorSpaceFromXYZ(displayRedGreenBlueXYZ, displayWhiteXYZ);
+ }
+ };
+
/**
* Local service that allows color transforms to be enabled from other system services.
*/
diff --git a/services/core/java/com/android/server/display/DisplayPowerController.java b/services/core/java/com/android/server/display/DisplayPowerController.java
index dc5be6a6a074..15c7ef75866f 100644
--- a/services/core/java/com/android/server/display/DisplayPowerController.java
+++ b/services/core/java/com/android/server/display/DisplayPowerController.java
@@ -1019,7 +1019,7 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
if (mDisplayWhiteBalanceController != null) {
if (state == Display.STATE_ON && mDisplayWhiteBalanceSettings.isEnabled()) {
mDisplayWhiteBalanceController.setEnabled(true);
- mDisplayWhiteBalanceController.updateScreenColorTemperature();
+ mDisplayWhiteBalanceController.updateDisplayColorTemperature();
} else {
mDisplayWhiteBalanceController.setEnabled(false);
}
diff --git a/services/core/java/com/android/server/display/whitebalance/DisplayWhiteBalanceController.java b/services/core/java/com/android/server/display/whitebalance/DisplayWhiteBalanceController.java
index b9aa34e89216..d95e92b71357 100644
--- a/services/core/java/com/android/server/display/whitebalance/DisplayWhiteBalanceController.java
+++ b/services/core/java/com/android/server/display/whitebalance/DisplayWhiteBalanceController.java
@@ -29,14 +29,14 @@ import java.io.PrintWriter;
/**
* The DisplayWhiteBalanceController drives display white-balance (automatically correcting the
- * screen color temperature depending on the ambient color temperature).
+ * display color temperature depending on the ambient color temperature).
*
* The DisplayWhiteBalanceController:
* - Uses the AmbientColorTemperatureSensor to detect changes in the ambient color temperature;
* - Uses the AmbientColorTemperatureFilter to average these changes over time, filter out the
* noise, and arrive at an estimate of the actual ambient color temperature;
- * - Uses the DisplayWhiteBalanceThrottler to decide whether the screen color tempearture should be
- * updated, suppressing changes that are too frequent or too minor.
+ * - Uses the DisplayWhiteBalanceThrottler to decide whether the display color tempearture should
+ * be updated, suppressing changes that are too frequent or too minor.
*/
public class DisplayWhiteBalanceController implements
AmbientSensor.AmbientBrightnessSensor.Callbacks,
@@ -76,8 +76,8 @@ public class DisplayWhiteBalanceController implements
// Override the ambient color temperature for debugging purposes.
private float mAmbientColorTemperatureOverride;
- // A piecewise linear relationship between ambient and display color temperatures
- private Spline.LinearSpline mAmbientToDisplayTemperatureSpline;
+ // A piecewise linear relationship between ambient and display color temperatures.
+ private Spline.LinearSpline mAmbientToDisplayColorTemperatureSpline;
/**
* @param brightnessSensor
@@ -91,7 +91,7 @@ public class DisplayWhiteBalanceController implements
* The filter used to average ambient color temperature changes over time, filter out the
* noise and arrive at an estimate of the actual ambient color temperature.
* @param throttler
- * The throttler used to determine whether the new screen color temperature should be
+ * The throttler used to determine whether the new display color temperature should be
* updated or not.
* @param lowLightAmbientBrightnessThreshold
* The ambient brightness threshold beneath which we fall back to a fixed ambient color
@@ -99,6 +99,12 @@ public class DisplayWhiteBalanceController implements
* @param lowLightAmbientColorTemperature
* The ambient color temperature to which we fall back when the ambient brightness drops
* beneath a certain threshold.
+ * @param ambientColorTemperatures
+ * The ambient color tempeartures used to map the ambient color temperature to the display
+ * color temperature (or null if no mapping is necessary).
+ * @param displayColorTemperatures
+ * The display color temperatures used to map the ambient color temperature to the display
+ * color temperature (or null if no mapping is necessary).
*
* @throws NullPointerException
* - brightnessSensor is null;
@@ -114,7 +120,7 @@ public class DisplayWhiteBalanceController implements
@NonNull AmbientFilter colorTemperatureFilter,
@NonNull DisplayWhiteBalanceThrottler throttler,
float lowLightAmbientBrightnessThreshold, float lowLightAmbientColorTemperature,
- float[] ambientTemperatures, float[] displayTemperatures) {
+ float[] ambientColorTemperatures, float[] displayColorTemperatures) {
validateArguments(brightnessSensor, brightnessFilter, colorTemperatureSensor,
colorTemperatureFilter, throttler);
mLoggingEnabled = false;
@@ -134,10 +140,10 @@ public class DisplayWhiteBalanceController implements
mAmbientColorTemperatureOverride = -1.0f;
try {
- mAmbientToDisplayTemperatureSpline = new Spline.LinearSpline(ambientTemperatures,
- displayTemperatures);
+ mAmbientToDisplayColorTemperatureSpline = new Spline.LinearSpline(
+ ambientColorTemperatures, displayColorTemperatures);
} catch (Exception e) {
- mAmbientToDisplayTemperatureSpline = null;
+ mAmbientToDisplayColorTemperatureSpline = null;
}
mColorDisplayServiceInternal = LocalServices.getService(ColorDisplayServiceInternal.class);
@@ -160,7 +166,7 @@ public class DisplayWhiteBalanceController implements
}
/**
- * Set an object to call back to when the screen color temperature should be updated.
+ * Set an object to call back to when the display color temperature should be updated.
*
* @param callbacks
* The object to call back to.
@@ -201,7 +207,7 @@ public class DisplayWhiteBalanceController implements
*
* This is only applied when the ambient color temperature changes or is updated (in which case
* it overrides the ambient color temperature estimate); in other words, it doesn't necessarily
- * change the screen color temperature immediately.
+ * change the display color temperature immediately.
*
* @param ambientColorTemperatureOverride
* The ambient color temperature override.
@@ -240,9 +246,8 @@ public class DisplayWhiteBalanceController implements
writer.println(" mLastAmbientColorTemperature=" + mLastAmbientColorTemperature);
writer.println(" mAmbientColorTemperatureHistory=" + mAmbientColorTemperatureHistory);
writer.println(" mAmbientColorTemperatureOverride=" + mAmbientColorTemperatureOverride);
- writer.println(" mAmbientToDisplayTemperatureSpline="
- + (mAmbientToDisplayTemperatureSpline == null ? "unused" :
- mAmbientToDisplayTemperatureSpline));
+ writer.println(" mAmbientToDisplayColorTemperatureSpline="
+ + mAmbientToDisplayColorTemperatureSpline);
}
@Override // AmbientSensor.AmbientBrightnessSensor.Callbacks
@@ -266,9 +271,9 @@ public class DisplayWhiteBalanceController implements
final long time = System.currentTimeMillis();
float ambientColorTemperature = mColorTemperatureFilter.getEstimate(time);
- if (mAmbientToDisplayTemperatureSpline != null) {
+ if (mAmbientToDisplayColorTemperatureSpline != null) {
ambientColorTemperature =
- mAmbientToDisplayTemperatureSpline.interpolate(ambientColorTemperature);
+ mAmbientToDisplayColorTemperatureSpline.interpolate(ambientColorTemperature);
}
final float ambientBrightness = mBrightnessFilter.getEstimate(time);
@@ -290,7 +295,7 @@ public class DisplayWhiteBalanceController implements
ambientColorTemperature = mAmbientColorTemperatureOverride;
}
- // When the screen color temperature needs to be updated, we call DisplayPowerController to
+ // When the display color temperature needs to be updated, we call DisplayPowerController to
// call our updateColorTemperature. The reason we don't call it directly is that we want
// all changes to the system to happen in a predictable order in DPC's main loop
// (updatePowerState).
@@ -308,9 +313,9 @@ public class DisplayWhiteBalanceController implements
}
/**
- * Updates the screen color temperature.
+ * Updates the display color temperature.
*/
- public void updateScreenColorTemperature() {
+ public void updateDisplayColorTemperature() {
float ambientColorTemperature = -1.0f;
// If both the pending and the current ambient color temperatures are -1, it means the DWBC
@@ -353,7 +358,7 @@ public class DisplayWhiteBalanceController implements
* Called whenever the display white-balance state has changed.
*
* Usually, this means the estimated ambient color temperature has changed enough, and the
- * screen color temperature should be updated; but it is also called by
+ * display color temperature should be updated; but it is also called if settings change.
*/
void updateWhiteBalance();
}
diff --git a/services/core/java/com/android/server/display/whitebalance/DisplayWhiteBalanceFactory.java b/services/core/java/com/android/server/display/whitebalance/DisplayWhiteBalanceFactory.java
index 56f4ca339eb3..449f115ad3e3 100644
--- a/services/core/java/com/android/server/display/whitebalance/DisplayWhiteBalanceFactory.java
+++ b/services/core/java/com/android/server/display/whitebalance/DisplayWhiteBalanceFactory.java
@@ -67,14 +67,14 @@ public class DisplayWhiteBalanceFactory {
final float lowLightAmbientColorTemperature = getFloat(resources,
com.android.internal.R.dimen
.config_displayWhiteBalanceLowLightAmbientColorTemperature);
- final float[] ambientTemperatures = getFloatArray(resources,
- com.android.internal.R.array.config_displayWhiteBalanceAmbientTemperatureValues);
- final float[] displayTemperatures = getFloatArray(resources,
- com.android.internal.R.array.config_displayWhiteBalanceDisplayTemperatureValues);
+ final float[] ambientColorTemperatures = getFloatArray(resources,
+ com.android.internal.R.array.config_displayWhiteBalanceAmbientColorTemperatures);
+ final float[] displayColorTempeartures = getFloatArray(resources,
+ com.android.internal.R.array.config_displayWhiteBalanceDisplayColorTemperatures);
final DisplayWhiteBalanceController controller = new DisplayWhiteBalanceController(
brightnessSensor, brightnessFilter, colorTemperatureSensor, colorTemperatureFilter,
throttler, lowLightAmbientBrightnessThreshold, lowLightAmbientColorTemperature,
- ambientTemperatures, displayTemperatures);
+ ambientColorTemperatures, displayColorTempeartures);
brightnessSensor.setCallbacks(controller);
colorTemperatureSensor.setCallbacks(controller);
return controller;
diff --git a/services/core/java/com/android/server/display/whitebalance/DisplayWhiteBalanceThrottler.java b/services/core/java/com/android/server/display/whitebalance/DisplayWhiteBalanceThrottler.java
index c1f0e983a366..5941bbb62d94 100644
--- a/services/core/java/com/android/server/display/whitebalance/DisplayWhiteBalanceThrottler.java
+++ b/services/core/java/com/android/server/display/whitebalance/DisplayWhiteBalanceThrottler.java
@@ -23,7 +23,7 @@ import java.util.Arrays;
/**
* The DisplayWhiteBalanceController uses the DisplayWhiteBalanceThrottler to decide whether the
- * screen color temperature should be updated, suppressing changes that are too frequent or too
+ * display color temperature should be updated, suppressing changes that are too frequent or too
* minor.
*/
class DisplayWhiteBalanceThrottler {
diff --git a/services/core/java/com/android/server/location/GnssLocationProvider.java b/services/core/java/com/android/server/location/GnssLocationProvider.java
index e71b156c3e86..243b6fe7a30e 100644
--- a/services/core/java/com/android/server/location/GnssLocationProvider.java
+++ b/services/core/java/com/android/server/location/GnssLocationProvider.java
@@ -373,6 +373,7 @@ public class GnssLocationProvider extends AbstractLocationProvider implements
private final NtpTimeHelper mNtpTimeHelper;
private final GnssBatchingProvider mGnssBatchingProvider;
private final GnssGeofenceProvider mGnssGeofenceProvider;
+ // Available only on GNSS HAL 2.0 implementations and later.
private GnssVisibilityControl mGnssVisibilityControl;
// Handler for processing events
@@ -463,8 +464,8 @@ public class GnssLocationProvider extends AbstractLocationProvider implements
}
};
- // TODO(b/119326010): replace OnSubscriptionsChangedListener with
- // ACTION_DEFAULT_DATA_SUBSCRIPTION_CHANGED broadcast reseiver.
+ // TODO: replace OnSubscriptionsChangedListener with ACTION_DEFAULT_DATA_SUBSCRIPTION_CHANGED
+ // broadcast receiver.
private final OnSubscriptionsChangedListener mOnSubscriptionsChangedListener =
new OnSubscriptionsChangedListener() {
@Override
@@ -676,8 +677,7 @@ public class GnssLocationProvider extends AbstractLocationProvider implements
mNtpTimeHelper.onNetworkAvailable();
if (mDownloadXtraDataPending == STATE_PENDING_NETWORK) {
if (mSupportsXtra) {
- // Download only if supported, (prevents an unneccesary on-boot
- // download)
+ // Download only if supported, (prevents an unnecessary on-boot download)
xtraDownloadRequest();
}
}
@@ -764,7 +764,7 @@ public class GnssLocationProvider extends AbstractLocationProvider implements
/** Returns true if the location request is too frequent. */
private boolean isRequestLocationRateLimited() {
- // TODO(b/73198123): implement exponential backoff.
+ // TODO: implement exponential backoff.
return false;
}
diff --git a/services/core/java/com/android/server/location/GnssVisibilityControl.java b/services/core/java/com/android/server/location/GnssVisibilityControl.java
index c3f25bfa2e5e..20f872a213fd 100644
--- a/services/core/java/com/android/server/location/GnssVisibilityControl.java
+++ b/services/core/java/com/android/server/location/GnssVisibilityControl.java
@@ -24,10 +24,13 @@ import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageManager;
+import android.database.ContentObserver;
+import android.location.LocationManager;
import android.os.Handler;
import android.os.Looper;
import android.os.PowerManager;
import android.os.UserHandle;
+import android.provider.Settings;
import android.text.TextUtils;
import android.util.Log;
import android.util.StatsLog;
@@ -70,7 +73,7 @@ class GnssVisibilityControl {
private final Handler mHandler;
private final Context mContext;
- private boolean mIsMasterLocationSettingsEnabled = true;
+ private boolean mIsDeviceLocationSettingsEnabled;
// Number of non-framework location access proxy apps is expected to be small (< 5).
private static final int HASH_MAP_INITIAL_CAPACITY_PROXY_APP_TO_LOCATION_PERMISSIONS = 7;
@@ -88,13 +91,9 @@ class GnssVisibilityControl {
mAppOps = mContext.getSystemService(AppOpsManager.class);
mPackageManager = mContext.getPackageManager();
- // Set to empty proxy app list initially until the configuration properties are loaded.
- updateNfwLocationAccessProxyAppsInGnssHal();
-
- // Listen for proxy app package installation, removal events.
- listenForProxyAppsPackageUpdates();
-
- // TODO(b/122855984): Handle global location settings on/off.
+ // Complete initialization as the first event to run in mHandler thread. After that,
+ // all object state read/update events run in the mHandler thread.
+ runOnHandler(this::handleInitialize);
}
void updateProxyApps(List<String> nfwLocationAccessProxyApps) {
@@ -105,10 +104,6 @@ class GnssVisibilityControl {
runOnHandler(() -> handleUpdateProxyApps(nfwLocationAccessProxyApps));
}
- void masterLocationSettingsUpdated(boolean enabled) {
- runOnHandler(() -> handleMasterLocationSettingsUpdated(enabled));
- }
-
void reportNfwNotification(String proxyAppPackageName, byte protocolStack,
String otherProtocolStackName, byte requestor, String requestorId, byte responseType,
boolean inEmergencyMode, boolean isCachedLocation) {
@@ -117,7 +112,19 @@ class GnssVisibilityControl {
requestor, requestorId, responseType, inEmergencyMode, isCachedLocation)));
}
+ private void handleInitialize() {
+ disableNfwLocationAccess(); // Disable until config properties are loaded.
+ listenForProxyAppsPackageUpdates();
+ listenForDeviceLocationSettingsUpdate();
+ mIsDeviceLocationSettingsEnabled = getDeviceLocationSettings();
+ }
+
+ private boolean getDeviceLocationSettings() {
+ return mContext.getSystemService(LocationManager.class).isLocationEnabled();
+ }
+
private void listenForProxyAppsPackageUpdates() {
+ // Listen for proxy apps package installation, removal events.
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(Intent.ACTION_PACKAGE_ADDED);
intentFilter.addAction(Intent.ACTION_PACKAGE_REMOVED);
@@ -143,11 +150,22 @@ class GnssVisibilityControl {
}, UserHandle.ALL, intentFilter, null, mHandler);
}
+ private void listenForDeviceLocationSettingsUpdate() {
+ mContext.getContentResolver().registerContentObserver(
+ Settings.Secure.getUriFor(Settings.Secure.LOCATION_MODE),
+ true,
+ new ContentObserver(mHandler) {
+ @Override
+ public void onChange(boolean selfChange) {
+ handleDeviceLocationSettingsUpdated();
+ }
+ }, UserHandle.USER_ALL);
+ }
+
private void handleProxyAppPackageUpdate(String pkgName, String action) {
final Boolean locationPermission = mProxyAppToLocationPermissions.get(pkgName);
- // pkgName is not one of the proxy apps in our list.
if (locationPermission == null) {
- return;
+ return; // ignore, pkgName is not one of the proxy apps in our list.
}
Log.i(TAG, "Proxy app " + pkgName + " package changed: " + action);
@@ -197,15 +215,33 @@ class GnssVisibilityControl {
return true;
}
}
-
return false;
}
- private void handleMasterLocationSettingsUpdated(boolean enabled) {
- mIsMasterLocationSettingsEnabled = enabled;
- Log.i(TAG, "Master location settings switch changed to "
- + (enabled ? "enabled" : "disabled"));
- updateNfwLocationAccessProxyAppsInGnssHal();
+ private void handleDeviceLocationSettingsUpdated() {
+ final boolean enabled = getDeviceLocationSettings();
+ Log.i(TAG, "Device location settings enabled: " + enabled);
+
+ if (mIsDeviceLocationSettingsEnabled == enabled) {
+ return;
+ }
+
+ mIsDeviceLocationSettingsEnabled = enabled;
+ if (!mIsDeviceLocationSettingsEnabled) {
+ disableNfwLocationAccess();
+ return;
+ }
+
+ // When device location settings was disabled, we already set the proxy app list
+ // to empty in GNSS HAL. Update only if the proxy app list is not empty.
+ String[] locationPermissionEnabledProxyApps = getLocationPermissionEnabledProxyApps();
+ if (locationPermissionEnabledProxyApps.length != 0) {
+ setNfwLocationAccessProxyAppsInGnssHal(locationPermissionEnabledProxyApps);
+ }
+ }
+
+ private void disableNfwLocationAccess() {
+ setNfwLocationAccessProxyAppsInGnssHal(NO_LOCATION_ENABLED_PROXY_APPS);
}
// Represents NfwNotification structure in IGnssVisibilityControlCallback.hal
@@ -316,8 +352,7 @@ class GnssVisibilityControl {
return mPackageManager.getApplicationInfo(pkgName, 0).uid;
} catch (PackageManager.NameNotFoundException e) {
if (DEBUG) {
- Log.d(TAG, "Non-framework location access proxy app "
- + pkgName + " is not found.");
+ Log.d(TAG, "Non-framework location access proxy app " + pkgName + " is not found.");
}
return null;
}
@@ -329,8 +364,14 @@ class GnssVisibilityControl {
}
private void updateNfwLocationAccessProxyAppsInGnssHal() {
- final String[] locationPermissionEnabledProxyApps = shouldDisableNfwLocationAccess()
- ? NO_LOCATION_ENABLED_PROXY_APPS : getLocationPermissionEnabledProxyApps();
+ if (!mIsDeviceLocationSettingsEnabled) {
+ return; // Keep non-framework location access disabled.
+ }
+ setNfwLocationAccessProxyAppsInGnssHal(getLocationPermissionEnabledProxyApps());
+ }
+
+ private void setNfwLocationAccessProxyAppsInGnssHal(
+ String[] locationPermissionEnabledProxyApps) {
final String proxyAppsStr = Arrays.toString(locationPermissionEnabledProxyApps);
Log.i(TAG, "Updating non-framework location access proxy apps in the GNSS HAL to: "
+ proxyAppsStr);
@@ -341,12 +382,8 @@ class GnssVisibilityControl {
}
}
- private boolean shouldDisableNfwLocationAccess() {
- return !mIsMasterLocationSettingsEnabled;
- }
-
private String[] getLocationPermissionEnabledProxyApps() {
- // Get a count of proxy apps with location permission enabled to array creation size.
+ // Get a count of proxy apps with location permission enabled for array creation size.
int countLocationPermissionEnabledProxyApps = 0;
for (Boolean hasLocationPermissionEnabled : mProxyAppToLocationPermissions.values()) {
if (hasLocationPermissionEnabled) {
diff --git a/services/core/java/com/android/server/om/OverlayManagerService.java b/services/core/java/com/android/server/om/OverlayManagerService.java
index e479a1539e25..d0c59c1b002e 100644
--- a/services/core/java/com/android/server/om/OverlayManagerService.java
+++ b/services/core/java/com/android/server/om/OverlayManagerService.java
@@ -320,6 +320,11 @@ public final class OverlayManagerService extends SystemService {
private final class PackageReceiver extends BroadcastReceiver {
@Override
public void onReceive(@NonNull final Context context, @NonNull final Intent intent) {
+ final String action = intent.getAction();
+ if (action == null) {
+ Slog.e(TAG, "Cannot handle package broadcast with null action");
+ return;
+ }
final Uri data = intent.getData();
if (data == null) {
Slog.e(TAG, "Cannot handle package broadcast with null data");
@@ -337,7 +342,7 @@ public final class OverlayManagerService extends SystemService {
userIds = new int[] { UserHandle.getUserId(extraUid) };
}
- switch (intent.getAction()) {
+ switch (action) {
case ACTION_PACKAGE_ADDED:
if (replacing) {
onPackageUpgraded(packageName, userIds);
diff --git a/services/core/java/com/android/server/pm/OWNERS b/services/core/java/com/android/server/pm/OWNERS
index 33b8641c145e..640b155e69d5 100644
--- a/services/core/java/com/android/server/pm/OWNERS
+++ b/services/core/java/com/android/server/pm/OWNERS
@@ -19,6 +19,9 @@ per-file BackgroundDexOptService.java = ngeoffray@google.com
per-file CompilerStats.java = agampe@google.com
per-file CompilerStats.java = calin@google.com
per-file CompilerStats.java = ngeoffray@google.com
+per-file DynamicCodeLoggingService.java = agampe@google.com
+per-file DynamicCodeLoggingService.java = calin@google.com
+per-file DynamicCodeLoggingService.java = ngeoffray@google.com
per-file InstructionSets.java = agampe@google.com
per-file InstructionSets.java = calin@google.com
per-file InstructionSets.java = ngeoffray@google.com
diff --git a/services/core/java/com/android/server/pm/PackageInstallerService.java b/services/core/java/com/android/server/pm/PackageInstallerService.java
index 86083494f3d6..f5d88e3cf56f 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerService.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerService.java
@@ -84,7 +84,7 @@ import com.android.internal.util.ImageUtils;
import com.android.internal.util.IndentingPrintWriter;
import com.android.server.IoThread;
import com.android.server.LocalServices;
-import com.android.server.pm.permission.PermissionManagerInternal;
+import com.android.server.pm.permission.PermissionManagerServiceInternal;
import libcore.io.IoUtils;
@@ -131,7 +131,7 @@ public class PackageInstallerService extends IPackageInstaller.Stub implements
private final Context mContext;
private final PackageManagerService mPm;
private final StagingManager mStagingManager;
- private final PermissionManagerInternal mPermissionManager;
+ private final PermissionManagerServiceInternal mPermissionManager;
private AppOpsManager mAppOps;
@@ -189,7 +189,7 @@ public class PackageInstallerService extends IPackageInstaller.Stub implements
public PackageInstallerService(Context context, PackageManagerService pm, ApexManager am) {
mContext = context;
mPm = pm;
- mPermissionManager = LocalServices.getService(PermissionManagerInternal.class);
+ mPermissionManager = LocalServices.getService(PermissionManagerServiceInternal.class);
mInstallThread = new HandlerThread(TAG);
mInstallThread.start();
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 61a1a2f81101..b1c186e9e9f8 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -238,7 +238,6 @@ import android.os.storage.StorageManager;
import android.os.storage.StorageManagerInternal;
import android.os.storage.VolumeInfo;
import android.os.storage.VolumeRecord;
-import android.permission.PermissionControllerManager;
import android.provider.DeviceConfig;
import android.provider.MediaStore;
import android.provider.Settings.Global;
@@ -291,7 +290,6 @@ import com.android.internal.util.DumpUtils;
import com.android.internal.util.FastXmlSerializer;
import com.android.internal.util.IndentingPrintWriter;
import com.android.internal.util.Preconditions;
-import com.android.internal.util.XmlUtils;
import com.android.server.AttributeCache;
import com.android.server.DeviceIdleController;
import com.android.server.EventLogTags;
@@ -315,9 +313,9 @@ import com.android.server.pm.dex.ViewCompiler;
import com.android.server.pm.permission.BasePermission;
import com.android.server.pm.permission.DefaultPermissionGrantPolicy;
import com.android.server.pm.permission.DefaultPermissionGrantPolicy.DefaultPermissionGrantedCallback;
-import com.android.server.pm.permission.PermissionManagerInternal;
-import com.android.server.pm.permission.PermissionManagerInternal.PermissionCallback;
import com.android.server.pm.permission.PermissionManagerService;
+import com.android.server.pm.permission.PermissionManagerServiceInternal;
+import com.android.server.pm.permission.PermissionManagerServiceInternal.PermissionCallback;
import com.android.server.pm.permission.PermissionsState;
import com.android.server.security.VerityUtils;
import com.android.server.storage.DeviceStorageMonitorInternal;
@@ -371,7 +369,6 @@ import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
-import java.util.concurrent.atomic.AtomicReference;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
import java.util.function.Predicate;
@@ -445,8 +442,6 @@ public class PackageManagerService extends IPackageManager.Stub
private static final boolean ENABLE_FREE_CACHE_V2 =
SystemProperties.getBoolean("fw.free_cache_v2", true);
- private static final long BACKUP_TIMEOUT_MILLIS = TimeUnit.SECONDS.toMillis(60);
-
private static final String PRECOMPILE_LAYOUTS = "pm.precompile_layouts";
private static final int RADIO_UID = Process.PHONE_UID;
@@ -940,7 +935,7 @@ public class PackageManagerService extends IPackageManager.Stub
// TODO remove this and go through mPermissonManager directly
final DefaultPermissionGrantPolicy mDefaultPermissionPolicy;
- private final PermissionManagerInternal mPermissionManager;
+ private final PermissionManagerServiceInternal mPermissionManager;
private final ComponentResolver mComponentResolver;
// List of packages names to keep cached, even if they are uninstalled for all users
@@ -1940,9 +1935,10 @@ public class PackageManagerService extends IPackageManager.Stub
}
}
- // We may also need to apply pending (restored) runtime
- // permission grants within these users.
- mSettings.applyPendingPermissionGrantsLPw(packageName, userId);
+ // We may also need to apply pending (restored) runtime permission grants
+ // within these users.
+ mPermissionManager.restoreDelayedRuntimePermissions(packageName,
+ UserHandle.of(userId));
// Persistent preferred activity might have came into effect due to this
// install.
@@ -18825,7 +18821,7 @@ public class PackageManagerService extends IPackageManager.Stub
// permission as requiring a review as this is the initial state.
int flags = 0;
if (ps.pkg.applicationInfo.targetSdkVersion < Build.VERSION_CODES.M && bp.isRuntime()) {
- flags |= FLAG_PERMISSION_REVIEW_REQUIRED;
+ flags |= FLAG_PERMISSION_REVIEW_REQUIRED | FLAG_PERMISSION_REVOKE_ON_UPGRADE;
}
if (permissionsState.updatePermissionFlags(bp, userId, userSettableMask, flags)) {
if (hasInstallState) {
@@ -19665,139 +19661,6 @@ public class PackageManagerService extends IPackageManager.Stub
}
@Override
- public byte[] getPermissionGrantBackup(int userId) {
- if (Binder.getCallingUid() != Process.SYSTEM_UID) {
- throw new SecurityException("Only the system may call getPermissionGrantBackup()");
- }
-
- AtomicReference<byte[]> backup = new AtomicReference<>();
- mContext.getSystemService(PermissionControllerManager.class).getRuntimePermissionBackup(
- UserHandle.of(userId), mContext.getMainExecutor(), (b) -> {
- synchronized (backup) {
- backup.set(b);
- backup.notifyAll();
- }
- });
-
- long start = System.currentTimeMillis();
- synchronized (backup) {
- while (backup.get() == null) {
- long timeLeft = start + BACKUP_TIMEOUT_MILLIS - System.currentTimeMillis();
- if (timeLeft <= 0) {
- return null;
- }
-
- try {
- backup.wait(timeLeft);
- } catch (InterruptedException ignored) {
- return null;
- }
- }
- }
-
- return backup.get();
- }
-
- @Override
- public void restorePermissionGrants(byte[] backup, int userId) {
- if (Binder.getCallingUid() != Process.SYSTEM_UID) {
- throw new SecurityException("Only the system may call restorePermissionGrants()");
- }
-
- try {
- final XmlPullParser parser = Xml.newPullParser();
- parser.setInput(new ByteArrayInputStream(backup), StandardCharsets.UTF_8.name());
- restoreFromXml(parser, userId, TAG_PERMISSION_BACKUP,
- (parser1, userId1) -> {
- synchronized (mPackages) {
- processRestoredPermissionGrantsLPr(parser1, userId1);
- }
- });
- } catch (Exception e) {
- if (DEBUG_BACKUP) {
- Slog.e(TAG, "Exception restoring preferred activities: " + e.getMessage());
- }
- }
- }
-
- @GuardedBy("mPackages")
- private void processRestoredPermissionGrantsLPr(XmlPullParser parser, int userId)
- throws XmlPullParserException, IOException {
- String pkgName = null;
- int outerDepth = parser.getDepth();
- int type;
- while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
- && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
- if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
- continue;
- }
-
- final String tagName = parser.getName();
- if (tagName.equals(TAG_GRANT)) {
- pkgName = parser.getAttributeValue(null, ATTR_PACKAGE_NAME);
- if (DEBUG_BACKUP) {
- Slog.v(TAG, "+++ Restoring grants for package " + pkgName);
- }
- } else if (tagName.equals(TAG_PERMISSION)) {
-
- final boolean isGranted = "true".equals(parser.getAttributeValue(null, ATTR_IS_GRANTED));
- final String permName = parser.getAttributeValue(null, ATTR_PERMISSION_NAME);
-
- int newFlagSet = 0;
- if ("true".equals(parser.getAttributeValue(null, ATTR_USER_SET))) {
- newFlagSet |= FLAG_PERMISSION_USER_SET;
- }
- if ("true".equals(parser.getAttributeValue(null, ATTR_USER_FIXED))) {
- newFlagSet |= FLAG_PERMISSION_USER_FIXED;
- }
- if ("true".equals(parser.getAttributeValue(null, ATTR_REVOKE_ON_UPGRADE))) {
- newFlagSet |= FLAG_PERMISSION_REVOKE_ON_UPGRADE;
- }
- if (DEBUG_BACKUP) {
- Slog.v(TAG, " + Restoring grant:"
- + " pkg=" + pkgName
- + " perm=" + permName
- + " granted=" + isGranted
- + " bits=0x" + Integer.toHexString(newFlagSet));
- }
- final PackageSetting ps = mSettings.mPackages.get(pkgName);
- if (ps != null) {
- // Already installed so we apply the grant immediately
- if (DEBUG_BACKUP) {
- Slog.v(TAG, " + already installed; applying");
- }
- PermissionsState perms = ps.getPermissionsState();
- BasePermission bp =
- (BasePermission) mPermissionManager.getPermissionTEMP(permName);
- if (bp != null) {
- if (isGranted) {
- perms.grantRuntimePermission(bp, userId);
- }
- if (newFlagSet != 0) {
- perms.updatePermissionFlags(
- bp, userId, USER_RUNTIME_GRANT_MASK, newFlagSet);
- }
- }
- } else {
- // Need to wait for post-restore install to apply the grant
- if (DEBUG_BACKUP) {
- Slog.v(TAG, " - not yet installed; saving for later");
- }
- mSettings.processRestoredPermissionGrantLPr(pkgName, permName,
- isGranted, newFlagSet, userId);
- }
- } else {
- PackageManagerService.reportSettingsProblem(Log.WARN,
- "Unknown element under <" + TAG_PERMISSION_BACKUP + ">: " + tagName);
- XmlUtils.skipCurrentTag(parser);
- }
- }
-
- scheduleWriteSettingsLocked();
- mSettings.writeRuntimePermissionsForUserLPr(userId, false);
- }
-
- @Override
public void addCrossProfileIntentFilter(IntentFilter intentFilter, String ownerPackage,
int sourceUserId, int targetUserId, int flags) {
mContext.enforceCallingOrSelfPermission(
@@ -21285,10 +21148,6 @@ public class PackageManagerService extends IPackageManager.Stub
}
}
- if (!checkin && dumpState.isDumping(DumpState.DUMP_PERMISSIONS) && packageName == null) {
- mSettings.dumpRestoredPermissionGrantsLPr(pw, dumpState);
- }
-
if (!checkin && dumpState.isDumping(DumpState.DUMP_FROZEN) && packageName == null) {
// XXX should handle packageName != null by dumping only install data that
// the given package is involved with.
diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java
index 975ffb25a784..92fe377e9495 100644
--- a/services/core/java/com/android/server/pm/Settings.java
+++ b/services/core/java/com/android/server/pm/Settings.java
@@ -19,10 +19,6 @@ package com.android.server.pm;
import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DEFAULT;
import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DISABLED;
import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_ENABLED;
-import static android.content.pm.PackageManager.FLAG_PERMISSION_REVOKE_ON_UPGRADE;
-import static android.content.pm.PackageManager.FLAG_PERMISSION_REVOKE_WHEN_REQUESTED;
-import static android.content.pm.PackageManager.FLAG_PERMISSION_USER_FIXED;
-import static android.content.pm.PackageManager.FLAG_PERMISSION_USER_SET;
import static android.content.pm.PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
import static android.content.pm.PackageManager.INSTALL_FAILED_SHARED_USER_INCOMPATIBLE;
import static android.content.pm.PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS;
@@ -249,23 +245,6 @@ public final class Settings {
private static final String ATTR_SDK_VERSION = "sdkVersion";
private static final String ATTR_DATABASE_VERSION = "databaseVersion";
- // Bookkeeping for restored permission grants
- private static final String TAG_RESTORED_RUNTIME_PERMISSIONS = "restored-perms";
- // package name: ATTR_PACKAGE_NAME
- private static final String TAG_PERMISSION_ENTRY = "perm";
- // permission name: ATTR_NAME
- // permission granted (boolean): ATTR_GRANTED
- private static final String ATTR_USER_SET = "set";
- private static final String ATTR_USER_FIXED = "fixed";
- private static final String ATTR_REVOKE_ON_UPGRADE = "rou";
- private static final String ATTR_REVOKE_WHEN_REQUESTED = "rwr";
-
- // Flag mask of restored permission grants that are applied at install time
- private static final int USER_RUNTIME_GRANT_MASK =
- FLAG_PERMISSION_USER_SET
- | FLAG_PERMISSION_USER_FIXED
- | FLAG_PERMISSION_REVOKE_ON_UPGRADE;
-
private final Object mLock;
private final RuntimePermissionPersistence mRuntimePermissionsPersistence;
@@ -303,26 +282,6 @@ public final class Settings {
int[] excludedUserIds;
}
- // Bookkeeping for restored user permission grants
- final class RestoredPermissionGrant {
- String permissionName;
- boolean granted;
- int grantBits;
-
- RestoredPermissionGrant(String name, boolean isGranted, int theGrantBits) {
- permissionName = name;
- granted = isGranted;
- grantBits = theGrantBits;
- }
- }
-
- // This would be more compact as a flat array of restored grants or something, but we
- // may have quite a few, especially during early device lifetime, and avoiding all those
- // linear lookups will be important.
- private final SparseArray<ArrayMap<String, ArraySet<RestoredPermissionGrant>>>
- mRestoredUserGrants =
- new SparseArray<ArrayMap<String, ArraySet<RestoredPermissionGrant>>>();
-
private static int mFirstAvailableUid = 0;
/** Map from volume UUID to {@link VersionInfo} */
@@ -461,43 +420,6 @@ public final class Settings {
return mRenamedPackages.put(pkgName, origPkgName);
}
- void applyPendingPermissionGrantsLPw(String packageName, int userId) {
- ArrayMap<String, ArraySet<RestoredPermissionGrant>> grantsByPackage =
- mRestoredUserGrants.get(userId);
- if (grantsByPackage == null || grantsByPackage.size() == 0) {
- return;
- }
-
- ArraySet<RestoredPermissionGrant> grants = grantsByPackage.get(packageName);
- if (grants == null || grants.size() == 0) {
- return;
- }
-
- final PackageSetting ps = mPackages.get(packageName);
- if (ps == null) {
- Slog.e(TAG, "Can't find supposedly installed package " + packageName);
- return;
- }
- final PermissionsState perms = ps.getPermissionsState();
-
- for (RestoredPermissionGrant grant : grants) {
- BasePermission bp = mPermissions.getPermission(grant.permissionName);
- if (bp != null) {
- if (grant.granted) {
- perms.grantRuntimePermission(bp, userId);
- }
- perms.updatePermissionFlags(bp, userId, USER_RUNTIME_GRANT_MASK, grant.grantBits);
- }
- }
-
- // And remove it from the pending-grant bookkeeping
- grantsByPackage.remove(packageName);
- if (grantsByPackage.size() < 1) {
- mRestoredUserGrants.remove(userId);
- }
- writeRuntimePermissionsForUserLPr(userId, false);
- }
-
public boolean canPropagatePermissionToInstantApp(String permName) {
return mPermissions.canPropagatePermissionToInstantApp(permName);
}
@@ -1982,13 +1904,6 @@ public final class Settings {
}
}
- // Specifically for backup/restore
- public void processRestoredPermissionGrantLPr(String pkgName, String permission,
- boolean isGranted, int restoredFlagSet, int userId) {
- mRuntimePermissionsPersistence.rememberRestoredUserGrantLPr(
- pkgName, permission, isGranted, restoredFlagSet, userId);
- }
-
void writeDefaultAppsLPr(XmlSerializer serializer, int userId)
throws IllegalArgumentException, IllegalStateException, IOException {
serializer.startTag(null, TAG_DEFAULT_APPS);
@@ -5014,51 +4929,6 @@ public final class Settings {
pw.print(mReadMessages.toString());
}
- void dumpRestoredPermissionGrantsLPr(PrintWriter pw, DumpState dumpState) {
- if (mRestoredUserGrants.size() > 0) {
- pw.println();
- pw.println("Restored (pending) permission grants:");
- for (int userIndex = 0; userIndex < mRestoredUserGrants.size(); userIndex++) {
- ArrayMap<String, ArraySet<RestoredPermissionGrant>> grantsByPackage =
- mRestoredUserGrants.valueAt(userIndex);
- if (grantsByPackage != null && grantsByPackage.size() > 0) {
- final int userId = mRestoredUserGrants.keyAt(userIndex);
- pw.print(" User "); pw.println(userId);
-
- for (int pkgIndex = 0; pkgIndex < grantsByPackage.size(); pkgIndex++) {
- ArraySet<RestoredPermissionGrant> grants = grantsByPackage.valueAt(pkgIndex);
- if (grants != null && grants.size() > 0) {
- final String pkgName = grantsByPackage.keyAt(pkgIndex);
- pw.print(" "); pw.print(pkgName); pw.println(" :");
-
- for (RestoredPermissionGrant g : grants) {
- pw.print(" ");
- pw.print(g.permissionName);
- if (g.granted) {
- pw.print(" GRANTED");
- }
- if ((g.grantBits&FLAG_PERMISSION_USER_SET) != 0) {
- pw.print(" user_set");
- }
- if ((g.grantBits&FLAG_PERMISSION_USER_FIXED) != 0) {
- pw.print(" user_fixed");
- }
- if ((g.grantBits&FLAG_PERMISSION_REVOKE_ON_UPGRADE) != 0) {
- pw.print(" revoke_on_upgrade");
- }
- if ((g.grantBits & FLAG_PERMISSION_REVOKE_WHEN_REQUESTED) != 0) {
- pw.print(" revoke_when_requested");
- }
- pw.println();
- }
- }
- }
- }
- }
- pw.println();
- }
- }
-
private static void dumpSplitNames(PrintWriter pw, PackageParser.Package pkg) {
if (pkg == null) {
pw.print("unknown");
@@ -5328,55 +5198,6 @@ public final class Settings {
serializer.endTag(null, TAG_RUNTIME_PERMISSIONS);
- // Now any restored permission grants that are waiting for the apps
- // in question to be installed. These are stored as per-package
- // TAG_RESTORED_RUNTIME_PERMISSIONS blocks, each containing some
- // number of individual permission grant entities.
- if (mRestoredUserGrants.get(userId) != null) {
- ArrayMap<String, ArraySet<RestoredPermissionGrant>> restoredGrants =
- mRestoredUserGrants.get(userId);
- if (restoredGrants != null) {
- final int pkgCount = restoredGrants.size();
- for (int i = 0; i < pkgCount; i++) {
- final ArraySet<RestoredPermissionGrant> pkgGrants =
- restoredGrants.valueAt(i);
- if (pkgGrants != null && pkgGrants.size() > 0) {
- final String pkgName = restoredGrants.keyAt(i);
- serializer.startTag(null, TAG_RESTORED_RUNTIME_PERMISSIONS);
- serializer.attribute(null, ATTR_PACKAGE_NAME, pkgName);
-
- final int N = pkgGrants.size();
- for (int z = 0; z < N; z++) {
- RestoredPermissionGrant g = pkgGrants.valueAt(z);
- serializer.startTag(null, TAG_PERMISSION_ENTRY);
- serializer.attribute(null, ATTR_NAME, g.permissionName);
-
- if (g.granted) {
- serializer.attribute(null, ATTR_GRANTED, "true");
- }
-
- if ((g.grantBits&FLAG_PERMISSION_USER_SET) != 0) {
- serializer.attribute(null, ATTR_USER_SET, "true");
- }
- if ((g.grantBits&FLAG_PERMISSION_USER_FIXED) != 0) {
- serializer.attribute(null, ATTR_USER_FIXED, "true");
- }
- if ((g.grantBits&FLAG_PERMISSION_REVOKE_ON_UPGRADE) != 0) {
- serializer.attribute(null, ATTR_REVOKE_ON_UPGRADE, "true");
- }
- if ((g.grantBits & FLAG_PERMISSION_REVOKE_WHEN_REQUESTED)
- != 0) {
- serializer.attribute(null, ATTR_REVOKE_WHEN_REQUESTED,
- "true");
- }
- serializer.endTag(null, TAG_PERMISSION_ENTRY);
- }
- serializer.endTag(null, TAG_RESTORED_RUNTIME_PERMISSIONS);
- }
- }
- }
- }
-
serializer.endDocument();
destination.finishWrite(out);
@@ -5455,29 +5276,6 @@ public final class Settings {
}
}
- // Backup/restore support
-
- public void rememberRestoredUserGrantLPr(String pkgName, String permission,
- boolean isGranted, int restoredFlagSet, int userId) {
- // This change will be remembered at write-settings time
- ArrayMap<String, ArraySet<RestoredPermissionGrant>> grantsByPackage =
- mRestoredUserGrants.get(userId);
- if (grantsByPackage == null) {
- grantsByPackage = new ArrayMap<String, ArraySet<RestoredPermissionGrant>>();
- mRestoredUserGrants.put(userId, grantsByPackage);
- }
-
- ArraySet<RestoredPermissionGrant> grants = grantsByPackage.get(pkgName);
- if (grants == null) {
- grants = new ArraySet<RestoredPermissionGrant>();
- grantsByPackage.put(pkgName, grants);
- }
-
- RestoredPermissionGrant grant = new RestoredPermissionGrant(permission,
- isGranted, restoredFlagSet);
- grants.add(grant);
- }
-
// Private internals
@GuardedBy("Settings.this.mLock")
@@ -5520,50 +5318,6 @@ public final class Settings {
}
parsePermissionsLPr(parser, sus.getPermissionsState(), userId);
} break;
-
- case TAG_RESTORED_RUNTIME_PERMISSIONS: {
- final String pkgName = parser.getAttributeValue(null, ATTR_PACKAGE_NAME);
- parseRestoredRuntimePermissionsLPr(parser, pkgName, userId);
- } break;
- }
- }
- }
-
- private void parseRestoredRuntimePermissionsLPr(XmlPullParser parser,
- final String pkgName, final int userId) throws IOException, XmlPullParserException {
- final int outerDepth = parser.getDepth();
- int type;
- while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
- && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
- if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
- continue;
- }
-
- switch (parser.getName()) {
- case TAG_PERMISSION_ENTRY: {
- final String permName = parser.getAttributeValue(null, ATTR_NAME);
- final boolean isGranted = "true".equals(
- parser.getAttributeValue(null, ATTR_GRANTED));
-
- int permBits = 0;
- if ("true".equals(parser.getAttributeValue(null, ATTR_USER_SET))) {
- permBits |= FLAG_PERMISSION_USER_SET;
- }
- if ("true".equals(parser.getAttributeValue(null, ATTR_USER_FIXED))) {
- permBits |= FLAG_PERMISSION_USER_FIXED;
- }
- if ("true".equals(parser.getAttributeValue(null, ATTR_REVOKE_ON_UPGRADE))) {
- permBits |= FLAG_PERMISSION_REVOKE_ON_UPGRADE;
- }
- if ("true".equals(parser.getAttributeValue(null,
- ATTR_REVOKE_WHEN_REQUESTED))) {
- permBits |= FLAG_PERMISSION_REVOKE_WHEN_REQUESTED;
- }
-
- if (isGranted || permBits != 0) {
- rememberRestoredUserGrantLPr(pkgName, permName, isGranted, permBits, userId);
- }
- } break;
}
}
}
diff --git a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
index 38940d6241a6..f56b98464cc3 100644
--- a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
+++ b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
@@ -30,6 +30,7 @@ import static android.app.AppOpsManager.permissionToOpCode;
import static android.content.pm.PackageManager.FLAG_PERMISSION_GRANTED_BY_DEFAULT;
import static android.content.pm.PackageManager.FLAG_PERMISSION_POLICY_FIXED;
import static android.content.pm.PackageManager.FLAG_PERMISSION_REVIEW_REQUIRED;
+import static android.content.pm.PackageManager.FLAG_PERMISSION_REVOKE_ON_UPGRADE;
import static android.content.pm.PackageManager.FLAG_PERMISSION_REVOKE_WHEN_REQUESTED;
import static android.content.pm.PackageManager.FLAG_PERMISSION_SYSTEM_FIXED;
import static android.content.pm.PackageManager.FLAG_PERMISSION_USER_FIXED;
@@ -43,6 +44,9 @@ import static com.android.server.pm.PackageManagerService.DEBUG_PACKAGE_SCANNING
import static com.android.server.pm.PackageManagerService.DEBUG_PERMISSIONS;
import static com.android.server.pm.PackageManagerService.DEBUG_REMOVE;
import static com.android.server.pm.PackageManagerService.PLATFORM_PACKAGE_NAME;
+import static com.android.server.pm.permission.PermissionsState.PERMISSION_OPERATION_FAILURE;
+
+import static java.util.concurrent.TimeUnit.SECONDS;
import android.Manifest;
import android.annotation.NonNull;
@@ -69,7 +73,9 @@ import android.os.UserManager;
import android.os.UserManagerInternal;
import android.os.storage.StorageManager;
import android.os.storage.StorageManagerInternal;
+import android.permission.PermissionControllerManager;
import android.permission.PermissionManager;
+import android.permission.PermissionManagerInternal;
import android.text.TextUtils;
import android.util.ArrayMap;
import android.util.ArraySet;
@@ -77,6 +83,7 @@ import android.util.EventLog;
import android.util.Log;
import android.util.Slog;
import android.util.SparseArray;
+import android.util.SparseBooleanArray;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.logging.MetricsLogger;
@@ -91,9 +98,8 @@ import com.android.server.pm.PackageManagerServiceUtils;
import com.android.server.pm.PackageSetting;
import com.android.server.pm.SharedUserSetting;
import com.android.server.pm.UserManagerService;
-import com.android.server.pm.permission.DefaultPermissionGrantPolicy
- .DefaultPermissionGrantedCallback;
-import com.android.server.pm.permission.PermissionManagerInternal.PermissionCallback;
+import com.android.server.pm.permission.DefaultPermissionGrantPolicy.DefaultPermissionGrantedCallback;
+import com.android.server.pm.permission.PermissionManagerServiceInternal.PermissionCallback;
import com.android.server.pm.permission.PermissionsState.PermissionState;
import libcore.util.EmptyArray;
@@ -106,6 +112,10 @@ import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
/**
* Manages all permissions and handles permissions related tasks.
@@ -122,6 +132,8 @@ public class PermissionManagerService {
/** Permission grant: grant as runtime a permission that was granted as an install time one. */
private static final int GRANT_UPGRADE = 4;
+ private static final long BACKUP_TIMEOUT_MILLIS = SECONDS.toMillis(60);
+
/** Cap the size of permission trees that 3rd party apps can define; in characters of text */
private static final int MAX_PERMISSION_TREE_FOOTPRINT = 32768;
/** Empty array to avoid allocations */
@@ -146,6 +158,9 @@ public class PermissionManagerService {
/** Internal connection to the user manager */
private final UserManagerInternal mUserManagerInt;
+ /** Permission controller: User space permission management */
+ private PermissionControllerManager mPermissionControllerManager;
+
/** Default permission policy to provide proper behaviour out-of-the-box */
private final DefaultPermissionGrantPolicy mDefaultPermissionGrantPolicy;
@@ -180,6 +195,16 @@ public class PermissionManagerService {
@GuardedBy("mLock")
private ArrayMap<String, List<String>> mBackgroundPermissions;
+ /**
+ * A permission backup might contain apps that are not installed. In this case we delay the
+ * restoration until the app is installed.
+ *
+ * <p>This array ({@code userId -> noDelayedBackupLeft}) is {@code true} for all the users where
+ * there is <u>no more</u> delayed backup left.
+ */
+ @GuardedBy("mLock")
+ private final SparseBooleanArray mHasNoDelayedPermBackup = new SparseBooleanArray();
+
PermissionManagerService(Context context,
@Nullable DefaultPermissionGrantedCallback defaultGrantCallback,
@NonNull Object externalLock) {
@@ -218,29 +243,31 @@ public class PermissionManagerService {
}
}
- LocalServices.addService(
- PermissionManagerInternal.class, new PermissionManagerInternalImpl());
+ PermissionManagerServiceInternalImpl localService =
+ new PermissionManagerServiceInternalImpl();
+ LocalServices.addService(PermissionManagerServiceInternal.class, localService);
+ LocalServices.addService(PermissionManagerInternal.class, localService);
}
/**
* Creates and returns an initialized, internal service for use by other components.
* <p>
* The object returned is identical to the one returned by the LocalServices class using:
- * {@code LocalServices.getService(PermissionManagerInternal.class);}
+ * {@code LocalServices.getService(PermissionManagerServiceInternal.class);}
* <p>
* NOTE: The external lock is temporary and should be removed. This needs to be a
* lock created by the permission manager itself.
*/
- public static PermissionManagerInternal create(Context context,
+ public static PermissionManagerServiceInternal create(Context context,
@Nullable DefaultPermissionGrantedCallback defaultGrantCallback,
@NonNull Object externalLock) {
- final PermissionManagerInternal permMgrInt =
- LocalServices.getService(PermissionManagerInternal.class);
+ final PermissionManagerServiceInternal permMgrInt =
+ LocalServices.getService(PermissionManagerServiceInternal.class);
if (permMgrInt != null) {
return permMgrInt;
}
new PermissionManagerService(context, defaultGrantCallback, externalLock);
- return LocalServices.getService(PermissionManagerInternal.class);
+ return LocalServices.getService(PermissionManagerServiceInternal.class);
}
@Nullable BasePermission getPermission(String permName) {
@@ -332,6 +359,74 @@ public class PermissionManagerService {
}
/**
+ * Get the state of the runtime permissions as xml file.
+ *
+ * <p>Can not be called on main thread.
+ *
+ * @param user The user the data should be extracted for
+ *
+ * @return The state as a xml file
+ */
+ private @Nullable byte[] backupRuntimePermissions(@NonNull UserHandle user) {
+ CompletableFuture<byte[]> backup = new CompletableFuture<>();
+ mPermissionControllerManager.getRuntimePermissionBackup(user, mContext.getMainExecutor(),
+ backup::complete);
+
+ try {
+ return backup.get(BACKUP_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS);
+ } catch (InterruptedException | ExecutionException | TimeoutException e) {
+ Slog.e(TAG, "Cannot create permission backup for " + user, e);
+ return null;
+ }
+ }
+
+ /**
+ * Restore a permission state previously backed up via {@link #backupRuntimePermissions}.
+ *
+ * <p>If not all state can be restored, the un-appliable state will be delayed and can be
+ * applied via {@link #restoreDelayedRuntimePermissions}.
+ *
+ * @param backup The state as an xml file
+ * @param user The user the data should be restored for
+ */
+ private void restoreRuntimePermissions(@NonNull byte[] backup, @NonNull UserHandle user) {
+ synchronized (mLock) {
+ mHasNoDelayedPermBackup.delete(user.getIdentifier());
+ mPermissionControllerManager.restoreRuntimePermissionBackup(backup, user);
+ }
+ }
+
+ /**
+ * Try to apply permission backup that was previously not applied.
+ *
+ * <p>Can not be called on main thread.
+ *
+ * @param packageName The package that is newly installed
+ * @param user The user the package is installed for
+ *
+ * @see #restoreRuntimePermissions
+ */
+ private void restoreDelayedRuntimePermissions(@NonNull String packageName,
+ @NonNull UserHandle user) {
+ synchronized (mLock) {
+ if (mHasNoDelayedPermBackup.get(user.getIdentifier(), false)) {
+ return;
+ }
+
+ mPermissionControllerManager.restoreDelayedRuntimePermissionBackup(packageName, user,
+ mContext.getMainExecutor(), (hasMoreBackup) -> {
+ if (hasMoreBackup) {
+ return;
+ }
+
+ synchronized (mLock) {
+ mHasNoDelayedPermBackup.put(user.getIdentifier(), true);
+ }
+ });
+ }
+ }
+
+ /**
* Returns {@code true} if the permission can be implied from another granted permission.
* <p>Some permissions, such as ACCESS_FINE_LOCATION, imply other permissions,
* such as ACCESS_COURSE_LOCATION. If the caller holds an umbrella permission, give
@@ -741,7 +836,6 @@ public class PermissionManagerService {
if (ps == null) {
return;
}
- final boolean isLegacySystemApp = mPackageManagerInt.isLegacySystemApp(pkg);
final PermissionsState permissionsState = ps.getPermissionsState();
PermissionsState origPermissions = permissionsState;
@@ -828,17 +922,9 @@ public class PermissionManagerService {
// For all apps normal permissions are install time ones.
grant = GRANT_INSTALL;
} else if (bp.isRuntime()) {
- // If a permission review is required for legacy apps we represent
- // their permissions as always granted runtime ones since we need
- // to keep the review required permission flag per user while an
- // install permission's state is shared across all users.
if (origPermissions.hasInstallPermission(bp.getName())) {
- // For legacy apps that became modern, install becomes runtime.
- grant = GRANT_UPGRADE;
- } else if (isLegacySystemApp) {
- // For legacy system apps, install becomes runtime.
- // We cannot check hasInstallPermission() for system apps since those
- // permissions were granted implicitly and not persisted pre-M.
+ // Before Q we represented some runtime permissions as install permissions,
+ // in Q we cannot do this anymore. Hence upgrade them all.
grant = GRANT_UPGRADE;
} else {
// For modern apps keep runtime permissions unchanged.
@@ -891,110 +977,111 @@ public class PermissionManagerService {
}
// Grant an install permission.
if (permissionsState.grantInstallPermission(bp) !=
- PermissionsState.PERMISSION_OPERATION_FAILURE) {
+ PERMISSION_OPERATION_FAILURE) {
changedInstallPermission = true;
}
} break;
case GRANT_RUNTIME: {
- // Grant previously granted runtime permissions.
- for (int userId : UserManagerService.getInstance().getUserIds()) {
- final PermissionState permissionState = origPermissions
+ for (int userId : currentUserIds) {
+ PermissionState permState = origPermissions
.getRuntimePermissionState(perm, userId);
- int flags = permissionState != null
- ? permissionState.getFlags() : 0;
- if (origPermissions.hasRuntimePermission(perm, userId)) {
- // Don't propagate the permission in a permission review
- // mode if the former was revoked, i.e. marked to not
- // propagate on upgrade. Note that in a permission review
- // mode install permissions are represented as constantly
- // granted runtime ones since we need to keep a per user
- // state associated with the permission. Also the revoke
- // on upgrade flag is no longer applicable and is reset.
- final boolean revokeOnUpgrade = (flags & PackageManager
- .FLAG_PERMISSION_REVOKE_ON_UPGRADE) != 0;
- if (revokeOnUpgrade) {
- flags &= ~PackageManager.FLAG_PERMISSION_REVOKE_ON_UPGRADE;
- // Since we changed the flags, we have to write.
- updatedUserIds = ArrayUtils.appendInt(
- updatedUserIds, userId);
- }
- if (!revokeOnUpgrade) {
- if (permissionsState.grantRuntimePermission(bp, userId) ==
- PermissionsState.PERMISSION_OPERATION_FAILURE) {
- // If we cannot put the permission as it was,
- // we have to write.
- updatedUserIds = ArrayUtils.appendInt(
- updatedUserIds, userId);
- }
+ int flags = permState != null ? permState.getFlags() : 0;
+
+ boolean wasChanged = false;
+
+ if (appSupportsRuntimePermissions) {
+ // Remove review flag as it is not necessary anymore
+ if ((flags & FLAG_PERMISSION_REVIEW_REQUIRED) != 0) {
+ flags &= ~FLAG_PERMISSION_REVIEW_REQUIRED;
+ wasChanged = true;
}
- // If the app supports runtime permissions no need for a review.
- if (appSupportsRuntimePermissions
- && (flags & PackageManager
- .FLAG_PERMISSION_REVIEW_REQUIRED) != 0) {
- flags &= ~PackageManager.FLAG_PERMISSION_REVIEW_REQUIRED;
- // Since we changed the flags, we have to write.
- updatedUserIds = ArrayUtils.appendInt(
- updatedUserIds, userId);
+ if ((flags & FLAG_PERMISSION_REVOKE_ON_UPGRADE) != 0) {
+ flags &= ~FLAG_PERMISSION_REVOKE_ON_UPGRADE;
+ wasChanged = true;
+ } else {
+ if (permState != null && permState.isGranted()) {
+ if (permissionsState.grantRuntimePermission(bp, userId)
+ == PERMISSION_OPERATION_FAILURE) {
+ wasChanged = true;
+ }
+ }
}
- } else if (!appSupportsRuntimePermissions) {
- // For legacy apps that need a permission review, every new
- // runtime permission is granted but it is pending a review.
- // We also need to review only platform defined runtime
- // permissions as these are the only ones the platform knows
- // how to disable the API to simulate revocation as legacy
- // apps don't expect to run with revoked permissions.
- if (PLATFORM_PACKAGE_NAME.equals(bp.getSourcePackageName())) {
- if ((flags & FLAG_PERMISSION_REVIEW_REQUIRED) == 0
- && !bp.isRemoved()) {
- flags |= FLAG_PERMISSION_REVIEW_REQUIRED;
- // We changed the flags, hence have to write.
- updatedUserIds = ArrayUtils.appendInt(
- updatedUserIds, userId);
+ } else {
+ if (permState == null) {
+ // New permission
+ if (PLATFORM_PACKAGE_NAME.equals(
+ bp.getSourcePackageName())) {
+ if (!bp.isRemoved()) {
+ flags |= FLAG_PERMISSION_REVIEW_REQUIRED
+ | FLAG_PERMISSION_REVOKE_ON_UPGRADE;
+ wasChanged = true;
+ }
}
}
+
if (permissionsState.grantRuntimePermission(bp, userId)
- != PermissionsState.PERMISSION_OPERATION_FAILURE) {
- // We changed the permission, hence have to write.
- updatedUserIds = ArrayUtils.appendInt(
- updatedUserIds, userId);
+ != PERMISSION_OPERATION_FAILURE) {
+ wasChanged = true;
}
}
- // Propagate the permission flags.
+
+ if (wasChanged) {
+ updatedUserIds = ArrayUtils.appendInt(updatedUserIds, userId);
+ }
+
permissionsState.updatePermissionFlags(bp, userId, flags, flags);
}
} break;
case GRANT_UPGRADE: {
- // Grant runtime permissions for a previously held install permission.
- final PermissionState permissionState = origPermissions
+ // Upgrade from Pre-Q to Q permission model. Make all permissions
+ // runtime
+ PermissionState permState = origPermissions
.getInstallPermissionState(perm);
- final int flags =
- (permissionState != null) ? permissionState.getFlags() : 0;
+ int flags = (permState != null) ? permState.getFlags() : 0;
+ // Remove install permission
if (origPermissions.revokeInstallPermission(bp)
- != PermissionsState.PERMISSION_OPERATION_FAILURE) {
- // We will be transferring the permission flags, so clear them.
+ != PERMISSION_OPERATION_FAILURE) {
origPermissions.updatePermissionFlags(bp, UserHandle.USER_ALL,
PackageManager.MASK_PERMISSION_FLAGS, 0);
changedInstallPermission = true;
}
- // If the permission is not to be promoted to runtime we ignore it and
- // also its other flags as they are not applicable to install permissions.
- if ((flags & PackageManager.FLAG_PERMISSION_REVOKE_ON_UPGRADE) == 0) {
- for (int userId : currentUserIds) {
+ for (int userId : currentUserIds) {
+ boolean wasChanged = false;
+
+ if (appSupportsRuntimePermissions) {
+ // Remove review flag as it is not necessary anymore
+ if ((flags & FLAG_PERMISSION_REVIEW_REQUIRED) != 0) {
+ flags &= ~FLAG_PERMISSION_REVIEW_REQUIRED;
+ wasChanged = true;
+ }
+
+ if ((flags & FLAG_PERMISSION_REVOKE_ON_UPGRADE) != 0) {
+ flags &= ~FLAG_PERMISSION_REVOKE_ON_UPGRADE;
+ wasChanged = true;
+ } else {
+ if (permissionsState.grantRuntimePermission(bp, userId) !=
+ PERMISSION_OPERATION_FAILURE) {
+ wasChanged = true;
+ }
+ }
+ } else {
if (permissionsState.grantRuntimePermission(bp, userId) !=
- PermissionsState.PERMISSION_OPERATION_FAILURE) {
- // Transfer the permission flags.
- permissionsState.updatePermissionFlags(bp, userId,
- flags, flags);
- // If we granted the permission, we have to write.
- updatedUserIds = ArrayUtils.appendInt(
- updatedUserIds, userId);
+ PERMISSION_OPERATION_FAILURE) {
+ flags |= FLAG_PERMISSION_REVIEW_REQUIRED;
+ wasChanged = true;
}
}
+
+ if (wasChanged) {
+ updatedUserIds = ArrayUtils.appendInt(updatedUserIds, userId);
+ }
+
+ permissionsState.updatePermissionFlags(bp, userId, flags, flags);
}
} break;
@@ -1011,7 +1098,7 @@ public class PermissionManagerService {
}
} else {
if (permissionsState.revokeInstallPermission(bp) !=
- PermissionsState.PERMISSION_OPERATION_FAILURE) {
+ PERMISSION_OPERATION_FAILURE) {
// Also drop the permission flags.
permissionsState.updatePermissionFlags(bp, UserHandle.USER_ALL,
PackageManager.MASK_PERMISSION_FLAGS, 0);
@@ -1094,6 +1181,10 @@ public class PermissionManagerService {
@NonNull int[] updatedUserIds) {
AppOpsManager appOpsManager = mContext.getSystemService(AppOpsManager.class);
+ if (pkg.applicationInfo.targetSdkVersion < Build.VERSION_CODES.M) {
+ return updatedUserIds;
+ }
+
String pkgName = pkg.packageName;
int[] users = UserManagerService.getInstance().getUserIds();
@@ -1119,26 +1210,14 @@ public class PermissionManagerService {
if ((flags & (FLAG_PERMISSION_GRANTED_BY_DEFAULT
| FLAG_PERMISSION_POLICY_FIXED | FLAG_PERMISSION_SYSTEM_FIXED))
== 0) {
- if (pkg.applicationInfo.targetSdkVersion < Build.VERSION_CODES.M) {
- if (permissionToOpCode(permission) != OP_NONE) {
- setAppOpMode(permission, pkg, userId, MODE_IGNORED);
-
- if (DEBUG_PERMISSIONS) {
- Slog.i(TAG, "Revoking app-op "
- + permissionToOp(permission) + " for " + pkgName
- + " as it is now requested");
- }
- }
- } else {
- int revokeResult = ps.revokeRuntimePermission(bp, userId);
- if (revokeResult
- != PermissionsState.PERMISSION_OPERATION_FAILURE) {
-
- if (DEBUG_PERMISSIONS) {
- Slog.i(TAG, "Revoking runtime permission " + permission
- + " for " + pkgName
- + " as it is now requested");
- }
+ int revokeResult = ps.revokeRuntimePermission(bp, userId);
+ if (revokeResult
+ != PERMISSION_OPERATION_FAILURE) {
+
+ if (DEBUG_PERMISSIONS) {
+ Slog.i(TAG, "Revoking runtime permission " + permission
+ + " for " + pkgName
+ + " as it is now requested");
}
}
@@ -1925,7 +2004,7 @@ public class PermissionManagerService {
// Development permissions must be handled specially, since they are not
// normal runtime permissions. For now they apply to all users.
if (permissionsState.grantInstallPermission(bp) !=
- PermissionsState.PERMISSION_OPERATION_FAILURE) {
+ PERMISSION_OPERATION_FAILURE) {
if (callback != null) {
callback.onInstallPermissionGranted();
}
@@ -1945,7 +2024,7 @@ public class PermissionManagerService {
final int result = permissionsState.grantRuntimePermission(bp, userId);
switch (result) {
- case PermissionsState.PERMISSION_OPERATION_FAILURE: {
+ case PERMISSION_OPERATION_FAILURE: {
return;
}
@@ -2045,7 +2124,7 @@ public class PermissionManagerService {
// Development permissions must be handled specially, since they are not
// normal runtime permissions. For now they apply to all users.
if (permissionsState.revokeInstallPermission(bp) !=
- PermissionsState.PERMISSION_OPERATION_FAILURE) {
+ PERMISSION_OPERATION_FAILURE) {
if (callback != null) {
callback.onInstallPermissionRevoked();
}
@@ -2054,7 +2133,7 @@ public class PermissionManagerService {
}
if (permissionsState.revokeRuntimePermission(bp, userId) ==
- PermissionsState.PERMISSION_OPERATION_FAILURE) {
+ PERMISSION_OPERATION_FAILURE) {
return;
}
@@ -2522,6 +2601,8 @@ public class PermissionManagerService {
throw new IllegalStateException("Signature|privileged permissions not in "
+ "privapp-permissions whitelist: " + mPrivappPermissionsViolations);
}
+
+ mPermissionControllerManager = mContext.getSystemService(PermissionControllerManager.class);
}
private static String getVolumeUuidForPackage(PackageParser.Package pkg) {
@@ -2574,7 +2655,7 @@ public class PermissionManagerService {
return mBackgroundPermissions;
}
- private class PermissionManagerInternalImpl extends PermissionManagerInternal {
+ private class PermissionManagerServiceInternalImpl extends PermissionManagerServiceInternal {
@Override
public void systemReady() {
PermissionManagerService.this.systemReady();
@@ -2737,5 +2818,21 @@ public class PermissionManagerService {
return mSettings.getPermissionLocked(permName);
}
}
+
+ @Override
+ public @Nullable byte[] backupRuntimePermissions(@NonNull UserHandle user) {
+ return PermissionManagerService.this.backupRuntimePermissions(user);
+ }
+
+ @Override
+ public void restoreRuntimePermissions(@NonNull byte[] backup, @NonNull UserHandle user) {
+ PermissionManagerService.this.restoreRuntimePermissions(backup, user);
+ }
+
+ @Override
+ public void restoreDelayedRuntimePermissions(@NonNull String packageName,
+ @NonNull UserHandle user) {
+ PermissionManagerService.this.restoreDelayedRuntimePermissions(packageName, user);
+ }
}
}
diff --git a/services/core/java/com/android/server/pm/permission/PermissionManagerInternal.java b/services/core/java/com/android/server/pm/permission/PermissionManagerServiceInternal.java
index f4979746bae3..1dd2408686c1 100644
--- a/services/core/java/com/android/server/pm/permission/PermissionManagerInternal.java
+++ b/services/core/java/com/android/server/pm/permission/PermissionManagerServiceInternal.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2017 The Android Open Source Project
+ * Copyright (C) 2019 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -18,19 +18,22 @@ package com.android.server.pm.permission;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.content.pm.PackageManager.PermissionInfoFlags;
import android.content.pm.PackageParser;
import android.content.pm.PermissionGroupInfo;
import android.content.pm.PermissionInfo;
-import android.content.pm.PackageManager.PermissionInfoFlags;
+import android.permission.PermissionManagerInternal;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
/**
- * Internal interfaces to be used by other components within the system server.
+ * Internal interfaces services.
+ *
+ * TODO: Should be merged into PermissionManagerInternal, but currently uses internal classes.
*/
-public abstract class PermissionManagerInternal {
+public abstract class PermissionManagerServiceInternal extends PermissionManagerInternal {
/**
* Callbacks invoked when interesting actions have been taken on a permission.
* <p>
diff --git a/services/core/java/com/android/server/pm/permission/TEST_MAPPING b/services/core/java/com/android/server/pm/permission/TEST_MAPPING
index 0892b32a6b91..2280d3fd9134 100644
--- a/services/core/java/com/android/server/pm/permission/TEST_MAPPING
+++ b/services/core/java/com/android/server/pm/permission/TEST_MAPPING
@@ -16,6 +16,9 @@
},
{
"include-filter": "android.permission.cts.SplitPermissionTest"
+ },
+ {
+ "include-filter": "android.permission.cts.PermissionFlagsTest"
}
]
},
diff --git a/services/core/java/com/android/server/policy/DisplayFoldController.java b/services/core/java/com/android/server/policy/DisplayFoldController.java
index fdcafa77a378..0c6b773396c8 100644
--- a/services/core/java/com/android/server/policy/DisplayFoldController.java
+++ b/services/core/java/com/android/server/policy/DisplayFoldController.java
@@ -42,10 +42,12 @@ class DisplayFoldController {
private final WindowManagerInternal mWindowManagerInternal;
private final DisplayManagerInternal mDisplayManagerInternal;
private final int mDisplayId;
+ private final Handler mHandler;
/** The display area while device is folded. */
private final Rect mFoldedArea;
- private final Handler mHandler;
+ /** The display area to override the original folded area. */
+ private Rect mOverrideFoldedArea = new Rect();
private final DisplayInfo mNonOverrideDisplayInfo = new DisplayInfo();
private final RemoteCallbackList<IDisplayFoldListener> mListeners = new RemoteCallbackList<>();
@@ -70,14 +72,23 @@ class DisplayFoldController {
return;
}
if (folded) {
+ Rect foldedArea;
+ if (!mOverrideFoldedArea.isEmpty()) {
+ foldedArea = mOverrideFoldedArea;
+ } else if (!mFoldedArea.isEmpty()) {
+ foldedArea = mFoldedArea;
+ } else {
+ return;
+ }
+
mDisplayManagerInternal.getNonOverrideDisplayInfo(mDisplayId, mNonOverrideDisplayInfo);
- final int dx = (mNonOverrideDisplayInfo.logicalWidth - mFoldedArea.width()) / 2
- - mFoldedArea.left;
- final int dy = (mNonOverrideDisplayInfo.logicalHeight - mFoldedArea.height()) / 2
- - mFoldedArea.top;
+ final int dx = (mNonOverrideDisplayInfo.logicalWidth - foldedArea.width()) / 2
+ - foldedArea.left;
+ final int dy = (mNonOverrideDisplayInfo.logicalHeight - foldedArea.height()) / 2
+ - foldedArea.top;
- mWindowManagerInternal.setForcedDisplaySize(mDisplayId, mFoldedArea.width(),
- mFoldedArea.height());
+ mWindowManagerInternal.setForcedDisplaySize(mDisplayId,
+ foldedArea.width(), foldedArea.height());
mDisplayManagerInternal.setDisplayOffsets(mDisplayId, -dx, -dy);
} else {
mWindowManagerInternal.clearForcedDisplaySize(mDisplayId);
@@ -114,6 +125,18 @@ class DisplayFoldController {
mListeners.unregister(listener);
}
+ void setOverrideFoldedArea(Rect area) {
+ mOverrideFoldedArea.set(area);
+ }
+
+ Rect getFoldedArea() {
+ if (!mOverrideFoldedArea.isEmpty()) {
+ return mOverrideFoldedArea;
+ } else {
+ return mFoldedArea;
+ }
+ }
+
/**
* Only used for the case that persist.debug.force_foldable is set.
* This is using proximity sensor to simulate the fold state switch.
@@ -125,7 +148,7 @@ class DisplayFoldController {
return null;
}
- final DisplayFoldController result = create(displayId);
+ final DisplayFoldController result = create(context, displayId);
sensorManager.registerListener(new SensorEventListener() {
@Override
public void onSensorChanged(SensorEvent event) {
@@ -141,13 +164,17 @@ class DisplayFoldController {
return result;
}
- static DisplayFoldController create(int displayId) {
+ static DisplayFoldController create(Context context, int displayId) {
final DisplayManagerInternal displayService =
LocalServices.getService(DisplayManagerInternal.class);
- final DisplayInfo displayInfo = new DisplayInfo();
- displayService.getNonOverrideDisplayInfo(displayId, displayInfo);
- final Rect foldedArea = new Rect(0, displayInfo.logicalHeight / 2,
- displayInfo.logicalWidth, displayInfo.logicalHeight);
+ final String configFoldedArea = context.getResources().getString(
+ com.android.internal.R.string.config_foldedArea);
+ final Rect foldedArea;
+ if (configFoldedArea == null || configFoldedArea.isEmpty()) {
+ foldedArea = new Rect();
+ } else {
+ foldedArea = Rect.unflattenFromString(configFoldedArea);
+ }
return new DisplayFoldController(LocalServices.getService(WindowManagerInternal.class),
displayService, displayId, foldedArea, DisplayThread.getHandler());
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index 2e3e3e430839..c87a81db16e4 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -125,6 +125,7 @@ import android.content.res.Resources;
import android.content.res.TypedArray;
import android.database.ContentObserver;
import android.graphics.PixelFormat;
+import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.hardware.display.DisplayManager;
import android.hardware.hdmi.HdmiAudioSystemClient;
@@ -1858,7 +1859,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
readConfigurationDependentBehaviors();
if (mLidControlsDisplayFold) {
- mDisplayFoldController = DisplayFoldController.create(DEFAULT_DISPLAY);
+ mDisplayFoldController = DisplayFoldController.create(context, DEFAULT_DISPLAY);
} else if (SystemProperties.getBoolean("persist.debug.force_foldable", false)) {
mDisplayFoldController = DisplayFoldController.createWithProxSensor(context,
DEFAULT_DISPLAY);
@@ -3221,6 +3222,21 @@ public class PhoneWindowManager implements WindowManagerPolicy {
}
@Override
+ public void setOverrideFoldedArea(Rect area) {
+ if (mDisplayFoldController != null) {
+ mDisplayFoldController.setOverrideFoldedArea(area);
+ }
+ }
+
+ @Override
+ public Rect getFoldedArea() {
+ if (mDisplayFoldController != null) {
+ return mDisplayFoldController.getFoldedArea();
+ }
+ return new Rect();
+ }
+
+ @Override
public void registerShortcutKey(long shortcutCode, IShortcutService shortcutService)
throws RemoteException {
synchronized (mLock) {
diff --git a/services/core/java/com/android/server/policy/WindowManagerPolicy.java b/services/core/java/com/android/server/policy/WindowManagerPolicy.java
index 870d61b2ab90..d7e4b6cff4d8 100644
--- a/services/core/java/com/android/server/policy/WindowManagerPolicy.java
+++ b/services/core/java/com/android/server/policy/WindowManagerPolicy.java
@@ -64,6 +64,7 @@ import static android.view.WindowManager.LayoutParams.isSystemAlertWindowType;
import static java.lang.annotation.RetentionPolicy.SOURCE;
import android.annotation.IntDef;
+import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.WindowConfiguration;
import android.content.Context;
@@ -1470,6 +1471,20 @@ public interface WindowManagerPolicy extends WindowManagerPolicyConstants {
default void unregisterDisplayFoldListener(IDisplayFoldListener listener) {}
/**
+ * Overrides the folded area.
+ *
+ * @param area the overriding folded area or an empty {@code Rect} to clear the override.
+ */
+ default void setOverrideFoldedArea(@NonNull Rect area) {}
+
+ /**
+ * Get the display folded area.
+ */
+ default @NonNull Rect getFoldedArea() {
+ return new Rect();
+ }
+
+ /**
* Updates the flag about whether AOD is showing.
*
* @return whether the value was changed.
diff --git a/services/core/java/com/android/server/role/RoleManagerService.java b/services/core/java/com/android/server/role/RoleManagerService.java
index d8531210cad8..c145a22de6cd 100644
--- a/services/core/java/com/android/server/role/RoleManagerService.java
+++ b/services/core/java/com/android/server/role/RoleManagerService.java
@@ -196,7 +196,7 @@ public class RoleManagerService extends SystemService implements RoleUserState.C
}
performInitialGrantsIfNecessary(userId);
}
- }, UserHandle.SYSTEM, intentFilter, null /* broadcastPermission */, null /* handler */);
+ }, UserHandle.ALL, intentFilter, null, null);
getContext().getContentResolver().registerContentObserver(
Settings.Global.getUriFor(Settings.Global.SMS_ACCESS_RESTRICTION_ENABLED), false,
diff --git a/services/core/java/com/android/server/stats/StatsCompanionService.java b/services/core/java/com/android/server/stats/StatsCompanionService.java
index f3393e2f29da..4815e5cd7b83 100644
--- a/services/core/java/com/android/server/stats/StatsCompanionService.java
+++ b/services/core/java/com/android/server/stats/StatsCompanionService.java
@@ -85,7 +85,9 @@ import android.os.SystemProperties;
import android.os.Temperature;
import android.os.UserHandle;
import android.os.UserManager;
+import android.os.storage.DiskInfo;
import android.os.storage.StorageManager;
+import android.os.storage.VolumeInfo;
import android.telephony.ModemActivityInfo;
import android.telephony.TelephonyManager;
import android.util.ArrayMap;
@@ -1942,6 +1944,41 @@ public class StatsCompanionService extends IStatsCompanionService.Stub {
}
}
+ private void pullTimeZoneDataInfo(int tagId,
+ long elapsedNanos, long wallClockNanos, List<StatsLogEventWrapper> pulledData) {
+ String tzDbVersion = "Unknown";
+ try {
+ tzDbVersion = android.icu.util.TimeZone.getTZDataVersion();
+ } catch (Exception e) {
+ Log.e(TAG, "Getting tzdb version failed: ", e);
+ }
+
+ StatsLogEventWrapper e = new StatsLogEventWrapper(tagId, elapsedNanos, wallClockNanos);
+ e.writeString(tzDbVersion);
+ pulledData.add(e);
+ }
+
+ private void pullSDCardInfo(int tagId, long elapsedNanos, long wallClockNanos,
+ List<StatsLogEventWrapper> pulledData) {
+ StorageManager storageManager = mContext.getSystemService(StorageManager.class);
+ if (storageManager != null) {
+ List<VolumeInfo> volumes = storageManager.getVolumes();
+ for (VolumeInfo vol : volumes) {
+ final String envState = VolumeInfo.getEnvironmentForState(vol.getState());
+ final DiskInfo diskInfo = vol.getDisk();
+ if (diskInfo != null && diskInfo.isSd()) {
+ if (envState.equals(Environment.MEDIA_MOUNTED)) {
+ StatsLogEventWrapper e =
+ new StatsLogEventWrapper(tagId, elapsedNanos, wallClockNanos);
+ e.writeInt(vol.getType() + 1);
+ e.writeLong(diskInfo.size);
+ pulledData.add(e);
+ }
+ }
+ }
+ }
+ }
+
/**
* Pulls various data.
*/
@@ -2130,6 +2167,14 @@ public class StatsCompanionService extends IStatsCompanionService.Stub {
pullDangerousPermissionState(elapsedNanos, wallClockNanos, ret);
break;
}
+ case StatsLog.TIME_ZONE_DATA_INFO: {
+ pullTimeZoneDataInfo(tagId, elapsedNanos, wallClockNanos, ret);
+ break;
+ }
+ case StatsLog.SDCARD_INFO: {
+ pullSDCardInfo(tagId, elapsedNanos, wallClockNanos, ret);
+ break;
+ }
default:
Slog.w(TAG, "No such tagId data as " + tagId);
return null;
diff --git a/services/core/java/com/android/server/telecom/TelecomLoaderService.java b/services/core/java/com/android/server/telecom/TelecomLoaderService.java
index 7a3f030f9dd7..f581bc0bca46 100644
--- a/services/core/java/com/android/server/telecom/TelecomLoaderService.java
+++ b/services/core/java/com/android/server/telecom/TelecomLoaderService.java
@@ -44,7 +44,7 @@ import com.android.server.LocalServices;
import com.android.server.SystemService;
import com.android.server.pm.UserManagerService;
import com.android.server.pm.permission.DefaultPermissionGrantPolicy;
-import com.android.server.pm.permission.PermissionManagerInternal;
+import com.android.server.pm.permission.PermissionManagerServiceInternal;
/**
* Starts the telecom component by binding to its ITelecomService implementation. Telecom is setup
@@ -133,7 +133,7 @@ public class TelecomLoaderService extends SystemService {
}
private DefaultPermissionGrantPolicy getDefaultPermissionGrantPolicy() {
- return LocalServices.getService(PermissionManagerInternal.class)
+ return LocalServices.getService(PermissionManagerServiceInternal.class)
.getDefaultPermissionGrantPolicy();
}
diff --git a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
index b0ef8a0d4209..071dde74f103 100644
--- a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
+++ b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
@@ -2243,12 +2243,9 @@ public class WallpaperManagerService extends IWallpaperManager.Stub
synchronized (mLock) {
mInAmbientMode = inAmbientMode;
final WallpaperData data = mWallpaperMap.get(mCurrentUserId);
- final boolean hasConnection = data != null && data.connection != null;
- final WallpaperInfo info = hasConnection ? data.connection.mInfo : null;
-
// The wallpaper info is null for image wallpaper, also use the engine in this case.
- if (hasConnection && (info == null && isAodImageWallpaperEnabled()
- || info != null && info.supportsAmbientMode())) {
+ if (data != null && data.connection != null && (data.connection.mInfo == null
+ || data.connection.mInfo.supportsAmbientMode())) {
// TODO(multi-display) Extends this method with specific display.
engine = data.connection.getDisplayConnectorOrCreate(DEFAULT_DISPLAY).mEngine;
} else {
diff --git a/services/core/java/com/android/server/wm/ActivityStarter.java b/services/core/java/com/android/server/wm/ActivityStarter.java
index c33a2c179ab7..d40948b305a2 100644
--- a/services/core/java/com/android/server/wm/ActivityStarter.java
+++ b/services/core/java/com/android/server/wm/ActivityStarter.java
@@ -830,12 +830,25 @@ class ActivityStarter {
new String[]{resolvedType}, PendingIntent.FLAG_CANCEL_CURRENT
| PendingIntent.FLAG_ONE_SHOT, null);
- final int flags = intent.getFlags();
Intent newIntent = new Intent(Intent.ACTION_REVIEW_PERMISSIONS);
- newIntent.setFlags(flags
- | FLAG_ACTIVITY_NEW_TASK
- | Intent.FLAG_ACTIVITY_MULTIPLE_TASK
- | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
+
+ int flags = intent.getFlags();
+ flags |= Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS;
+
+ /*
+ * Prevent reuse of review activity: Each app needs their own review activity. By
+ * default activities launched with NEW_TASK or NEW_DOCUMENT try to reuse activities
+ * with the same launch parameters (extras are ignored). Hence to avoid possible
+ * reuse force a new activity via the MULTIPLE_TASK flag.
+ *
+ * Activities that are not launched with NEW_TASK or NEW_DOCUMENT are not re-used,
+ * hence no need to add the flag in this case.
+ */
+ if ((flags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_NEW_DOCUMENT)) != 0) {
+ flags |= Intent.FLAG_ACTIVITY_MULTIPLE_TASK;
+ }
+ newIntent.setFlags(flags);
+
newIntent.putExtra(Intent.EXTRA_PACKAGE_NAME, aInfo.packageName);
newIntent.putExtra(Intent.EXTRA_INTENT, new IntentSender(target));
if (resultRecord != null) {
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 168c9adb61be..7beee0e33355 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -22,6 +22,7 @@ import static android.Manifest.permission.MANAGE_APP_TOKENS;
import static android.Manifest.permission.READ_FRAME_BUFFER;
import static android.Manifest.permission.REGISTER_WINDOW_MANAGER_LISTENERS;
import static android.Manifest.permission.RESTRICTED_VR_ACCESS;
+import static android.Manifest.permission.WRITE_SECURE_SETTINGS;
import static android.app.ActivityManagerInternal.ALLOW_FULL_ONLY;
import static android.app.ActivityTaskManager.SPLIT_SCREEN_CREATE_MODE_TOP_OR_LEFT;
import static android.app.AppOpsManager.OP_SYSTEM_ALERT_WINDOW;
@@ -3759,6 +3760,41 @@ public class WindowManagerService extends IWindowManager.Stub
mPolicy.unregisterDisplayFoldListener(listener);
}
+ /**
+ * Overrides the folded area.
+ *
+ * @param area the overriding folded area or an empty {@code Rect} to clear the override.
+ */
+ void setOverrideFoldedArea(@NonNull Rect area) {
+ if (mContext.checkCallingOrSelfPermission(WRITE_SECURE_SETTINGS)
+ != PackageManager.PERMISSION_GRANTED) {
+ throw new SecurityException("Must hold permission " + WRITE_SECURE_SETTINGS);
+ }
+
+ long origId = Binder.clearCallingIdentity();
+ try {
+ synchronized (mGlobalLock) {
+ mPolicy.setOverrideFoldedArea(area);
+ }
+ } finally {
+ Binder.restoreCallingIdentity(origId);
+ }
+ }
+
+ /**
+ * Get the display folded area.
+ */
+ @NonNull Rect getFoldedArea() {
+ long origId = Binder.clearCallingIdentity();
+ try {
+ synchronized (mGlobalLock) {
+ return mPolicy.getFoldedArea();
+ }
+ } finally {
+ Binder.restoreCallingIdentity(origId);
+ }
+ }
+
@Override
public int getPreferredOptionsPanelGravity(int displayId) {
synchronized (mGlobalLock) {
@@ -4826,11 +4862,9 @@ public class WindowManagerService extends IWindowManager.Stub
@Override
public void setForcedDisplaySize(int displayId, int width, int height) {
- if (mContext.checkCallingOrSelfPermission(
- android.Manifest.permission.WRITE_SECURE_SETTINGS) !=
- PackageManager.PERMISSION_GRANTED) {
- throw new SecurityException("Must hold permission " +
- android.Manifest.permission.WRITE_SECURE_SETTINGS);
+ if (mContext.checkCallingOrSelfPermission(WRITE_SECURE_SETTINGS)
+ != PackageManager.PERMISSION_GRANTED) {
+ throw new SecurityException("Must hold permission " + WRITE_SECURE_SETTINGS);
}
final long ident = Binder.clearCallingIdentity();
@@ -4848,11 +4882,9 @@ public class WindowManagerService extends IWindowManager.Stub
@Override
public void setForcedDisplayScalingMode(int displayId, int mode) {
- if (mContext.checkCallingOrSelfPermission(
- android.Manifest.permission.WRITE_SECURE_SETTINGS) !=
- PackageManager.PERMISSION_GRANTED) {
- throw new SecurityException("Must hold permission " +
- android.Manifest.permission.WRITE_SECURE_SETTINGS);
+ if (mContext.checkCallingOrSelfPermission(WRITE_SECURE_SETTINGS)
+ != PackageManager.PERMISSION_GRANTED) {
+ throw new SecurityException("Must hold permission " + WRITE_SECURE_SETTINGS);
}
final long ident = Binder.clearCallingIdentity();
@@ -4917,11 +4949,9 @@ public class WindowManagerService extends IWindowManager.Stub
@Override
public void clearForcedDisplaySize(int displayId) {
- if (mContext.checkCallingOrSelfPermission(
- android.Manifest.permission.WRITE_SECURE_SETTINGS) !=
- PackageManager.PERMISSION_GRANTED) {
- throw new SecurityException("Must hold permission " +
- android.Manifest.permission.WRITE_SECURE_SETTINGS);
+ if (mContext.checkCallingOrSelfPermission(WRITE_SECURE_SETTINGS)
+ != PackageManager.PERMISSION_GRANTED) {
+ throw new SecurityException("Must hold permission " + WRITE_SECURE_SETTINGS);
}
final long ident = Binder.clearCallingIdentity();
@@ -4962,11 +4992,9 @@ public class WindowManagerService extends IWindowManager.Stub
@Override
public void setForcedDisplayDensityForUser(int displayId, int density, int userId) {
- if (mContext.checkCallingOrSelfPermission(
- android.Manifest.permission.WRITE_SECURE_SETTINGS) !=
- PackageManager.PERMISSION_GRANTED) {
- throw new SecurityException("Must hold permission " +
- android.Manifest.permission.WRITE_SECURE_SETTINGS);
+ if (mContext.checkCallingOrSelfPermission(WRITE_SECURE_SETTINGS)
+ != PackageManager.PERMISSION_GRANTED) {
+ throw new SecurityException("Must hold permission " + WRITE_SECURE_SETTINGS);
}
final int targetUserId = ActivityManager.handleIncomingUser(Binder.getCallingPid(),
@@ -4987,11 +5015,9 @@ public class WindowManagerService extends IWindowManager.Stub
@Override
public void clearForcedDisplayDensityForUser(int displayId, int userId) {
- if (mContext.checkCallingOrSelfPermission(
- android.Manifest.permission.WRITE_SECURE_SETTINGS) !=
- PackageManager.PERMISSION_GRANTED) {
- throw new SecurityException("Must hold permission " +
- android.Manifest.permission.WRITE_SECURE_SETTINGS);
+ if (mContext.checkCallingOrSelfPermission(WRITE_SECURE_SETTINGS)
+ != PackageManager.PERMISSION_GRANTED) {
+ throw new SecurityException("Must hold permission " + WRITE_SECURE_SETTINGS);
}
final int callingUserId = ActivityManager.handleIncomingUser(Binder.getCallingPid(),
@@ -5056,11 +5082,9 @@ public class WindowManagerService extends IWindowManager.Stub
@Override
public void setOverscan(int displayId, int left, int top, int right, int bottom) {
- if (mContext.checkCallingOrSelfPermission(
- android.Manifest.permission.WRITE_SECURE_SETTINGS) !=
- PackageManager.PERMISSION_GRANTED) {
- throw new SecurityException("Must hold permission " +
- android.Manifest.permission.WRITE_SECURE_SETTINGS);
+ if (mContext.checkCallingOrSelfPermission(WRITE_SECURE_SETTINGS)
+ != PackageManager.PERMISSION_GRANTED) {
+ throw new SecurityException("Must hold permission " + WRITE_SECURE_SETTINGS);
}
final long ident = Binder.clearCallingIdentity();
try {
@@ -5090,11 +5114,7 @@ public class WindowManagerService extends IWindowManager.Stub
@Override
public void startWindowTrace(){
- try {
- mWindowTracing.startTrace(null /* printwriter */);
- } catch (IOException e) {
- throw new RuntimeException(e);
- }
+ mWindowTracing.startTrace(null /* printwriter */);
}
@Override
diff --git a/services/core/java/com/android/server/wm/WindowManagerShellCommand.java b/services/core/java/com/android/server/wm/WindowManagerShellCommand.java
index 83e3c71cbee3..d13ee459c115 100644
--- a/services/core/java/com/android/server/wm/WindowManagerShellCommand.java
+++ b/services/core/java/com/android/server/wm/WindowManagerShellCommand.java
@@ -62,6 +62,8 @@ public class WindowManagerShellCommand extends ShellCommand {
return runDisplaySize(pw);
case "density":
return runDisplayDensity(pw);
+ case "folded-area":
+ return runDisplayFoldedArea(pw);
case "overscan":
return runDisplayOverscan(pw);
case "scaling":
@@ -207,6 +209,40 @@ public class WindowManagerShellCommand extends ShellCommand {
return 0;
}
+ private void printFoldedArea(PrintWriter pw) {
+ final Rect foldedArea = mInternal.getFoldedArea();
+ if (foldedArea.isEmpty()) {
+ pw.println("Folded area: none");
+ } else {
+ pw.println("Folded area: " + foldedArea.left + "," + foldedArea.top + ","
+ + foldedArea.right + "," + foldedArea.bottom);
+ }
+ }
+
+ private int runDisplayFoldedArea(PrintWriter pw) {
+ final String areaStr = getNextArg();
+ final Rect rect = new Rect();
+ if (areaStr == null) {
+ printFoldedArea(pw);
+ return 0;
+ } else if ("reset".equals(areaStr)) {
+ rect.setEmpty();
+ } else {
+ final Pattern flattenedPattern = Pattern.compile(
+ "(-?\\d+),(-?\\d+),(-?\\d+),(-?\\d+)");
+ final Matcher matcher = flattenedPattern.matcher(areaStr);
+ if (!matcher.matches()) {
+ getErrPrintWriter().println("Error: area should be LEFT,TOP,RIGHT,BOTTOM");
+ return -1;
+ }
+ rect.set(Integer.parseInt(matcher.group(1)), Integer.parseInt(matcher.group(2)),
+ Integer.parseInt(matcher.group(3)), Integer.parseInt(matcher.group(4)));
+ }
+
+ mInternal.setOverrideFoldedArea(rect);
+ return 0;
+ }
+
private int runDisplayOverscan(PrintWriter pw) throws RemoteException {
String overscanStr = getNextArgRequired();
Rect rect = new Rect();
@@ -335,6 +371,8 @@ public class WindowManagerShellCommand extends ShellCommand {
pw.println(" width and height in pixels unless suffixed with 'dp'.");
pw.println(" density [reset|DENSITY] [-d DISPLAY_ID]");
pw.println(" Return or override display density.");
+ pw.println(" folded-area [reset|LEFT,TOP,RIGHT,BOTTOM]");
+ pw.println(" Return or override folded area.");
pw.println(" overscan [reset|LEFT,TOP,RIGHT,BOTTOM] [-d DISPLAY ID]");
pw.println(" Set overscan area for display.");
pw.println(" scaling [off|auto] [-d DISPLAY_ID]");
diff --git a/services/core/java/com/android/server/wm/WindowTraceBuffer.java b/services/core/java/com/android/server/wm/WindowTraceBuffer.java
index e4461ea90c91..2ce6e6c1d049 100644
--- a/services/core/java/com/android/server/wm/WindowTraceBuffer.java
+++ b/services/core/java/com/android/server/wm/WindowTraceBuffer.java
@@ -20,7 +20,6 @@ import static com.android.server.wm.WindowManagerTraceFileProto.MAGIC_NUMBER;
import static com.android.server.wm.WindowManagerTraceFileProto.MAGIC_NUMBER_H;
import static com.android.server.wm.WindowManagerTraceFileProto.MAGIC_NUMBER_L;
-import android.os.Trace;
import android.util.proto.ProtoOutputStream;
import com.android.internal.annotations.VisibleForTesting;
@@ -36,24 +35,30 @@ import java.util.Queue;
/**
* Buffer used for window tracing.
*/
-abstract class WindowTraceBuffer {
+class WindowTraceBuffer {
private static final long MAGIC_NUMBER_VALUE = ((long) MAGIC_NUMBER_H << 32) | MAGIC_NUMBER_L;
- final Object mBufferLock = new Object();
- final Queue<ProtoOutputStream> mBuffer = new ArrayDeque<>();
- final File mTraceFile;
- int mBufferSize;
- private final int mBufferCapacity;
+ private final Object mBufferLock = new Object();
- WindowTraceBuffer(int size, File traceFile) throws IOException {
- mBufferCapacity = size;
- mTraceFile = traceFile;
+ private final Queue<ProtoOutputStream> mBuffer = new ArrayDeque<>();
+ private int mBufferUsedSize;
+ private int mBufferCapacity;
- initTraceFile();
+ WindowTraceBuffer(int bufferCapacity) {
+ mBufferCapacity = bufferCapacity;
+ resetBuffer();
}
int getAvailableSpace() {
- return mBufferCapacity - mBufferSize;
+ return mBufferCapacity - mBufferUsedSize;
+ }
+
+ int size() {
+ return mBuffer.size();
+ }
+
+ void setCapacity(int capacity) {
+ mBufferCapacity = capacity;
}
/**
@@ -70,42 +75,37 @@ abstract class WindowTraceBuffer {
+ mBufferCapacity + " Object size: " + protoLength);
}
synchronized (mBufferLock) {
- boolean canAdd = canAdd(protoLength);
- if (canAdd) {
- mBuffer.add(proto);
- mBufferSize += protoLength;
- }
+ discardOldest(protoLength);
+ mBuffer.add(proto);
+ mBufferUsedSize += protoLength;
mBufferLock.notify();
}
}
- /**
- * Stops the buffer execution and flush all buffer content to the disk.
- *
- * @throws IOException if the buffer cannot write its contents to the {@link #mTraceFile}
- */
- void dump() throws IOException, InterruptedException {
- try {
- Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "writeTraceToFile");
- writeTraceToFile();
- } finally {
- Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER);
- }
- }
-
- @VisibleForTesting
boolean contains(byte[] other) {
return mBuffer.stream()
.anyMatch(p -> Arrays.equals(p.getBytes(), other));
}
- private void initTraceFile() throws IOException {
- mTraceFile.delete();
- try (OutputStream os = new FileOutputStream(mTraceFile)) {
- mTraceFile.setReadable(true, false);
- ProtoOutputStream proto = new ProtoOutputStream(os);
- proto.write(MAGIC_NUMBER, MAGIC_NUMBER_VALUE);
- proto.flush();
+ /**
+ * Writes the trace buffer to disk.
+ */
+ void writeTraceToFile(File traceFile) throws IOException {
+ synchronized (mBufferLock) {
+ traceFile.delete();
+ traceFile.setReadable(true, false);
+ try (OutputStream os = new FileOutputStream(traceFile)) {
+ ProtoOutputStream proto = new ProtoOutputStream();
+ proto.write(MAGIC_NUMBER, MAGIC_NUMBER_VALUE);
+ os.write(proto.getBytes());
+ while (!mBuffer.isEmpty()) {
+ proto = mBuffer.poll();
+ mBufferUsedSize -= proto.getRawSize();
+ byte[] protoBytes = proto.getBytes();
+ os.write(protoBytes);
+ }
+ os.flush();
+ }
}
}
@@ -114,59 +114,48 @@ abstract class WindowTraceBuffer {
* smaller than the overall buffer size.
*
* @param protoLength byte array representation of the Proto object to add
- * @return {@code true} if the element can be added to the buffer or not
- */
- abstract boolean canAdd(int protoLength);
-
- /**
- * Flush all buffer content to the disk.
- *
- * @throws IOException if the buffer cannot write its contents to the {@link #mTraceFile}
*/
- abstract void writeTraceToFile() throws IOException, InterruptedException;
-
- /**
- * Builder for a {@code WindowTraceBuffer} which creates a {@link WindowTraceRingBuffer} for
- * continuous mode or a {@link WindowTraceQueueBuffer} otherwise
- */
- static class Builder {
- private boolean mContinuous;
- private File mTraceFile;
- private int mBufferCapacity;
-
- Builder setContinuousMode(boolean continuous) {
- mContinuous = continuous;
- return this;
- }
+ private void discardOldest(int protoLength) {
+ long availableSpace = getAvailableSpace();
- Builder setTraceFile(File traceFile) {
- mTraceFile = traceFile;
- return this;
- }
+ while (availableSpace < protoLength) {
- Builder setBufferCapacity(int size) {
- mBufferCapacity = size;
- return this;
+ ProtoOutputStream item = mBuffer.poll();
+ if (item == null) {
+ throw new IllegalStateException("No element to discard from buffer");
+ }
+ mBufferUsedSize -= item.getRawSize();
+ availableSpace = getAvailableSpace();
}
+ }
- File getFile() {
- return mTraceFile;
+ /**
+ * Removes all elements form the buffer
+ */
+ void resetBuffer() {
+ synchronized (mBufferLock) {
+ mBuffer.clear();
+ mBufferUsedSize = 0;
}
+ }
- WindowTraceBuffer build() throws IOException {
- if (mBufferCapacity <= 0) {
- throw new IllegalStateException("Buffer capacity must be greater than 0.");
- }
-
- if (mTraceFile == null) {
- throw new IllegalArgumentException("A valid trace file must be specified.");
- }
+ @VisibleForTesting
+ int getBufferSize() {
+ return mBufferUsedSize;
+ }
- if (mContinuous) {
- return new WindowTraceRingBuffer(mBufferCapacity, mTraceFile);
- } else {
- return new WindowTraceQueueBuffer(mBufferCapacity, mTraceFile);
- }
+ String getStatus() {
+ synchronized (mBufferLock) {
+ return "Buffer size: "
+ + mBufferCapacity
+ + " bytes"
+ + "\n"
+ + "Buffer usage: "
+ + mBufferUsedSize
+ + " bytes"
+ + "\n"
+ + "Elements in the buffer: "
+ + mBuffer.size();
}
}
}
diff --git a/services/core/java/com/android/server/wm/WindowTraceQueueBuffer.java b/services/core/java/com/android/server/wm/WindowTraceQueueBuffer.java
deleted file mode 100644
index 5888b7a799cf..000000000000
--- a/services/core/java/com/android/server/wm/WindowTraceQueueBuffer.java
+++ /dev/null
@@ -1,105 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server.wm;
-
-import static android.os.Build.IS_USER;
-
-import android.util.Log;
-import android.util.proto.ProtoOutputStream;
-
-import com.android.internal.annotations.VisibleForTesting;
-
-import java.io.File;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.OutputStream;
-
-/**
- * A buffer structure backed by a {@link java.util.concurrent.BlockingQueue} to store the first
- * {@code #size size} bytes of window trace elements.
- * Once the buffer is full it will no longer accepts new elements.
- */
-class WindowTraceQueueBuffer extends WindowTraceBuffer {
- private static final String TAG = "WindowTracing";
-
- private Thread mConsumerThread;
- private boolean mCancel;
-
- @VisibleForTesting
- WindowTraceQueueBuffer(int size, File traceFile, boolean startConsumerThread)
- throws IOException {
- super(size, traceFile);
- if (startConsumerThread) {
- initializeConsumerThread();
- }
- }
-
- WindowTraceQueueBuffer(int size, File traceFile) throws IOException {
- this(size, traceFile, !IS_USER);
- }
-
- private void initializeConsumerThread() {
- mCancel = false;
- mConsumerThread = new Thread(() -> {
- try {
- loop();
- } catch (InterruptedException e) {
- Log.i(TAG, "Interrupting trace consumer thread");
- } catch (IOException e) {
- Log.e(TAG, "Failed to execute trace consumer thread", e);
- }
- }, "window_tracing");
- mConsumerThread.start();
- }
-
- private void loop() throws IOException, InterruptedException {
- while (!mCancel) {
- ProtoOutputStream proto;
- synchronized (mBufferLock) {
- mBufferLock.wait();
- proto = mBuffer.poll();
- if (proto != null) {
- mBufferSize -= proto.getRawSize();
- }
- }
- if (proto != null) {
- try (OutputStream os = new FileOutputStream(mTraceFile, true)) {
- byte[] protoBytes = proto.getBytes();
- os.write(protoBytes);
- }
- }
- }
- }
-
- @Override
- boolean canAdd(int protoLength) {
- long availableSpace = getAvailableSpace();
- return availableSpace >= protoLength;
- }
-
- @Override
- void writeTraceToFile() throws InterruptedException {
- synchronized (mBufferLock) {
- mCancel = true;
- mBufferLock.notify();
- }
- if (mConsumerThread != null) {
- mConsumerThread.join();
- mConsumerThread = null;
- }
- }
-}
diff --git a/services/core/java/com/android/server/wm/WindowTraceRingBuffer.java b/services/core/java/com/android/server/wm/WindowTraceRingBuffer.java
deleted file mode 100644
index 77d30be816bc..000000000000
--- a/services/core/java/com/android/server/wm/WindowTraceRingBuffer.java
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server.wm;
-
-import android.util.proto.ProtoOutputStream;
-
-import java.io.File;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.OutputStream;
-
-/**
- * A ring buffer to store the {@code #size size} bytes of window trace data.
- * The buffer operates on a trace entry level, that is, if the new trace data is larger than the
- * available buffer space, the buffer will discard as many full trace entries as necessary to fit
- * the new trace.
- */
-class WindowTraceRingBuffer extends WindowTraceBuffer {
- WindowTraceRingBuffer(int size, File traceFile) throws IOException {
- super(size, traceFile);
- }
-
- @Override
- boolean canAdd(int protoLength) {
- long availableSpace = getAvailableSpace();
-
- while (availableSpace < protoLength) {
- discardOldest();
- availableSpace = getAvailableSpace();
- }
-
- return true;
- }
-
- @Override
- void writeTraceToFile() throws IOException {
- synchronized (mBufferLock) {
- try (OutputStream os = new FileOutputStream(mTraceFile, true)) {
- while (!mBuffer.isEmpty()) {
- ProtoOutputStream proto = mBuffer.poll();
- mBufferSize -= proto.getRawSize();
- byte[] protoBytes = proto.getBytes();
- os.write(protoBytes);
- }
- }
- }
- }
-
- private void discardOldest() {
- ProtoOutputStream item = mBuffer.poll();
- if (item == null) {
- throw new IllegalStateException("No element to discard from buffer");
- }
- mBufferSize -= item.getRawSize();
- }
-}
diff --git a/services/core/java/com/android/server/wm/WindowTracing.java b/services/core/java/com/android/server/wm/WindowTracing.java
index abc474d756b7..0ce215c88dad 100644
--- a/services/core/java/com/android/server/wm/WindowTracing.java
+++ b/services/core/java/com/android/server/wm/WindowTracing.java
@@ -31,8 +31,6 @@ import android.util.Log;
import android.util.proto.ProtoOutputStream;
import android.view.Choreographer;
-import com.android.internal.annotations.VisibleForTesting;
-
import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
@@ -47,139 +45,191 @@ class WindowTracing {
* Maximum buffer size, currently defined as 512 KB
* Size was experimentally defined to fit between 100 to 150 elements.
*/
- private static final int WINDOW_TRACE_BUFFER_SIZE = 512 * 1024;
+ private static final int BUFFER_CAPACITY_CRITICAL = 512 * 1024;
+ private static final int BUFFER_CAPACITY_TRIM = 2048 * 1024;
+ private static final int BUFFER_CAPACITY_ALL = 4096 * 1024;
+ private static final String TRACE_FILENAME = "/data/misc/wmtrace/wm_trace.pb";
private static final String TAG = "WindowTracing";
private final WindowManagerService mService;
private final Choreographer mChoreographer;
private final WindowManagerGlobalLock mGlobalLock;
- private final Object mLock = new Object();
- private final WindowTraceBuffer.Builder mBufferBuilder;
-
- private WindowTraceBuffer mTraceBuffer;
+ private final Object mEnabledLock = new Object();
+ private final File mTraceFile;
+ private final WindowTraceBuffer mBuffer;
+ private final Choreographer.FrameCallback mFrameCallback = (frameTimeNanos) ->
+ log("onFrame" /* where */);
- private @WindowTraceLogLevel int mWindowTraceLogLevel = WindowTraceLogLevel.TRIM;
- private boolean mContinuousMode;
+ private @WindowTraceLogLevel int mLogLevel = WindowTraceLogLevel.TRIM;
+ private boolean mLogOnFrame = false;
private boolean mEnabled;
private volatile boolean mEnabledLockFree;
private boolean mScheduled;
- private Choreographer.FrameCallback mFrameCallback = (frameTimeNanos) ->
- log("onFrame" /* where */);
- private WindowTracing(File file, WindowManagerService service, Choreographer choreographer) {
- this(file, service, choreographer, service.mGlobalLock);
+ static WindowTracing createDefaultAndStartLooper(WindowManagerService service,
+ Choreographer choreographer) {
+ File file = new File(TRACE_FILENAME);
+ return new WindowTracing(file, service, choreographer, BUFFER_CAPACITY_TRIM);
}
- @VisibleForTesting
- WindowTracing(File file, WindowManagerService service, Choreographer choreographer,
- WindowManagerGlobalLock globalLock) {
- mBufferBuilder = new WindowTraceBuffer.Builder()
- .setTraceFile(file)
- .setBufferCapacity(WINDOW_TRACE_BUFFER_SIZE);
+ private WindowTracing(File file, WindowManagerService service, Choreographer choreographer,
+ int bufferCapacity) {
+ this(file, service, choreographer, service.mGlobalLock, bufferCapacity);
+ }
+ WindowTracing(File file, WindowManagerService service, Choreographer choreographer,
+ WindowManagerGlobalLock globalLock, int bufferCapacity) {
mChoreographer = choreographer;
mService = service;
mGlobalLock = globalLock;
+ mTraceFile = file;
+ mBuffer = new WindowTraceBuffer(bufferCapacity);
+ setLogLevel(WindowTraceLogLevel.TRIM, null /* pw */);
}
- void startTrace(@Nullable PrintWriter pw) throws IOException {
+ void startTrace(@Nullable PrintWriter pw) {
if (IS_USER) {
logAndPrintln(pw, "Error: Tracing is not supported on user builds.");
return;
}
- synchronized (mLock) {
- logAndPrintln(pw, "Start tracing to " + mBufferBuilder.getFile() + ".");
- if (mTraceBuffer != null) {
- writeTraceToFileLocked();
- }
- mTraceBuffer = mBufferBuilder
- .setContinuousMode(mContinuousMode)
- .build();
+ synchronized (mEnabledLock) {
+ logAndPrintln(pw, "Start tracing to " + mTraceFile + ".");
+ mBuffer.resetBuffer();
mEnabled = mEnabledLockFree = true;
}
}
- private void logAndPrintln(@Nullable PrintWriter pw, String msg) {
- Log.i(TAG, msg);
- if (pw != null) {
- pw.println(msg);
- pw.flush();
- }
- }
-
void stopTrace(@Nullable PrintWriter pw) {
if (IS_USER) {
logAndPrintln(pw, "Error: Tracing is not supported on user builds.");
return;
}
- synchronized (mLock) {
- logAndPrintln(pw, "Stop tracing to " + mBufferBuilder.getFile()
- + ". Waiting for traces to flush.");
+ synchronized (mEnabledLock) {
+ logAndPrintln(pw, "Stop tracing to " + mTraceFile + ". Waiting for traces to flush.");
mEnabled = mEnabledLockFree = false;
- synchronized (mLock) {
- if (mEnabled) {
- logAndPrintln(pw, "ERROR: tracing was re-enabled while waiting for flush.");
- throw new IllegalStateException("tracing enabled while waiting for flush.");
- }
- writeTraceToFileLocked();
- mTraceBuffer = null;
+ if (mEnabled) {
+ logAndPrintln(pw, "ERROR: tracing was re-enabled while waiting for flush.");
+ throw new IllegalStateException("tracing enabled while waiting for flush.");
}
- logAndPrintln(pw, "Trace written to " + mBufferBuilder.getFile() + ".");
+ writeTraceToFileLocked();
+ logAndPrintln(pw, "Trace written to " + mTraceFile + ".");
}
}
- @VisibleForTesting
- void setContinuousMode(boolean continuous, PrintWriter pw) {
- logAndPrintln(pw, "Setting window tracing continuous mode to " + continuous);
+ private void setLogLevel(@WindowTraceLogLevel int logLevel, PrintWriter pw) {
+ logAndPrintln(pw, "Setting window tracing log level to " + logLevel);
+ mLogLevel = logLevel;
- if (mEnabled) {
- logAndPrintln(pw, "Trace is currently active, change will take effect once the "
- + "trace is restarted.");
+ switch (logLevel) {
+ case WindowTraceLogLevel.ALL: {
+ setBufferCapacity(BUFFER_CAPACITY_ALL, pw);
+ break;
+ }
+ case WindowTraceLogLevel.TRIM: {
+ setBufferCapacity(BUFFER_CAPACITY_TRIM, pw);
+ break;
+ }
+ case WindowTraceLogLevel.CRITICAL: {
+ setBufferCapacity(BUFFER_CAPACITY_CRITICAL, pw);
+ break;
+ }
}
- mContinuousMode = continuous;
- mWindowTraceLogLevel = (continuous) ? WindowTraceLogLevel.CRITICAL :
- WindowTraceLogLevel.TRIM;
}
- boolean isEnabled() {
- return mEnabledLockFree;
+ private void setLogFrequency(boolean onFrame, PrintWriter pw) {
+ logAndPrintln(pw, "Setting window tracing log frequency to "
+ + ((onFrame) ? "frame" : "transaction"));
+ mLogOnFrame = onFrame;
}
- static WindowTracing createDefaultAndStartLooper(WindowManagerService service,
- Choreographer choreographer) {
- File file = new File("/data/misc/wmtrace/wm_trace.pb");
- return new WindowTracing(file, service, choreographer);
+ private void setBufferCapacity(int capacity, PrintWriter pw) {
+ logAndPrintln(pw, "Setting window tracing buffer capacity to " + capacity + "bytes");
+ mBuffer.setCapacity(capacity);
+ }
+
+ boolean isEnabled() {
+ return mEnabledLockFree;
}
int onShellCommand(ShellCommand shell) {
PrintWriter pw = shell.getOutPrintWriter();
- try {
- String cmd = shell.getNextArgRequired();
- switch (cmd) {
- case "start":
- startTrace(pw);
- return 0;
- case "stop":
- stopTrace(pw);
- return 0;
- case "continuous":
- setContinuousMode(Boolean.valueOf(shell.getNextArgRequired()), pw);
- return 0;
- default:
- pw.println("Unknown command: " + cmd);
- return -1;
- }
- } catch (IOException e) {
- logAndPrintln(pw, e.toString());
- throw new RuntimeException(e);
+ String cmd = shell.getNextArgRequired();
+ switch (cmd) {
+ case "start":
+ startTrace(pw);
+ return 0;
+ case "stop":
+ stopTrace(pw);
+ return 0;
+ case "status":
+ logAndPrintln(pw, getStatus());
+ return 0;
+ case "frame":
+ setLogFrequency(true /* onFrame */, pw);
+ mBuffer.resetBuffer();
+ return 0;
+ case "transaction":
+ setLogFrequency(false /* onFrame */, pw);
+ mBuffer.resetBuffer();
+ return 0;
+ case "level":
+ String logLevelStr = shell.getNextArgRequired().toLowerCase();
+ switch (logLevelStr) {
+ case "all": {
+ setLogLevel(WindowTraceLogLevel.ALL, pw);
+ break;
+ }
+ case "trim": {
+ setLogLevel(WindowTraceLogLevel.TRIM, pw);
+ break;
+ }
+ case "critical": {
+ setLogLevel(WindowTraceLogLevel.CRITICAL, pw);
+ break;
+ }
+ default: {
+ setLogLevel(WindowTraceLogLevel.TRIM, pw);
+ break;
+ }
+ }
+ mBuffer.resetBuffer();
+ return 0;
+ case "size":
+ setBufferCapacity(Integer.parseInt(shell.getNextArgRequired()) * 1024, pw);
+ mBuffer.resetBuffer();
+ return 0;
+ default:
+ pw.println("Unknown command: " + cmd);
+ pw.println("Window manager trace options:");
+ pw.println(" start: Start logging");
+ pw.println(" stop: Stop logging");
+ pw.println(" frame: Log trace once per frame");
+ pw.println(" transaction: Log each transaction");
+ pw.println(" size: Set the maximum log size (in KB)");
+ pw.println(" level [lvl]: Set the log level between");
+ pw.println(" lvl may be one of:");
+ pw.println(" critical: Only visible windows with reduced information");
+ pw.println(" trim: All windows with reduced");
+ pw.println(" all: All window and information");
+ return -1;
}
}
+ private String getStatus() {
+ return "Status: "
+ + ((isEnabled()) ? "Enabled" : "Disabled")
+ + "\n"
+ + "Log level: "
+ + mLogLevel
+ + "\n"
+ + mBuffer.getStatus();
+ }
+
/**
* If tracing is enabled, log the current state or schedule the next frame to be logged,
- * according to {@link #mContinuousMode}.
+ * according to {@link #mLogOnFrame}.
*
* @param where Logging point descriptor
*/
@@ -188,7 +238,7 @@ class WindowTracing {
return;
}
- if (mContinuousMode) {
+ if (mLogOnFrame) {
schedule();
} else {
log(where);
@@ -215,25 +265,24 @@ class WindowTracing {
private void log(String where) {
Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "traceStateLocked");
try {
- synchronized (mGlobalLock) {
- ProtoOutputStream os = new ProtoOutputStream();
- long tokenOuter = os.start(ENTRY);
- os.write(ELAPSED_REALTIME_NANOS, SystemClock.elapsedRealtimeNanos());
- os.write(WHERE, where);
+ ProtoOutputStream os = new ProtoOutputStream();
+ long tokenOuter = os.start(ENTRY);
+ os.write(ELAPSED_REALTIME_NANOS, SystemClock.elapsedRealtimeNanos());
+ os.write(WHERE, where);
+ long tokenInner = os.start(WINDOW_MANAGER_SERVICE);
+ synchronized (mGlobalLock) {
Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "writeToProtoLocked");
try {
- long tokenInner = os.start(WINDOW_MANAGER_SERVICE);
- mService.writeToProtoLocked(os, mWindowTraceLogLevel);
- os.end(tokenInner);
+ mService.writeToProtoLocked(os, mLogLevel);
} finally {
Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER);
}
- os.end(tokenOuter);
- mTraceBuffer.add(os);
-
- mScheduled = false;
}
+ os.end(tokenInner);
+ os.end(tokenOuter);
+ mBuffer.add(os);
+ mScheduled = false;
} catch (Exception e) {
Log.wtf(TAG, "Exception while tracing state", e);
} finally {
@@ -242,31 +291,37 @@ class WindowTracing {
}
/**
- * Writes the trace buffer to disk. This method has no internal synchronization and should be
- * externally synchronized
+ * Writes the trace buffer to new file for the bugreport.
+ *
+ * This method is synchronized with {@code #startTrace(PrintWriter)} and
+ * {@link #stopTrace(PrintWriter)}.
*/
- private void writeTraceToFileLocked() {
- if (mTraceBuffer == null) {
- return;
+ void writeTraceToFile() {
+ synchronized (mEnabledLock) {
+ writeTraceToFileLocked();
}
+ }
- try {
- mTraceBuffer.dump();
- } catch (IOException e) {
- Log.e(TAG, "Unable to write buffer to file", e);
- } catch (InterruptedException e) {
- Log.e(TAG, "Unable to interrupt window tracing file write thread", e);
+ private void logAndPrintln(@Nullable PrintWriter pw, String msg) {
+ Log.i(TAG, msg);
+ if (pw != null) {
+ pw.println(msg);
+ pw.flush();
}
}
/**
- * Writes the trace buffer to disk and clones it into a new file for the bugreport.
- * This method is synchronized with {@code #startTrace(PrintWriter)} and
- * {@link #stopTrace(PrintWriter)}.
+ * Writes the trace buffer to disk. This method has no internal synchronization and should be
+ * externally synchronized
*/
- void writeTraceToFile() {
- synchronized (mLock) {
- writeTraceToFileLocked();
+ private void writeTraceToFileLocked() {
+ try {
+ Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "writeTraceToFileLocked");
+ mBuffer.writeTraceToFile(mTraceFile);
+ } catch (IOException e) {
+ Log.e(TAG, "Unable to write buffer to file", e);
+ } finally {
+ Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER);
}
}
-}
+} \ No newline at end of file
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index a6017f2c1e86..aae159c2edcb 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -36,6 +36,7 @@ import android.content.res.Configuration;
import android.content.res.Resources.Theme;
import android.database.sqlite.SQLiteCompatibilityWalFlags;
import android.database.sqlite.SQLiteGlobal;
+import android.net.NetworkStackClient;
import android.os.BaseBundle;
import android.os.Binder;
import android.os.Build;
@@ -1350,9 +1351,7 @@ public final class SystemServer {
traceBeginAndSlog("StartNetworkStack");
try {
- final android.net.NetworkStack networkStack =
- context.getSystemService(android.net.NetworkStack.class);
- networkStack.start(context);
+ NetworkStackClient.getInstance().start(context);
} catch (Throwable e) {
reportWtf("starting Network Stack", e);
}
diff --git a/services/net/Android.bp b/services/net/Android.bp
index 9946cc3db0e8..8ad4d7679107 100644
--- a/services/net/Android.bp
+++ b/services/net/Android.bp
@@ -3,6 +3,7 @@ java_library_static {
srcs: ["java/**/*.java"],
static_libs: [
"netd_aidl_interface-java",
+ "networkstack-aidl-interfaces-java",
]
}
diff --git a/services/net/java/android/net/NetworkStackClient.java b/services/net/java/android/net/NetworkStackClient.java
new file mode 100644
index 000000000000..1eb7b98d801a
--- /dev/null
+++ b/services/net/java/android/net/NetworkStackClient.java
@@ -0,0 +1,289 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.net;
+
+import static android.content.pm.PackageManager.PERMISSION_GRANTED;
+import static android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK;
+import static android.os.IServiceManager.DUMP_FLAG_PRIORITY_HIGH;
+import static android.os.IServiceManager.DUMP_FLAG_PRIORITY_NORMAL;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.ServiceConnection;
+import android.content.pm.PackageManager;
+import android.net.dhcp.DhcpServingParamsParcel;
+import android.net.dhcp.IDhcpServerCallbacks;
+import android.net.ip.IIpClientCallbacks;
+import android.os.Binder;
+import android.os.IBinder;
+import android.os.Process;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+import android.os.UserHandle;
+import android.util.Slog;
+
+import com.android.internal.annotations.GuardedBy;
+
+import java.lang.reflect.InvocationTargetException;
+import java.util.ArrayList;
+
+/**
+ * Service used to communicate with the network stack, which is running in a separate module.
+ * @hide
+ */
+public class NetworkStackClient {
+ private static final String TAG = NetworkStackClient.class.getSimpleName();
+
+ private static final int NETWORKSTACK_TIMEOUT_MS = 10_000;
+
+ private static NetworkStackClient sInstance;
+
+ @NonNull
+ @GuardedBy("mPendingNetStackRequests")
+ private final ArrayList<NetworkStackCallback> mPendingNetStackRequests = new ArrayList<>();
+ @Nullable
+ @GuardedBy("mPendingNetStackRequests")
+ private INetworkStackConnector mConnector;
+
+ private volatile boolean mNetworkStackStartRequested = false;
+
+ private interface NetworkStackCallback {
+ void onNetworkStackConnected(INetworkStackConnector connector);
+ }
+
+ private NetworkStackClient() { }
+
+ /**
+ * Get the NetworkStackClient singleton instance.
+ */
+ public static synchronized NetworkStackClient getInstance() {
+ if (sInstance == null) {
+ sInstance = new NetworkStackClient();
+ }
+ return sInstance;
+ }
+
+ /**
+ * Create a DHCP server according to the specified parameters.
+ *
+ * <p>The server will be returned asynchronously through the provided callbacks.
+ */
+ public void makeDhcpServer(final String ifName, final DhcpServingParamsParcel params,
+ final IDhcpServerCallbacks cb) {
+ requestConnector(connector -> {
+ try {
+ connector.makeDhcpServer(ifName, params, cb);
+ } catch (RemoteException e) {
+ e.rethrowFromSystemServer();
+ }
+ });
+ }
+
+ /**
+ * Create an IpClient on the specified interface.
+ *
+ * <p>The IpClient will be returned asynchronously through the provided callbacks.
+ */
+ public void makeIpClient(String ifName, IIpClientCallbacks cb) {
+ requestConnector(connector -> {
+ try {
+ connector.makeIpClient(ifName, cb);
+ } catch (RemoteException e) {
+ e.rethrowFromSystemServer();
+ }
+ });
+ }
+
+ /**
+ * Create a NetworkMonitor.
+ *
+ * <p>The INetworkMonitor will be returned asynchronously through the provided callbacks.
+ */
+ public void makeNetworkMonitor(
+ NetworkParcelable network, String name, INetworkMonitorCallbacks cb) {
+ requestConnector(connector -> {
+ try {
+ connector.makeNetworkMonitor(network, name, cb);
+ } catch (RemoteException e) {
+ e.rethrowFromSystemServer();
+ }
+ });
+ }
+
+ private class NetworkStackConnection implements ServiceConnection {
+ @Override
+ public void onServiceConnected(ComponentName name, IBinder service) {
+ registerNetworkStackService(service);
+ }
+
+ @Override
+ public void onServiceDisconnected(ComponentName name) {
+ // TODO: crash/reboot the system ?
+ Slog.wtf(TAG, "Lost network stack connector");
+ }
+ };
+
+ private void registerNetworkStackService(@NonNull IBinder service) {
+ final INetworkStackConnector connector = INetworkStackConnector.Stub.asInterface(service);
+
+ ServiceManager.addService(Context.NETWORK_STACK_SERVICE, service, false /* allowIsolated */,
+ DUMP_FLAG_PRIORITY_HIGH | DUMP_FLAG_PRIORITY_NORMAL);
+
+ final ArrayList<NetworkStackCallback> requests;
+ synchronized (mPendingNetStackRequests) {
+ requests = new ArrayList<>(mPendingNetStackRequests);
+ mPendingNetStackRequests.clear();
+ mConnector = connector;
+ }
+
+ for (NetworkStackCallback r : requests) {
+ r.onNetworkStackConnected(connector);
+ }
+ }
+
+ /**
+ * Start the network stack. Should be called only once on device startup.
+ *
+ * <p>This method will start the network stack either in the network stack process, or inside
+ * the system server on devices that do not support the network stack module. The network stack
+ * connector will then be delivered asynchronously to clients that requested it before it was
+ * started.
+ */
+ public void start(Context context) {
+ mNetworkStackStartRequested = true;
+ // Try to bind in-process if the library is available
+ IBinder connector = null;
+ try {
+ final Class service = Class.forName(
+ "com.android.server.NetworkStackService",
+ true /* initialize */,
+ context.getClassLoader());
+ connector = (IBinder) service.getMethod("makeConnector", Context.class)
+ .invoke(null, context);
+ } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
+ Slog.wtf(TAG, "Could not create network stack connector from NetworkStackService");
+ // TODO: crash/reboot system here ?
+ return;
+ } catch (ClassNotFoundException e) {
+ // Normal behavior if stack is provided by the app: fall through
+ }
+
+ // In-process network stack. Add the service to the service manager here.
+ if (connector != null) {
+ registerNetworkStackService(connector);
+ return;
+ }
+ // Start the network stack process. The service will be added to the service manager in
+ // NetworkStackConnection.onServiceConnected().
+ final Intent intent = new Intent(INetworkStackConnector.class.getName());
+ final ComponentName comp = intent.resolveSystemService(context.getPackageManager(), 0);
+ intent.setComponent(comp);
+
+ if (comp == null) {
+ Slog.wtf(TAG, "Could not resolve the network stack with " + intent);
+ // TODO: crash/reboot system server ?
+ return;
+ }
+ final PackageManager pm = context.getPackageManager();
+ int uid = -1;
+ try {
+ uid = pm.getPackageUid(comp.getPackageName(), UserHandle.USER_SYSTEM);
+ } catch (PackageManager.NameNotFoundException e) {
+ Slog.wtf("Network stack package not found", e);
+ // Fall through
+ }
+ if (uid != Process.NETWORK_STACK_UID) {
+ throw new SecurityException("Invalid network stack UID: " + uid);
+ }
+
+ final int hasPermission =
+ pm.checkPermission(PERMISSION_MAINLINE_NETWORK_STACK, comp.getPackageName());
+ if (hasPermission != PERMISSION_GRANTED) {
+ throw new SecurityException(
+ "Network stack does not have permission " + PERMISSION_MAINLINE_NETWORK_STACK);
+ }
+
+ if (!context.bindServiceAsUser(intent, new NetworkStackConnection(),
+ Context.BIND_AUTO_CREATE | Context.BIND_IMPORTANT, UserHandle.SYSTEM)) {
+ Slog.wtf(TAG,
+ "Could not bind to network stack in-process, or in app with " + intent);
+ // TODO: crash/reboot system server if no network stack after a timeout ?
+ }
+ }
+
+ /**
+ * For non-system server clients, get the connector registered by the system server.
+ */
+ private INetworkStackConnector getRemoteConnector() {
+ // Block until the NetworkStack connector is registered in ServiceManager.
+ // <p>This is only useful for non-system processes that do not have a way to be notified of
+ // registration completion. Adding a callback system would be too heavy weight considering
+ // that the connector is registered on boot, so it is unlikely that a client would request
+ // it before it is registered.
+ // TODO: consider blocking boot on registration and simplify much of the logic in this class
+ IBinder connector;
+ try {
+ final long before = System.currentTimeMillis();
+ while ((connector = ServiceManager.getService(Context.NETWORK_STACK_SERVICE)) == null) {
+ Thread.sleep(20);
+ if (System.currentTimeMillis() - before > NETWORKSTACK_TIMEOUT_MS) {
+ Slog.e(TAG, "Timeout waiting for NetworkStack connector");
+ return null;
+ }
+ }
+ } catch (InterruptedException e) {
+ Slog.e(TAG, "Error waiting for NetworkStack connector", e);
+ return null;
+ }
+
+ return INetworkStackConnector.Stub.asInterface(connector);
+ }
+
+ private void requestConnector(@NonNull NetworkStackCallback request) {
+ // TODO: PID check.
+ final int caller = Binder.getCallingUid();
+ if (caller != Process.SYSTEM_UID && !UserHandle.isSameApp(caller, Process.BLUETOOTH_UID)) {
+ // Don't even attempt to obtain the connector and give a nice error message
+ throw new SecurityException(
+ "Only the system server should try to bind to the network stack.");
+ }
+
+ if (!mNetworkStackStartRequested) {
+ // The network stack is not being started in this process, e.g. this process is not
+ // the system server. Get a remote connector registered by the system server.
+ final INetworkStackConnector connector = getRemoteConnector();
+ synchronized (mPendingNetStackRequests) {
+ mConnector = connector;
+ }
+ request.onNetworkStackConnected(connector);
+ return;
+ }
+
+ final INetworkStackConnector connector;
+ synchronized (mPendingNetStackRequests) {
+ connector = mConnector;
+ if (connector == null) {
+ mPendingNetStackRequests.add(request);
+ return;
+ }
+ }
+
+ request.onNetworkStackConnected(connector);
+ }
+}
diff --git a/core/java/android/net/dhcp/DhcpServerCallbacks.java b/services/net/java/android/net/dhcp/DhcpServerCallbacks.java
index bb56876c77f5..bb56876c77f5 100644
--- a/core/java/android/net/dhcp/DhcpServerCallbacks.java
+++ b/services/net/java/android/net/dhcp/DhcpServerCallbacks.java
diff --git a/core/java/android/net/ip/IpClientCallbacks.java b/services/net/java/android/net/ip/IpClientCallbacks.java
index db01ae4d4d9c..db01ae4d4d9c 100644
--- a/core/java/android/net/ip/IpClientCallbacks.java
+++ b/services/net/java/android/net/ip/IpClientCallbacks.java
diff --git a/services/net/java/android/net/ip/IpClientUtil.java b/services/net/java/android/net/ip/IpClientUtil.java
index 2a2a67a92a86..bf917bf88b2d 100644
--- a/services/net/java/android/net/ip/IpClientUtil.java
+++ b/services/net/java/android/net/ip/IpClientUtil.java
@@ -23,8 +23,7 @@ import android.content.Context;
import android.net.DhcpResultsParcelable;
import android.net.LinkProperties;
import android.net.LinkPropertiesParcelable;
-import android.net.NetworkStack;
-import android.net.ip.IIpClientCallbacks;
+import android.net.NetworkStackClient;
import android.os.ConditionVariable;
import java.io.FileDescriptor;
@@ -76,30 +75,17 @@ public class IpClientUtil {
*
* <p>This is a convenience method to allow clients to use {@link IpClientCallbacks} instead of
* {@link IIpClientCallbacks}.
- * @see {@link NetworkStack#makeIpClient(String, IIpClientCallbacks)}
+ * @see {@link NetworkStackClient#makeIpClient(String, IIpClientCallbacks)}
*/
public static void makeIpClient(Context context, String ifName, IpClientCallbacks callback) {
- context.getSystemService(NetworkStack.class)
- .makeIpClient(ifName, new IpClientCallbacksProxy(callback));
- }
-
- /**
- * Create a new IpClient.
- *
- * <p>This is a convenience method to allow clients to use {@link IpClientCallbacksProxy}
- * instead of {@link IIpClientCallbacks}.
- * @see {@link NetworkStack#makeIpClient(String, IIpClientCallbacks)}
- */
- public static void makeIpClient(
- Context context, String ifName, IpClientCallbacksProxy callback) {
- context.getSystemService(NetworkStack.class)
- .makeIpClient(ifName, callback);
+ // TODO: migrate clients and remove context argument
+ NetworkStackClient.getInstance().makeIpClient(ifName, new IpClientCallbacksProxy(callback));
}
/**
* Wrapper to relay calls from {@link IIpClientCallbacks} to {@link IpClientCallbacks}.
*/
- public static class IpClientCallbacksProxy extends IIpClientCallbacks.Stub {
+ private static class IpClientCallbacksProxy extends IIpClientCallbacks.Stub {
protected final IpClientCallbacks mCb;
/**
diff --git a/services/net/java/android/net/ip/IpServer.java b/services/net/java/android/net/ip/IpServer.java
index 7910c9a69310..34fc7354d63e 100644
--- a/services/net/java/android/net/ip/IpServer.java
+++ b/services/net/java/android/net/ip/IpServer.java
@@ -22,7 +22,6 @@ import static android.net.util.NetworkConstants.FF;
import static android.net.util.NetworkConstants.RFC7421_PREFIX_LENGTH;
import static android.net.util.NetworkConstants.asByte;
-import android.content.Context;
import android.net.ConnectivityManager;
import android.net.INetd;
import android.net.INetworkStackStatusCallback;
@@ -31,7 +30,7 @@ import android.net.InterfaceConfiguration;
import android.net.IpPrefix;
import android.net.LinkAddress;
import android.net.LinkProperties;
-import android.net.NetworkStack;
+import android.net.NetworkStackClient;
import android.net.RouteInfo;
import android.net.dhcp.DhcpServerCallbacks;
import android.net.dhcp.DhcpServingParamsParcel;
@@ -132,10 +131,6 @@ public class IpServer extends StateMachine {
}
public static class Dependencies {
- private final Context mContext;
- public Dependencies(Context context) {
- mContext = context;
- }
public RouterAdvertisementDaemon getRouterAdvertisementDaemon(InterfaceParams ifParams) {
return new RouterAdvertisementDaemon(ifParams);
}
@@ -153,7 +148,7 @@ public class IpServer extends StateMachine {
*/
public void makeDhcpServer(String ifName, DhcpServingParamsParcel params,
DhcpServerCallbacks cb) {
- mContext.getSystemService(NetworkStack.class).makeDhcpServer(ifName, params, cb);
+ NetworkStackClient.getInstance().makeDhcpServer(ifName, params, cb);
}
}
diff --git a/services/tests/servicestests/src/com/android/server/backup/testutils/IPackageManagerStub.java b/services/tests/servicestests/src/com/android/server/backup/testutils/IPackageManagerStub.java
index 0355e84d884d..5cb6cbb93b5b 100644
--- a/services/tests/servicestests/src/com/android/server/backup/testutils/IPackageManagerStub.java
+++ b/services/tests/servicestests/src/com/android/server/backup/testutils/IPackageManagerStub.java
@@ -556,16 +556,6 @@ public class IPackageManagerStub implements IPackageManager {
}
@Override
- public byte[] getPermissionGrantBackup(int userId) throws RemoteException {
- return new byte[0];
- }
-
- @Override
- public void restorePermissionGrants(byte[] backup, int userId) throws RemoteException {
-
- }
-
- @Override
public ComponentName getHomeActivities(List<ResolveInfo> outHomeCandidates)
throws RemoteException {
return null;
diff --git a/services/tests/servicestests/src/com/android/server/display/ColorDisplayServiceTest.java b/services/tests/servicestests/src/com/android/server/display/ColorDisplayServiceTest.java
index 5900fc57296c..01759d2e8f4a 100644
--- a/services/tests/servicestests/src/com/android/server/display/ColorDisplayServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/display/ColorDisplayServiceTest.java
@@ -98,6 +98,8 @@ public class ColorDisplayServiceTest {
mColorDisplayService = new ColorDisplayService(mContext);
mBinderService = mColorDisplayService.new BinderService();
+ LocalServices.addService(ColorDisplayService.ColorDisplayServiceInternal.class,
+ mColorDisplayService.new ColorDisplayServiceInternal());
}
@After
@@ -110,6 +112,8 @@ public class ColorDisplayServiceTest {
mUserId = UserHandle.USER_NULL;
mContext = null;
+
+ LocalServices.removeServiceForTest(ColorDisplayService.ColorDisplayServiceInternal.class);
}
@AfterClass
@@ -979,6 +983,99 @@ public class ColorDisplayServiceTest {
assertActiveColorMode(ColorDisplayManager.COLOR_MODE_NATURAL);
}
+ @Test
+ public void displayWhiteBalance_enable() {
+ setWhiteBalance(true /* Enable DWB Setting */);
+ setActivated(false /* activated */, -30 /* lastActivatedTimeOffset */);
+ mBinderService.setColorMode(ColorDisplayManager.COLOR_MODE_NATURAL);
+ startService();
+ assertDwbActive(true);
+ }
+
+ @Test
+ public void displayWhiteBalance_disableAfterNightDisplayEnable() {
+ setWhiteBalance(true /* Enable DWB Setting */);
+
+ startService();
+ /* Enable nightlight */
+ setAutoModeTwilight(-120 /* sunsetOffset */, -60 /* sunriseOffset */);
+ setActivated(true /* activated */, -30 /* lastActivatedTimeOffset */);
+
+ /* Since we are using FakeSettingsProvider which could not trigger observer change,
+ * force an update here.*/
+ mColorDisplayService.updateDisplayWhiteBalanceStatus();
+ assertDwbActive(false);
+ }
+
+ @Test
+ public void displayWhiteBalance_enableAfterNightDisplayDisable() {
+ setWhiteBalance(true /* Enable DWB Setting */);
+ startService();
+ /* Enable nightlight */
+ setAutoModeTwilight(-120 /* sunsetOffset */, -60 /* sunriseOffset */);
+ setActivated(true /* activated */, -30 /* lastActivatedTimeOffset */);
+
+ mColorDisplayService.updateDisplayWhiteBalanceStatus();
+ assertDwbActive(false);
+
+ /* Disable nightlight */
+ setActivated(false /* activated */, -30 /* lastActivatedTimeOffset */);
+ mColorDisplayService.updateDisplayWhiteBalanceStatus();
+ assertDwbActive(true);
+ }
+
+ @Test
+ public void displayWhiteBalance_enableAfterLinearColorMode() {
+ setWhiteBalance(true /* Enable DWB Setting */);
+ setActivated(false /* activated */, -30 /* lastActivatedTimeOffset */);
+ startService();
+ mBinderService.setColorMode(ColorDisplayManager.COLOR_MODE_NATURAL);
+
+ mColorDisplayService.updateDisplayWhiteBalanceStatus();
+ assertDwbActive(true);
+ }
+
+ @Test
+ public void displayWhiteBalance_setTemperatureOverMax() {
+ int max = mColorDisplayService.mDisplayWhiteBalanceTintController.mTemperatureMax;
+
+ ColorDisplayService.ColorDisplayServiceInternal cdsInternal = LocalServices.getService(
+ ColorDisplayService.ColorDisplayServiceInternal.class);
+ cdsInternal.setDisplayWhiteBalanceColorTemperature(max+1);
+
+ assertWithMessage("Unexpected temperature set")
+ .that(mColorDisplayService.mDisplayWhiteBalanceTintController.mCurrentColorTemperature)
+ .isEqualTo(max);
+ }
+
+ @Test
+ public void displayWhiteBalance_setTemperatureBelowMin() {
+ int min = mColorDisplayService.mDisplayWhiteBalanceTintController.mTemperatureMin;
+
+ ColorDisplayService.ColorDisplayServiceInternal cdsInternal = LocalServices.getService(
+ ColorDisplayService.ColorDisplayServiceInternal.class);
+ cdsInternal.setDisplayWhiteBalanceColorTemperature(min - 1);
+
+ assertWithMessage("Unexpected temperature set")
+ .that(mColorDisplayService.mDisplayWhiteBalanceTintController.mCurrentColorTemperature)
+ .isEqualTo(min);
+ }
+
+ @Test
+ public void displayWhiteBalance_setValidTemperature() {
+ int min = mColorDisplayService.mDisplayWhiteBalanceTintController.mTemperatureMin;
+ int max = mColorDisplayService.mDisplayWhiteBalanceTintController.mTemperatureMax;
+ int valToSet = (min + max) / 2;
+
+ ColorDisplayService.ColorDisplayServiceInternal cdsInternal = LocalServices.getService(
+ ColorDisplayService.ColorDisplayServiceInternal.class);
+ cdsInternal.setDisplayWhiteBalanceColorTemperature(valToSet);
+
+ assertWithMessage("Unexpected temperature set")
+ .that(mColorDisplayService.mDisplayWhiteBalanceTintController.mCurrentColorTemperature)
+ .isEqualTo(valToSet);
+ }
+
/**
* Configures Night display to use a custom schedule.
*
@@ -1041,6 +1138,16 @@ public class ColorDisplayServiceTest {
}
/**
+ * Configures the Display White Balance setting state.
+ *
+ * @param state {@code true} if display white balance should be enabled
+ */
+ private void setWhiteBalance(boolean state) {
+ Secure.putIntForUser(mContext.getContentResolver(),
+ Secure.DISPLAY_WHITE_BALANCE_ENABLED, state ? 1 : 0, mUserId);
+ }
+
+ /**
* Configures color mode.
*/
private void setColorMode(int colorMode) {
@@ -1111,6 +1218,17 @@ public class ColorDisplayServiceTest {
}
/**
+ * Convenience method for asserting that the DWB active status matches expectation.
+ *
+ * @param enabled the expected active status.
+ */
+ private void assertDwbActive(boolean enabled) {
+ assertWithMessage("Incorrect Display White Balance state")
+ .that(mColorDisplayService.mDisplayWhiteBalanceTintController.isActivated())
+ .isEqualTo(enabled);
+ }
+
+ /**
* Convenience for making a {@link LocalTime} instance with an offset relative to now.
*
* @param offsetMinutes the offset relative to now (in minutes)
diff --git a/services/tests/servicestests/src/com/android/server/pm/PackageManagerSettingsTests.java b/services/tests/servicestests/src/com/android/server/pm/PackageManagerSettingsTests.java
index 6d28ed19af4f..50734efacac9 100644
--- a/services/tests/servicestests/src/com/android/server/pm/PackageManagerSettingsTests.java
+++ b/services/tests/servicestests/src/com/android/server/pm/PackageManagerSettingsTests.java
@@ -55,8 +55,8 @@ import androidx.test.runner.AndroidJUnit4;
import com.android.internal.os.AtomicFile;
import com.android.server.LocalServices;
-import com.android.server.pm.permission.PermissionManagerInternal;
import com.android.server.pm.permission.PermissionManagerService;
+import com.android.server.pm.permission.PermissionManagerServiceInternal;
import org.junit.After;
import org.junit.Before;
@@ -88,7 +88,8 @@ public class PackageManagerSettingsTests {
writeOldFiles();
final Context context = InstrumentationRegistry.getContext();
final Object lock = new Object();
- PermissionManagerInternal pmInt = PermissionManagerService.create(context, null, lock);
+ PermissionManagerServiceInternal pmInt = PermissionManagerService.create(context, null,
+ lock);
Settings settings =
new Settings(context.getFilesDir(), pmInt.getPermissionSettings(), lock);
assertThat(settings.readLPw(createFakeUsers()), is(true));
@@ -103,7 +104,8 @@ public class PackageManagerSettingsTests {
writeOldFiles();
final Context context = InstrumentationRegistry.getContext();
final Object lock = new Object();
- PermissionManagerInternal pmInt = PermissionManagerService.create(context, null, lock);
+ PermissionManagerServiceInternal pmInt = PermissionManagerService.create(context, null,
+ lock);
Settings settings =
new Settings(context.getFilesDir(), pmInt.getPermissionSettings(), lock);
assertThat(settings.readLPw(createFakeUsers()), is(true));
@@ -120,7 +122,8 @@ public class PackageManagerSettingsTests {
writeOldFiles();
final Context context = InstrumentationRegistry.getContext();
final Object lock = new Object();
- PermissionManagerInternal pmInt = PermissionManagerService.create(context, null, lock);
+ PermissionManagerServiceInternal pmInt = PermissionManagerService.create(context, null,
+ lock);
Settings settings =
new Settings(context.getFilesDir(), pmInt.getPermissionSettings(), lock);
assertThat(settings.readLPw(createFakeUsers()), is(true));
@@ -143,7 +146,8 @@ public class PackageManagerSettingsTests {
writeOldFiles();
final Context context = InstrumentationRegistry.getContext();
final Object lock = new Object();
- PermissionManagerInternal pmInt = PermissionManagerService.create(context, null, lock);
+ PermissionManagerServiceInternal pmInt = PermissionManagerService.create(context, null,
+ lock);
Settings settings =
new Settings(context.getFilesDir(), pmInt.getPermissionSettings(), lock);
assertThat(settings.readLPw(createFakeUsers()), is(true));
@@ -313,7 +317,8 @@ public class PackageManagerSettingsTests {
writeOldFiles();
final Context context = InstrumentationRegistry.getContext();
final Object lock = new Object();
- PermissionManagerInternal pmInt = PermissionManagerService.create(context, null, lock);
+ PermissionManagerServiceInternal pmInt = PermissionManagerService.create(context, null,
+ lock);
Settings settings =
new Settings(context.getFilesDir(), pmInt.getPermissionSettings(), lock);
assertThat(settings.readLPw(createFakeUsers()), is(true));
@@ -507,7 +512,8 @@ public class PackageManagerSettingsTests {
public void testUpdatePackageSetting03() {
final Context context = InstrumentationRegistry.getContext();
final Object lock = new Object();
- PermissionManagerInternal pmInt = PermissionManagerService.create(context, null, lock);
+ PermissionManagerServiceInternal pmInt = PermissionManagerService.create(context, null,
+ lock);
final Settings testSettings01 =
new Settings(context.getFilesDir(), pmInt.getPermissionSettings(), lock);
final SharedUserSetting testUserSetting01 = createSharedUserSetting(
@@ -625,7 +631,8 @@ public class PackageManagerSettingsTests {
public void testCreateNewSetting03() {
final Context context = InstrumentationRegistry.getContext();
final Object lock = new Object();
- PermissionManagerInternal pmInt = PermissionManagerService.create(context, null, lock);
+ PermissionManagerServiceInternal pmInt = PermissionManagerService.create(context, null,
+ lock);
final Settings testSettings01 =
new Settings(context.getFilesDir(), pmInt.getPermissionSettings(), lock);
final SharedUserSetting testUserSetting01 = createSharedUserSetting(
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowTraceBufferTest.java b/services/tests/wmtests/src/com/android/server/wm/WindowTraceBufferTest.java
index 2b8e307e23b7..b299f0dd7253 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowTraceBufferTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowTraceBufferTest.java
@@ -36,11 +36,10 @@ import org.junit.Before;
import org.junit.Test;
import java.io.File;
-import java.io.IOException;
/**
- * Test class for {@link WindowTraceBuffer} and {@link WindowTraceQueueBuffer}.
+ * Test class for {@link WindowTraceBuffer}.
*
* Build/Install/Run:
* atest WmTests:WindowTraceBufferTest
@@ -49,12 +48,15 @@ import java.io.IOException;
@Presubmit
public class WindowTraceBufferTest {
private File mFile;
+ private WindowTraceBuffer mBuffer;
@Before
public void setUp() throws Exception {
final Context testContext = getInstrumentation().getContext();
mFile = testContext.getFileStreamPath("tracing_test.dat");
mFile.delete();
+
+ mBuffer = new WindowTraceBuffer(10);
}
@After
@@ -63,145 +65,112 @@ public class WindowTraceBufferTest {
}
@Test
- public void testTraceQueueBuffer_addItem() throws Exception {
- ProtoOutputStream toWrite1 = getDummy(1);
- ProtoOutputStream toWrite2 = getDummy(2);
- ProtoOutputStream toWrite3 = getDummy(3);
- final int objectSize = toWrite1.getRawSize();
- final int bufferCapacity = objectSize * 2;
-
- final WindowTraceBuffer buffer = buildQueueBuffer(bufferCapacity);
-
- buffer.add(toWrite1);
- byte[] toWrite1Bytes = toWrite1.getBytes();
- assertTrue("First element should be in the list",
- buffer.contains(toWrite1Bytes));
-
- buffer.add(toWrite2);
- byte[] toWrite2Bytes = toWrite2.getBytes();
- assertTrue("First element should be in the list",
- buffer.contains(toWrite1Bytes));
- assertTrue("Second element should be in the list",
- buffer.contains(toWrite2Bytes));
-
- buffer.add(toWrite3);
- byte[] toWrite3Bytes = toWrite3.getBytes();
- assertTrue("First element should be in the list",
- buffer.contains(toWrite1Bytes));
- assertTrue("Second element should be in the list",
- buffer.contains(toWrite2Bytes));
- assertTrue("Third element should not be in the list",
- !buffer.contains(toWrite3Bytes));
-
- assertEquals("Buffer should have 2 elements", buffer.mBuffer.size(), 2);
- assertEquals(String.format("Buffer is full, used space should be %d", bufferCapacity),
- buffer.mBufferSize, bufferCapacity);
- assertEquals("Buffer is full, available space should be 0",
- buffer.getAvailableSpace(), 0);
- }
-
- @Test
- public void testTraceRingBuffer_addItem() throws Exception {
+ public void test_addItem() {
ProtoOutputStream toWrite = getDummy(1);
final int objectSize = toWrite.getRawSize();
+ mBuffer.setCapacity(objectSize);
+ mBuffer.resetBuffer();
- final WindowTraceBuffer buffer = buildRingBuffer(objectSize);
-
- Preconditions.checkArgument(buffer.mBuffer.isEmpty());
+ Preconditions.checkArgument(mBuffer.size() == 0);
- buffer.add(toWrite);
+ mBuffer.add(toWrite);
- assertEquals("Item was not added to the buffer", buffer.mBuffer.size(), 1);
+ assertEquals("Item was not added to the buffer", 1, mBuffer.size());
assertEquals("Total buffer getSize differs from inserted object",
- buffer.mBufferSize, objectSize);
- assertEquals("Available buffer space does not match used one",
- buffer.getAvailableSpace(), 0);
+ mBuffer.getBufferSize(), objectSize);
+ assertEquals("Available buffer space does not match used one", 0,
+ mBuffer.getAvailableSpace());
}
@Test
- public void testTraceRingBuffer_addItemMustOverwriteOne() throws Exception {
+ public void test_addItemMustOverwriteOne() {
ProtoOutputStream toWrite1 = getDummy(1);
ProtoOutputStream toWrite2 = getDummy(2);
ProtoOutputStream toWrite3 = getDummy(3);
final int objectSize = toWrite1.getRawSize();
-
final int bufferCapacity = objectSize * 2 + 1;
- final WindowTraceBuffer buffer = buildRingBuffer(bufferCapacity);
+ mBuffer.setCapacity(bufferCapacity);
+ mBuffer.resetBuffer();
- buffer.add(toWrite1);
+ mBuffer.add(toWrite1);
byte[] toWrite1Bytes = toWrite1.getBytes();
assertTrue("First element should be in the list",
- buffer.contains(toWrite1Bytes));
+ mBuffer.contains(toWrite1Bytes));
- buffer.add(toWrite2);
+ mBuffer.add(toWrite2);
byte[] toWrite2Bytes = toWrite2.getBytes();
assertTrue("First element should be in the list",
- buffer.contains(toWrite1Bytes));
+ mBuffer.contains(toWrite1Bytes));
assertTrue("Second element should be in the list",
- buffer.contains(toWrite2Bytes));
+ mBuffer.contains(toWrite2Bytes));
- buffer.add(toWrite3);
+ mBuffer.add(toWrite3);
byte[] toWrite3Bytes = toWrite3.getBytes();
assertTrue("First element should not be in the list",
- !buffer.contains(toWrite1Bytes));
+ !mBuffer.contains(toWrite1Bytes));
assertTrue("Second element should be in the list",
- buffer.contains(toWrite2Bytes));
+ mBuffer.contains(toWrite2Bytes));
assertTrue("Third element should be in the list",
- buffer.contains(toWrite3Bytes));
- assertEquals("Buffer should have 2 elements", buffer.mBuffer.size(), 2);
+ mBuffer.contains(toWrite3Bytes));
+ assertEquals("Buffer should have 2 elements", 2, mBuffer.size());
assertEquals(String.format("Buffer is full, used space should be %d", bufferCapacity),
- buffer.mBufferSize, bufferCapacity - 1);
- assertEquals(" Buffer is full, available space should be 0",
- buffer.getAvailableSpace(), 1);
+ mBuffer.getBufferSize(), bufferCapacity - 1);
+ assertEquals(" Buffer is full, available space should be 0", 1,
+ mBuffer.getAvailableSpace());
}
@Test
- public void testTraceRingBuffer_addItemMustOverwriteMultiple() throws Exception {
+ public void test_addItemMustOverwriteMultiple() {
ProtoOutputStream toWriteSmall1 = getDummy(1);
ProtoOutputStream toWriteSmall2 = getDummy(2);
final int objectSize = toWriteSmall1.getRawSize();
-
final int bufferCapacity = objectSize * 2;
- final WindowTraceBuffer buffer = buildRingBuffer(bufferCapacity);
+ mBuffer.setCapacity(bufferCapacity);
+ mBuffer.resetBuffer();
ProtoOutputStream toWriteBig = new ProtoOutputStream();
toWriteBig.write(MAGIC_NUMBER, 1);
toWriteBig.write(MAGIC_NUMBER, 2);
- buffer.add(toWriteSmall1);
+ mBuffer.add(toWriteSmall1);
byte[] toWriteSmall1Bytes = toWriteSmall1.getBytes();
assertTrue("First element should be in the list",
- buffer.contains(toWriteSmall1Bytes));
+ mBuffer.contains(toWriteSmall1Bytes));
- buffer.add(toWriteSmall2);
+ mBuffer.add(toWriteSmall2);
byte[] toWriteSmall2Bytes = toWriteSmall2.getBytes();
assertTrue("First element should be in the list",
- buffer.contains(toWriteSmall1Bytes));
+ mBuffer.contains(toWriteSmall1Bytes));
assertTrue("Second element should be in the list",
- buffer.contains(toWriteSmall2Bytes));
+ mBuffer.contains(toWriteSmall2Bytes));
- buffer.add(toWriteBig);
+ mBuffer.add(toWriteBig);
byte[] toWriteBigBytes = toWriteBig.getBytes();
assertTrue("Third element should overwrite all others",
- !buffer.contains(toWriteSmall1Bytes));
+ !mBuffer.contains(toWriteSmall1Bytes));
assertTrue("Third element should overwrite all others",
- !buffer.contains(toWriteSmall2Bytes));
+ !mBuffer.contains(toWriteSmall2Bytes));
assertTrue("Third element should overwrite all others",
- buffer.contains(toWriteBigBytes));
+ mBuffer.contains(toWriteBigBytes));
- assertEquals(" Buffer should have only 1 big element", buffer.mBuffer.size(), 1);
+ assertEquals(" Buffer should have only 1 big element", 1, mBuffer.size());
assertEquals(String.format(" Buffer is full, used space should be %d", bufferCapacity),
- buffer.mBufferSize, bufferCapacity);
- assertEquals(" Buffer is full, available space should be 0",
- buffer.getAvailableSpace(), 0);
+ mBuffer.getBufferSize(), bufferCapacity);
+ assertEquals(" Buffer is full, available space should be 0", 0,
+ mBuffer.getAvailableSpace());
}
- private WindowTraceBuffer buildRingBuffer(int capacity) throws IOException {
- return new WindowTraceBuffer.Builder()
- .setContinuousMode(true)
- .setBufferCapacity(capacity)
- .setTraceFile(mFile)
- .build();
+ @Test
+ public void test_startResetsBuffer() {
+ ProtoOutputStream toWrite = getDummy(1);
+ mBuffer.resetBuffer();
+ Preconditions.checkArgument(mBuffer.size() == 0);
+
+ mBuffer.add(toWrite);
+ assertEquals("Item was not added to the buffer", 1, mBuffer.size());
+ mBuffer.resetBuffer();
+ assertEquals("Buffer should be empty after reset", 0, mBuffer.size());
+ assertEquals("Buffer size should be 0 after reset", 0, mBuffer.getBufferSize());
}
private ProtoOutputStream getDummy(int value) {
@@ -212,7 +181,4 @@ public class WindowTraceBufferTest {
return toWrite;
}
- private WindowTraceBuffer buildQueueBuffer(int size) throws IOException {
- return new WindowTraceQueueBuffer(size, mFile, false);
- }
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowTracingTest.java b/services/tests/wmtests/src/com/android/server/wm/WindowTracingTest.java
index 3c6e2405adff..8358fdd18e0e 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowTracingTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowTracingTest.java
@@ -88,8 +88,7 @@ public class WindowTracingTest {
mFile.delete();
mWindowTracing = new WindowTracing(mFile, mWmMock, mChoreographer,
- new WindowManagerGlobalLock());
- mWindowTracing.setContinuousMode(false /* continuous */, null /* pw */);
+ new WindowManagerGlobalLock(), 1024);
}
@After
@@ -103,13 +102,13 @@ public class WindowTracingTest {
}
@Test
- public void isEnabled_returnsTrueAfterStart() throws Exception {
+ public void isEnabled_returnsTrueAfterStart() {
mWindowTracing.startTrace(mock(PrintWriter.class));
assertTrue(mWindowTracing.isEnabled());
}
@Test
- public void isEnabled_returnsFalseAfterStop() throws Exception {
+ public void isEnabled_returnsFalseAfterStop() {
mWindowTracing.startTrace(mock(PrintWriter.class));
mWindowTracing.stopTrace(mock(PrintWriter.class));
assertFalse(mWindowTracing.isEnabled());
@@ -133,6 +132,8 @@ public class WindowTracingTest {
mWindowTracing.startTrace(mock(PrintWriter.class));
mWindowTracing.stopTrace(mock(PrintWriter.class));
+ assertTrue("Trace file should exist", mFile.exists());
+
byte[] header = new byte[MAGIC_HEADER.length];
try (InputStream is = new FileInputStream(mFile)) {
assertEquals(MAGIC_HEADER.length, is.read(header));
diff --git a/services/usage/java/com/android/server/usage/IntervalStats.java b/services/usage/java/com/android/server/usage/IntervalStats.java
index f1ddfe4cd0d5..8feed7fdb785 100644
--- a/services/usage/java/com/android/server/usage/IntervalStats.java
+++ b/services/usage/java/com/android/server/usage/IntervalStats.java
@@ -15,7 +15,6 @@
*/
package com.android.server.usage;
-import static android.app.usage.UsageEvents.Event.ACTIVITY_DESTROYED;
import static android.app.usage.UsageEvents.Event.ACTIVITY_PAUSED;
import static android.app.usage.UsageEvents.Event.ACTIVITY_RESUMED;
import static android.app.usage.UsageEvents.Event.ACTIVITY_STOPPED;
@@ -302,27 +301,6 @@ public class IntervalStats {
UsageStats usageStats = packageStats.valueAt(i);
usageStats.update(null, timeStamp, eventType, instanceId);
}
- } else if (eventType == ACTIVITY_DESTROYED) {
- UsageStats usageStats = packageStats.get(packageName);
- if (usageStats != null) {
- // If previous event is not ACTIVITY_STOPPED, convert ACTIVITY_DESTROYED
- // to ACTIVITY_STOPPED and add to event list.
- // Otherwise do not add anything to event list. (Because we want to save space
- // and we do not want a ACTIVITY_STOPPED followed by
- // ACTIVITY_DESTROYED in event list).
- final int index = usageStats.mActivities.indexOfKey(instanceId);
- if (index >= 0) {
- final int type = usageStats.mActivities.valueAt(index);
- if (type != ACTIVITY_STOPPED) {
- Event event = new Event(ACTIVITY_STOPPED, timeStamp);
- event.mPackage = packageName;
- event.mClass = className;
- event.mInstanceId = instanceId;
- addEvent(event);
- }
- }
- usageStats.update(className, timeStamp, ACTIVITY_DESTROYED, instanceId);
- }
} else {
UsageStats usageStats = getOrCreateUsageStats(packageName);
usageStats.update(className, timeStamp, eventType, instanceId);
diff --git a/services/usage/java/com/android/server/usage/UsageStatsService.java b/services/usage/java/com/android/server/usage/UsageStatsService.java
index af5278f222b8..ebb0210cb553 100644
--- a/services/usage/java/com/android/server/usage/UsageStatsService.java
+++ b/services/usage/java/com/android/server/usage/UsageStatsService.java
@@ -145,8 +145,16 @@ public class UsageStatsService extends SystemService implements
AppTimeLimitController mAppTimeLimit;
final SparseArray<ArraySet<String>> mUsageReporters = new SparseArray();
- final SparseArray<String> mVisibleActivities = new SparseArray();
+ final SparseArray<ActivityData> mVisibleActivities = new SparseArray();
+ private static class ActivityData {
+ private final String mTaskRootPackage;
+ private final String mTaskRootClass;
+ private ActivityData(String taskRootPackage, String taskRootClass) {
+ mTaskRootPackage = taskRootPackage;
+ mTaskRootClass = taskRootClass;
+ }
+ }
private UsageStatsManagerInternal.AppIdleStateChangeListener mStandbyChangeListener =
new UsageStatsManagerInternal.AppIdleStateChangeListener() {
@@ -464,47 +472,57 @@ public class UsageStatsService extends SystemService implements
final long elapsedRealtime = SystemClock.elapsedRealtime();
convertToSystemTimeLocked(event);
- if (event.getPackageName() != null
- && mPackageManagerInternal.isPackageEphemeral(userId, event.getPackageName())) {
+ if (event.mPackage != null
+ && mPackageManagerInternal.isPackageEphemeral(userId, event.mPackage)) {
event.mFlags |= Event.FLAG_IS_PACKAGE_INSTANT_APP;
}
- final UserUsageStatsService service =
- getUserDataAndInitializeIfNeededLocked(userId, timeNow);
- service.reportEvent(event);
-
- mAppStandby.reportEvent(event, elapsedRealtime, userId);
-
- String packageName;
-
- switch(mUsageSource) {
- case USAGE_SOURCE_CURRENT_ACTIVITY:
- packageName = event.getPackageName();
- break;
- case USAGE_SOURCE_TASK_ROOT_ACTIVITY:
- default:
- packageName = event.getTaskRootPackageName();
- if (packageName == null) {
- packageName = event.getPackageName();
- }
- break;
- }
-
switch (event.mEventType) {
case Event.ACTIVITY_RESUMED:
- synchronized (mVisibleActivities) {
- // check if this activity has already been resumed
- if (mVisibleActivities.get(event.mInstanceId) != null) break;
- mVisibleActivities.put(event.mInstanceId, event.getClassName());
- try {
- mAppTimeLimit.noteUsageStart(packageName, userId);
- } catch (IllegalArgumentException iae) {
- Slog.e(TAG, "Failed to note usage start", iae);
+ // check if this activity has already been resumed
+ if (mVisibleActivities.get(event.mInstanceId) != null) break;
+ mVisibleActivities.put(event.mInstanceId,
+ new ActivityData(event.mTaskRootPackage, event.mTaskRootClass));
+ try {
+ switch(mUsageSource) {
+ case USAGE_SOURCE_CURRENT_ACTIVITY:
+ mAppTimeLimit.noteUsageStart(event.mPackage, userId);
+ break;
+ case USAGE_SOURCE_TASK_ROOT_ACTIVITY:
+ default:
+ mAppTimeLimit.noteUsageStart(event.mTaskRootPackage, userId);
+ break;
+ }
+ } catch (IllegalArgumentException iae) {
+ Slog.e(TAG, "Failed to note usage start", iae);
+ }
+ break;
+ case Event.ACTIVITY_PAUSED:
+ if (event.mTaskRootPackage == null) {
+ // Task Root info is missing. Repair the event based on previous data
+ final ActivityData prevData = mVisibleActivities.get(event.mInstanceId);
+ if (prevData == null) {
+ Slog.w(TAG, "Unexpected activity event reported! (" + event.mPackage
+ + "/" + event.mClass + " event : " + event.mEventType
+ + " instanceId : " + event.mInstanceId + ")");
+ } else {
+ event.mTaskRootPackage = prevData.mTaskRootPackage;
+ event.mTaskRootClass = prevData.mTaskRootClass;
}
}
break;
- case Event.ACTIVITY_STOPPED:
case Event.ACTIVITY_DESTROYED:
+ // Treat activity destroys like activity stops.
+ event.mEventType = Event.ACTIVITY_STOPPED;
+ // Fallthrough
+ case Event.ACTIVITY_STOPPED:
+ final ActivityData prevData =
+ mVisibleActivities.removeReturnOld(event.mInstanceId);
+ if (prevData == null) {
+ // The activity stop was already handled.
+ return;
+ }
+
ArraySet<String> tokens;
synchronized (mUsageReporters) {
tokens = mUsageReporters.removeReturnOld(event.mInstanceId);
@@ -517,7 +535,7 @@ public class UsageStatsService extends SystemService implements
final String token = tokens.valueAt(i);
try {
mAppTimeLimit.noteUsageStop(
- buildFullToken(event.getPackageName(), token), userId);
+ buildFullToken(event.mPackage, token), userId);
} catch (IllegalArgumentException iae) {
Slog.w(TAG, "Failed to stop usage for during reporter death: "
+ iae);
@@ -525,18 +543,32 @@ public class UsageStatsService extends SystemService implements
}
}
}
-
- synchronized (mVisibleActivities) {
- if (mVisibleActivities.removeReturnOld(event.mInstanceId) != null) {
- try {
- mAppTimeLimit.noteUsageStop(packageName, userId);
- } catch (IllegalArgumentException iae) {
- Slog.w(TAG, "Failed to note usage stop", iae);
- }
+ if (event.mTaskRootPackage == null) {
+ // Task Root info is missing. Repair the event based on previous data
+ event.mTaskRootPackage = prevData.mTaskRootPackage;
+ event.mTaskRootClass = prevData.mTaskRootClass;
+ }
+ try {
+ switch(mUsageSource) {
+ case USAGE_SOURCE_CURRENT_ACTIVITY:
+ mAppTimeLimit.noteUsageStop(event.mPackage, userId);
+ break;
+ case USAGE_SOURCE_TASK_ROOT_ACTIVITY:
+ default:
+ mAppTimeLimit.noteUsageStop(event.mTaskRootPackage, userId);
+ break;
}
+ } catch (IllegalArgumentException iae) {
+ Slog.w(TAG, "Failed to note usage stop", iae);
}
break;
}
+
+ final UserUsageStatsService service =
+ getUserDataAndInitializeIfNeededLocked(userId, timeNow);
+ service.reportEvent(event);
+
+ mAppStandby.reportEvent(event, elapsedRealtime, userId);
}
}
diff --git a/telecomm/java/android/telecom/Connection.java b/telecomm/java/android/telecom/Connection.java
index bd0d4ae27800..ae12a17e1e2f 100644
--- a/telecomm/java/android/telecom/Connection.java
+++ b/telecomm/java/android/telecom/Connection.java
@@ -623,7 +623,7 @@ public abstract class Connection extends Conferenceable {
"android.telecom.event.HANDOVER_FAILED";
/**
- * Connection extra key used to store SIP invite fields for an incoming call for IMS calls
+ * String Connection extra key used to store SIP invite fields for an incoming call for IMS call
*/
public static final String EXTRA_SIP_INVITE = "android.telecom.extra.SIP_INVITE";
diff --git a/telephony/java/android/provider/Telephony.java b/telephony/java/android/provider/Telephony.java
index a1c32b5f80a3..2462beeb28a8 100644
--- a/telephony/java/android/provider/Telephony.java
+++ b/telephony/java/android/provider/Telephony.java
@@ -2123,6 +2123,11 @@ public final class Telephony {
* @hide - not meant for public use
*/
public interface RcsColumns {
+ // TODO(sahinc): Turn this to true once the schema finalizes, so that people can update
+ // their messaging databases. NOTE: move the switch/case update in MmsSmsDatabaseHelper to
+ // the latest version of the database before turning this flag to true.
+ boolean IS_RCS_TABLE_SCHEMA_CODE_COMPLETE = false;
+
/**
* The authority for the content provider
*/
diff --git a/telephony/java/android/telephony/SmsMessage.java b/telephony/java/android/telephony/SmsMessage.java
index 099015fd3d0e..2aa4768d3f00 100644
--- a/telephony/java/android/telephony/SmsMessage.java
+++ b/telephony/java/android/telephony/SmsMessage.java
@@ -981,4 +981,13 @@ public class SmsMessage {
return false;
}
+
+ /**
+ * {@hide}
+ * Returns the recipient address(receiver) of this SMS message in String form or null if
+ * unavailable.
+ */
+ public String getRecipientAddress() {
+ return mWrappedSmsMessage.getRecipientAddress();
+ }
}
diff --git a/telephony/java/android/telephony/SubscriptionManager.java b/telephony/java/android/telephony/SubscriptionManager.java
index 836a50bf05c7..94f26a8a8d61 100644
--- a/telephony/java/android/telephony/SubscriptionManager.java
+++ b/telephony/java/android/telephony/SubscriptionManager.java
@@ -1236,7 +1236,7 @@ public class SubscriptionManager {
@SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges
@RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
public List<SubscriptionInfo> getActiveSubscriptionInfoList() {
- return getActiveSubscriptionInfoList(false);
+ return getActiveSubscriptionInfoList(/* userVisibleonly */true);
}
/**
@@ -2858,15 +2858,24 @@ public class SubscriptionManager {
/**
* Whether system UI should hide a subscription. If it's a bundled opportunistic
* subscription, it shouldn't show up in anywhere in Settings app, dialer app,
- * or status bar.
+ * or status bar. Exception is if caller is carrier app, in which case they will
+ * want to see their own hidden subscriptions.
*
* @param info the subscriptionInfo to check against.
* @return true if this subscription should be hidden.
*
* @hide
*/
- public static boolean shouldHideSubscription(SubscriptionInfo info) {
- return (info != null && !TextUtils.isEmpty(info.getGroupUuid()) && info.isOpportunistic());
+ private boolean shouldHideSubscription(SubscriptionInfo info) {
+ if (info == null) return false;
+
+ // If hasCarrierPrivileges or canManageSubscription returns true, it means caller
+ // has carrier privilege.
+ boolean hasCarrierPrivilegePermission = (info.isEmbedded() && canManageSubscription(info))
+ || TelephonyManager.from(mContext).hasCarrierPrivileges(info.getSubscriptionId());
+
+ return (!TextUtils.isEmpty(info.getGroupUuid()) && info.isOpportunistic()
+ && !hasCarrierPrivilegePermission);
}
/**
diff --git a/telephony/java/android/telephony/ims/ImsCallProfile.java b/telephony/java/android/telephony/ims/ImsCallProfile.java
index 73f055649b3f..d5c70793d3bc 100644
--- a/telephony/java/android/telephony/ims/ImsCallProfile.java
+++ b/telephony/java/android/telephony/ims/ImsCallProfile.java
@@ -266,6 +266,11 @@ public final class ImsCallProfile implements Parcelable {
public static final String EXTRA_DISPLAY_TEXT = "DisplayText";
public static final String EXTRA_ADDITIONAL_CALL_INFO = "AdditionalCallInfo";
public static final String EXTRA_IS_CALL_PULL = "CallPull";
+
+ /**
+ * String extra property
+ * Containing fields from the SIP INVITE message for an IMS call
+ */
public static final String EXTRA_ADDITIONAL_SIP_INVITE_FIELDS =
"android.telephony.ims.extra.ADDITIONAL_SIP_INVITE_FIELDS";
diff --git a/telephony/java/com/android/internal/telephony/SmsMessageBase.java b/telephony/java/com/android/internal/telephony/SmsMessageBase.java
index 190eac4d8c02..ffdc4b676f90 100644
--- a/telephony/java/com/android/internal/telephony/SmsMessageBase.java
+++ b/telephony/java/com/android/internal/telephony/SmsMessageBase.java
@@ -41,6 +41,9 @@ public abstract class SmsMessageBase {
@UnsupportedAppUsage
protected SmsAddress mOriginatingAddress;
+ /** {@hide} The address of the receiver */
+ protected SmsAddress mRecipientAddress;
+
/** {@hide} The message body as a string. May be null if the message isn't text */
@UnsupportedAppUsage
protected String mMessageBody;
@@ -457,4 +460,17 @@ public abstract class SmsMessageBase {
return ted;
}
+
+ /**
+ * {@hide}
+ * Returns the receiver address of this SMS message in String
+ * form or null if unavailable
+ */
+ public String getRecipientAddress() {
+ if (mRecipientAddress == null) {
+ return null;
+ }
+
+ return mRecipientAddress.getAddressString();
+ }
}
diff --git a/telephony/java/com/android/internal/telephony/cdma/SmsMessage.java b/telephony/java/com/android/internal/telephony/cdma/SmsMessage.java
index 1da5eac27002..a31fa0b6a725 100644
--- a/telephony/java/com/android/internal/telephony/cdma/SmsMessage.java
+++ b/telephony/java/com/android/internal/telephony/cdma/SmsMessage.java
@@ -601,18 +601,24 @@ public class SmsMessage extends SmsMessageBase {
} else if (addr.numberMode == CdmaSmsAddress.NUMBER_MODE_DATA_NETWORK) {
if (numberType == 2)
- Rlog.e(LOG_TAG, "TODO: Originating Addr is email id");
+ Rlog.e(LOG_TAG, "TODO: Addr is email id");
else
Rlog.e(LOG_TAG,
- "TODO: Originating Addr is data network address");
+ "TODO: Addr is data network address");
} else {
- Rlog.e(LOG_TAG, "Originating Addr is of incorrect type");
+ Rlog.e(LOG_TAG, "Addr is of incorrect type");
}
} else {
Rlog.e(LOG_TAG, "Incorrect Digit mode");
}
addr.origBytes = data;
- Rlog.i(LOG_TAG, "Originating Addr=" + addr.toString());
+ Rlog.pii(LOG_TAG, "Addr=" + addr.toString());
+ mOriginatingAddress = addr;
+ if (parameterId == DESTINATION_ADDRESS) {
+ // Original address awlays indicates one sender's address for 3GPP2
+ // Here add recipient address support along with 3GPP
+ mRecipientAddress = addr;
+ }
break;
case ORIGINATING_SUB_ADDRESS:
case DESTINATION_SUB_ADDRESS:
@@ -667,7 +673,7 @@ public class SmsMessage extends SmsMessageBase {
}
/**
- * Parses a SMS message from its BearerData stream. (mobile-terminated only)
+ * Parses a SMS message from its BearerData stream.
*/
public void parseSms() {
// Message Waiting Info Record defined in 3GPP2 C.S-0005, 3.7.5.6
@@ -697,16 +703,15 @@ public class SmsMessage extends SmsMessageBase {
}
if (mOriginatingAddress != null) {
- mOriginatingAddress.address = new String(mOriginatingAddress.origBytes);
- if (mOriginatingAddress.ton == CdmaSmsAddress.TON_INTERNATIONAL_OR_IP) {
- if (mOriginatingAddress.address.charAt(0) != '+') {
- mOriginatingAddress.address = "+" + mOriginatingAddress.address;
- }
- }
+ decodeSmsDisplayAddress(mOriginatingAddress);
if (VDBG) Rlog.v(LOG_TAG, "SMS originating address: "
+ mOriginatingAddress.address);
}
+ if (mRecipientAddress != null) {
+ decodeSmsDisplayAddress(mRecipientAddress);
+ }
+
if (mBearerData.msgCenterTimeStamp != null) {
mScTimeMillis = mBearerData.msgCenterTimeStamp.toMillis(true);
}
@@ -731,7 +736,8 @@ public class SmsMessage extends SmsMessageBase {
status = mBearerData.errorClass << 8;
status |= mBearerData.messageStatus;
}
- } else if (mBearerData.messageType != BearerData.MESSAGE_TYPE_DELIVER) {
+ } else if (mBearerData.messageType != BearerData.MESSAGE_TYPE_DELIVER
+ && mBearerData.messageType != BearerData.MESSAGE_TYPE_SUBMIT) {
throw new RuntimeException("Unsupported message type: " + mBearerData.messageType);
}
@@ -743,6 +749,16 @@ public class SmsMessage extends SmsMessageBase {
}
}
+ private void decodeSmsDisplayAddress(SmsAddress addr) {
+ addr.address = new String(addr.origBytes);
+ if (addr.ton == CdmaSmsAddress.TON_INTERNATIONAL_OR_IP) {
+ if (addr.address.charAt(0) != '+') {
+ addr.address = "+" + addr.address;
+ }
+ }
+ Rlog.pii(LOG_TAG, " decodeSmsDisplayAddress = " + addr.address);
+ }
+
/**
* Parses a broadcast SMS, possibly containing a CMAS alert.
*
diff --git a/telephony/java/com/android/internal/telephony/gsm/SmsMessage.java b/telephony/java/com/android/internal/telephony/gsm/SmsMessage.java
index 015efa6a0c7d..19465a44e4e8 100644
--- a/telephony/java/com/android/internal/telephony/gsm/SmsMessage.java
+++ b/telephony/java/com/android/internal/telephony/gsm/SmsMessage.java
@@ -71,9 +71,6 @@ public class SmsMessage extends SmsMessageBase {
// e.g. 23.040 9.2.2.1
private boolean mReplyPathPresent = false;
- /** The address of the receiver. */
- private GsmSmsAddress mRecipientAddress;
-
/**
* TP-Status - status of a previously submitted SMS.
* This field applies to SMS-STATUS-REPORT messages. 0 indicates success;
diff --git a/test-mock/api/test-current.txt b/test-mock/api/test-current.txt
index ab10800ac534..0cb8f22d8070 100644
--- a/test-mock/api/test-current.txt
+++ b/test-mock/api/test-current.txt
@@ -9,10 +9,12 @@ package android.test.mock {
method public java.util.List<android.content.pm.PackageInfo> getInstalledPackagesAsUser(int, int);
method public String[] getNamesForUids(int[]);
method public String getPermissionControllerPackageName();
+ method public int getPermissionFlags(String, String, android.os.UserHandle);
method @NonNull public String getServicesSystemSharedLibraryPackageName();
method @NonNull public String getSharedSystemSharedLibraryPackageName();
method public void grantRuntimePermission(String, String, android.os.UserHandle);
method public void revokeRuntimePermission(String, String, android.os.UserHandle);
+ method public void updatePermissionFlags(String, String, int, int, android.os.UserHandle);
}
}
diff --git a/tests/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java
index e57d838bcf92..a10fb4ee1305 100644
--- a/tests/net/java/com/android/server/ConnectivityServiceTest.java
+++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java
@@ -20,6 +20,7 @@ import static android.net.ConnectivityManager.CONNECTIVITY_ACTION;
import static android.net.ConnectivityManager.PRIVATE_DNS_MODE_OFF;
import static android.net.ConnectivityManager.PRIVATE_DNS_MODE_OPPORTUNISTIC;
import static android.net.ConnectivityManager.PRIVATE_DNS_MODE_PROVIDER_HOSTNAME;
+import static android.net.ConnectivityManager.NETID_UNSET;
import static android.net.ConnectivityManager.TYPE_ETHERNET;
import static android.net.ConnectivityManager.TYPE_MOBILE;
import static android.net.ConnectivityManager.TYPE_MOBILE_FOTA;
@@ -123,7 +124,7 @@ import android.net.NetworkMisc;
import android.net.NetworkParcelable;
import android.net.NetworkRequest;
import android.net.NetworkSpecifier;
-import android.net.NetworkStack;
+import android.net.NetworkStackClient;
import android.net.NetworkUtils;
import android.net.ProxyInfo;
import android.net.RouteInfo;
@@ -245,7 +246,7 @@ public class ConnectivityServiceTest {
@Mock INetworkStatsService mStatsService;
@Mock INetworkPolicyManager mNpm;
@Mock INetd mMockNetd;
- @Mock NetworkStack mNetworkStack;
+ @Mock NetworkStackClient mNetworkStack;
private ArgumentCaptor<String[]> mStringArrayCaptor = ArgumentCaptor.forClass(String[].class);
@@ -901,11 +902,14 @@ public class ConnectivityServiceTest {
public void setUids(Set<UidRange> uids) {
mNetworkCapabilities.setUids(uids);
- updateCapabilities();
+ updateCapabilities(null /* defaultNetwork */);
}
@Override
public int getNetId() {
+ if (mMockNetworkAgent == null) {
+ return NETID_UNSET;
+ }
return mMockNetworkAgent.getNetwork().netId;
}
@@ -927,12 +931,13 @@ public class ConnectivityServiceTest {
}
@Override
- public void updateCapabilities() {
- if (!mConnected) return;
- super.updateCapabilities();
- // Because super.updateCapabilities will update the capabilities of the agent but not
- // the mock agent, the mock agent needs to know about them.
+ public NetworkCapabilities updateCapabilities(Network defaultNetwork) {
+ if (!mConnected) return null;
+ super.updateCapabilities(defaultNetwork);
+ // Because super.updateCapabilities will update the capabilities of the agent but
+ // not the mock agent, the mock agent needs to know about them.
copyCapabilitiesToNetworkAgent();
+ return new NetworkCapabilities(mNetworkCapabilities);
}
private void copyCapabilitiesToNetworkAgent() {
@@ -1077,6 +1082,11 @@ public class ConnectivityServiceTest {
}
@Override
+ protected NetworkStackClient getNetworkStack() {
+ return mNetworkStack;
+ }
+
+ @Override
public WakeupMessage makeWakeupMessage(
Context context, Handler handler, String cmdName, int cmd, Object obj) {
return new FakeWakeupMessage(context, handler, cmdName, cmd, 0, 0, obj);
@@ -4690,6 +4700,7 @@ public class ConnectivityServiceTest {
vpnNetworkAgent.connect(false);
mMockVpn.connect();
+ mMockVpn.setUnderlyingNetworks(new Network[0]);
genericNetworkCallback.expectAvailableCallbacksUnvalidated(vpnNetworkAgent);
genericNotVpnNetworkCallback.assertNoCallback();
@@ -4722,6 +4733,7 @@ public class ConnectivityServiceTest {
ranges.add(new UidRange(uid, uid));
mMockVpn.setUids(ranges);
+ vpnNetworkAgent.setUids(ranges);
genericNetworkCallback.expectAvailableCallbacksValidated(vpnNetworkAgent);
genericNotVpnNetworkCallback.assertNoCallback();
@@ -4755,12 +4767,11 @@ public class ConnectivityServiceTest {
}
@Test
- public void testVpnWithAndWithoutInternet() {
+ public void testVpnWithoutInternet() {
final int uid = Process.myUid();
final TestNetworkCallback defaultCallback = new TestNetworkCallback();
mCm.registerDefaultNetworkCallback(defaultCallback);
- defaultCallback.assertNoCallback();
mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
mWiFiNetworkAgent.connect(true);
@@ -4782,11 +4793,30 @@ public class ConnectivityServiceTest {
vpnNetworkAgent.disconnect();
defaultCallback.assertNoCallback();
- vpnNetworkAgent = new MockNetworkAgent(TRANSPORT_VPN);
+ mCm.unregisterNetworkCallback(defaultCallback);
+ }
+
+ @Test
+ public void testVpnWithInternet() {
+ final int uid = Process.myUid();
+
+ final TestNetworkCallback defaultCallback = new TestNetworkCallback();
+ mCm.registerDefaultNetworkCallback(defaultCallback);
+
+ mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
+ mWiFiNetworkAgent.connect(true);
+
+ defaultCallback.expectAvailableThenValidatedCallbacks(mWiFiNetworkAgent);
+ assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
+
+ MockNetworkAgent vpnNetworkAgent = new MockNetworkAgent(TRANSPORT_VPN);
+ final ArraySet<UidRange> ranges = new ArraySet<>();
+ ranges.add(new UidRange(uid, uid));
mMockVpn.setNetworkAgent(vpnNetworkAgent);
mMockVpn.setUids(ranges);
vpnNetworkAgent.connect(true /* validated */, true /* hasInternet */);
mMockVpn.connect();
+
defaultCallback.expectAvailableThenValidatedCallbacks(vpnNetworkAgent);
assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
@@ -4794,14 +4824,6 @@ public class ConnectivityServiceTest {
defaultCallback.expectCallback(CallbackState.LOST, vpnNetworkAgent);
defaultCallback.expectAvailableCallbacksValidated(mWiFiNetworkAgent);
- vpnNetworkAgent = new MockNetworkAgent(TRANSPORT_VPN);
- ranges.clear();
- mMockVpn.setNetworkAgent(vpnNetworkAgent);
- mMockVpn.setUids(ranges);
- vpnNetworkAgent.connect(false /* validated */, true /* hasInternet */);
- mMockVpn.connect();
- defaultCallback.assertNoCallback();
-
mCm.unregisterNetworkCallback(defaultCallback);
}
@@ -4904,6 +4926,70 @@ public class ConnectivityServiceTest {
}
@Test
+ public void testNullUnderlyingNetworks() {
+ final int uid = Process.myUid();
+
+ final TestNetworkCallback vpnNetworkCallback = new TestNetworkCallback();
+ final NetworkRequest vpnNetworkRequest = new NetworkRequest.Builder()
+ .removeCapability(NET_CAPABILITY_NOT_VPN)
+ .addTransportType(TRANSPORT_VPN)
+ .build();
+ NetworkCapabilities nc;
+ mCm.registerNetworkCallback(vpnNetworkRequest, vpnNetworkCallback);
+ vpnNetworkCallback.assertNoCallback();
+
+ final MockNetworkAgent vpnNetworkAgent = new MockNetworkAgent(TRANSPORT_VPN);
+ final ArraySet<UidRange> ranges = new ArraySet<>();
+ ranges.add(new UidRange(uid, uid));
+ mMockVpn.setNetworkAgent(vpnNetworkAgent);
+ mMockVpn.connect();
+ mMockVpn.setUids(ranges);
+ vpnNetworkAgent.connect(true /* validated */, false /* hasInternet */);
+
+ vpnNetworkCallback.expectAvailableThenValidatedCallbacks(vpnNetworkAgent);
+ nc = mCm.getNetworkCapabilities(vpnNetworkAgent.getNetwork());
+ assertTrue(nc.hasTransport(TRANSPORT_VPN));
+ assertFalse(nc.hasTransport(TRANSPORT_CELLULAR));
+ assertFalse(nc.hasTransport(TRANSPORT_WIFI));
+ // By default, VPN is set to track default network (i.e. its underlying networks is null).
+ // In case of no default network, VPN is considered metered.
+ assertFalse(nc.hasCapability(NET_CAPABILITY_NOT_METERED));
+
+ // Connect to Cell; Cell is the default network.
+ mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
+ mCellNetworkAgent.connect(true);
+
+ vpnNetworkCallback.expectCapabilitiesLike((caps) -> caps.hasTransport(TRANSPORT_VPN)
+ && caps.hasTransport(TRANSPORT_CELLULAR) && !caps.hasTransport(TRANSPORT_WIFI)
+ && !caps.hasCapability(NET_CAPABILITY_NOT_METERED),
+ vpnNetworkAgent);
+
+ // Connect to WiFi; WiFi is the new default.
+ mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
+ mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
+ mWiFiNetworkAgent.connect(true);
+
+ vpnNetworkCallback.expectCapabilitiesLike((caps) -> caps.hasTransport(TRANSPORT_VPN)
+ && !caps.hasTransport(TRANSPORT_CELLULAR) && caps.hasTransport(TRANSPORT_WIFI)
+ && caps.hasCapability(NET_CAPABILITY_NOT_METERED),
+ vpnNetworkAgent);
+
+ // Disconnect Cell. The default network did not change, so there shouldn't be any changes in
+ // the capabilities.
+ mCellNetworkAgent.disconnect();
+
+ // Disconnect wifi too. Now we have no default network.
+ mWiFiNetworkAgent.disconnect();
+
+ vpnNetworkCallback.expectCapabilitiesLike((caps) -> caps.hasTransport(TRANSPORT_VPN)
+ && !caps.hasTransport(TRANSPORT_CELLULAR) && !caps.hasTransport(TRANSPORT_WIFI)
+ && !caps.hasCapability(NET_CAPABILITY_NOT_METERED),
+ vpnNetworkAgent);
+
+ mMockVpn.disconnect();
+ }
+
+ @Test
public void testNetworkBlockedStatus() {
final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
final NetworkRequest cellRequest = new NetworkRequest.Builder()
diff --git a/tests/net/java/com/android/server/connectivity/LingerMonitorTest.java b/tests/net/java/com/android/server/connectivity/LingerMonitorTest.java
index e877a8f7e6c1..5057443eee07 100644
--- a/tests/net/java/com/android/server/connectivity/LingerMonitorTest.java
+++ b/tests/net/java/com/android/server/connectivity/LingerMonitorTest.java
@@ -38,7 +38,6 @@ import android.net.NetworkCapabilities;
import android.net.NetworkFactory;
import android.net.NetworkInfo;
import android.net.NetworkMisc;
-import android.net.NetworkStack;
import android.os.INetworkManagementService;
import android.support.test.filters.SmallTest;
import android.support.test.runner.AndroidJUnit4;
@@ -75,16 +74,12 @@ public class LingerMonitorTest {
@Mock NetworkMisc mMisc;
@Mock NetworkNotificationManager mNotifier;
@Mock Resources mResources;
- @Mock NetworkStack mNetworkStack;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
when(mCtx.getResources()).thenReturn(mResources);
when(mCtx.getPackageName()).thenReturn("com.android.server.connectivity");
- when(mCtx.getSystemServiceName(NetworkStack.class))
- .thenReturn(Context.NETWORK_STACK_SERVICE);
- when(mCtx.getSystemService(Context.NETWORK_STACK_SERVICE)).thenReturn(mNetworkStack);
mMonitor = new TestableLingerMonitor(mCtx, mNotifier, HIGH_DAILY_LIMIT, HIGH_RATE_LIMIT);
}
diff --git a/tests/net/java/com/android/server/connectivity/TetheringTest.java b/tests/net/java/com/android/server/connectivity/TetheringTest.java
index a4a735d1a89d..533d7ad2a472 100644
--- a/tests/net/java/com/android/server/connectivity/TetheringTest.java
+++ b/tests/net/java/com/android/server/connectivity/TetheringTest.java
@@ -195,10 +195,6 @@ public class TetheringTest {
}
public class MockIpServerDependencies extends IpServer.Dependencies {
- MockIpServerDependencies() {
- super(null);
- }
-
@Override
public RouterAdvertisementDaemon getRouterAdvertisementDaemon(
InterfaceParams ifParams) {
@@ -266,7 +262,7 @@ public class TetheringTest {
}
@Override
- public IpServer.Dependencies getIpServerDependencies(Context context) {
+ public IpServer.Dependencies getIpServerDependencies() {
return mIpServerDependencies;
}
diff --git a/tests/net/java/com/android/server/connectivity/VpnTest.java b/tests/net/java/com/android/server/connectivity/VpnTest.java
index 46de3d0608ff..f169d6b5bee3 100644
--- a/tests/net/java/com/android/server/connectivity/VpnTest.java
+++ b/tests/net/java/com/android/server/connectivity/VpnTest.java
@@ -566,7 +566,7 @@ public class VpnTest {
final NetworkCapabilities caps = new NetworkCapabilities();
- Vpn.updateCapabilities(
+ Vpn.applyUnderlyingCapabilities(
mConnectivityManager, new Network[] {}, caps, false /* isAlwaysMetered */);
assertTrue(caps.hasTransport(TRANSPORT_VPN));
assertFalse(caps.hasTransport(TRANSPORT_CELLULAR));
@@ -577,7 +577,7 @@ public class VpnTest {
assertTrue(caps.hasCapability(NET_CAPABILITY_NOT_ROAMING));
assertTrue(caps.hasCapability(NET_CAPABILITY_NOT_CONGESTED));
- Vpn.updateCapabilities(
+ Vpn.applyUnderlyingCapabilities(
mConnectivityManager,
new Network[] {mobile},
caps,
@@ -591,7 +591,7 @@ public class VpnTest {
assertFalse(caps.hasCapability(NET_CAPABILITY_NOT_ROAMING));
assertTrue(caps.hasCapability(NET_CAPABILITY_NOT_CONGESTED));
- Vpn.updateCapabilities(
+ Vpn.applyUnderlyingCapabilities(
mConnectivityManager, new Network[] {wifi}, caps, false /* isAlwaysMetered */);
assertTrue(caps.hasTransport(TRANSPORT_VPN));
assertFalse(caps.hasTransport(TRANSPORT_CELLULAR));
@@ -602,7 +602,7 @@ public class VpnTest {
assertTrue(caps.hasCapability(NET_CAPABILITY_NOT_ROAMING));
assertTrue(caps.hasCapability(NET_CAPABILITY_NOT_CONGESTED));
- Vpn.updateCapabilities(
+ Vpn.applyUnderlyingCapabilities(
mConnectivityManager, new Network[] {wifi}, caps, true /* isAlwaysMetered */);
assertTrue(caps.hasTransport(TRANSPORT_VPN));
assertFalse(caps.hasTransport(TRANSPORT_CELLULAR));
@@ -613,7 +613,7 @@ public class VpnTest {
assertTrue(caps.hasCapability(NET_CAPABILITY_NOT_ROAMING));
assertTrue(caps.hasCapability(NET_CAPABILITY_NOT_CONGESTED));
- Vpn.updateCapabilities(
+ Vpn.applyUnderlyingCapabilities(
mConnectivityManager,
new Network[] {mobile, wifi},
caps,
diff --git a/tools/aapt2/Debug.cpp b/tools/aapt2/Debug.cpp
index 5f664f5fdd5c..98324850f3f5 100644
--- a/tools/aapt2/Debug.cpp
+++ b/tools/aapt2/Debug.cpp
@@ -435,7 +435,7 @@ void Debug::DumpResStringPool(const android::ResStringPool* pool, text::Printer*
const size_t NS = pool->size();
for (size_t s=0; s<NS; s++) {
String8 str = pool->string8ObjectAt(s);
- printer->Print(StringPrintf("String #%zd: %s\n", s, str.string()));
+ printer->Print(StringPrintf("String #%zd : %s\n", s, str.string()));
}
}
diff --git a/tools/aapt2/ResourceParser.cpp b/tools/aapt2/ResourceParser.cpp
index 2f8ca2d62061..c1887822ce7d 100644
--- a/tools/aapt2/ResourceParser.cpp
+++ b/tools/aapt2/ResourceParser.cpp
@@ -1084,7 +1084,7 @@ bool ResourceParser::ParseOverlayable(xml::XmlPullParser* parser, ParsedResource
// Create a overlayable entry grouping that represents this <overlayable>
auto overlayable = std::make_shared<Overlayable>(
overlayable_name.value(), (overlayable_actor) ? overlayable_actor.value() : "",
- out_resource->source);
+ source_);
bool error = false;
std::string comment;
@@ -1113,6 +1113,13 @@ bool ResourceParser::ParseOverlayable(xml::XmlPullParser* parser, ParsedResource
const std::string& element_name = parser->element_name();
const std::string& element_namespace = parser->element_namespace();
if (element_namespace.empty() && element_name == "item") {
+ if (current_policies == OverlayableItem::Policy::kNone) {
+ diag_->Error(DiagMessage(element_source)
+ << "<item> within an <overlayable> must be inside a <policy> block");
+ error = true;
+ continue;
+ }
+
// Items specify the name and type of resource that should be overlayable
Maybe<StringPiece> item_name = xml::FindNonEmptyAttribute(parser, "name");
if (!item_name) {
@@ -1169,6 +1176,8 @@ bool ResourceParser::ParseOverlayable(xml::XmlPullParser* parser, ParsedResource
current_policies |= OverlayableItem::Policy::kSystem;
} else if (trimmed_part == "vendor") {
current_policies |= OverlayableItem::Policy::kVendor;
+ } else if (trimmed_part == "signature") {
+ current_policies |= OverlayableItem::Policy::kSignature;
} else {
diag_->Error(DiagMessage(element_source)
<< "<policy> has unsupported type '" << trimmed_part << "'");
@@ -1176,6 +1185,11 @@ bool ResourceParser::ParseOverlayable(xml::XmlPullParser* parser, ParsedResource
continue;
}
}
+ } else {
+ diag_->Error(DiagMessage(element_source)
+ << "<policy> must have a 'type' attribute");
+ error = true;
+ continue;
}
} else if (!ShouldIgnoreElement(element_namespace, element_name)) {
diag_->Error(DiagMessage(element_source) << "invalid element <" << element_name << "> "
diff --git a/tools/aapt2/ResourceParser_test.cpp b/tools/aapt2/ResourceParser_test.cpp
index 827c7deaf452..25b76b0c1fa0 100644
--- a/tools/aapt2/ResourceParser_test.cpp
+++ b/tools/aapt2/ResourceParser_test.cpp
@@ -894,8 +894,10 @@ TEST_F(ResourceParserTest, ParsePlatformIndependentNewline) {
TEST_F(ResourceParserTest, ParseOverlayable) {
std::string input = R"(
<overlayable name="Name" actor="overlay://theme">
- <item type="string" name="foo" />
- <item type="drawable" name="bar" />
+ <policy type="signature">
+ <item type="string" name="foo" />
+ <item type="drawable" name="bar" />
+ </policy>
</overlayable>)";
ASSERT_TRUE(TestParse(input));
@@ -906,7 +908,7 @@ TEST_F(ResourceParserTest, ParseOverlayable) {
OverlayableItem& result_overlayable_item = search_result.value().entry->overlayable_item.value();
EXPECT_THAT(result_overlayable_item.overlayable->name, Eq("Name"));
EXPECT_THAT(result_overlayable_item.overlayable->actor, Eq("overlay://theme"));
- EXPECT_THAT(result_overlayable_item.policies, Eq(OverlayableItem::Policy::kNone));
+ EXPECT_THAT(result_overlayable_item.policies, Eq(OverlayableItem::Policy::kSignature));
search_result = table_.FindResource(test::ParseNameOrDie("drawable/bar"));
ASSERT_TRUE(search_result);
@@ -915,7 +917,7 @@ TEST_F(ResourceParserTest, ParseOverlayable) {
result_overlayable_item = search_result.value().entry->overlayable_item.value();
EXPECT_THAT(result_overlayable_item.overlayable->name, Eq("Name"));
EXPECT_THAT(result_overlayable_item.overlayable->actor, Eq("overlay://theme"));
- EXPECT_THAT(result_overlayable_item.policies, Eq(OverlayableItem::Policy::kNone));
+ EXPECT_THAT(result_overlayable_item.policies, Eq(OverlayableItem::Policy::kSignature));
}
TEST_F(ResourceParserTest, ParseOverlayableRequiresName) {
@@ -931,7 +933,6 @@ TEST_F(ResourceParserTest, ParseOverlayableBadActorFail) {
TEST_F(ResourceParserTest, ParseOverlayablePolicy) {
std::string input = R"(
<overlayable name="Name">
- <item type="string" name="foo" />
<policy type="product">
<item type="string" name="bar" />
</policy>
@@ -944,23 +945,18 @@ TEST_F(ResourceParserTest, ParseOverlayablePolicy) {
<policy type="public">
<item type="string" name="faz" />
</policy>
+ <policy type="signature">
+ <item type="string" name="foz" />
+ </policy>
</overlayable>)";
ASSERT_TRUE(TestParse(input));
- auto search_result = table_.FindResource(test::ParseNameOrDie("string/foo"));
+ auto search_result = table_.FindResource(test::ParseNameOrDie("string/bar"));
ASSERT_TRUE(search_result);
ASSERT_THAT(search_result.value().entry, NotNull());
ASSERT_TRUE(search_result.value().entry->overlayable_item);
OverlayableItem result_overlayable_item = search_result.value().entry->overlayable_item.value();
EXPECT_THAT(result_overlayable_item.overlayable->name, Eq("Name"));
- EXPECT_THAT(result_overlayable_item.policies, Eq(OverlayableItem::Policy::kNone));
-
- search_result = table_.FindResource(test::ParseNameOrDie("string/bar"));
- ASSERT_TRUE(search_result);
- ASSERT_THAT(search_result.value().entry, NotNull());
- ASSERT_TRUE(search_result.value().entry->overlayable_item);
- result_overlayable_item = search_result.value().entry->overlayable_item.value();
- EXPECT_THAT(result_overlayable_item.overlayable->name, Eq("Name"));
EXPECT_THAT(result_overlayable_item.policies, Eq(OverlayableItem::Policy::kProduct));
search_result = table_.FindResource(test::ParseNameOrDie("string/fiz"));
@@ -986,6 +982,30 @@ TEST_F(ResourceParserTest, ParseOverlayablePolicy) {
result_overlayable_item = search_result.value().entry->overlayable_item.value();
EXPECT_THAT(result_overlayable_item.overlayable->name, Eq("Name"));
EXPECT_THAT(result_overlayable_item.policies, Eq(OverlayableItem::Policy::kPublic));
+
+ search_result = table_.FindResource(test::ParseNameOrDie("string/foz"));
+ ASSERT_TRUE(search_result);
+ ASSERT_THAT(search_result.value().entry, NotNull());
+ ASSERT_TRUE(search_result.value().entry->overlayable_item);
+ result_overlayable_item = search_result.value().entry->overlayable_item.value();
+ EXPECT_THAT(result_overlayable_item.overlayable->name, Eq("Name"));
+ EXPECT_THAT(result_overlayable_item.policies, Eq(OverlayableItem::Policy::kSignature));
+}
+
+TEST_F(ResourceParserTest, ParseOverlayableNoPolicyError) {
+ std::string input = R"(
+ <overlayable name="Name">
+ <item type="string" name="foo" />
+ </overlayable>)";
+ EXPECT_FALSE(TestParse(input));
+
+ input = R"(
+ <overlayable name="Name">
+ <policy>
+ <item name="foo" />
+ </policy>
+ </overlayable>)";
+ EXPECT_FALSE(TestParse(input));
}
TEST_F(ResourceParserTest, ParseOverlayableBadPolicyError) {
diff --git a/tools/aapt2/ResourceTable.h b/tools/aapt2/ResourceTable.h
index 7ca99ea42b50..32dfd260e53c 100644
--- a/tools/aapt2/ResourceTable.h
+++ b/tools/aapt2/ResourceTable.h
@@ -92,6 +92,9 @@ struct OverlayableItem {
// The resource can be overlaid by any overlay on the product partition.
kProduct = 0x08,
+
+ // The resource can be overlaid by any overlay signed with the same signature as its actor.
+ kSignature = 0x010,
};
std::shared_ptr<Overlayable> overlayable;
diff --git a/tools/aapt2/ResourceUtils.cpp b/tools/aapt2/ResourceUtils.cpp
index ab4805f626a5..0032960ff93e 100644
--- a/tools/aapt2/ResourceUtils.cpp
+++ b/tools/aapt2/ResourceUtils.cpp
@@ -727,7 +727,7 @@ std::unique_ptr<Item> ParseBinaryResValue(const ResourceType& type, const Config
// This must be a FileReference.
std::unique_ptr<FileReference> file_ref =
util::make_unique<FileReference>(dst_pool->MakeRef(
- str, StringPool::Context(StringPool::Context::kHighPriority, config), data));
+ str, StringPool::Context(StringPool::Context::kHighPriority, config)));
if (type == ResourceType::kRaw) {
file_ref->type = ResourceFile::Type::kUnknown;
} else if (util::EndsWith(*file_ref->path, ".xml")) {
@@ -739,7 +739,7 @@ std::unique_ptr<Item> ParseBinaryResValue(const ResourceType& type, const Config
}
// There are no styles associated with this string, so treat it as a simple string.
- return util::make_unique<String>(dst_pool->MakeRef(str, StringPool::Context(config), data));
+ return util::make_unique<String>(dst_pool->MakeRef(str, StringPool::Context(config)));
}
} break;
diff --git a/tools/aapt2/Resources.proto b/tools/aapt2/Resources.proto
index 9a1d94288363..a2fd7c664b04 100644
--- a/tools/aapt2/Resources.proto
+++ b/tools/aapt2/Resources.proto
@@ -138,10 +138,10 @@ message AllowNew {
// Represents a set of overlayable resources.
message Overlayable {
- // The name of the <overlyabale>.
+ // The name of the <overlayable>.
string name = 1;
- // The location of the <overlyabale> declaration in the source.
+ // The location of the <overlayable> declaration in the source.
Source source = 2;
// The component responsible for enabling and disabling overlays targeting this <overlayable>.
diff --git a/tools/aapt2/StringPool.cpp b/tools/aapt2/StringPool.cpp
index a8c26668b3a5..8eabd3225d87 100644
--- a/tools/aapt2/StringPool.cpp
+++ b/tools/aapt2/StringPool.cpp
@@ -165,13 +165,12 @@ StringPool::Ref StringPool::MakeRef(const StringPiece& str) {
return MakeRefImpl(str, Context{}, true);
}
-StringPool::Ref StringPool::MakeRef(const StringPiece& str, const Context& context,
- Maybe<size_t> index) {
- return MakeRefImpl(str, context, true, index);
+StringPool::Ref StringPool::MakeRef(const StringPiece& str, const Context& context) {
+ return MakeRefImpl(str, context, true);
}
StringPool::Ref StringPool::MakeRefImpl(const StringPiece& str, const Context& context,
- bool unique, Maybe<size_t> index) {
+ bool unique) {
if (unique) {
auto range = indexed_strings_.equal_range(str);
for (auto iter = range.first; iter != range.second; ++iter) {
@@ -181,26 +180,15 @@ StringPool::Ref StringPool::MakeRefImpl(const StringPiece& str, const Context& c
}
}
- const size_t size = strings_.size();
- // Insert the string at the end of the string vector if no index is specified
- const size_t insertion_index = index ? index.value() : size;
-
std::unique_ptr<Entry> entry(new Entry());
entry->value = str.to_string();
entry->context = context;
- entry->index_ = insertion_index;
+ entry->index_ = strings_.size();
entry->ref_ = 0;
entry->pool_ = this;
Entry* borrow = entry.get();
- if (insertion_index == size) {
- strings_.emplace_back(std::move(entry));
- } else {
- // Allocate enough space for the string at the index
- strings_.resize(std::max(insertion_index + 1, size));
- strings_[insertion_index] = std::move(entry);
- }
-
+ strings_.emplace_back(std::move(entry));
indexed_strings_.insert(std::make_pair(StringPiece(borrow->value), borrow));
return Ref(borrow);
}
diff --git a/tools/aapt2/StringPool.h b/tools/aapt2/StringPool.h
index 115d5d315b8f..1006ca970dc5 100644
--- a/tools/aapt2/StringPool.h
+++ b/tools/aapt2/StringPool.h
@@ -166,8 +166,7 @@ class StringPool {
// Adds a string to the pool, unless it already exists, with a context object that can be used
// when sorting the string pool. Returns a reference to the string in the pool.
- Ref MakeRef(const android::StringPiece& str, const Context& context,
- Maybe<size_t> index = {});
+ Ref MakeRef(const android::StringPiece& str, const Context& context);
// Adds a string from another string pool. Returns a reference to the string in the string pool.
Ref MakeRef(const Ref& ref);
@@ -211,8 +210,7 @@ class StringPool {
static bool Flatten(BigBuffer* out, const StringPool& pool, bool utf8, IDiagnostics* diag);
- Ref MakeRefImpl(const android::StringPiece& str, const Context& context, bool unique,
- Maybe<size_t> index = {});
+ Ref MakeRefImpl(const android::StringPiece& str, const Context& context, bool unique);
void ReAssignIndices();
std::vector<std::unique_ptr<Entry>> strings_;
diff --git a/tools/aapt2/StringPool_test.cpp b/tools/aapt2/StringPool_test.cpp
index 648be7d33754..9a7238b584ba 100644
--- a/tools/aapt2/StringPool_test.cpp
+++ b/tools/aapt2/StringPool_test.cpp
@@ -84,24 +84,6 @@ TEST(StringPoolTest, MaintainInsertionOrderIndex) {
EXPECT_THAT(ref_c.index(), Eq(2u));
}
-TEST(StringPoolTest, AssignStringIndex) {
- StringPool pool;
-
- StringPool::Ref ref_a = pool.MakeRef("0", StringPool::Context{}, 0u);
- StringPool::Ref ref_b = pool.MakeRef("1", StringPool::Context{}, 1u);
- StringPool::Ref ref_c = pool.MakeRef("5", StringPool::Context{}, 5u);
- StringPool::Ref ref_d = pool.MakeRef("2", StringPool::Context{}, 2u);
- StringPool::Ref ref_e = pool.MakeRef("4", StringPool::Context{}, 4u);
- StringPool::Ref ref_f = pool.MakeRef("3", StringPool::Context{}, 3u);
-
- EXPECT_THAT(ref_a.index(), Eq(0u));
- EXPECT_THAT(ref_b.index(), Eq(1u));
- EXPECT_THAT(ref_d.index(), Eq(2u));
- EXPECT_THAT(ref_f.index(), Eq(3u));
- EXPECT_THAT(ref_e.index(), Eq(4u));
- EXPECT_THAT(ref_c.index(), Eq(5u));
-}
-
TEST(StringPoolTest, PruneStringsWithNoReferences) {
StringPool pool;
diff --git a/tools/aapt2/cmd/Convert.cpp b/tools/aapt2/cmd/Convert.cpp
index 7a74ba925ba0..0cf86ccdd59f 100644
--- a/tools/aapt2/cmd/Convert.cpp
+++ b/tools/aapt2/cmd/Convert.cpp
@@ -43,7 +43,8 @@ namespace aapt {
class IApkSerializer {
public:
- IApkSerializer(IAaptContext* context, const Source& source) : context_(context), source_(source) {}
+ IApkSerializer(IAaptContext* context, const Source& source) : context_(context),
+ source_(source) {}
virtual bool SerializeXml(const xml::XmlResource* xml, const std::string& path, bool utf16,
IArchiveWriter* writer, uint32_t compression_flags) = 0;
@@ -167,7 +168,7 @@ class ProtoApkSerializer : public IApkSerializer {
std::unique_ptr<io::IData> data = file->file->OpenAsData();
if (!data) {
context_->GetDiagnostics()->Error(DiagMessage(source_)
- << "failed to open file " << *file->path);
+ << "failed to open file " << *file->path);
return false;
}
@@ -175,7 +176,7 @@ class ProtoApkSerializer : public IApkSerializer {
std::unique_ptr<xml::XmlResource> xml = xml::Inflate(data->data(), data->size(), &error);
if (xml == nullptr) {
context_->GetDiagnostics()->Error(DiagMessage(source_) << "failed to parse binary XML: "
- << error);
+ << error);
return false;
}
@@ -256,9 +257,6 @@ class Context : public IAaptContext {
int Convert(IAaptContext* context, LoadedApk* apk, IArchiveWriter* output_writer,
ApkFormat output_format, TableFlattenerOptions table_flattener_options,
XmlFlattenerOptions xml_flattener_options) {
- // Do not change the ordering of strings in the values string pool
- table_flattener_options.sort_stringpool_entries = false;
-
unique_ptr<IApkSerializer> serializer;
if (output_format == ApkFormat::kBinary) {
serializer.reset(new BinaryApkSerializer(context, apk->GetSource(), table_flattener_options,
@@ -274,7 +272,7 @@ int Convert(IAaptContext* context, LoadedApk* apk, IArchiveWriter* output_writer
io::IFile* manifest = apk->GetFileCollection()->FindFile(kAndroidManifestPath);
if (!serializer->SerializeXml(apk->GetManifest(), kAndroidManifestPath, true /*utf16*/,
output_writer, (manifest != nullptr && manifest->WasCompressed())
- ? ArchiveEntry::kCompress : 0u)) {
+ ? ArchiveEntry::kCompress : 0u)) {
context->GetDiagnostics()->Error(DiagMessage(apk->GetSource())
<< "failed to serialize AndroidManifest.xml");
return 1;
@@ -303,8 +301,7 @@ int Convert(IAaptContext* context, LoadedApk* apk, IArchiveWriter* output_writer
if (files_written.insert(*file->path).second) {
if (!serializer->SerializeFile(file, output_writer)) {
context->GetDiagnostics()->Error(DiagMessage(apk->GetSource())
- << "failed to serialize file "
- << *file->path);
+ << "failed to serialize file " << *file->path);
return 1;
}
}
@@ -338,7 +335,7 @@ int Convert(IAaptContext* context, LoadedApk* apk, IArchiveWriter* output_writer
if (!io::CopyFileToArchivePreserveCompression(context, file, path, output_writer)) {
context->GetDiagnostics()->Error(DiagMessage(apk->GetSource())
- << "failed to copy file " << path);
+ << "failed to copy file " << path);
return 1;
}
}
diff --git a/tools/aapt2/cmd/Link.cpp b/tools/aapt2/cmd/Link.cpp
index 8463046a80eb..4961aa51dc16 100644
--- a/tools/aapt2/cmd/Link.cpp
+++ b/tools/aapt2/cmd/Link.cpp
@@ -400,7 +400,8 @@ static bool IsTransitionElement(const std::string& name) {
static bool IsVectorElement(const std::string& name) {
return name == "vector" || name == "animated-vector" || name == "pathInterpolator" ||
- name == "objectAnimator" || name == "gradient" || name == "animated-selector";
+ name == "objectAnimator" || name == "gradient" || name == "animated-selector" ||
+ name == "set";
}
template <typename T>
diff --git a/tools/aapt2/format/binary/BinaryResourceParser.cpp b/tools/aapt2/format/binary/BinaryResourceParser.cpp
index 40aaa05c2b30..59eb9ec2d418 100644
--- a/tools/aapt2/format/binary/BinaryResourceParser.cpp
+++ b/tools/aapt2/format/binary/BinaryResourceParser.cpp
@@ -401,7 +401,6 @@ bool BinaryResourceParser::ParseType(const ResourceTablePackage* package,
if (entry->flags & ResTable_entry::FLAG_PUBLIC) {
Visibility visibility;
visibility.level = Visibility::Level::kPublic;
- visibility.source = source_.WithLine(0);
if (!table_->SetVisibilityWithIdMangled(name, visibility, res_id, diag_)) {
return false;
}
@@ -448,7 +447,6 @@ bool BinaryResourceParser::ParseOverlayable(const ResChunk_header* chunk) {
arraysize(header->name)));
overlayable->actor = util::Utf16ToUtf8(strcpy16_dtoh((const char16_t*)header->actor,
arraysize(header->name)));
- overlayable->source = source_.WithLine(0);
ResChunkPullParser parser(GetChunkData(chunk),
GetChunkDataLen(chunk));
@@ -473,6 +471,10 @@ bool BinaryResourceParser::ParseOverlayable(const ResChunk_header* chunk) {
& ResTable_overlayable_policy_header::POLICY_PRODUCT_PARTITION) {
policies |= OverlayableItem::Policy::kProduct;
}
+ if (policy_header->policy_flags
+ & ResTable_overlayable_policy_header::POLICY_SIGNATURE) {
+ policies |= OverlayableItem::Policy::kSignature;
+ }
const ResTable_ref* const ref_begin = reinterpret_cast<const ResTable_ref*>(
((uint8_t *)policy_header) + util::DeviceToHost32(policy_header->header.headerSize));
@@ -491,7 +493,6 @@ bool BinaryResourceParser::ParseOverlayable(const ResChunk_header* chunk) {
}
OverlayableItem overlayable_item(overlayable);
- overlayable_item.source = source_.WithLine(0);
overlayable_item.policies = policies;
if (!table_->SetOverlayable(iter->second, overlayable_item, diag_)) {
return false;
diff --git a/tools/aapt2/format/binary/TableFlattener.cpp b/tools/aapt2/format/binary/TableFlattener.cpp
index 9d341cc1ca4a..d677317dc98d 100644
--- a/tools/aapt2/format/binary/TableFlattener.cpp
+++ b/tools/aapt2/format/binary/TableFlattener.cpp
@@ -274,7 +274,9 @@ class PackageFlattener {
FlattenLibrarySpec(buffer);
}
- FlattenOverlayable(buffer);
+ if (!FlattenOverlayable(buffer)) {
+ return false;
+ }
pkg_writer.Finish();
return true;
@@ -468,23 +470,29 @@ class PackageFlattener {
overlayable_chunk = &chunk;
}
+ if (item.policies == 0) {
+ context_->GetDiagnostics()->Error(DiagMessage(item.overlayable->source)
+ << "overlayable "
+ << entry->name
+ << " does not specify policy");
+ return false;
+ }
+
uint32_t policy_flags = 0;
- if (item.policies == OverlayableItem::Policy::kNone) {
- // Encode overlayable entries defined without a policy as publicly overlayable
+ if (item.policies & OverlayableItem::Policy::kPublic) {
policy_flags |= ResTable_overlayable_policy_header::POLICY_PUBLIC;
- } else {
- if (item.policies & OverlayableItem::Policy::kPublic) {
- policy_flags |= ResTable_overlayable_policy_header::POLICY_PUBLIC;
- }
- if (item.policies & OverlayableItem::Policy::kSystem) {
- policy_flags |= ResTable_overlayable_policy_header::POLICY_SYSTEM_PARTITION;
- }
- if (item.policies & OverlayableItem::Policy::kVendor) {
- policy_flags |= ResTable_overlayable_policy_header::POLICY_VENDOR_PARTITION;
- }
- if (item.policies & OverlayableItem::Policy::kProduct) {
- policy_flags |= ResTable_overlayable_policy_header::POLICY_PRODUCT_PARTITION;
- }
+ }
+ if (item.policies & OverlayableItem::Policy::kSystem) {
+ policy_flags |= ResTable_overlayable_policy_header::POLICY_SYSTEM_PARTITION;
+ }
+ if (item.policies & OverlayableItem::Policy::kVendor) {
+ policy_flags |= ResTable_overlayable_policy_header::POLICY_VENDOR_PARTITION;
+ }
+ if (item.policies & OverlayableItem::Policy::kProduct) {
+ policy_flags |= ResTable_overlayable_policy_header::POLICY_PRODUCT_PARTITION;
+ }
+ if (item.policies & OverlayableItem::Policy::kSignature) {
+ policy_flags |= ResTable_overlayable_policy_header::POLICY_SIGNATURE;
}
auto policy = overlayable_chunk->policy_ids.find(policy_flags);
@@ -702,17 +710,15 @@ class PackageFlattener {
} // namespace
bool TableFlattener::Consume(IAaptContext* context, ResourceTable* table) {
- if (options_.sort_stringpool_entries) {
- // We must do this before writing the resources, since the string pool IDs may change.
- table->string_pool.Prune();
- table->string_pool.Sort([](const StringPool::Context &a, const StringPool::Context &b) -> int {
- int diff = util::compare(a.priority, b.priority);
- if (diff == 0) {
- diff = a.config.compare(b.config);
- }
- return diff;
- });
- }
+ // We must do this before writing the resources, since the string pool IDs may change.
+ table->string_pool.Prune();
+ table->string_pool.Sort([](const StringPool::Context& a, const StringPool::Context& b) -> int {
+ int diff = util::compare(a.priority, b.priority);
+ if (diff == 0) {
+ diff = a.config.compare(b.config);
+ }
+ return diff;
+ });
// Write the ResTable header.
ChunkWriter table_writer(buffer_);
diff --git a/tools/aapt2/format/binary/TableFlattener.h b/tools/aapt2/format/binary/TableFlattener.h
index 71330e3fb74f..73c17295556b 100644
--- a/tools/aapt2/format/binary/TableFlattener.h
+++ b/tools/aapt2/format/binary/TableFlattener.h
@@ -44,9 +44,6 @@ struct TableFlattenerOptions {
// Set of whitelisted resource names to avoid altering in key stringpool
std::set<std::string> whitelisted_resources;
- // When true, sort the entries in the values string pool by priority and configuration.
- bool sort_stringpool_entries = true;
-
// Map from original resource paths to shortened resource paths.
std::map<std::string, std::string> shortened_path_map;
};
diff --git a/tools/aapt2/format/binary/TableFlattener_test.cpp b/tools/aapt2/format/binary/TableFlattener_test.cpp
index ddc117399390..4c5dbec8ade8 100644
--- a/tools/aapt2/format/binary/TableFlattener_test.cpp
+++ b/tools/aapt2/format/binary/TableFlattener_test.cpp
@@ -671,9 +671,6 @@ TEST_F(TableFlattenerTest, FlattenMultipleOverlayablePolicies) {
overlayable_item_two.policies |= OverlayableItem::Policy::kSystem;
overlayable_item_two.policies |= OverlayableItem::Policy::kVendor;
- std::string name_three = "com.app.test:integer/overlayable_three_item";
- OverlayableItem overlayable_item_three(overlayable);
-
std::unique_ptr<ResourceTable> table =
test::ResourceTableBuilder()
.SetPackageId("com.app.test", 0x7f)
@@ -683,8 +680,6 @@ TEST_F(TableFlattenerTest, FlattenMultipleOverlayablePolicies) {
.SetOverlayable(name_one, overlayable_item_one)
.AddSimple(name_two, ResourceId(0x7f020002))
.SetOverlayable(name_two, overlayable_item_two)
- .AddSimple(name_three, ResourceId(0x7f020003))
- .SetOverlayable(name_three, overlayable_item_three)
.Build();
ResourceTable output_table;
@@ -713,16 +708,6 @@ TEST_F(TableFlattenerTest, FlattenMultipleOverlayablePolicies) {
EXPECT_EQ(overlayable_item.policies, OverlayableItem::Policy::kSystem
| OverlayableItem::Policy::kProduct
| OverlayableItem::Policy::kVendor);
-
- search_result = output_table.FindResource(test::ParseNameOrDie(name_three));
- ASSERT_TRUE(search_result);
- ASSERT_THAT(search_result.value().entry, NotNull());
- ASSERT_TRUE(search_result.value().entry->overlayable_item);
- overlayable_item = search_result.value().entry->overlayable_item.value();
- EXPECT_EQ(overlayable_item.policies, OverlayableItem::Policy::kPublic);
- EXPECT_EQ(overlayable_item.overlayable->name, "TestName");
- EXPECT_EQ(overlayable_item.overlayable->actor, "overlay://theme");
- EXPECT_EQ(overlayable_item.policies, OverlayableItem::Policy::kPublic);
}
TEST_F(TableFlattenerTest, FlattenMultipleOverlayable) {
@@ -745,6 +730,8 @@ TEST_F(TableFlattenerTest, FlattenMultipleOverlayable) {
std::string name_three = "com.app.test:integer/overlayable_three";
OverlayableItem overlayable_item_three(group_one);
+ overlayable_item_three.policies |= OverlayableItem::Policy::kSignature;
+
std::unique_ptr<ResourceTable> table =
test::ResourceTableBuilder()
.SetPackageId("com.app.test", 0x7f)
@@ -793,7 +780,22 @@ TEST_F(TableFlattenerTest, FlattenMultipleOverlayable) {
result_overlayable = search_result.value().entry->overlayable_item.value();
EXPECT_EQ(result_overlayable.overlayable->name, "OtherName");
EXPECT_EQ(result_overlayable.overlayable->actor, "overlay://customization");
- EXPECT_EQ(result_overlayable.policies, OverlayableItem::Policy::kPublic);
+ EXPECT_EQ(result_overlayable.policies, OverlayableItem::Policy::kSignature);
+}
+
+TEST_F(TableFlattenerTest, FlattenOverlayableNoPolicyFails) {
+ auto group = std::make_shared<Overlayable>("TestName", "overlay://theme");
+ std::string name_zero = "com.app.test:integer/overlayable_zero";
+ OverlayableItem overlayable_item_zero(group);
+
+ std::unique_ptr<ResourceTable> table =
+ test::ResourceTableBuilder()
+ .SetPackageId("com.app.test", 0x7f)
+ .AddSimple(name_zero, ResourceId(0x7f020000))
+ .SetOverlayable(name_zero, overlayable_item_zero)
+ .Build();
+ ResourceTable output_table;
+ ASSERT_FALSE(Flatten(context_.get(), {}, table.get(), &output_table));
}
} // namespace aapt
diff --git a/tools/aapt2/format/proto/ProtoDeserialize.cpp b/tools/aapt2/format/proto/ProtoDeserialize.cpp
index aff1b391f861..06f1bf74d7e7 100644
--- a/tools/aapt2/format/proto/ProtoDeserialize.cpp
+++ b/tools/aapt2/format/proto/ProtoDeserialize.cpp
@@ -390,6 +390,9 @@ bool DeserializeOverlayableItemFromPb(const pb::OverlayableItem& pb_overlayable,
case pb::OverlayableItem::PRODUCT:
out_overlayable->policies |= OverlayableItem::Policy::kProduct;
break;
+ case pb::OverlayableItem::SIGNATURE:
+ out_overlayable->policies |= OverlayableItem::Policy::kSignature;
+ break;
default:
*out_error = "unknown overlayable policy";
return false;
diff --git a/tools/aapt2/format/proto/ProtoSerialize.cpp b/tools/aapt2/format/proto/ProtoSerialize.cpp
index b549e2369f98..eb2b1a2f35d3 100644
--- a/tools/aapt2/format/proto/ProtoSerialize.cpp
+++ b/tools/aapt2/format/proto/ProtoSerialize.cpp
@@ -309,6 +309,9 @@ static void SerializeOverlayableItemToPb(const OverlayableItem& overlayable_item
if (overlayable_item.policies & OverlayableItem::Policy::kVendor) {
pb_overlayable_item->add_policy(pb::OverlayableItem::VENDOR);
}
+ if (overlayable_item.policies & OverlayableItem::Policy::kSignature) {
+ pb_overlayable_item->add_policy(pb::OverlayableItem::SIGNATURE);
+ }
SerializeSourceToPb(overlayable_item.source, source_pool,
pb_overlayable_item->mutable_source());
diff --git a/tools/aapt2/format/proto/ProtoSerialize_test.cpp b/tools/aapt2/format/proto/ProtoSerialize_test.cpp
index cce3939704cf..d369ac4c8816 100644
--- a/tools/aapt2/format/proto/ProtoSerialize_test.cpp
+++ b/tools/aapt2/format/proto/ProtoSerialize_test.cpp
@@ -526,6 +526,10 @@ TEST(ProtoSerializeTest, SerializeAndDeserializeOverlayable) {
"FontPack", "overlay://theme"));
overlayable_item_baz.policies |= OverlayableItem::Policy::kPublic;
+ OverlayableItem overlayable_item_boz(std::make_shared<Overlayable>(
+ "IconPack", "overlay://theme"));
+ overlayable_item_boz.policies |= OverlayableItem::Policy::kSignature;
+
OverlayableItem overlayable_item_biz(std::make_shared<Overlayable>(
"Other", "overlay://customization"));
overlayable_item_biz.comment ="comment";
@@ -536,6 +540,7 @@ TEST(ProtoSerializeTest, SerializeAndDeserializeOverlayable) {
.SetOverlayable("com.app.a:bool/foo", overlayable_item_foo)
.SetOverlayable("com.app.a:bool/bar", overlayable_item_bar)
.SetOverlayable("com.app.a:bool/baz", overlayable_item_baz)
+ .SetOverlayable("com.app.a:bool/boz", overlayable_item_boz)
.SetOverlayable("com.app.a:bool/biz", overlayable_item_biz)
.AddValue("com.app.a:bool/fiz", ResourceUtils::TryParseBool("true"))
.Build();
@@ -576,6 +581,14 @@ TEST(ProtoSerializeTest, SerializeAndDeserializeOverlayable) {
EXPECT_THAT(overlayable_item.overlayable->actor, Eq("overlay://theme"));
EXPECT_THAT(overlayable_item.policies, Eq(OverlayableItem::Policy::kPublic));
+ search_result = new_table.FindResource(test::ParseNameOrDie("com.app.a:bool/boz"));
+ ASSERT_TRUE(search_result);
+ ASSERT_TRUE(search_result.value().entry->overlayable_item);
+ overlayable_item = search_result.value().entry->overlayable_item.value();
+ EXPECT_THAT(overlayable_item.overlayable->name, Eq("IconPack"));
+ EXPECT_THAT(overlayable_item.overlayable->actor, Eq("overlay://theme"));
+ EXPECT_THAT(overlayable_item.policies, Eq(OverlayableItem::Policy::kSignature));
+
search_result = new_table.FindResource(test::ParseNameOrDie("com.app.a:bool/biz"));
ASSERT_TRUE(search_result);
ASSERT_TRUE(search_result.value().entry->overlayable_item);
diff --git a/wifi/java/android/net/wifi/p2p/WifiP2pGroup.java b/wifi/java/android/net/wifi/p2p/WifiP2pGroup.java
index 72e57a16712b..8a1b21c990c7 100644
--- a/wifi/java/android/net/wifi/p2p/WifiP2pGroup.java
+++ b/wifi/java/android/net/wifi/p2p/WifiP2pGroup.java
@@ -67,7 +67,7 @@ public class WifiP2pGroup implements Parcelable {
/** The network id in the wpa_supplicant */
private int mNetId;
- /** The frequency used by this group */
+ /** The frequency (in MHz) used by this group */
private int mFrequency;
/** P2P group started string pattern */
@@ -273,7 +273,7 @@ public class WifiP2pGroup implements Parcelable {
this.mNetId = netId;
}
- /** Get the operating frequency of the p2p group */
+ /** Get the operating frequency (in MHz) of the p2p group */
public int getFrequency() {
return mFrequency;
}